[llvm] r279851 - [InstCombine] add helper function for icmp (and (sh X, Y), C2), C1 ; NFC

Sanjay Patel via llvm-commits llvm-commits at lists.llvm.org
Fri Aug 26 11:28:47 PDT 2016


Author: spatel
Date: Fri Aug 26 13:28:46 2016
New Revision: 279851

URL: http://llvm.org/viewvc/llvm-project?rev=279851&view=rev
Log:
[InstCombine] add helper function for icmp (and (sh X, Y), C2), C1 ; NFC

Like other recent changes near here, the goal is to allow vector types for
all of these folds. Splitting things up makes it easier to incrementally 
enhance the code and easier to read.

Modified:
    llvm/trunk/lib/Transforms/InstCombine/InstCombineCompares.cpp
    llvm/trunk/lib/Transforms/InstCombine/InstCombineInternal.h

Modified: llvm/trunk/lib/Transforms/InstCombine/InstCombineCompares.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/InstCombine/InstCombineCompares.cpp?rev=279851&r1=279850&r2=279851&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/InstCombine/InstCombineCompares.cpp (original)
+++ llvm/trunk/lib/Transforms/InstCombine/InstCombineCompares.cpp Fri Aug 26 13:28:46 2016
@@ -1389,65 +1389,29 @@ Instruction *InstCombiner::foldICmpXorCo
   return nullptr;
 }
 
-/// Fold icmp (and X, C2), C1.
-Instruction *InstCombiner::foldICmpAndConstConst(ICmpInst &Cmp,
-                                                 BinaryOperator *And,
-                                                 const APInt *C1) {
+/// Fold icmp (and (sh X, Y), C2), C1.
+Instruction *InstCombiner::foldICmpAndShift(ICmpInst &Cmp, BinaryOperator *And,
+                                            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;
 
+  // FIXME: This could be passed in as APInt.
   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() && 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 >> 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;
+  if (!Shift || !Shift->isShift())
+    return nullptr;
 
   // This seemingly simple opportunity to fold away a shift turns out to be
   // rather complicated. See PR17827 for details.
-  if (ShAmt) {
+  if (auto *ShAmt = dyn_cast<ConstantInt>(Shift->getOperand(1))) {
     bool CanFold = false;
     unsigned ShiftOpcode = Shift->getOpcode();
     if (ShiftOpcode == Instruction::AShr) {
@@ -1513,7 +1477,7 @@ Instruction *InstCombiner::foldICmpAndCo
   // 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() &&
+  if (Shift->hasOneUse() && *C1 == 0 && Cmp.isEquality() &&
       !Shift->isArithmeticShift() && !isa<Constant>(Shift->getOperand(0))) {
     // Compute C2 << Y.
     Value *NS;
@@ -1532,6 +1496,59 @@ Instruction *InstCombiner::foldICmpAndCo
     return &Cmp;
   }
 
+  return nullptr;
+}
+
+/// Fold icmp (and X, C2), C1.
+Instruction *InstCombiner::foldICmpAndConstConst(ICmpInst &Cmp,
+                                                 BinaryOperator *And,
+                                                 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;
+
+  // FIXME: Use m_APInt.
+  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() && 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 (Instruction *I = foldICmpAndShift(Cmp, And, C1))
+    return I;
+
   // (icmp pred (and (or (lshr A, B), A), 1), 0) -->
   //    (icmp pred (and A, (or (shl 1, B), 1), 0))
   //

Modified: llvm/trunk/lib/Transforms/InstCombine/InstCombineInternal.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/InstCombine/InstCombineInternal.h?rev=279851&r1=279850&r2=279851&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/InstCombine/InstCombineInternal.h (original)
+++ llvm/trunk/lib/Transforms/InstCombine/InstCombineInternal.h Fri Aug 26 13:28:46 2016
@@ -580,7 +580,9 @@ private:
   Instruction *foldICmpAddConstant(ICmpInst &Cmp, BinaryOperator *Add,
                                    const APInt *C);
   Instruction *foldICmpAndConstConst(ICmpInst &Cmp, BinaryOperator *And,
-                                     const APInt *C);
+                                     const APInt *C1);
+  Instruction *foldICmpAndShift(ICmpInst &Cmp, BinaryOperator *And,
+                                const APInt *C1);
 
   Instruction *foldICmpEqualityWithConstant(ICmpInst &ICI);
   Instruction *foldICmpIntrinsicWithConstant(ICmpInst &ICI);




More information about the llvm-commits mailing list