[llvm] r279339 - [InstCombine] use m_APInt to allow icmp (shl X, Y), C folds for splat constant vectors, part 1

Sanjay Patel via llvm-commits llvm-commits at lists.llvm.org
Fri Aug 19 15:33:26 PDT 2016


Author: spatel
Date: Fri Aug 19 17:33:26 2016
New Revision: 279339

URL: http://llvm.org/viewvc/llvm-project?rev=279339&view=rev
Log:
[InstCombine] use m_APInt to allow icmp (shl X, Y), C folds for splat constant vectors, part 1

This is a partial enablement (move the ConstantInt guard down) because there are many
different folds here and one of the later ones will require reworking 'isSignBitCheck'.

Modified:
    llvm/trunk/lib/Transforms/InstCombine/InstCombineCompares.cpp
    llvm/trunk/test/Transforms/InstCombine/getelementptr.ll
    llvm/trunk/test/Transforms/InstCombine/icmp.ll

Modified: llvm/trunk/lib/Transforms/InstCombine/InstCombineCompares.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/InstCombine/InstCombineCompares.cpp?rev=279339&r1=279338&r2=279339&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/InstCombine/InstCombineCompares.cpp (original)
+++ llvm/trunk/lib/Transforms/InstCombine/InstCombineCompares.cpp Fri Aug 19 17:33:26 2016
@@ -1990,20 +1990,14 @@ static Instruction *foldICmpShlOne(ICmpI
 /// Fold icmp (shl X, Y), C.
 Instruction *InstCombiner::foldICmpShlConstant(ICmpInst &Cmp, Instruction *Shl,
                                                const APInt *C) {
-  // FIXME: This should use m_APInt to allow splat vectors.
-  ConstantInt *ShAmt = dyn_cast<ConstantInt>(Shl->getOperand(1));
-  if (!ShAmt)
+  const APInt *ShiftAmt;
+  if (!match(Shl->getOperand(1), m_APInt(ShiftAmt)))
     return foldICmpShlOne(Cmp, Shl, C);
 
-  // FIXME: This check restricts all folds under here to scalar types.
-  ConstantInt *RHS = dyn_cast<ConstantInt>(Cmp.getOperand(1));
-  if (!RHS)
-    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.
   unsigned TypeBits = C->getBitWidth();
-  if (ShAmt->uge(TypeBits))
+  if (ShiftAmt->uge(TypeBits))
     return nullptr;
 
   ICmpInst::Predicate Pred = Cmp.getPredicate();
@@ -2011,25 +2005,30 @@ Instruction *InstCombiner::foldICmpShlCo
   if (Cmp.isEquality()) {
     // If the shift is NUW, then it is just shifting out zeros, no need for an
     // AND.
+    Constant *LShrC = ConstantInt::get(Shl->getType(), C->lshr(*ShiftAmt));
     if (cast<BinaryOperator>(Shl)->hasNoUnsignedWrap())
-      return new ICmpInst(Pred, X, ConstantExpr::getLShr(RHS, ShAmt));
+      return new ICmpInst(Pred, X, LShrC);
 
     // If the shift is NSW and we compare to 0, then it is just shifting out
     // sign bits, no need for an AND either.
     if (cast<BinaryOperator>(Shl)->hasNoSignedWrap() && *C == 0)
-      return new ICmpInst(Pred, X, ConstantExpr::getLShr(RHS, ShAmt));
+      return new ICmpInst(Pred, X, LShrC);
 
     if (Shl->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 = ConstantInt::get(Shl->getType(),
+          APInt::getLowBitsSet(TypeBits, TypeBits - ShiftAmt->getZExtValue()));
 
       Value *And = Builder->CreateAnd(X, Mask, Shl->getName() + ".mask");
-      return new ICmpInst(Pred, And, ConstantExpr::getLShr(RHS, ShAmt));
+      return new ICmpInst(Pred, And, LShrC);
     }
   }
 
+  // FIXME: This check restricts all folds under here to scalar types.
+  ConstantInt *RHS = dyn_cast<ConstantInt>(Cmp.getOperand(1));
+  if (!RHS)
+    return nullptr;
+
   // If this is a signed comparison to 0 and the shift is sign preserving,
   // use the shift LHS operand instead; isSignTest may change 'Pred', so only
   // do that if we're sure to not continue on in this function.
@@ -2042,7 +2041,7 @@ Instruction *InstCombiner::foldICmpShlCo
     // (X << 31) <s 0  --> (X&1) != 0
     Constant *Mask = ConstantInt::get(
         X->getType(),
-        APInt::getOneBitSet(TypeBits, TypeBits - ShAmt->getZExtValue() - 1));
+        APInt::getOneBitSet(TypeBits, TypeBits - ShiftAmt->getZExtValue() - 1));
     Value *And = Builder->CreateAnd(X, Mask, Shl->getName() + ".mask");
     return new ICmpInst(TrueIfSigned ? ICmpInst::ICMP_NE : ICmpInst::ICMP_EQ,
                         And, Constant::getNullValue(And->getType()));
@@ -2054,7 +2053,7 @@ Instruction *InstCombiner::foldICmpShlCo
   // This enables to get rid of the shift in favor of a trunc which can be
   // 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);
+  unsigned Amt = ShiftAmt->getLimitedValue(TypeBits - 1);
   if (Shl->hasOneUse() && Amt != 0 && C->countTrailingZeros() >= Amt) {
     Type *NTy = IntegerType::get(Cmp.getContext(), TypeBits - Amt);
     Constant *NCI = ConstantExpr::getTrunc(

Modified: llvm/trunk/test/Transforms/InstCombine/getelementptr.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/getelementptr.ll?rev=279339&r1=279338&r2=279339&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/getelementptr.ll (original)
+++ llvm/trunk/test/Transforms/InstCombine/getelementptr.ll Fri Aug 19 17:33:26 2016
@@ -175,10 +175,10 @@ define i1 @test13(i64 %X, %S* %P) {
 ; CHECK:    %C = icmp eq i64 %X, -1
 }
 
+; This is a test of icmp + shl nuw in disguise - 4611... is 0x3fff...
 define <2 x i1> @test13_vector(<2 x i64> %X, <2 x %S*> %P) nounwind {
 ; CHECK-LABEL: @test13_vector(
-; CHECK-NEXT:    [[A_IDX:%.*]] = shl nuw <2 x i64> %X, <i64 2, i64 2>
-; CHECK-NEXT:    [[C:%.*]] = icmp eq <2 x i64> [[A_IDX]], <i64 -4, i64 -4>
+; CHECK-NEXT:    [[C:%.*]] = icmp eq <2 x i64> %X, <i64 4611686018427387903, i64 4611686018427387903>
 ; CHECK-NEXT:    ret <2 x i1> [[C]]
 ;
   %A = getelementptr inbounds %S, <2 x %S*> %P, <2 x i64> zeroinitializer, <2 x i32> <i32 1, i32 1>, <2 x i64> %X
@@ -197,10 +197,10 @@ define i1 @test13_as1(i16 %X, %S addrspa
   ret i1 %C
 }
 
+; This is a test of icmp + shl nuw in disguise - 16383 is 0x3fff.
 define <2 x i1> @test13_vector_as1(<2 x i16> %X, <2 x %S addrspace(1)*> %P) {
 ; CHECK-LABEL: @test13_vector_as1(
-; CHECK-NEXT:    [[A_IDX:%.*]] = shl nuw <2 x i16> %X, <i16 2, i16 2>
-; CHECK-NEXT:    [[C:%.*]] = icmp eq <2 x i16> [[A_IDX]], <i16 -4, i16 -4>
+; CHECK-NEXT:    [[C:%.*]] = icmp eq <2 x i16> %X, <i16 16383, i16 16383>
 ; CHECK-NEXT:    ret <2 x i1> [[C]]
 ;
   %A = getelementptr inbounds %S, <2 x %S addrspace(1)*> %P, <2 x i16> <i16 0, i16 0>, <2 x i32> <i32 1, i32 1>, <2 x i16> %X

Modified: llvm/trunk/test/Transforms/InstCombine/icmp.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/icmp.ll?rev=279339&r1=279338&r2=279339&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/icmp.ll (original)
+++ llvm/trunk/test/Transforms/InstCombine/icmp.ll Fri Aug 19 17:33:26 2016
@@ -1183,11 +1183,9 @@ define i1 @icmp_shl_nsw_eq(i32 %x) {
   ret i1 %cmp
 }
 
-; FIXME: Vectors should fold the same way.
 define <2 x i1> @icmp_shl_nsw_eq_vec(<2 x i32> %x) {
 ; CHECK-LABEL: @icmp_shl_nsw_eq_vec(
-; CHECK-NEXT:    [[MUL:%.*]] = shl nsw <2 x i32> %x, <i32 5, i32 5>
-; CHECK-NEXT:    [[CMP:%.*]] = icmp eq <2 x i32> [[MUL]], zeroinitializer
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq <2 x i32> %x, zeroinitializer
 ; CHECK-NEXT:    ret <2 x i1> [[CMP]]
 ;
   %mul = shl nsw <2 x i32> %x, <i32 5, i32 5>
@@ -1206,11 +1204,10 @@ define i1 @icmp_shl_eq(i32 %x) {
   ret i1 %cmp
 }
 
-; FIXME: Vectors should fold the same way.
 define <2 x i1> @icmp_shl_eq_vec(<2 x i32> %x) {
 ; CHECK-LABEL: @icmp_shl_eq_vec(
-; CHECK-NEXT:    [[MUL:%.*]] = shl <2 x i32> %x, <i32 5, i32 5>
-; CHECK-NEXT:    [[CMP:%.*]] = icmp eq <2 x i32> [[MUL]], zeroinitializer
+; CHECK-NEXT:    [[MUL_MASK:%.*]] = and <2 x i32> %x, <i32 134217727, i32 134217727>
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq <2 x i32> [[MUL_MASK]], zeroinitializer
 ; CHECK-NEXT:    ret <2 x i1> [[CMP]]
 ;
   %mul = shl <2 x i32> %x, <i32 5, i32 5>
@@ -1228,11 +1225,9 @@ define i1 @icmp_shl_nsw_ne(i32 %x) {
   ret i1 %cmp
 }
 
-; FIXME: Vectors should fold the same way.
 define <2 x i1> @icmp_shl_nsw_ne_vec(<2 x i32> %x) {
 ; CHECK-LABEL: @icmp_shl_nsw_ne_vec(
-; CHECK-NEXT:    [[MUL:%.*]] = shl nsw <2 x i32> %x, <i32 7, i32 7>
-; CHECK-NEXT:    [[CMP:%.*]] = icmp ne <2 x i32> [[MUL]], zeroinitializer
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ne <2 x i32> %x, zeroinitializer
 ; CHECK-NEXT:    ret <2 x i1> [[CMP]]
 ;
   %mul = shl nsw <2 x i32> %x, <i32 7, i32 7>
@@ -1251,11 +1246,10 @@ define i1 @icmp_shl_ne(i32 %x) {
   ret i1 %cmp
 }
 
-; FIXME: Vectors should fold the same way.
 define <2 x i1> @icmp_shl_ne_vec(<2 x i32> %x) {
 ; CHECK-LABEL: @icmp_shl_ne_vec(
-; CHECK-NEXT:    [[MUL:%.*]] = shl <2 x i32> %x, <i32 7, i32 7>
-; CHECK-NEXT:    [[CMP:%.*]] = icmp ne <2 x i32> [[MUL]], zeroinitializer
+; CHECK-NEXT:    [[MUL_MASK:%.*]] = and <2 x i32> %x, <i32 33554431, i32 33554431>
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ne <2 x i32> [[MUL_MASK]], zeroinitializer
 ; CHECK-NEXT:    ret <2 x i1> [[CMP]]
 ;
   %mul = shl <2 x i32> %x, <i32 7, i32 7>
@@ -1263,6 +1257,16 @@ define <2 x i1> @icmp_shl_ne_vec(<2 x i3
   ret <2 x i1> %cmp
 }
 
+define <2 x i1> @icmp_shl_nuw_ne_vec(<2 x i32> %x) {
+; CHECK-LABEL: @icmp_shl_nuw_ne_vec(
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ne <2 x i32> %x, <i32 2, i32 2>
+; CHECK-NEXT:    ret <2 x i1> [[CMP]]
+;
+  %shl = shl nuw <2 x i32> %x, <i32 7, i32 7>
+  %cmp = icmp ne <2 x i32> %shl, <i32 256, i32 256>
+  ret <2 x i1> %cmp
+}
+
 ; If the (mul x, C) preserved the sign and this is sign test,
 ; compare the LHS operand instead
 define i1 @icmp_mul_nsw(i32 %x) {




More information about the llvm-commits mailing list