forked from OSchip/llvm-project
[InstCombine] add helper functions for foldICmpWithConstant; NFCI
Besides breaking up a 700 line function to improve readability, this sinks the 'FIXME: ConstantInt' check into each helper. So now we can independently break that restriction within any of the helper functions. As much as possible, the code was only {cut/paste/clang-format}'ed to minimize risk (no functional changes intended), so several more readability improvements are still possible. llvm-svn: 278828
This commit is contained in:
parent
5cd57177a5
commit
a3f4f0828b
|
@ -1179,7 +1179,8 @@ Instruction *InstCombiner::foldICmpAddOpConst(Instruction &ICI,
|
|||
|
||||
/// Fold "icmp pred, ([su]div X, DivRHS), CmpRHS" where DivRHS and CmpRHS are
|
||||
/// both known to be integer constants.
|
||||
Instruction *InstCombiner::foldICmpDivConst(ICmpInst &ICI, BinaryOperator *DivI,
|
||||
Instruction *InstCombiner::foldICmpDivConstConst(ICmpInst &ICI,
|
||||
BinaryOperator *DivI,
|
||||
ConstantInt *DivRHS) {
|
||||
ConstantInt *CmpRHS = cast<ConstantInt>(ICI.getOperand(1));
|
||||
const APInt &CmpRHSV = CmpRHS->getValue();
|
||||
|
@ -1335,7 +1336,8 @@ Instruction *InstCombiner::foldICmpDivConst(ICmpInst &ICI, BinaryOperator *DivI,
|
|||
}
|
||||
|
||||
/// Handle "icmp(([al]shr X, cst1), cst2)".
|
||||
Instruction *InstCombiner::foldICmpShrConst(ICmpInst &ICI, BinaryOperator *Shr,
|
||||
Instruction *InstCombiner::foldICmpShrConstConst(ICmpInst &ICI,
|
||||
BinaryOperator *Shr,
|
||||
ConstantInt *ShAmt) {
|
||||
const APInt &CmpRHSV = cast<ConstantInt>(ICI.getOperand(1))->getValue();
|
||||
|
||||
|
@ -1382,7 +1384,8 @@ Instruction *InstCombiner::foldICmpShrConst(ICmpInst &ICI, BinaryOperator *Shr,
|
|||
assert(TheDiv->getOpcode() == Instruction::SDiv ||
|
||||
TheDiv->getOpcode() == Instruction::UDiv);
|
||||
|
||||
Instruction *Res = foldICmpDivConst(ICI, TheDiv, cast<ConstantInt>(DivCst));
|
||||
Instruction *Res =
|
||||
foldICmpDivConstConst(ICI, TheDiv, cast<ConstantInt>(DivCst));
|
||||
assert(Res && "This div/cst should have folded!");
|
||||
return Res;
|
||||
}
|
||||
|
@ -1530,21 +1533,14 @@ Instruction *InstCombiner::foldICmpCstShlConst(ICmpInst &I, Value *Op, Value *A,
|
|||
return getConstant(false);
|
||||
}
|
||||
|
||||
/// Try to fold integer comparisons with a constant operand: icmp Pred X, C.
|
||||
Instruction *InstCombiner::foldICmpWithConstant(ICmpInst &ICI) {
|
||||
Instruction *LHSI;
|
||||
const APInt *RHSV;
|
||||
if (!match(ICI.getOperand(0), m_Instruction(LHSI)) ||
|
||||
!match(ICI.getOperand(1), m_APInt(RHSV)))
|
||||
return nullptr;
|
||||
|
||||
Instruction *InstCombiner::foldICmpTruncConstant(ICmpInst &ICI,
|
||||
Instruction *LHSI,
|
||||
const APInt *RHSV) {
|
||||
// FIXME: This check restricts all folds under here to scalar types.
|
||||
ConstantInt *RHS = dyn_cast<ConstantInt>(ICI.getOperand(1));
|
||||
if (!RHS)
|
||||
return nullptr;
|
||||
|
||||
switch (LHSI->getOpcode()) {
|
||||
case Instruction::Trunc:
|
||||
if (RHS->isOne() && RHSV->getBitWidth() > 1) {
|
||||
// icmp slt trunc(signum(V)) 1 --> icmp slt V, 1
|
||||
Value *V = nullptr;
|
||||
|
@ -1570,9 +1566,16 @@ Instruction *InstCombiner::foldICmpWithConstant(ICmpInst &ICI) {
|
|||
Builder->getInt(NewRHS));
|
||||
}
|
||||
}
|
||||
break;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Instruction *InstCombiner::foldICmpXorConstant(ICmpInst &ICI, Instruction *LHSI,
|
||||
const APInt *RHSV) {
|
||||
// FIXME: This check restricts all folds under here to scalar types.
|
||||
ConstantInt *RHS = dyn_cast<ConstantInt>(ICI.getOperand(1));
|
||||
if (!RHS)
|
||||
return nullptr;
|
||||
|
||||
case Instruction::Xor: // (icmp pred (xor X, XorCst), CI)
|
||||
if (ConstantInt *XorCst = dyn_cast<ConstantInt>(LHSI->getOperand(1))) {
|
||||
// If this is a comparison that tests the signbit (X < 0) or (x > -1),
|
||||
// fold the xor.
|
||||
|
@ -1595,19 +1598,16 @@ Instruction *InstCombiner::foldICmpWithConstant(ICmpInst &ICI) {
|
|||
isTrueIfPositive ^= true;
|
||||
|
||||
if (isTrueIfPositive)
|
||||
return new ICmpInst(ICmpInst::ICMP_SGT, CompareVal,
|
||||
SubOne(RHS));
|
||||
return new ICmpInst(ICmpInst::ICMP_SGT, CompareVal, SubOne(RHS));
|
||||
else
|
||||
return new ICmpInst(ICmpInst::ICMP_SLT, CompareVal,
|
||||
AddOne(RHS));
|
||||
return new ICmpInst(ICmpInst::ICMP_SLT, CompareVal, AddOne(RHS));
|
||||
}
|
||||
|
||||
if (LHSI->hasOneUse()) {
|
||||
// (icmp u/s (xor A SignBit), C) -> (icmp s/u A, (xor C SignBit))
|
||||
if (!ICI.isEquality() && XorCst->getValue().isSignBit()) {
|
||||
const APInt &SignBit = XorCst->getValue();
|
||||
ICmpInst::Predicate Pred = ICI.isSigned()
|
||||
? ICI.getUnsignedPredicate()
|
||||
ICmpInst::Predicate Pred = ICI.isSigned() ? ICI.getUnsignedPredicate()
|
||||
: ICI.getSignedPredicate();
|
||||
return new ICmpInst(Pred, LHSI->getOperand(0),
|
||||
Builder->getInt(*RHSV ^ SignBit));
|
||||
|
@ -1616,8 +1616,7 @@ Instruction *InstCombiner::foldICmpWithConstant(ICmpInst &ICI) {
|
|||
// (icmp u/s (xor A ~SignBit), C) -> (icmp s/u (xor C ~SignBit), A)
|
||||
if (!ICI.isEquality() && XorCst->isMaxValue(true)) {
|
||||
const APInt &NotSignBit = XorCst->getValue();
|
||||
ICmpInst::Predicate Pred = ICI.isSigned()
|
||||
? ICI.getUnsignedPredicate()
|
||||
ICmpInst::Predicate Pred = ICI.isSigned() ? ICI.getUnsignedPredicate()
|
||||
: ICI.getSignedPredicate();
|
||||
Pred = ICI.getSwappedPredicate(Pred);
|
||||
return new ICmpInst(Pred, LHSI->getOperand(0),
|
||||
|
@ -1637,8 +1636,16 @@ Instruction *InstCombiner::foldICmpWithConstant(ICmpInst &ICI) {
|
|||
XorCst->getValue() == -(*RHSV) && RHSV->isPowerOf2())
|
||||
return new ICmpInst(ICmpInst::ICMP_UGE, LHSI->getOperand(0), XorCst);
|
||||
}
|
||||
break;
|
||||
case Instruction::And: // (icmp pred (and X, AndCst), RHS)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Instruction *InstCombiner::foldICmpAndConstant(ICmpInst &ICI, Instruction *LHSI,
|
||||
const APInt *RHSV) {
|
||||
// FIXME: This check restricts all folds under here to scalar types.
|
||||
ConstantInt *RHS = dyn_cast<ConstantInt>(ICI.getOperand(1));
|
||||
if (!RHS)
|
||||
return nullptr;
|
||||
|
||||
if (LHSI->hasOneUse() && isa<ConstantInt>(LHSI->getOperand(1)) &&
|
||||
LHSI->getOperand(0)->hasOneUse()) {
|
||||
ConstantInt *AndCst = cast<ConstantInt>(LHSI->getOperand(1));
|
||||
|
@ -1669,8 +1676,7 @@ Instruction *InstCombiner::foldICmpWithConstant(ICmpInst &ICI) {
|
|||
// Make sure we don't compare the upper bits, SimplifyDemandedBits
|
||||
// should fold the icmp to true/false in that case.
|
||||
if (ICI.isEquality() && RHSV->getActiveBits() <= Ty->getBitWidth()) {
|
||||
Value *NewAnd =
|
||||
Builder->CreateAnd(Cast->getOperand(0),
|
||||
Value *NewAnd = Builder->CreateAnd(Cast->getOperand(0),
|
||||
ConstantExpr::getTrunc(AndCst, Ty));
|
||||
NewAnd->takeName(LHSI);
|
||||
return new ICmpInst(ICI.getPredicate(), NewAnd,
|
||||
|
@ -1761,9 +1767,8 @@ Instruction *InstCombiner::foldICmpWithConstant(ICmpInst &ICI) {
|
|||
// Turn ((X >> Y) & C) == 0 into (X & (C << Y)) == 0. The later is
|
||||
// preferable because it allows the C<<Y expression to be hoisted out
|
||||
// of a loop if Y is invariant and X is not.
|
||||
if (Shift && Shift->hasOneUse() && *RHSV == 0 &&
|
||||
ICI.isEquality() && !Shift->isArithmeticShift() &&
|
||||
!isa<Constant>(Shift->getOperand(0))) {
|
||||
if (Shift && Shift->hasOneUse() && *RHSV == 0 && ICI.isEquality() &&
|
||||
!Shift->isArithmeticShift() && !isa<Constant>(Shift->getOperand(0))) {
|
||||
// Compute C << Y.
|
||||
Value *NS;
|
||||
if (Shift->getOpcode() == Instruction::LShr) {
|
||||
|
@ -1836,8 +1841,7 @@ Instruction *InstCombiner::foldICmpWithConstant(ICmpInst &ICI) {
|
|||
|
||||
// Try to optimize things like "A[i]&42 == 0" to index computations.
|
||||
if (LoadInst *LI = dyn_cast<LoadInst>(LHSI->getOperand(0))) {
|
||||
if (GetElementPtrInst *GEP =
|
||||
dyn_cast<GetElementPtrInst>(LI->getOperand(0)))
|
||||
if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(LI->getOperand(0)))
|
||||
if (GlobalVariable *GV = dyn_cast<GlobalVariable>(GEP->getOperand(0)))
|
||||
if (GV->isConstant() && GV->hasDefinitiveInitializer() &&
|
||||
!LI->isVolatile() && isa<ConstantInt>(LHSI->getOperand(1))) {
|
||||
|
@ -1851,8 +1855,8 @@ Instruction *InstCombiner::foldICmpWithConstant(ICmpInst &ICI) {
|
|||
// X & -C != -C -> X <= u ~C
|
||||
// iff C is a power of 2
|
||||
if (ICI.isEquality() && RHS == LHSI->getOperand(1) && (-(*RHSV)).isPowerOf2())
|
||||
return new ICmpInst(
|
||||
ICI.getPredicate() == ICmpInst::ICMP_EQ ? ICmpInst::ICMP_UGT
|
||||
return new ICmpInst(ICI.getPredicate() == ICmpInst::ICMP_EQ
|
||||
? ICmpInst::ICMP_UGT
|
||||
: ICmpInst::ICMP_ULE,
|
||||
LHSI->getOperand(0), SubOne(RHS));
|
||||
|
||||
|
@ -1872,9 +1876,16 @@ Instruction *InstCombiner::foldICmpWithConstant(ICmpInst &ICI) {
|
|||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Instruction *InstCombiner::foldICmpOrConstant(ICmpInst &ICI, Instruction *LHSI,
|
||||
const APInt *RHSV) {
|
||||
// FIXME: This check restricts all folds under here to scalar types.
|
||||
ConstantInt *RHS = dyn_cast<ConstantInt>(ICI.getOperand(1));
|
||||
if (!RHS)
|
||||
return nullptr;
|
||||
|
||||
case Instruction::Or: {
|
||||
if (RHS->isOne()) {
|
||||
// icmp slt signum(V) 1 --> icmp slt V, 1
|
||||
Value *V = nullptr;
|
||||
|
@ -1885,7 +1896,8 @@ Instruction *InstCombiner::foldICmpWithConstant(ICmpInst &ICI) {
|
|||
}
|
||||
|
||||
if (!ICI.isEquality() || !RHS->isNullValue() || !LHSI->hasOneUse())
|
||||
break;
|
||||
return nullptr;
|
||||
|
||||
Value *P, *Q;
|
||||
if (match(LHSI, m_Or(m_PtrToInt(m_Value(P)), m_PtrToInt(m_Value(Q))))) {
|
||||
// Simplify icmp eq (or (ptrtoint P), (ptrtoint Q)), 0
|
||||
|
@ -1901,12 +1913,19 @@ Instruction *InstCombiner::foldICmpWithConstant(ICmpInst &ICI) {
|
|||
Op = BinaryOperator::CreateOr(ICIP, ICIQ);
|
||||
return Op;
|
||||
}
|
||||
break;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
case Instruction::Mul: { // (icmp pred (mul X, Val), CI)
|
||||
Instruction *InstCombiner::foldICmpMulConstant(ICmpInst &ICI, Instruction *LHSI,
|
||||
const APInt *RHSV) {
|
||||
// FIXME: This check restricts all folds under here to scalar types.
|
||||
ConstantInt *RHS = dyn_cast<ConstantInt>(ICI.getOperand(1));
|
||||
if (!RHS)
|
||||
return nullptr;
|
||||
|
||||
ConstantInt *Val = dyn_cast<ConstantInt>(LHSI->getOperand(1));
|
||||
if (!Val) break;
|
||||
if (!Val)
|
||||
return nullptr;
|
||||
|
||||
// If this is a signed comparison to 0 and the mul is sign preserving,
|
||||
// use the mul LHS operand instead.
|
||||
|
@ -1918,10 +1937,16 @@ Instruction *InstCombiner::foldICmpWithConstant(ICmpInst &ICI) {
|
|||
LHSI->getOperand(0),
|
||||
Constant::getNullValue(RHS->getType()));
|
||||
|
||||
break;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
case Instruction::Shl: { // (icmp pred (shl X, ShAmt), CI)
|
||||
Instruction *InstCombiner::foldICmpShlConstant(ICmpInst &ICI, Instruction *LHSI,
|
||||
const APInt *RHSV) {
|
||||
// FIXME: This check restricts all folds under here to scalar types.
|
||||
ConstantInt *RHS = dyn_cast<ConstantInt>(ICI.getOperand(1));
|
||||
if (!RHS)
|
||||
return nullptr;
|
||||
|
||||
uint32_t TypeBits = RHSV->getBitWidth();
|
||||
ConstantInt *ShAmt = dyn_cast<ConstantInt>(LHSI->getOperand(1));
|
||||
if (!ShAmt) {
|
||||
|
@ -1952,8 +1977,7 @@ Instruction *InstCombiner::foldICmpWithConstant(ICmpInst &ICI) {
|
|||
Pred = ICmpInst::ICMP_NE;
|
||||
}
|
||||
|
||||
return new ICmpInst(Pred, X,
|
||||
ConstantInt::get(RHS->getType(), RHSLog2));
|
||||
return new ICmpInst(Pred, X, ConstantInt::get(RHS->getType(), RHSLog2));
|
||||
} else if (ICI.isSigned()) {
|
||||
if (RHSV->isAllOnesValue()) {
|
||||
// (1 << X) <= -1 -> X == 31
|
||||
|
@ -1984,21 +2008,20 @@ Instruction *InstCombiner::foldICmpWithConstant(ICmpInst &ICI) {
|
|||
Pred, X, ConstantInt::get(RHS->getType(), RHSV->logBase2()));
|
||||
}
|
||||
}
|
||||
break;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Check that the shift amount is in range. If not, don't perform
|
||||
// undefined shifts. When the shift is visited it will be
|
||||
// simplified.
|
||||
if (ShAmt->uge(TypeBits))
|
||||
break;
|
||||
return nullptr;
|
||||
|
||||
if (ICI.isEquality()) {
|
||||
// If we are comparing against bits always shifted out, the
|
||||
// comparison cannot succeed.
|
||||
Constant *Comp =
|
||||
ConstantExpr::getShl(ConstantExpr::getLShr(RHS, ShAmt),
|
||||
ShAmt);
|
||||
ConstantExpr::getShl(ConstantExpr::getLShr(RHS, ShAmt), ShAmt);
|
||||
if (Comp != RHS) { // Comparing against a bit that we know is zero.
|
||||
bool IsICMP_NE = ICI.getPredicate() == ICmpInst::ICMP_NE;
|
||||
Constant *Cst = Builder->getInt1(IsICMP_NE);
|
||||
|
@ -2020,11 +2043,11 @@ Instruction *InstCombiner::foldICmpWithConstant(ICmpInst &ICI) {
|
|||
if (LHSI->hasOneUse()) {
|
||||
// Otherwise strength reduce the shift into an and.
|
||||
uint32_t ShAmtVal = (uint32_t)ShAmt->getLimitedValue(TypeBits);
|
||||
Constant *Mask = Builder->getInt(APInt::getLowBitsSet(TypeBits,
|
||||
TypeBits - ShAmtVal));
|
||||
Constant *Mask =
|
||||
Builder->getInt(APInt::getLowBitsSet(TypeBits, TypeBits - ShAmtVal));
|
||||
|
||||
Value *And =
|
||||
Builder->CreateAnd(LHSI->getOperand(0),Mask, LHSI->getName()+".mask");
|
||||
Value *And = Builder->CreateAnd(LHSI->getOperand(0), Mask,
|
||||
LHSI->getName() + ".mask");
|
||||
return new ICmpInst(ICI.getPredicate(), And,
|
||||
ConstantExpr::getLShr(RHS, ShAmt));
|
||||
}
|
||||
|
@ -2033,10 +2056,8 @@ Instruction *InstCombiner::foldICmpWithConstant(ICmpInst &ICI) {
|
|||
// If this is a signed comparison to 0 and the shift is sign preserving,
|
||||
// use the shift LHS operand instead.
|
||||
ICmpInst::Predicate pred = ICI.getPredicate();
|
||||
if (isSignTest(pred, RHS) &&
|
||||
cast<BinaryOperator>(LHSI)->hasNoSignedWrap())
|
||||
return new ICmpInst(pred,
|
||||
LHSI->getOperand(0),
|
||||
if (isSignTest(pred, RHS) && cast<BinaryOperator>(LHSI)->hasNoSignedWrap())
|
||||
return new ICmpInst(pred, LHSI->getOperand(0),
|
||||
Constant::getNullValue(RHS->getType()));
|
||||
|
||||
// Otherwise, if this is a comparison of the sign bit, simplify to and/test.
|
||||
|
@ -2044,11 +2065,11 @@ Instruction *InstCombiner::foldICmpWithConstant(ICmpInst &ICI) {
|
|||
if (LHSI->hasOneUse() &&
|
||||
isSignBitCheck(ICI.getPredicate(), RHS, TrueIfSigned)) {
|
||||
// (X << 31) <s 0 --> (X&1) != 0
|
||||
Constant *Mask = ConstantInt::get(LHSI->getOperand(0)->getType(),
|
||||
APInt::getOneBitSet(TypeBits,
|
||||
TypeBits-ShAmt->getZExtValue()-1));
|
||||
Value *And =
|
||||
Builder->CreateAnd(LHSI->getOperand(0), Mask, LHSI->getName()+".mask");
|
||||
Constant *Mask = ConstantInt::get(
|
||||
LHSI->getOperand(0)->getType(),
|
||||
APInt::getOneBitSet(TypeBits, TypeBits - ShAmt->getZExtValue() - 1));
|
||||
Value *And = Builder->CreateAnd(LHSI->getOperand(0), Mask,
|
||||
LHSI->getName() + ".mask");
|
||||
return new ICmpInst(TrueIfSigned ? ICmpInst::ICMP_NE : ICmpInst::ICMP_EQ,
|
||||
And, Constant::getNullValue(And->getType()));
|
||||
}
|
||||
|
@ -2060,27 +2081,28 @@ Instruction *InstCombiner::foldICmpWithConstant(ICmpInst &ICI) {
|
|||
// free on the target. It has the additional benefit of comparing to a
|
||||
// smaller constant, which will be target friendly.
|
||||
unsigned Amt = ShAmt->getLimitedValue(TypeBits - 1);
|
||||
if (LHSI->hasOneUse() &&
|
||||
Amt != 0 && RHSV->countTrailingZeros() >= Amt) {
|
||||
if (LHSI->hasOneUse() && Amt != 0 && RHSV->countTrailingZeros() >= Amt) {
|
||||
Type *NTy = IntegerType::get(ICI.getContext(), TypeBits - Amt);
|
||||
Constant *NCI = ConstantExpr::getTrunc(
|
||||
ConstantExpr::getAShr(RHS,
|
||||
ConstantInt::get(RHS->getType(), Amt)),
|
||||
NTy);
|
||||
ConstantExpr::getAShr(RHS, ConstantInt::get(RHS->getType(), Amt)), NTy);
|
||||
return new ICmpInst(ICI.getPredicate(),
|
||||
Builder->CreateTrunc(LHSI->getOperand(0), NTy),
|
||||
NCI);
|
||||
Builder->CreateTrunc(LHSI->getOperand(0), NTy), NCI);
|
||||
}
|
||||
|
||||
break;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
case Instruction::LShr: // (icmp pred (shr X, ShAmt), CI)
|
||||
case Instruction::AShr: {
|
||||
Instruction *InstCombiner::foldICmpShrConstant(ICmpInst &ICI, Instruction *LHSI,
|
||||
const APInt *RHSV) {
|
||||
// FIXME: This check restricts all folds under here to scalar types.
|
||||
ConstantInt *RHS = dyn_cast<ConstantInt>(ICI.getOperand(1));
|
||||
if (!RHS)
|
||||
return nullptr;
|
||||
|
||||
// Handle equality comparisons of shift-by-constant.
|
||||
BinaryOperator *BO = cast<BinaryOperator>(LHSI);
|
||||
if (ConstantInt *ShAmt = dyn_cast<ConstantInt>(LHSI->getOperand(1))) {
|
||||
if (Instruction *Res = foldICmpShrConst(ICI, BO, ShAmt))
|
||||
if (Instruction *Res = foldICmpShrConstConst(ICI, BO, ShAmt))
|
||||
return Res;
|
||||
}
|
||||
|
||||
|
@ -2089,10 +2111,18 @@ Instruction *InstCombiner::foldICmpWithConstant(ICmpInst &ICI) {
|
|||
if (RHSV->isMinValue())
|
||||
return new ICmpInst(ICI.getPredicate(), BO->getOperand(0), RHS);
|
||||
}
|
||||
break;
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
case Instruction::UDiv:
|
||||
Instruction *InstCombiner::foldICmpUDivConstant(ICmpInst &ICI,
|
||||
Instruction *LHSI,
|
||||
const APInt *RHSV) {
|
||||
// FIXME: This check restricts all folds under here to scalar types.
|
||||
ConstantInt *RHS = dyn_cast<ConstantInt>(ICI.getOperand(1));
|
||||
if (!RHS)
|
||||
return nullptr;
|
||||
|
||||
if (ConstantInt *DivLHS = dyn_cast<ConstantInt>(LHSI->getOperand(0))) {
|
||||
Value *X = LHSI->getOperand(1);
|
||||
const APInt &C1 = RHS->getValue();
|
||||
|
@ -2112,8 +2142,17 @@ Instruction *InstCombiner::foldICmpWithConstant(ICmpInst &ICI) {
|
|||
ConstantInt::get(X->getType(), C2.udiv(C1)));
|
||||
}
|
||||
}
|
||||
// fall-through
|
||||
case Instruction::SDiv:
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Instruction *InstCombiner::foldICmpDivConstant(ICmpInst &ICI, Instruction *LHSI,
|
||||
const APInt *RHSV) {
|
||||
// FIXME: This check restricts all folds under here to scalar types.
|
||||
ConstantInt *RHS = dyn_cast<ConstantInt>(ICI.getOperand(1));
|
||||
if (!RHS)
|
||||
return nullptr;
|
||||
|
||||
// Fold: icmp pred ([us]div X, C1), C2 -> range test
|
||||
// Fold this div into the comparison, producing a range check.
|
||||
// Determine, based on the divide type, what the range is being
|
||||
|
@ -2121,14 +2160,24 @@ Instruction *InstCombiner::foldICmpWithConstant(ICmpInst &ICI) {
|
|||
// it, otherwise compute the range [low, hi) bounding the new value.
|
||||
// See: InsertRangeTest above for the kinds of replacements possible.
|
||||
if (ConstantInt *DivRHS = dyn_cast<ConstantInt>(LHSI->getOperand(1)))
|
||||
if (Instruction *R = foldICmpDivConst(ICI, cast<BinaryOperator>(LHSI),
|
||||
DivRHS))
|
||||
if (Instruction *R =
|
||||
foldICmpDivConstConst(ICI, cast<BinaryOperator>(LHSI), DivRHS))
|
||||
return R;
|
||||
break;
|
||||
|
||||
case Instruction::Sub: {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Instruction *InstCombiner::foldICmpSubConstant(ICmpInst &ICI, Instruction *LHSI,
|
||||
const APInt *RHSV) {
|
||||
// FIXME: This check restricts all folds under here to scalar types.
|
||||
ConstantInt *RHS = dyn_cast<ConstantInt>(ICI.getOperand(1));
|
||||
if (!RHS)
|
||||
return nullptr;
|
||||
|
||||
ConstantInt *LHSC = dyn_cast<ConstantInt>(LHSI->getOperand(0));
|
||||
if (!LHSC) break;
|
||||
if (!LHSC)
|
||||
return nullptr;
|
||||
|
||||
const APInt &LHSV = LHSC->getValue();
|
||||
|
||||
// C1-X <u C2 -> (X|(C2-1)) == C1
|
||||
|
@ -2147,18 +2196,26 @@ Instruction *InstCombiner::foldICmpWithConstant(ICmpInst &ICI) {
|
|||
(*RHSV + 1).isPowerOf2() && (LHSV & *RHSV) == *RHSV)
|
||||
return new ICmpInst(ICmpInst::ICMP_NE,
|
||||
Builder->CreateOr(LHSI->getOperand(1), *RHSV), LHSC);
|
||||
break;
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
case Instruction::Add:
|
||||
Instruction *InstCombiner::foldICmpAddConstant(ICmpInst &ICI, Instruction *LHSI,
|
||||
const APInt *RHSV) {
|
||||
// FIXME: This check restricts all folds under here to scalar types.
|
||||
ConstantInt *RHS = dyn_cast<ConstantInt>(ICI.getOperand(1));
|
||||
if (!RHS)
|
||||
return nullptr;
|
||||
|
||||
// Fold: icmp pred (add X, C1), C2
|
||||
if (!ICI.isEquality()) {
|
||||
ConstantInt *LHSC = dyn_cast<ConstantInt>(LHSI->getOperand(1));
|
||||
if (!LHSC) break;
|
||||
const APInt &LHSV = LHSC->getValue();
|
||||
if (!LHSC)
|
||||
return nullptr;
|
||||
|
||||
ConstantRange CR = ICI.makeConstantRange(ICI.getPredicate(), *RHSV)
|
||||
.subtract(LHSV);
|
||||
const APInt &LHSV = LHSC->getValue();
|
||||
ConstantRange CR =
|
||||
ICI.makeConstantRange(ICI.getPredicate(), *RHSV).subtract(LHSV);
|
||||
|
||||
if (ICI.isSigned()) {
|
||||
if (CR.getLower().isSignBit()) {
|
||||
|
@ -2196,6 +2253,62 @@ Instruction *InstCombiner::foldICmpWithConstant(ICmpInst &ICI) {
|
|||
Builder->CreateAnd(LHSI->getOperand(0), ~(*RHSV)),
|
||||
ConstantExpr::getNeg(LHSC));
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/// Try to fold integer comparisons with a constant operand: icmp Pred X, C.
|
||||
Instruction *InstCombiner::foldICmpWithConstant(ICmpInst &ICI) {
|
||||
Instruction *LHSI;
|
||||
const APInt *RHSV;
|
||||
if (!match(ICI.getOperand(0), m_Instruction(LHSI)) ||
|
||||
!match(ICI.getOperand(1), m_APInt(RHSV)))
|
||||
return nullptr;
|
||||
|
||||
switch (LHSI->getOpcode()) {
|
||||
case Instruction::Trunc:
|
||||
if (Instruction *I = foldICmpTruncConstant(ICI, LHSI, RHSV))
|
||||
return I;
|
||||
break;
|
||||
case Instruction::Xor:
|
||||
if (Instruction *I = foldICmpXorConstant(ICI, LHSI, RHSV))
|
||||
return I;
|
||||
break;
|
||||
case Instruction::And:
|
||||
if (Instruction *I = foldICmpAndConstant(ICI, LHSI, RHSV))
|
||||
return I;
|
||||
break;
|
||||
case Instruction::Or:
|
||||
if (Instruction *I = foldICmpOrConstant(ICI, LHSI, RHSV))
|
||||
return I;
|
||||
break;
|
||||
case Instruction::Mul:
|
||||
if (Instruction *I = foldICmpMulConstant(ICI, LHSI, RHSV))
|
||||
return I;
|
||||
break;
|
||||
case Instruction::Shl:
|
||||
if (Instruction *I = foldICmpShlConstant(ICI, LHSI, RHSV))
|
||||
return I;
|
||||
break;
|
||||
case Instruction::LShr:
|
||||
case Instruction::AShr:
|
||||
if (Instruction *I = foldICmpShrConstant(ICI, LHSI, RHSV))
|
||||
return I;
|
||||
break;
|
||||
case Instruction::UDiv:
|
||||
if (Instruction *I = foldICmpUDivConstant(ICI, LHSI, RHSV))
|
||||
return I;
|
||||
// fall-through
|
||||
case Instruction::SDiv:
|
||||
if (Instruction *I = foldICmpDivConstant(ICI, LHSI, RHSV))
|
||||
return I;
|
||||
break;
|
||||
case Instruction::Sub:
|
||||
if (Instruction *I = foldICmpSubConstant(ICI, LHSI, RHSV))
|
||||
return I;
|
||||
break;
|
||||
case Instruction::Add:
|
||||
if (Instruction *I = foldICmpAddConstant(ICI, LHSI, RHSV))
|
||||
return I;
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -548,9 +548,9 @@ private:
|
|||
ConstantInt *AndCst = nullptr);
|
||||
Instruction *foldFCmpIntToFPConst(FCmpInst &I, Instruction *LHSI,
|
||||
Constant *RHSC);
|
||||
Instruction *foldICmpDivConst(ICmpInst &ICI, BinaryOperator *DivI,
|
||||
Instruction *foldICmpDivConstConst(ICmpInst &ICI, BinaryOperator *DivI,
|
||||
ConstantInt *DivRHS);
|
||||
Instruction *foldICmpShrConst(ICmpInst &ICI, BinaryOperator *DivI,
|
||||
Instruction *foldICmpShrConstConst(ICmpInst &ICI, BinaryOperator *DivI,
|
||||
ConstantInt *DivRHS);
|
||||
Instruction *foldICmpCstShrConst(ICmpInst &I, Value *Op, Value *A,
|
||||
ConstantInt *CI1, ConstantInt *CI2);
|
||||
|
@ -560,6 +560,30 @@ private:
|
|||
ICmpInst::Predicate Pred);
|
||||
Instruction *foldICmpWithCastAndCast(ICmpInst &ICI);
|
||||
Instruction *foldICmpWithConstant(ICmpInst &ICI);
|
||||
|
||||
Instruction *foldICmpTruncConstant(ICmpInst &ICI, Instruction *LHSI,
|
||||
const APInt *RHSV);
|
||||
Instruction *foldICmpAndConstant(ICmpInst &ICI, Instruction *LHSI,
|
||||
const APInt *RHSV);
|
||||
Instruction *foldICmpXorConstant(ICmpInst &ICI, Instruction *LHSI,
|
||||
const APInt *RHSV);
|
||||
Instruction *foldICmpOrConstant(ICmpInst &ICI, Instruction *LHSI,
|
||||
const APInt *RHSV);
|
||||
Instruction *foldICmpMulConstant(ICmpInst &ICI, Instruction *LHSI,
|
||||
const APInt *RHSV);
|
||||
Instruction *foldICmpShlConstant(ICmpInst &ICI, Instruction *LHSI,
|
||||
const APInt *RHSV);
|
||||
Instruction *foldICmpShrConstant(ICmpInst &ICI, Instruction *LHSI,
|
||||
const APInt *RHSV);
|
||||
Instruction *foldICmpUDivConstant(ICmpInst &ICI, Instruction *LHSI,
|
||||
const APInt *RHSV);
|
||||
Instruction *foldICmpDivConstant(ICmpInst &ICI, Instruction *LHSI,
|
||||
const APInt *RHSV);
|
||||
Instruction *foldICmpSubConstant(ICmpInst &ICI, Instruction *LHSI,
|
||||
const APInt *RHSV);
|
||||
Instruction *foldICmpAddConstant(ICmpInst &ICI, Instruction *LHSI,
|
||||
const APInt *RHSV);
|
||||
|
||||
Instruction *foldICmpEqualityWithConstant(ICmpInst &ICI);
|
||||
Instruction *foldICmpIntrinsicWithConstant(ICmpInst &ICI);
|
||||
|
||||
|
|
Loading…
Reference in New Issue