[llvm] r312382 - [InstCombine][InstSimplify] Teach decomposeBitTestICmp to look through truncate instructions

Craig Topper via llvm-commits llvm-commits at lists.llvm.org
Fri Sep 1 14:27:34 PDT 2017


Author: ctopper
Date: Fri Sep  1 14:27:34 2017
New Revision: 312382

URL: http://llvm.org/viewvc/llvm-project?rev=312382&view=rev
Log:
[InstCombine][InstSimplify] Teach decomposeBitTestICmp to look through truncate instructions

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

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

Modified: llvm/trunk/include/llvm/Analysis/CmpInstAnalysis.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/CmpInstAnalysis.h?rev=312382&r1=312381&r2=312382&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Analysis/CmpInstAnalysis.h (original)
+++ llvm/trunk/include/llvm/Analysis/CmpInstAnalysis.h Fri Sep  1 14:27:34 2017
@@ -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
 

Modified: llvm/trunk/lib/Analysis/CmpInstAnalysis.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/CmpInstAnalysis.cpp?rev=312382&r1=312381&r2=312382&view=diff
==============================================================================
--- llvm/trunk/lib/Analysis/CmpInstAnalysis.cpp (original)
+++ llvm/trunk/lib/Analysis/CmpInstAnalysis.cpp Fri Sep  1 14:27:34 2017
@@ -66,9 +66,11 @@ bool llvm::PredicatesFoldable(ICmpInst::
 
 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 *L
     break;
   }
 
-  X = LHS;
+  if (LookThruTrunc && match(LHS, m_Trunc(m_Value(X)))) {
+    Mask = Mask.zext(X->getType()->getScalarSizeInBits());
+  } else {
+    X = LHS;
+  }
+
   return true;
 }

Modified: llvm/trunk/lib/Analysis/InstructionSimplify.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/InstructionSimplify.cpp?rev=312382&r1=312381&r2=312382&view=diff
==============================================================================
--- llvm/trunk/lib/Analysis/InstructionSimplify.cpp (original)
+++ llvm/trunk/lib/Analysis/InstructionSimplify.cpp Fri Sep  1 14:27:34 2017
@@ -3629,19 +3629,6 @@ static Value *simplifySelectWithFakeICmp
   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);
 }

Modified: llvm/trunk/lib/Transforms/InstCombine/InstCombineSelect.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/InstCombine/InstCombineSelect.cpp?rev=312382&r1=312381&r2=312382&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/InstCombine/InstCombineSelect.cpp (original)
+++ llvm/trunk/lib/Transforms/InstCombine/InstCombineSelect.cpp Fri Sep  1 14:27:34 2017
@@ -724,7 +724,7 @@ Instruction *InstCombiner::foldSelectIns
       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");

Modified: llvm/trunk/test/Transforms/InstCombine/bit-checks.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/bit-checks.ll?rev=312382&r1=312381&r2=312382&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/bit-checks.ll (original)
+++ llvm/trunk/test/Transforms/InstCombine/bit-checks.ll Fri Sep  1 14:27:34 2017
@@ -520,12 +520,9 @@ define i32 @main7g(i32 %argc, i32 %argc2
 
 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




More information about the llvm-commits mailing list