[InstCombine] use m_APInt to allow icmp (binop X, Y), C folds with constant splat...
authorSanjay Patel <spatel@rotateright.com>
Wed, 3 Aug 2016 18:59:03 +0000 (18:59 +0000)
committerSanjay Patel <spatel@rotateright.com>
Wed, 3 Aug 2016 18:59:03 +0000 (18:59 +0000)
This removes the restriction for the icmp constant, but as noted by the FIXME comments,
we still need to change individual checks for binop operand constants.

llvm-svn: 277629

llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
llvm/test/Transforms/InstCombine/add.ll
llvm/test/Transforms/InstCombine/compare-udiv.ll
llvm/test/Transforms/InstCombine/getelementptr.ll
llvm/test/Transforms/InstCombine/sub.ll
llvm/test/Transforms/InstCombine/xor.ll

index 9d94b27..4b949ab 100644 (file)
@@ -2203,22 +2203,23 @@ Instruction *InstCombiner::foldICmpWithConstant(ICmpInst &ICI,
 /// Simplify icmp_eq and icmp_ne instructions with binary operator LHS and
 /// integer constant RHS.
 Instruction *InstCombiner::foldICmpEqualityWithConstant(ICmpInst &ICI) {
-  // FIXME: If we use m_APInt() instead of m_ConstantInt(), it would enable
-  // vector types with constant splat vectors to be optimized too.
   BinaryOperator *BO;
-  ConstantInt *RHS;
+  const APInt *RHSV;
+  // FIXME: Some of these folds could work with arbitrary constants, but this
+  // match is limited to scalars and vector splat constants.
   if (!ICI.isEquality() || !match(ICI.getOperand(0), m_BinOp(BO)) ||
-      !match(ICI.getOperand(1), m_ConstantInt(RHS)))
+      !match(ICI.getOperand(1), m_APInt(RHSV)))
     return nullptr;
 
-  const APInt &RHSV = RHS->getValue();
+  Constant *RHS = cast<Constant>(ICI.getOperand(1));
   bool isICMP_NE = ICI.getPredicate() == ICmpInst::ICMP_NE;
   Value *BOp0 = BO->getOperand(0), *BOp1 = BO->getOperand(1);
 
   switch (BO->getOpcode()) {
   case Instruction::SRem:
     // If we have a signed (X % (2^c)) == 0, turn it into an unsigned one.
-    if (RHSV == 0 && isa<ConstantInt>(BOp1) && BO->hasOneUse()) {
+    // FIXME: Vectors are excluded by ConstantInt.
+    if (*RHSV == 0 && isa<ConstantInt>(BOp1) && BO->hasOneUse()) {
       const APInt &V = cast<ConstantInt>(BOp1)->getValue();
       if (V.sgt(1) && V.isPowerOf2()) {
         Value *NewRem = Builder->CreateURem(BOp0, BOp1, BO->getName());
@@ -2229,11 +2230,12 @@ Instruction *InstCombiner::foldICmpEqualityWithConstant(ICmpInst &ICI) {
     break;
   case Instruction::Add:
     // Replace ((add A, B) != C) with (A != C-B) if B & C are constants.
+    // FIXME: Vectors are excluded by ConstantInt.
     if (ConstantInt *BOp1C = dyn_cast<ConstantInt>(BOp1)) {
       if (BO->hasOneUse())
         return new ICmpInst(ICI.getPredicate(), BOp0,
                             ConstantExpr::getSub(RHS, BOp1C));
-    } else if (RHSV == 0) {
+    } else if (*RHSV == 0) {
       // Replace ((add A, B) != 0) with (A != -B) if A or B is
       // efficiently invertible, or if the add has just this one use.
       if (Value *NegVal = dyn_castNegVal(BOp1))
@@ -2254,7 +2256,7 @@ Instruction *InstCombiner::foldICmpEqualityWithConstant(ICmpInst &ICI) {
         // the explicit xor.
         return new ICmpInst(ICI.getPredicate(), BOp0,
                             ConstantExpr::getXor(RHS, BOC));
-      } else if (RHSV == 0) {
+      } else if (*RHSV == 0) {
         // Replace ((xor A, B) != 0) with (A != B)
         return new ICmpInst(ICI.getPredicate(), BOp0, BOp1);
       }
@@ -2262,11 +2264,12 @@ Instruction *InstCombiner::foldICmpEqualityWithConstant(ICmpInst &ICI) {
     break;
   case Instruction::Sub:
     if (BO->hasOneUse()) {
+      // FIXME: Vectors are excluded by ConstantInt.
       if (ConstantInt *BOp0C = dyn_cast<ConstantInt>(BOp0)) {
         // Replace ((sub A, B) != C) with (B != A-C) if A & C are constants.
         return new ICmpInst(ICI.getPredicate(), BOp1,
                             ConstantExpr::getSub(BOp0C, RHS));
-      } else if (RHSV == 0) {
+      } else if (*RHSV == 0) {
         // Replace ((sub A, B) != 0) with (A != B)
         return new ICmpInst(ICI.getPredicate(), BOp0, BOp1);
       }
@@ -2275,6 +2278,7 @@ Instruction *InstCombiner::foldICmpEqualityWithConstant(ICmpInst &ICI) {
   case Instruction::Or:
     // If bits are being or'd in that are not present in the constant we
     // are comparing against, then the comparison could never succeed!
+    // FIXME: Vectors are excluded by ConstantInt.
     if (ConstantInt *BOC = dyn_cast<ConstantInt>(BOp1)) {
       Constant *NotCI = ConstantExpr::getNot(RHS);
       if (!ConstantExpr::getAnd(BOC, NotCI)->isNullValue())
@@ -2292,14 +2296,15 @@ Instruction *InstCombiner::foldICmpEqualityWithConstant(ICmpInst &ICI) {
     break;
 
   case Instruction::And:
+    // FIXME: Vectors are excluded by ConstantInt.
     if (ConstantInt *BOC = dyn_cast<ConstantInt>(BOp1)) {
       // If bits are being compared against that are and'd out, then the
       // comparison can never succeed!
-      if ((RHSV & ~BOC->getValue()) != 0)
+      if ((*RHSV & ~BOC->getValue()) != 0)
         return replaceInstUsesWith(ICI, Builder->getInt1(isICMP_NE));
 
       // If we have ((X & C) == C), turn it into ((X & C) != 0).
-      if (RHS == BOC && RHSV.isPowerOf2())
+      if (RHS == BOC && RHSV->isPowerOf2())
         return new ICmpInst(isICMP_NE ? ICmpInst::ICMP_EQ : ICmpInst::ICMP_NE,
                             BO, Constant::getNullValue(RHS->getType()));
 
@@ -2316,7 +2321,7 @@ Instruction *InstCombiner::foldICmpEqualityWithConstant(ICmpInst &ICI) {
       }
 
       // ((X & ~7) == 0) --> X < 8
-      if (RHSV == 0 && isHighOnes(BOC)) {
+      if (*RHSV == 0 && isHighOnes(BOC)) {
         Constant *NegX = ConstantExpr::getNeg(BOC);
         ICmpInst::Predicate Pred =
             isICMP_NE ? ICmpInst::ICMP_UGE : ICmpInst::ICMP_ULT;
@@ -2325,7 +2330,8 @@ Instruction *InstCombiner::foldICmpEqualityWithConstant(ICmpInst &ICI) {
     }
     break;
   case Instruction::Mul:
-    if (RHSV == 0 && BO->hasNoSignedWrap()) {
+    if (*RHSV == 0 && BO->hasNoSignedWrap()) {
+      // FIXME: Vectors are excluded by ConstantInt.
       if (ConstantInt *BOC = dyn_cast<ConstantInt>(BOp1)) {
         // The trivial case (mul X, 0) is handled by InstSimplify
         // General case : (mul X, C) != 0 iff X != 0
@@ -2337,7 +2343,7 @@ Instruction *InstCombiner::foldICmpEqualityWithConstant(ICmpInst &ICI) {
     }
     break;
   case Instruction::UDiv:
-    if (RHSV == 0) {
+    if (*RHSV == 0) {
       // (icmp eq/ne (udiv A, B), 0) -> (icmp ugt/ule i32 B, A)
       ICmpInst::Predicate Pred =
           isICMP_NE ? ICmpInst::ICMP_ULE : ICmpInst::ICMP_UGT;
index e75c032..10c1592 100644 (file)
@@ -109,12 +109,10 @@ define i1 @test10(i8 %A, i8 %b) {
   ret i1 %c
 }
 
-; FIXME: Vectors should fold the same way.
-
 define <2 x i1> @test10vec(<2 x i8> %a, <2 x i8> %b) {
 ; CHECK-LABEL: @test10vec(
-; CHECK-NEXT:    [[C:%.*]] = add <2 x i8> %a, %b
-; CHECK-NEXT:    [[D:%.*]] = icmp ne <2 x i8> [[C]], zeroinitializer
+; CHECK-NEXT:    [[C:%.*]] = sub <2 x i8> zeroinitializer, %b
+; CHECK-NEXT:    [[D:%.*]] = icmp ne <2 x i8> %a, [[C]]
 ; CHECK-NEXT:    ret <2 x i1> [[D]]
 ;
   %c = add <2 x i8> %a, %b
@@ -133,11 +131,9 @@ define i1 @test11(i8 %A) {
   ret i1 %c
 }
 
-; FIXME: Vectors should fold the same way.
 define <2 x i1> @test11vec(<2 x i8> %a) {
 ; CHECK-LABEL: @test11vec(
-; CHECK-NEXT:    [[B:%.*]] = add <2 x i8> %a, <i8 -1, i8 -1>
-; CHECK-NEXT:    [[C:%.*]] = icmp ne <2 x i8> [[B]], zeroinitializer
+; CHECK-NEXT:    [[C:%.*]] = icmp ne <2 x i8> %a, <i8 1, i8 1>
 ; CHECK-NEXT:    ret <2 x i1> [[C]]
 ;
   %b = add <2 x i8> %a, <i8 -1, i8 -1>
index de7e930..8eb0715 100644 (file)
@@ -1,8 +1,6 @@
 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
 ; RUN: opt -instcombine -S < %s | FileCheck %s
 
-; FIXME: Vectors should get the same folds as scalars for all tests.
-
 define i1 @test1(i32 %n, i32 %d) {
 ; CHECK-LABEL: @test1(
 ; CHECK-NEXT:    [[CMP1:%.*]] = icmp ugt i32 %d, %n
@@ -15,8 +13,7 @@ define i1 @test1(i32 %n, i32 %d) {
 
 define <2 x i1> @test1vec(<2 x i32> %n, <2 x i32> %d) {
 ; CHECK-LABEL: @test1vec(
-; CHECK-NEXT:    [[DIV:%.*]] = udiv <2 x i32> %n, %d
-; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq <2 x i32> [[DIV]], zeroinitializer
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp ugt <2 x i32> %d, %n
 ; CHECK-NEXT:    ret <2 x i1> [[CMP1]]
 ;
   %div = udiv <2 x i32> %n, %d
@@ -36,8 +33,7 @@ define i1 @test2(i32 %d) {
 
 define <2 x i1> @test2vec(<2 x i32> %d) {
 ; CHECK-LABEL: @test2vec(
-; CHECK-NEXT:    [[DIV:%.*]] = udiv <2 x i32> <i32 64, i32 63>, %d
-; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq <2 x i32> [[DIV]], zeroinitializer
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp ugt <2 x i32> %d, <i32 64, i32 63>
 ; CHECK-NEXT:    ret <2 x i1> [[CMP1]]
 ;
   %div = udiv <2 x i32> <i32 64, i32 63>, %d
@@ -57,8 +53,7 @@ define i1 @test3(i32 %n, i32 %d) {
 
 define <2 x i1> @test3vec(<2 x i32> %n, <2 x i32> %d) {
 ; CHECK-LABEL: @test3vec(
-; CHECK-NEXT:    [[DIV:%.*]] = udiv <2 x i32> %n, %d
-; CHECK-NEXT:    [[CMP1:%.*]] = icmp ne <2 x i32> [[DIV]], zeroinitializer
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp ule <2 x i32> %d, %n
 ; CHECK-NEXT:    ret <2 x i1> [[CMP1]]
 ;
   %div = udiv <2 x i32> %n, %d
@@ -78,8 +73,7 @@ define i1 @test4(i32 %d) {
 
 define <2 x i1> @test4vec(<2 x i32> %d) {
 ; CHECK-LABEL: @test4vec(
-; CHECK-NEXT:    [[DIV:%.*]] = udiv <2 x i32> <i32 64, i32 65>, %d
-; CHECK-NEXT:    [[CMP1:%.*]] = icmp ne <2 x i32> [[DIV]], zeroinitializer
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp ult <2 x i32> %d, <i32 65, i32 66>
 ; CHECK-NEXT:    ret <2 x i1> [[CMP1]]
 ;
   %div = udiv <2 x i32> <i32 64, i32 65>, %d
@@ -98,9 +92,7 @@ define i1 @test5(i32 %d) {
 
 define <2 x i1> @test5vec(<2 x i32> %d) {
 ; CHECK-LABEL: @test5vec(
-; CHECK-NEXT:    [[DIV:%.*]] = udiv <2 x i32> <i32 -1, i32 -1>, %d
-; CHECK-NEXT:    [[CMP1:%.*]] = icmp ne <2 x i32> [[DIV]], zeroinitializer
-; CHECK-NEXT:    ret <2 x i1> [[CMP1]]
+; CHECK-NEXT:    ret <2 x i1> <i1 true, i1 true>
 ;
   %div = udiv <2 x i32> <i32 -1, i32 -1>, %d
   %cmp1 = icmp ne <2 x i32> %div, zeroinitializer
@@ -119,8 +111,7 @@ define i1 @test6(i32 %d) {
 
 define <2 x i1> @test6vec(<2 x i32> %d) {
 ; CHECK-LABEL: @test6vec(
-; CHECK-NEXT:    [[DIV:%.*]] = udiv <2 x i32> <i32 5, i32 5>, %d
-; CHECK-NEXT:    [[CMP1:%.*]] = icmp ne <2 x i32> [[DIV]], zeroinitializer
+; CHECK-NEXT:    [[CMP1:%.*]] = icmp ult <2 x i32> %d, <i32 6, i32 6>
 ; CHECK-NEXT:    ret <2 x i1> [[CMP1]]
 ;
   %div = udiv <2 x i32> <i32 5, i32 5>, %d
@@ -157,6 +148,8 @@ define i1 @test8(i32 %d) {
   ret i1 %cmp1
 }
 
+; FIXME: Vectors should get the same folds as scalars for all tests.
+
 define <2 x i1> @test8vec(<2 x i32> %d) {
 ; CHECK-LABEL: @test8vec(
 ; CHECK-NEXT:    [[DIV:%.*]] = udiv <2 x i32> <i32 4, i32 4>, %d
index 7446734..a3c2beb 100644 (file)
@@ -177,9 +177,10 @@ define i1 @test13(i64 %X, %S* %P) {
 
 define <2 x i1> @test13_vector(<2 x i64> %X, <2 x %S*> %P) nounwind {
 ; CHECK-LABEL: @test13_vector(
-; CHECK-NEXT: shl nuw <2 x i64> %X, <i64 2, i64 2>
-; CHECK-NEXT: add <2 x i64> %A.idx, <i64 4, i64 4>
-; CHECK-NEXT: icmp eq <2 x i64> %A.offs, zeroinitializer
+; 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:    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
   %B = getelementptr inbounds %S, <2 x %S*> %P, <2 x i64> <i64 0, i64 0>, <2 x i32> <i32 0, i32 0>
   %C = icmp eq <2 x i32*> %A, %B
@@ -198,10 +199,10 @@ define i1 @test13_as1(i16 %X, %S addrspace(1)* %P) {
 
 define <2 x i1> @test13_vector_as1(<2 x i16> %X, <2 x %S addrspace(1)*> %P) {
 ; CHECK-LABEL: @test13_vector_as1(
-; CHECK-NEXT: shl nuw <2 x i16> %X, <i16 2, i16 2>
-; CHECK-NEXT: add <2 x i16> %A.idx, <i16 4, i16 4>
-; CHECK-NEXT: icmp eq <2 x i16> %A.offs, zeroinitializer
-; CHECK-NEXT: ret <2 x i1>
+; 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:    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
   %B = getelementptr inbounds %S, <2 x %S addrspace(1)*> %P, <2 x i16> <i16 0, i16 0>, <2 x i32> <i32 0, i32 0>
   %C = icmp eq <2 x i32 addrspace(1)*> %A, %B
index 3df7e50..78189c8 100644 (file)
@@ -110,12 +110,9 @@ define i1 @test11(i8 %A, i8 %B) {
   ret i1 %D
 }
 
-; FIXME: Vectors should get the same folds as scalars.
-
 define <2 x i1> @test11vec(<2 x i8> %A, <2 x i8> %B) {
 ; CHECK-LABEL: @test11vec(
-; CHECK-NEXT:    [[C:%.*]] = sub <2 x i8> %A, %B
-; CHECK-NEXT:    [[D:%.*]] = icmp ne <2 x i8> [[C]], zeroinitializer
+; CHECK-NEXT:    [[D:%.*]] = icmp ne <2 x i8> %A, %B
 ; CHECK-NEXT:    ret <2 x i1> [[D]]
 ;
   %C = sub <2 x i8> %A, %B
index 3441997..cd13777 100644 (file)
@@ -105,12 +105,9 @@ define i1 @test9(i8 %A) {
   ret i1 %C
 }
 
-; FIXME: Vectors should fold the same way.
-
 define <2 x i1> @test9vec(<2 x i8> %a) {
 ; CHECK-LABEL: @test9vec(
-; CHECK-NEXT:    [[B:%.*]] = xor <2 x i8> %a, <i8 123, i8 123>
-; CHECK-NEXT:    [[C:%.*]] = icmp eq <2 x i8> [[B]], <i8 34, i8 34>
+; CHECK-NEXT:    [[C:%.*]] = icmp eq <2 x i8> %a, <i8 89, i8 89>
 ; CHECK-NEXT:    ret <2 x i1> [[C]]
 ;
   %b = xor <2 x i8> %a, <i8 123, i8 123>
@@ -150,12 +147,9 @@ define i1 @test12(i8 %A) {
   ret i1 %c
 }
 
-; FIXME: Vectors should fold the same way.
-
 define <2 x i1> @test12vec(<2 x i8> %a) {
 ; CHECK-LABEL: @test12vec(
-; CHECK-NEXT:    [[B:%.*]] = xor <2 x i8> %a, <i8 4, i8 4>
-; CHECK-NEXT:    [[C:%.*]] = icmp ne <2 x i8> [[B]], zeroinitializer
+; CHECK-NEXT:    [[C:%.*]] = icmp ne <2 x i8> %a, <i8 4, i8 4>
 ; CHECK-NEXT:    ret <2 x i1> [[C]]
 ;
   %b = xor <2 x i8> %a, <i8 4, i8 4>