[llvm] r277629 - [InstCombine] use m_APInt to allow icmp (binop X, Y), C folds with constant splat vectors

Sanjay Patel via llvm-commits llvm-commits at lists.llvm.org
Wed Aug 3 11:59:03 PDT 2016


Author: spatel
Date: Wed Aug  3 13:59:03 2016
New Revision: 277629

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

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.


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

Modified: llvm/trunk/lib/Transforms/InstCombine/InstCombineCompares.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/InstCombine/InstCombineCompares.cpp?rev=277629&r1=277628&r2=277629&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/InstCombine/InstCombineCompares.cpp (original)
+++ llvm/trunk/lib/Transforms/InstCombine/InstCombineCompares.cpp Wed Aug  3 13:59:03 2016
@@ -2203,22 +2203,23 @@ Instruction *InstCombiner::foldICmpWithC
 /// 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::foldICmpEqual
     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::foldICmpEqual
         // 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::foldICmpEqual
     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::foldICmpEqual
   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::foldICmpEqual
     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::foldICmpEqual
       }
 
       // ((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::foldICmpEqual
     }
     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::foldICmpEqual
     }
     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;

Modified: llvm/trunk/test/Transforms/InstCombine/add.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/add.ll?rev=277629&r1=277628&r2=277629&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/add.ll (original)
+++ llvm/trunk/test/Transforms/InstCombine/add.ll Wed Aug  3 13:59:03 2016
@@ -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>

Modified: llvm/trunk/test/Transforms/InstCombine/compare-udiv.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/compare-udiv.ll?rev=277629&r1=277628&r2=277629&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/compare-udiv.ll (original)
+++ llvm/trunk/test/Transforms/InstCombine/compare-udiv.ll Wed Aug  3 13:59:03 2016
@@ -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

Modified: llvm/trunk/test/Transforms/InstCombine/getelementptr.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/getelementptr.ll?rev=277629&r1=277628&r2=277629&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/getelementptr.ll (original)
+++ llvm/trunk/test/Transforms/InstCombine/getelementptr.ll Wed Aug  3 13:59:03 2016
@@ -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 addrspa
 
 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

Modified: llvm/trunk/test/Transforms/InstCombine/sub.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/sub.ll?rev=277629&r1=277628&r2=277629&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/sub.ll (original)
+++ llvm/trunk/test/Transforms/InstCombine/sub.ll Wed Aug  3 13:59:03 2016
@@ -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

Modified: llvm/trunk/test/Transforms/InstCombine/xor.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/xor.ll?rev=277629&r1=277628&r2=277629&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/xor.ll (original)
+++ llvm/trunk/test/Transforms/InstCombine/xor.ll Wed Aug  3 13:59:03 2016
@@ -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>




More information about the llvm-commits mailing list