mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-12 13:30:51 +00:00
[InstCombine, InstSimplify] Move xforms from Combine to Simplify
There were several SelectInst combines that always returned an existing instruction instead of modifying an old one or creating a new one. These are prime candidates for moving to InstSimplify. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@239229 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
ce986b6bc0
commit
134cb22902
@ -3144,6 +3144,90 @@ Value *llvm::SimplifyFCmpInst(unsigned Predicate, Value *LHS, Value *RHS,
|
||||
RecursionLimit);
|
||||
}
|
||||
|
||||
/// SimplifyWithOpReplaced - See if V simplifies when its operand Op is
|
||||
/// replaced with RepOp.
|
||||
static const Value *SimplifyWithOpReplaced(Value *V, Value *Op, Value *RepOp,
|
||||
const Query &Q,
|
||||
unsigned MaxRecurse) {
|
||||
// Trivial replacement.
|
||||
if (V == Op)
|
||||
return RepOp;
|
||||
|
||||
auto *I = dyn_cast<Instruction>(V);
|
||||
if (!I)
|
||||
return nullptr;
|
||||
|
||||
// If this is a binary operator, try to simplify it with the replaced op.
|
||||
if (auto *B = dyn_cast<BinaryOperator>(I)) {
|
||||
// Consider:
|
||||
// %cmp = icmp eq i32 %x, 2147483647
|
||||
// %add = add nsw i32 %x, 1
|
||||
// %sel = select i1 %cmp, i32 -2147483648, i32 %add
|
||||
//
|
||||
// We can't replace %sel with %add unless we strip away the flags.
|
||||
if (isa<OverflowingBinaryOperator>(B))
|
||||
if (B->hasNoSignedWrap() || B->hasNoUnsignedWrap())
|
||||
return nullptr;
|
||||
if (isa<PossiblyExactOperator>(B))
|
||||
if (B->isExact())
|
||||
return nullptr;
|
||||
|
||||
if (MaxRecurse) {
|
||||
if (B->getOperand(0) == Op)
|
||||
return SimplifyBinOp(B->getOpcode(), RepOp, B->getOperand(1), Q,
|
||||
MaxRecurse - 1);
|
||||
if (B->getOperand(1) == Op)
|
||||
return SimplifyBinOp(B->getOpcode(), B->getOperand(0), RepOp, Q,
|
||||
MaxRecurse - 1);
|
||||
}
|
||||
}
|
||||
|
||||
// Same for CmpInsts.
|
||||
if (CmpInst *C = dyn_cast<CmpInst>(I)) {
|
||||
if (MaxRecurse) {
|
||||
if (C->getOperand(0) == Op)
|
||||
return SimplifyCmpInst(C->getPredicate(), RepOp, C->getOperand(1), Q,
|
||||
MaxRecurse - 1);
|
||||
if (C->getOperand(1) == Op)
|
||||
return SimplifyCmpInst(C->getPredicate(), C->getOperand(0), RepOp, Q,
|
||||
MaxRecurse - 1);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: We could hand off more cases to instsimplify here.
|
||||
|
||||
// If all operands are constant after substituting Op for RepOp then we can
|
||||
// constant fold the instruction.
|
||||
if (Constant *CRepOp = dyn_cast<Constant>(RepOp)) {
|
||||
// Build a list of all constant operands.
|
||||
SmallVector<Constant *, 8> ConstOps;
|
||||
for (unsigned i = 0, e = I->getNumOperands(); i != e; ++i) {
|
||||
if (I->getOperand(i) == Op)
|
||||
ConstOps.push_back(CRepOp);
|
||||
else if (Constant *COp = dyn_cast<Constant>(I->getOperand(i)))
|
||||
ConstOps.push_back(COp);
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
// All operands were constants, fold it.
|
||||
if (ConstOps.size() == I->getNumOperands()) {
|
||||
if (CmpInst *C = dyn_cast<CmpInst>(I))
|
||||
return ConstantFoldCompareInstOperands(C->getPredicate(), ConstOps[0],
|
||||
ConstOps[1], Q.DL, Q.TLI);
|
||||
|
||||
if (LoadInst *LI = dyn_cast<LoadInst>(I))
|
||||
if (!LI->isVolatile())
|
||||
return ConstantFoldLoadFromConstPtr(ConstOps[0], Q.DL);
|
||||
|
||||
return ConstantFoldInstOperands(I->getOpcode(), I->getType(), ConstOps,
|
||||
Q.DL, Q.TLI);
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/// SimplifySelectInst - Given operands for a SelectInst, see if we can fold
|
||||
/// the result. If not, this returns null.
|
||||
static Value *SimplifySelectInst(Value *CondVal, Value *TrueVal,
|
||||
@ -3172,29 +3256,28 @@ static Value *SimplifySelectInst(Value *CondVal, Value *TrueVal,
|
||||
if (isa<UndefValue>(FalseVal)) // select C, X, undef -> X
|
||||
return TrueVal;
|
||||
|
||||
const auto *ICI = dyn_cast<ICmpInst>(CondVal);
|
||||
unsigned BitWidth = TrueVal->getType()->getScalarSizeInBits();
|
||||
if (ICI && BitWidth) {
|
||||
if (const auto *ICI = dyn_cast<ICmpInst>(CondVal)) {
|
||||
unsigned BitWidth = Q.DL.getTypeSizeInBits(TrueVal->getType());
|
||||
ICmpInst::Predicate Pred = ICI->getPredicate();
|
||||
Value *CmpLHS = ICI->getOperand(0);
|
||||
Value *CmpRHS = ICI->getOperand(1);
|
||||
APInt MinSignedValue = APInt::getSignBit(BitWidth);
|
||||
Value *X;
|
||||
const APInt *Y;
|
||||
bool TrueWhenUnset;
|
||||
bool IsBitTest = false;
|
||||
if (ICmpInst::isEquality(Pred) &&
|
||||
match(ICI->getOperand(0), m_And(m_Value(X), m_APInt(Y))) &&
|
||||
match(ICI->getOperand(1), m_Zero())) {
|
||||
match(CmpLHS, m_And(m_Value(X), m_APInt(Y))) &&
|
||||
match(CmpRHS, m_Zero())) {
|
||||
IsBitTest = true;
|
||||
TrueWhenUnset = Pred == ICmpInst::ICMP_EQ;
|
||||
} else if (Pred == ICmpInst::ICMP_SLT &&
|
||||
match(ICI->getOperand(1), m_Zero())) {
|
||||
X = ICI->getOperand(0);
|
||||
} else if (Pred == ICmpInst::ICMP_SLT && match(CmpRHS, m_Zero())) {
|
||||
X = CmpLHS;
|
||||
Y = &MinSignedValue;
|
||||
IsBitTest = true;
|
||||
TrueWhenUnset = false;
|
||||
} else if (Pred == ICmpInst::ICMP_SGT &&
|
||||
match(ICI->getOperand(1), m_AllOnes())) {
|
||||
X = ICI->getOperand(0);
|
||||
} else if (Pred == ICmpInst::ICMP_SGT && match(CmpRHS, m_AllOnes())) {
|
||||
X = CmpLHS;
|
||||
Y = &MinSignedValue;
|
||||
IsBitTest = true;
|
||||
TrueWhenUnset = true;
|
||||
@ -3225,6 +3308,50 @@ static Value *SimplifySelectInst(Value *CondVal, Value *TrueVal,
|
||||
return TrueWhenUnset ? TrueVal : FalseVal;
|
||||
}
|
||||
}
|
||||
if (ICI->hasOneUse()) {
|
||||
const APInt *C;
|
||||
if (match(CmpRHS, m_APInt(C))) {
|
||||
// X < MIN ? T : F --> F
|
||||
if (Pred == ICmpInst::ICMP_SLT && C->isMinSignedValue())
|
||||
return FalseVal;
|
||||
// X < MIN ? T : F --> F
|
||||
if (Pred == ICmpInst::ICMP_ULT && C->isMinValue())
|
||||
return FalseVal;
|
||||
// X > MAX ? T : F --> F
|
||||
if (Pred == ICmpInst::ICMP_SGT && C->isMaxSignedValue())
|
||||
return FalseVal;
|
||||
// X > MAX ? T : F --> F
|
||||
if (Pred == ICmpInst::ICMP_UGT && C->isMaxValue())
|
||||
return FalseVal;
|
||||
}
|
||||
}
|
||||
|
||||
// If we have an equality comparison then we know the value in one of the
|
||||
// arms of the select. See if substituting this value into the arm and
|
||||
// simplifying the result yields the same value as the other arm.
|
||||
if (Pred == ICmpInst::ICMP_EQ) {
|
||||
if (SimplifyWithOpReplaced(FalseVal, CmpLHS, CmpRHS, Q, MaxRecurse) ==
|
||||
TrueVal ||
|
||||
SimplifyWithOpReplaced(FalseVal, CmpRHS, CmpLHS, Q, MaxRecurse) ==
|
||||
TrueVal)
|
||||
return FalseVal;
|
||||
if (SimplifyWithOpReplaced(TrueVal, CmpLHS, CmpRHS, Q, MaxRecurse) ==
|
||||
FalseVal ||
|
||||
SimplifyWithOpReplaced(TrueVal, CmpRHS, CmpLHS, Q, MaxRecurse) ==
|
||||
FalseVal)
|
||||
return FalseVal;
|
||||
} else if (Pred == ICmpInst::ICMP_NE) {
|
||||
if (SimplifyWithOpReplaced(TrueVal, CmpLHS, CmpRHS, Q, MaxRecurse) ==
|
||||
FalseVal ||
|
||||
SimplifyWithOpReplaced(TrueVal, CmpRHS, CmpLHS, Q, MaxRecurse) ==
|
||||
FalseVal)
|
||||
return TrueVal;
|
||||
if (SimplifyWithOpReplaced(FalseVal, CmpLHS, CmpRHS, Q, MaxRecurse) ==
|
||||
TrueVal ||
|
||||
SimplifyWithOpReplaced(FalseVal, CmpRHS, CmpLHS, Q, MaxRecurse) ==
|
||||
TrueVal)
|
||||
return TrueVal;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
|
@ -276,85 +276,6 @@ Instruction *InstCombiner::FoldSelectIntoOp(SelectInst &SI, Value *TrueVal,
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/// SimplifyWithOpReplaced - See if V simplifies when its operand Op is
|
||||
/// replaced with RepOp.
|
||||
static Value *SimplifyWithOpReplaced(Value *V, Value *Op, Value *RepOp,
|
||||
const TargetLibraryInfo *TLI,
|
||||
const DataLayout &DL, DominatorTree *DT,
|
||||
AssumptionCache *AC) {
|
||||
// Trivial replacement.
|
||||
if (V == Op)
|
||||
return RepOp;
|
||||
|
||||
Instruction *I = dyn_cast<Instruction>(V);
|
||||
if (!I)
|
||||
return nullptr;
|
||||
|
||||
// If this is a binary operator, try to simplify it with the replaced op.
|
||||
if (BinaryOperator *B = dyn_cast<BinaryOperator>(I)) {
|
||||
// Consider:
|
||||
// %cmp = icmp eq i32 %x, 2147483647
|
||||
// %add = add nsw i32 %x, 1
|
||||
// %sel = select i1 %cmp, i32 -2147483648, i32 %add
|
||||
//
|
||||
// We can't replace %sel with %add unless we strip away the flags.
|
||||
if (isa<OverflowingBinaryOperator>(B))
|
||||
if (B->hasNoSignedWrap() || B->hasNoUnsignedWrap())
|
||||
return nullptr;
|
||||
if (isa<PossiblyExactOperator>(B))
|
||||
if (B->isExact())
|
||||
return nullptr;
|
||||
|
||||
if (B->getOperand(0) == Op)
|
||||
return SimplifyBinOp(B->getOpcode(), RepOp, B->getOperand(1), DL, TLI);
|
||||
if (B->getOperand(1) == Op)
|
||||
return SimplifyBinOp(B->getOpcode(), B->getOperand(0), RepOp, DL, TLI);
|
||||
}
|
||||
|
||||
// Same for CmpInsts.
|
||||
if (CmpInst *C = dyn_cast<CmpInst>(I)) {
|
||||
if (C->getOperand(0) == Op)
|
||||
return SimplifyCmpInst(C->getPredicate(), RepOp, C->getOperand(1), DL,
|
||||
TLI, DT, AC);
|
||||
if (C->getOperand(1) == Op)
|
||||
return SimplifyCmpInst(C->getPredicate(), C->getOperand(0), RepOp, DL,
|
||||
TLI, DT, AC);
|
||||
}
|
||||
|
||||
// TODO: We could hand off more cases to instsimplify here.
|
||||
|
||||
// If all operands are constant after substituting Op for RepOp then we can
|
||||
// constant fold the instruction.
|
||||
if (Constant *CRepOp = dyn_cast<Constant>(RepOp)) {
|
||||
// Build a list of all constant operands.
|
||||
SmallVector<Constant*, 8> ConstOps;
|
||||
for (unsigned i = 0, e = I->getNumOperands(); i != e; ++i) {
|
||||
if (I->getOperand(i) == Op)
|
||||
ConstOps.push_back(CRepOp);
|
||||
else if (Constant *COp = dyn_cast<Constant>(I->getOperand(i)))
|
||||
ConstOps.push_back(COp);
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
// All operands were constants, fold it.
|
||||
if (ConstOps.size() == I->getNumOperands()) {
|
||||
if (CmpInst *C = dyn_cast<CmpInst>(I))
|
||||
return ConstantFoldCompareInstOperands(C->getPredicate(), ConstOps[0],
|
||||
ConstOps[1], DL, TLI);
|
||||
|
||||
if (LoadInst *LI = dyn_cast<LoadInst>(I))
|
||||
if (!LI->isVolatile())
|
||||
return ConstantFoldLoadFromConstPtr(ConstOps[0], DL);
|
||||
|
||||
return ConstantFoldInstOperands(I->getOpcode(), I->getType(), ConstOps,
|
||||
DL, TLI);
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/// foldSelectICmpAndOr - We want to turn:
|
||||
/// (select (icmp eq (and X, C1), 0), Y, (or Y, C2))
|
||||
/// into:
|
||||
@ -490,14 +411,6 @@ Instruction *InstCombiner::visitSelectInstWithICmp(SelectInst &SI,
|
||||
// here, so make sure the select is the only user.
|
||||
if (ICI->hasOneUse())
|
||||
if (ConstantInt *CI = dyn_cast<ConstantInt>(CmpRHS)) {
|
||||
// X < MIN ? T : F --> F
|
||||
if ((Pred == ICmpInst::ICMP_SLT || Pred == ICmpInst::ICMP_ULT)
|
||||
&& CI->isMinValue(Pred == ICmpInst::ICMP_SLT))
|
||||
return ReplaceInstUsesWith(SI, FalseVal);
|
||||
// X > MAX ? T : F --> F
|
||||
else if ((Pred == ICmpInst::ICMP_SGT || Pred == ICmpInst::ICMP_UGT)
|
||||
&& CI->isMaxValue(Pred == ICmpInst::ICMP_SGT))
|
||||
return ReplaceInstUsesWith(SI, FalseVal);
|
||||
switch (Pred) {
|
||||
default: break;
|
||||
case ICmpInst::ICMP_ULT:
|
||||
@ -611,33 +524,6 @@ Instruction *InstCombiner::visitSelectInstWithICmp(SelectInst &SI,
|
||||
}
|
||||
}
|
||||
|
||||
// If we have an equality comparison then we know the value in one of the
|
||||
// arms of the select. See if substituting this value into the arm and
|
||||
// simplifying the result yields the same value as the other arm.
|
||||
if (Pred == ICmpInst::ICMP_EQ) {
|
||||
if (SimplifyWithOpReplaced(FalseVal, CmpLHS, CmpRHS, TLI, DL, DT, AC) ==
|
||||
TrueVal ||
|
||||
SimplifyWithOpReplaced(FalseVal, CmpRHS, CmpLHS, TLI, DL, DT, AC) ==
|
||||
TrueVal)
|
||||
return ReplaceInstUsesWith(SI, FalseVal);
|
||||
if (SimplifyWithOpReplaced(TrueVal, CmpLHS, CmpRHS, TLI, DL, DT, AC) ==
|
||||
FalseVal ||
|
||||
SimplifyWithOpReplaced(TrueVal, CmpRHS, CmpLHS, TLI, DL, DT, AC) ==
|
||||
FalseVal)
|
||||
return ReplaceInstUsesWith(SI, FalseVal);
|
||||
} else if (Pred == ICmpInst::ICMP_NE) {
|
||||
if (SimplifyWithOpReplaced(TrueVal, CmpLHS, CmpRHS, TLI, DL, DT, AC) ==
|
||||
FalseVal ||
|
||||
SimplifyWithOpReplaced(TrueVal, CmpRHS, CmpLHS, TLI, DL, DT, AC) ==
|
||||
FalseVal)
|
||||
return ReplaceInstUsesWith(SI, TrueVal);
|
||||
if (SimplifyWithOpReplaced(FalseVal, CmpLHS, CmpRHS, TLI, DL, DT, AC) ==
|
||||
TrueVal ||
|
||||
SimplifyWithOpReplaced(FalseVal, CmpRHS, CmpLHS, TLI, DL, DT, AC) ==
|
||||
TrueVal)
|
||||
return ReplaceInstUsesWith(SI, TrueVal);
|
||||
}
|
||||
|
||||
// NOTE: if we wanted to, this is where to detect integer MIN/MAX
|
||||
|
||||
if (CmpRHS != CmpLHS && isa<Constant>(CmpRHS)) {
|
||||
@ -652,7 +538,8 @@ Instruction *InstCombiner::visitSelectInstWithICmp(SelectInst &SI,
|
||||
}
|
||||
}
|
||||
|
||||
if (unsigned BitWidth = TrueVal->getType()->getScalarSizeInBits()) {
|
||||
{
|
||||
unsigned BitWidth = DL.getTypeSizeInBits(TrueVal->getType());
|
||||
APInt MinSignedValue = APInt::getSignBit(BitWidth);
|
||||
Value *X;
|
||||
const APInt *Y, *C;
|
||||
|
Loading…
Reference in New Issue
Block a user