[llvm] r279837 - [InstCombine] clean up foldICmpAndConstConst(); NFC
Sanjay Patel via llvm-commits
llvm-commits at lists.llvm.org
Fri Aug 26 10:15:22 PDT 2016
Author: spatel
Date: Fri Aug 26 12:15:22 2016
New Revision: 279837
URL: http://llvm.org/viewvc/llvm-project?rev=279837&view=rev
Log:
[InstCombine] clean up foldICmpAndConstConst(); NFC
1. Early exit to reduce indent
2. Fix comments and variable names to match
3. Reformat comments / clang-format code
Modified:
llvm/trunk/lib/Transforms/InstCombine/InstCombineCompares.cpp
Modified: llvm/trunk/lib/Transforms/InstCombine/InstCombineCompares.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/InstCombine/InstCombineCompares.cpp?rev=279837&r1=279836&r2=279837&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/InstCombine/InstCombineCompares.cpp (original)
+++ llvm/trunk/lib/Transforms/InstCombine/InstCombineCompares.cpp Fri Aug 26 12:15:22 2016
@@ -1389,206 +1389,200 @@ Instruction *InstCombiner::foldICmpXorCo
return nullptr;
}
-/// Fold icmp (and X, C2), C.
+/// Fold icmp (and X, C2), C1.
Instruction *InstCombiner::foldICmpAndConstConst(ICmpInst &Cmp,
BinaryOperator *And,
- const APInt *C) {
+ const APInt *C1) {
// FIXME: This check restricts all folds under here to scalar types.
ConstantInt *RHS = dyn_cast<ConstantInt>(Cmp.getOperand(1));
if (!RHS)
return nullptr;
- if (And->hasOneUse() && isa<ConstantInt>(And->getOperand(1)) &&
- And->getOperand(0)->hasOneUse()) {
- ConstantInt *AndCst = cast<ConstantInt>(And->getOperand(1));
-
- // If the LHS is an AND of a truncating cast, we can widen the
- // and/compare to be the input width without changing the value
- // produced, eliminating a cast.
- if (TruncInst *Cast = dyn_cast<TruncInst>(And->getOperand(0))) {
- // We can do this transformation if either the AND constant does not
- // have its sign bit set or if it is an equality comparison.
- // Extending a relational comparison when we're checking the sign
- // bit would not work.
- if (Cmp.isEquality() || (!AndCst->isNegative() && C->isNonNegative())) {
- Value *NewAnd =
- Builder->CreateAnd(Cast->getOperand(0),
- ConstantExpr::getZExt(AndCst, Cast->getSrcTy()));
- NewAnd->takeName(And);
- return new ICmpInst(Cmp.getPredicate(), NewAnd,
- ConstantExpr::getZExt(RHS, Cast->getSrcTy()));
- }
+ auto *C2 = dyn_cast<ConstantInt>(And->getOperand(1));
+ if (!C2)
+ return nullptr;
+
+ if (!And->hasOneUse() || !And->getOperand(0)->hasOneUse())
+ return nullptr;
+
+ // If the LHS is an AND of a truncating cast, we can widen the and/compare to
+ // be the input width without changing the value produced, eliminating a cast.
+ if (TruncInst *Cast = dyn_cast<TruncInst>(And->getOperand(0))) {
+ // We can do this transformation if either the AND constant does not have
+ // its sign bit set or if it is an equality comparison. Extending a
+ // relational comparison when we're checking the sign bit would not work.
+ if (Cmp.isEquality() || (!C2->isNegative() && C1->isNonNegative())) {
+ Value *NewAnd = Builder->CreateAnd(
+ Cast->getOperand(0), ConstantExpr::getZExt(C2, Cast->getSrcTy()));
+ NewAnd->takeName(And);
+ return new ICmpInst(Cmp.getPredicate(), NewAnd,
+ ConstantExpr::getZExt(RHS, Cast->getSrcTy()));
}
+ }
- // If the LHS is an AND of a zext, and we have an equality compare, we can
- // shrink the and/compare to the smaller type, eliminating the cast.
- if (ZExtInst *Cast = dyn_cast<ZExtInst>(And->getOperand(0))) {
- IntegerType *Ty = cast<IntegerType>(Cast->getSrcTy());
- // Make sure we don't compare the upper bits, SimplifyDemandedBits
- // should fold the icmp to true/false in that case.
- if (Cmp.isEquality() && C->getActiveBits() <= Ty->getBitWidth()) {
- Value *NewAnd = Builder->CreateAnd(Cast->getOperand(0),
- ConstantExpr::getTrunc(AndCst, Ty));
- NewAnd->takeName(And);
- return new ICmpInst(Cmp.getPredicate(), NewAnd,
- ConstantExpr::getTrunc(RHS, Ty));
- }
+ // If the LHS is an AND of a zext, and we have an equality compare, we can
+ // shrink the and/compare to the smaller type, eliminating the cast.
+ if (ZExtInst *Cast = dyn_cast<ZExtInst>(And->getOperand(0))) {
+ IntegerType *Ty = cast<IntegerType>(Cast->getSrcTy());
+ // Make sure we don't compare the upper bits, SimplifyDemandedBits
+ // should fold the icmp to true/false in that case.
+ if (Cmp.isEquality() && C1->getActiveBits() <= Ty->getBitWidth()) {
+ Value *NewAnd = Builder->CreateAnd(Cast->getOperand(0),
+ ConstantExpr::getTrunc(C2, Ty));
+ NewAnd->takeName(And);
+ return new ICmpInst(Cmp.getPredicate(), NewAnd,
+ ConstantExpr::getTrunc(RHS, Ty));
}
+ }
- // If this is: (X >> C1) & C2 != C3 (where any shift and any compare
- // could exist), turn it into (X & (C2 << C1)) != (C3 << C1). This
- // happens a LOT in code produced by the C front-end, for bitfield
- // access.
- BinaryOperator *Shift = dyn_cast<BinaryOperator>(And->getOperand(0));
- if (Shift && !Shift->isShift())
- Shift = nullptr;
-
- ConstantInt *ShAmt;
- ShAmt = Shift ? dyn_cast<ConstantInt>(Shift->getOperand(1)) : nullptr;
-
- // This seemingly simple opportunity to fold away a shift turns out to
- // be rather complicated. See PR17827
- // ( http://llvm.org/bugs/show_bug.cgi?id=17827 ) for details.
- if (ShAmt) {
- bool CanFold = false;
- unsigned ShiftOpcode = Shift->getOpcode();
- if (ShiftOpcode == Instruction::AShr) {
- // There may be some constraints that make this possible,
- // but nothing simple has been discovered yet.
- CanFold = false;
- } else if (ShiftOpcode == Instruction::Shl) {
- // For a left shift, we can fold if the comparison is not signed.
- // We can also fold a signed comparison if the mask value and
- // comparison value are not negative. These constraints may not be
- // obvious, but we can prove that they are correct using an SMT
- // solver.
- if (!Cmp.isSigned() || (!AndCst->isNegative() && !RHS->isNegative()))
- CanFold = true;
- } else if (ShiftOpcode == Instruction::LShr) {
- // For a logical right shift, we can fold if the comparison is not
- // signed. We can also fold a signed comparison if the shifted mask
- // value and the shifted comparison value are not negative.
- // These constraints may not be obvious, but we can prove that they
- // are correct using an SMT solver.
- if (!Cmp.isSigned())
- CanFold = true;
- else {
- ConstantInt *ShiftedAndCst =
- cast<ConstantInt>(ConstantExpr::getShl(AndCst, ShAmt));
- ConstantInt *ShiftedRHSCst =
- cast<ConstantInt>(ConstantExpr::getShl(RHS, ShAmt));
+ // If this is: (X >> C3) & C2 != C1 (where any shift and any compare could
+ // exist), turn it into (X & (C2 << C3)) != (C1 << C3). This happens a LOT in
+ // code produced by the clang front-end, for bitfield access.
+ BinaryOperator *Shift = dyn_cast<BinaryOperator>(And->getOperand(0));
+ if (Shift && !Shift->isShift())
+ Shift = nullptr;
+
+ ConstantInt *ShAmt;
+ ShAmt = Shift ? dyn_cast<ConstantInt>(Shift->getOperand(1)) : nullptr;
+
+ // This seemingly simple opportunity to fold away a shift turns out to be
+ // rather complicated. See PR17827 for details.
+ if (ShAmt) {
+ bool CanFold = false;
+ unsigned ShiftOpcode = Shift->getOpcode();
+ if (ShiftOpcode == Instruction::AShr) {
+ // There may be some constraints that make this possible, but nothing
+ // simple has been discovered yet.
+ CanFold = false;
+ } else if (ShiftOpcode == Instruction::Shl) {
+ // For a left shift, we can fold if the comparison is not signed. We can
+ // also fold a signed comparison if the mask value and comparison value
+ // are not negative. These constraints may not be obvious, but we can
+ // prove that they are correct using an SMT solver.
+ if (!Cmp.isSigned() || (!C2->isNegative() && !RHS->isNegative()))
+ CanFold = true;
+ } else if (ShiftOpcode == Instruction::LShr) {
+ // For a logical right shift, we can fold if the comparison is not signed.
+ // We can also fold a signed comparison if the shifted mask value and the
+ // shifted comparison value are not negative. These constraints may not be
+ // obvious, but we can prove that they are correct using an SMT solver.
+ if (!Cmp.isSigned())
+ CanFold = true;
+ else {
+ ConstantInt *ShiftedAndCst =
+ cast<ConstantInt>(ConstantExpr::getShl(C2, ShAmt));
+ ConstantInt *ShiftedRHSCst =
+ cast<ConstantInt>(ConstantExpr::getShl(RHS, ShAmt));
- if (!ShiftedAndCst->isNegative() && !ShiftedRHSCst->isNegative())
- CanFold = true;
- }
+ if (!ShiftedAndCst->isNegative() && !ShiftedRHSCst->isNegative())
+ CanFold = true;
}
+ }
- if (CanFold) {
- Constant *NewCst;
+ if (CanFold) {
+ Constant *NewCst;
+ if (ShiftOpcode == Instruction::Shl)
+ NewCst = ConstantExpr::getLShr(RHS, ShAmt);
+ else
+ NewCst = ConstantExpr::getShl(RHS, ShAmt);
+
+ // Check to see if we are shifting out any of the bits being compared.
+ if (ConstantExpr::get(ShiftOpcode, NewCst, ShAmt) != RHS) {
+ // If we shifted bits out, the fold is not going to work out. As a
+ // special case, check to see if this means that the result is always
+ // true or false now.
+ if (Cmp.getPredicate() == ICmpInst::ICMP_EQ)
+ return replaceInstUsesWith(Cmp, Builder->getFalse());
+ if (Cmp.getPredicate() == ICmpInst::ICMP_NE)
+ return replaceInstUsesWith(Cmp, Builder->getTrue());
+ } else {
+ Cmp.setOperand(1, NewCst);
+ Constant *NewAndCst;
if (ShiftOpcode == Instruction::Shl)
- NewCst = ConstantExpr::getLShr(RHS, ShAmt);
+ NewAndCst = ConstantExpr::getLShr(C2, ShAmt);
else
- NewCst = ConstantExpr::getShl(RHS, ShAmt);
-
- // Check to see if we are shifting out any of the bits being
- // compared.
- if (ConstantExpr::get(ShiftOpcode, NewCst, ShAmt) != RHS) {
- // If we shifted bits out, the fold is not going to work out.
- // As a special case, check to see if this means that the
- // result is always true or false now.
- if (Cmp.getPredicate() == ICmpInst::ICMP_EQ)
- return replaceInstUsesWith(Cmp, Builder->getFalse());
- if (Cmp.getPredicate() == ICmpInst::ICMP_NE)
- return replaceInstUsesWith(Cmp, Builder->getTrue());
- } else {
- Cmp.setOperand(1, NewCst);
- Constant *NewAndCst;
- if (ShiftOpcode == Instruction::Shl)
- NewAndCst = ConstantExpr::getLShr(AndCst, ShAmt);
- else
- NewAndCst = ConstantExpr::getShl(AndCst, ShAmt);
- And->setOperand(1, NewAndCst);
- And->setOperand(0, Shift->getOperand(0));
- Worklist.Add(Shift); // Shift is dead.
- return &Cmp;
- }
+ NewAndCst = ConstantExpr::getShl(C2, ShAmt);
+ And->setOperand(1, NewAndCst);
+ And->setOperand(0, Shift->getOperand(0));
+ Worklist.Add(Shift); // Shift is dead.
+ return &Cmp;
}
}
+ }
- // 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() && *C == 0 && Cmp.isEquality() &&
- !Shift->isArithmeticShift() && !isa<Constant>(Shift->getOperand(0))) {
- // Compute C << Y.
- Value *NS;
- if (Shift->getOpcode() == Instruction::LShr) {
- NS = Builder->CreateShl(AndCst, Shift->getOperand(1));
- } else {
- // Insert a logical shift.
- NS = Builder->CreateLShr(AndCst, Shift->getOperand(1));
- }
+ // Turn ((X >> Y) & C2) == 0 into (X & (C2 << Y)) == 0. The latter is
+ // preferable because it allows the C2 << Y expression to be hoisted out of a
+ // loop if Y is invariant and X is not.
+ if (Shift && Shift->hasOneUse() && *C1 == 0 && Cmp.isEquality() &&
+ !Shift->isArithmeticShift() && !isa<Constant>(Shift->getOperand(0))) {
+ // Compute C2 << Y.
+ Value *NS;
+ if (Shift->getOpcode() == Instruction::LShr) {
+ NS = Builder->CreateShl(C2, Shift->getOperand(1));
+ } else {
+ // Insert a logical shift.
+ NS = Builder->CreateLShr(C2, Shift->getOperand(1));
+ }
+
+ // Compute X & (C2 << Y).
+ Value *NewAnd =
+ Builder->CreateAnd(Shift->getOperand(0), NS, And->getName());
- // Compute X & (C << Y).
- Value *NewAnd =
- Builder->CreateAnd(Shift->getOperand(0), NS, And->getName());
-
- Cmp.setOperand(0, NewAnd);
- return &Cmp;
- }
-
- // (icmp pred (and (or (lshr X, Y), X), 1), 0) -->
- // (icmp pred (and X, (or (shl 1, Y), 1), 0))
- //
- // iff pred isn't signed
- {
- Value *X, *Y, *LShr;
- if (!Cmp.isSigned() && *C == 0) {
- if (match(And->getOperand(1), m_One())) {
- Constant *One = cast<Constant>(And->getOperand(1));
- Value *Or = And->getOperand(0);
- if (match(Or, m_Or(m_Value(LShr), m_Value(X))) &&
- match(LShr, m_LShr(m_Specific(X), m_Value(Y)))) {
- unsigned UsesRemoved = 0;
- if (And->hasOneUse())
- ++UsesRemoved;
- if (Or->hasOneUse())
- ++UsesRemoved;
- if (LShr->hasOneUse())
- ++UsesRemoved;
- Value *NewOr = nullptr;
- // Compute X & ((1 << Y) | 1)
- if (auto *C = dyn_cast<Constant>(Y)) {
- if (UsesRemoved >= 1)
- NewOr =
- ConstantExpr::getOr(ConstantExpr::getNUWShl(One, C), One);
- } else {
- if (UsesRemoved >= 3)
- NewOr = Builder->CreateOr(Builder->CreateShl(One, Y,
- LShr->getName(),
- /*HasNUW=*/true),
- One, Or->getName());
- }
- if (NewOr) {
- Value *NewAnd = Builder->CreateAnd(X, NewOr, And->getName());
- Cmp.setOperand(0, NewAnd);
- return &Cmp;
- }
+ Cmp.setOperand(0, NewAnd);
+ return &Cmp;
+ }
+
+ // (icmp pred (and (or (lshr A, B), A), 1), 0) -->
+ // (icmp pred (and A, (or (shl 1, B), 1), 0))
+ //
+ // iff pred isn't signed
+ {
+ Value *A, *B, *LShr;
+ if (!Cmp.isSigned() && *C1 == 0) {
+ if (match(And->getOperand(1), m_One())) {
+ Constant *One = cast<Constant>(And->getOperand(1));
+ Value *Or = And->getOperand(0);
+ if (match(Or, m_Or(m_Value(LShr), m_Value(A))) &&
+ match(LShr, m_LShr(m_Specific(A), m_Value(B)))) {
+ unsigned UsesRemoved = 0;
+ if (And->hasOneUse())
+ ++UsesRemoved;
+ if (Or->hasOneUse())
+ ++UsesRemoved;
+ if (LShr->hasOneUse())
+ ++UsesRemoved;
+ Value *NewOr = nullptr;
+ // Compute A & ((1 << B) | 1)
+ if (auto *C = dyn_cast<Constant>(B)) {
+ if (UsesRemoved >= 1)
+ NewOr = ConstantExpr::getOr(ConstantExpr::getNUWShl(One, C), One);
+ } else {
+ if (UsesRemoved >= 3)
+ NewOr =
+ Builder->CreateOr(Builder->CreateShl(One, B, LShr->getName(),
+ /*HasNUW=*/true),
+ One, Or->getName());
+ }
+ if (NewOr) {
+ Value *NewAnd = Builder->CreateAnd(A, NewOr, And->getName());
+ Cmp.setOperand(0, NewAnd);
+ return &Cmp;
}
}
}
}
+ }
- // Replace ((X & AndCst) > RHSV) with ((X & AndCst) != 0), if any
- // bit set in (X & AndCst) will produce a result greater than RHSV.
- if (Cmp.getPredicate() == ICmpInst::ICMP_UGT) {
- unsigned NTZ = AndCst->getValue().countTrailingZeros();
- if ((NTZ < AndCst->getBitWidth()) &&
- APInt::getOneBitSet(AndCst->getBitWidth(), NTZ).ugt(*C))
- return new ICmpInst(ICmpInst::ICMP_NE, And,
- Constant::getNullValue(RHS->getType()));
- }
+ // Replace ((X & C2) > C1) with ((X & C2) != 0), if any bit set in (X & C2)
+ // will produce a result greater than C1.
+ if (Cmp.getPredicate() == ICmpInst::ICMP_UGT) {
+ unsigned NTZ = C2->getValue().countTrailingZeros();
+ if ((NTZ < C2->getBitWidth()) &&
+ APInt::getOneBitSet(C2->getBitWidth(), NTZ).ugt(*C1))
+ return new ICmpInst(ICmpInst::ICMP_NE, And,
+ Constant::getNullValue(RHS->getType()));
}
+
return nullptr;
}
More information about the llvm-commits
mailing list