]> granicus.if.org Git - llvm/commitdiff
[InstCombine][InstSimplify] Teach decomposeBitTestICmp to look through truncate instr...
authorCraig Topper <craig.topper@intel.com>
Fri, 1 Sep 2017 21:27:34 +0000 (21:27 +0000)
committerCraig Topper <craig.topper@intel.com>
Fri, 1 Sep 2017 21:27:34 +0000 (21:27 +0000)
This patch teaches decomposeBitTestICmp to look through truncate instructions on the input to the compare. If a truncate is found it will now return the pre-truncated Value and appropriately extend the APInt mask.

This allows some code to be removed from InstSimplify that was doing this functionality.

This allows InstCombine's bit test combining code to match a pre-truncate Value with the same Value appear with an 'and' on another icmp. Or it allows us to combine a truncate to i16 and a truncate to i8. This also required removing the type check from the beginning of getMaskedTypeForICmpPair, but I believe that's ok because we still have to find two values from the input to each icmp that are equal before we'll do any transformation. So the type check was really just serving as an early out.

There was one user of decomposeBitTestICmp that didn't want to look through truncates, so I've added a flag to prevent that behavior when necessary.

Differential Revision: https://reviews.llvm.org/D37158

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@312382 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/Analysis/CmpInstAnalysis.h
lib/Analysis/CmpInstAnalysis.cpp
lib/Analysis/InstructionSimplify.cpp
lib/Transforms/InstCombine/InstCombineSelect.cpp
test/Transforms/InstCombine/bit-checks.ll

index 1079d5abc7f8a87540bbafbc3586ce149ce1aab4..3cc69d9fea29f33dd02d9c07dd6bd4f183b1d0f1 100644 (file)
@@ -64,7 +64,8 @@ namespace llvm {
   /// returned predicate is either == or !=. Returns false if decomposition
   /// fails.
   bool decomposeBitTestICmp(Value *LHS, Value *RHS, CmpInst::Predicate &Pred,
-                            Value *&X, APInt &Mask);
+                            Value *&X, APInt &Mask,
+                            bool LookThroughTrunc = true);
 
 } // end namespace llvm
 
index c879b8729dc3dd5aa7f9a4b6a5591b27eee13623..159c1a2d135ac9d594f3ab6a69c930f64f6becf6 100644 (file)
@@ -66,9 +66,11 @@ bool llvm::PredicatesFoldable(ICmpInst::Predicate p1, ICmpInst::Predicate p2) {
 
 bool llvm::decomposeBitTestICmp(Value *LHS, Value *RHS,
                                 CmpInst::Predicate &Pred,
-                                Value *&X, APInt &Mask) {
+                                Value *&X, APInt &Mask, bool LookThruTrunc) {
+  using namespace PatternMatch;
+
   const APInt *C;
-  if (!match(RHS, PatternMatch::m_APInt(C)))
+  if (!match(RHS, m_APInt(C)))
     return false;
 
   switch (Pred) {
@@ -132,6 +134,11 @@ bool llvm::decomposeBitTestICmp(Value *LHS, Value *RHS,
     break;
   }
 
-  X = LHS;
+  if (LookThruTrunc && match(LHS, m_Trunc(m_Value(X)))) {
+    Mask = Mask.zext(X->getType()->getScalarSizeInBits());
+  } else {
+    X = LHS;
+  }
+
   return true;
 }
index d155f6b4803d2df3d72c3b89f06b530d9f3a5c40..94d71817049be742d058fb3c1afaef47935f955a 100644 (file)
@@ -3629,19 +3629,6 @@ static Value *simplifySelectWithFakeICmpEq(Value *CmpLHS, Value *CmpRHS,
   if (!decomposeBitTestICmp(CmpLHS, CmpRHS, Pred, X, Mask))
     return nullptr;
 
-  unsigned BitWidth = TrueVal->getType()->getScalarSizeInBits();
-  if (!BitWidth)
-    return nullptr;
-
-  Value *ExtX;
-  if (match(X, m_Trunc(m_Value(ExtX))) &&
-      (ExtX == TrueVal || ExtX == FalseVal)) {
-    // icmp slt (trunc X), 0  <--> icmp ne (and X, C), 0
-    // icmp sgt (trunc X), -1 <--> icmp eq (and X, C), 0
-    X = ExtX;
-    Mask = Mask.zext(BitWidth);
-  }
-
   return simplifySelectBitTest(TrueVal, FalseVal, X, &Mask,
                                Pred == ICmpInst::ICMP_EQ);
 }
index 11602ab101e21b9e2c0114b5d951d8106c7879e2..83aeda5935e06a12add1db802b54ceac066e6886 100644 (file)
@@ -724,7 +724,7 @@ Instruction *InstCombiner::foldSelectInstWithICmp(SelectInst &SI,
       ICmpInst::Predicate Pred = ICI->getPredicate();
       Value *X;
       APInt Mask;
-      if (decomposeBitTestICmp(CmpLHS, CmpRHS, Pred, X, Mask)) {
+      if (decomposeBitTestICmp(CmpLHS, CmpRHS, Pred, X, Mask, false)) {
         if (Mask.isSignMask()) {
           assert(X == CmpLHS && "Expected to use the compare input directly");
           assert(ICmpInst::isEquality(Pred) && "Expected equality predicate");
index 3be67690431aea519e20a99a9f0c5cd3e715c982..1ecd305e807d90c85a863e7c7645b0bdaa925a77 100644 (file)
@@ -520,12 +520,9 @@ define i32 @main7g(i32 %argc, i32 %argc2, i32 %argc3, i32 %argc4, i32 %argc5) {
 
 define i32 @main8(i32 %argc) {
 ; CHECK-LABEL: @main8(
-; CHECK-NEXT:    [[AND:%.*]] = and i32 [[ARGC:%.*]], 64
-; CHECK-NEXT:    [[TOBOOL:%.*]] = icmp ne i32 [[AND]], 0
-; CHECK-NEXT:    [[TRUNC2:%.*]] = trunc i32 [[ARGC]] to i8
-; CHECK-NEXT:    [[TOBOOL3:%.*]] = icmp slt i8 [[TRUNC2]], 0
-; CHECK-NEXT:    [[OR_COND:%.*]] = or i1 [[TOBOOL]], [[TOBOOL3]]
-; CHECK-NEXT:    [[RETVAL_0:%.*]] = select i1 [[OR_COND]], i32 2, i32 1
+; CHECK-NEXT:    [[TMP1:%.*]] = and i32 [[ARGC:%.*]], 192
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 0
+; CHECK-NEXT:    [[RETVAL_0:%.*]] = select i1 [[TMP2]], i32 1, i32 2
 ; CHECK-NEXT:    ret i32 [[RETVAL_0]]
 ;
   %and = and i32 %argc, 64
@@ -539,12 +536,9 @@ define i32 @main8(i32 %argc) {
 
 define i32 @main9(i32 %argc) {
 ; CHECK-LABEL: @main9(
-; CHECK-NEXT:    [[AND:%.*]] = and i32 [[ARGC:%.*]], 64
-; CHECK-NEXT:    [[TOBOOL:%.*]] = icmp ne i32 [[AND]], 0
-; CHECK-NEXT:    [[TRUNC2:%.*]] = trunc i32 [[ARGC]] to i8
-; CHECK-NEXT:    [[TOBOOL3:%.*]] = icmp slt i8 [[TRUNC2]], 0
-; CHECK-NEXT:    [[OR_COND:%.*]] = and i1 [[TOBOOL]], [[TOBOOL3]]
-; CHECK-NEXT:    [[RETVAL_0:%.*]] = select i1 [[OR_COND]], i32 2, i32 1
+; CHECK-NEXT:    [[TMP1:%.*]] = and i32 [[ARGC:%.*]], 192
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 192
+; CHECK-NEXT:    [[RETVAL_0:%.*]] = select i1 [[TMP2]], i32 2, i32 1
 ; CHECK-NEXT:    ret i32 [[RETVAL_0]]
 ;
   %and = and i32 %argc, 64
@@ -558,12 +552,9 @@ define i32 @main9(i32 %argc) {
 
 define i32 @main10(i32 %argc) {
 ; CHECK-LABEL: @main10(
-; CHECK-NEXT:    [[AND:%.*]] = and i32 [[ARGC:%.*]], 64
-; CHECK-NEXT:    [[TOBOOL:%.*]] = icmp eq i32 [[AND]], 0
-; CHECK-NEXT:    [[TRUNC2:%.*]] = trunc i32 [[ARGC]] to i8
-; CHECK-NEXT:    [[TOBOOL3:%.*]] = icmp sgt i8 [[TRUNC2]], -1
-; CHECK-NEXT:    [[OR_COND:%.*]] = and i1 [[TOBOOL]], [[TOBOOL3]]
-; CHECK-NEXT:    [[RETVAL_0:%.*]] = select i1 [[OR_COND]], i32 2, i32 1
+; CHECK-NEXT:    [[TMP1:%.*]] = and i32 [[ARGC:%.*]], 192
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 0
+; CHECK-NEXT:    [[RETVAL_0:%.*]] = select i1 [[TMP2]], i32 2, i32 1
 ; CHECK-NEXT:    ret i32 [[RETVAL_0]]
 ;
   %and = and i32 %argc, 64
@@ -577,12 +568,9 @@ define i32 @main10(i32 %argc) {
 
 define i32 @main11(i32 %argc) {
 ; CHECK-LABEL: @main11(
-; CHECK-NEXT:    [[AND:%.*]] = and i32 [[ARGC:%.*]], 64
-; CHECK-NEXT:    [[TOBOOL:%.*]] = icmp eq i32 [[AND]], 0
-; CHECK-NEXT:    [[TRUNC2:%.*]] = trunc i32 [[ARGC]] to i8
-; CHECK-NEXT:    [[TOBOOL3:%.*]] = icmp sgt i8 [[TRUNC2]], -1
-; CHECK-NEXT:    [[OR_COND:%.*]] = or i1 [[TOBOOL]], [[TOBOOL3]]
-; CHECK-NEXT:    [[RETVAL_0:%.*]] = select i1 [[OR_COND]], i32 2, i32 1
+; CHECK-NEXT:    [[TMP1:%.*]] = and i32 [[ARGC:%.*]], 192
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 192
+; CHECK-NEXT:    [[RETVAL_0:%.*]] = select i1 [[TMP2]], i32 1, i32 2
 ; CHECK-NEXT:    ret i32 [[RETVAL_0]]
 ;
   %and = and i32 %argc, 64
@@ -596,12 +584,9 @@ define i32 @main11(i32 %argc) {
 
 define i32 @main12(i32 %argc) {
 ; CHECK-LABEL: @main12(
-; CHECK-NEXT:    [[TRUNC:%.*]] = trunc i32 [[ARGC:%.*]] to i16
-; CHECK-NEXT:    [[TOBOOL:%.*]] = icmp slt i16 [[TRUNC]], 0
-; CHECK-NEXT:    [[TRUNC2:%.*]] = trunc i32 [[ARGC]] to i8
-; CHECK-NEXT:    [[TOBOOL3:%.*]] = icmp slt i8 [[TRUNC2]], 0
-; CHECK-NEXT:    [[OR_COND:%.*]] = or i1 [[TOBOOL]], [[TOBOOL3]]
-; CHECK-NEXT:    [[RETVAL_0:%.*]] = select i1 [[OR_COND]], i32 2, i32 1
+; CHECK-NEXT:    [[TMP1:%.*]] = and i32 [[ARGC:%.*]], 32896
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 0
+; CHECK-NEXT:    [[RETVAL_0:%.*]] = select i1 [[TMP2]], i32 1, i32 2
 ; CHECK-NEXT:    ret i32 [[RETVAL_0]]
 ;
   %trunc = trunc i32 %argc to i16
@@ -615,12 +600,9 @@ define i32 @main12(i32 %argc) {
 
 define i32 @main13(i32 %argc) {
 ; CHECK-LABEL: @main13(
-; CHECK-NEXT:    [[TRUNC:%.*]] = trunc i32 [[ARGC:%.*]] to i16
-; CHECK-NEXT:    [[TOBOOL:%.*]] = icmp slt i16 [[TRUNC]], 0
-; CHECK-NEXT:    [[TRUNC2:%.*]] = trunc i32 [[ARGC]] to i8
-; CHECK-NEXT:    [[TOBOOL3:%.*]] = icmp slt i8 [[TRUNC2]], 0
-; CHECK-NEXT:    [[OR_COND:%.*]] = and i1 [[TOBOOL]], [[TOBOOL3]]
-; CHECK-NEXT:    [[RETVAL_0:%.*]] = select i1 [[OR_COND]], i32 2, i32 1
+; CHECK-NEXT:    [[TMP1:%.*]] = and i32 [[ARGC:%.*]], 32896
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 32896
+; CHECK-NEXT:    [[RETVAL_0:%.*]] = select i1 [[TMP2]], i32 2, i32 1
 ; CHECK-NEXT:    ret i32 [[RETVAL_0]]
 ;
   %trunc = trunc i32 %argc to i16
@@ -634,12 +616,9 @@ define i32 @main13(i32 %argc) {
 
 define i32 @main14(i32 %argc) {
 ; CHECK-LABEL: @main14(
-; CHECK-NEXT:    [[TRUNC:%.*]] = trunc i32 [[ARGC:%.*]] to i16
-; CHECK-NEXT:    [[TOBOOL:%.*]] = icmp sgt i16 [[TRUNC]], -1
-; CHECK-NEXT:    [[TRUNC2:%.*]] = trunc i32 [[ARGC]] to i8
-; CHECK-NEXT:    [[TOBOOL3:%.*]] = icmp sgt i8 [[TRUNC2]], -1
-; CHECK-NEXT:    [[OR_COND:%.*]] = and i1 [[TOBOOL]], [[TOBOOL3]]
-; CHECK-NEXT:    [[RETVAL_0:%.*]] = select i1 [[OR_COND]], i32 2, i32 1
+; CHECK-NEXT:    [[TMP1:%.*]] = and i32 [[ARGC:%.*]], 32896
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 0
+; CHECK-NEXT:    [[RETVAL_0:%.*]] = select i1 [[TMP2]], i32 2, i32 1
 ; CHECK-NEXT:    ret i32 [[RETVAL_0]]
 ;
   %trunc = trunc i32 %argc to i16
@@ -653,12 +632,9 @@ define i32 @main14(i32 %argc) {
 
 define i32 @main15(i32 %argc) {
 ; CHECK-LABEL: @main15(
-; CHECK-NEXT:    [[TRUNC:%.*]] = trunc i32 [[ARGC:%.*]] to i16
-; CHECK-NEXT:    [[TOBOOL:%.*]] = icmp sgt i16 [[TRUNC]], -1
-; CHECK-NEXT:    [[TRUNC2:%.*]] = trunc i32 [[ARGC]] to i8
-; CHECK-NEXT:    [[TOBOOL3:%.*]] = icmp sgt i8 [[TRUNC2]], -1
-; CHECK-NEXT:    [[OR_COND:%.*]] = or i1 [[TOBOOL]], [[TOBOOL3]]
-; CHECK-NEXT:    [[RETVAL_0:%.*]] = select i1 [[OR_COND]], i32 2, i32 1
+; CHECK-NEXT:    [[TMP1:%.*]] = and i32 [[ARGC:%.*]], 32896
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 32896
+; CHECK-NEXT:    [[RETVAL_0:%.*]] = select i1 [[TMP2]], i32 1, i32 2
 ; CHECK-NEXT:    ret i32 [[RETVAL_0]]
 ;
   %trunc = trunc i32 %argc to i16