[llvm] r310893 - [InstSimplify] Teach decomposeBitTestICmp to handle non-canonical compares

Craig Topper via llvm-commits llvm-commits at lists.llvm.org
Mon Aug 14 15:11:43 PDT 2017


Author: ctopper
Date: Mon Aug 14 15:11:43 2017
New Revision: 310893

URL: http://llvm.org/viewvc/llvm-project?rev=310893&view=rev
Log:
[InstSimplify] Teach decomposeBitTestICmp to handle non-canonical compares

This adds support non-canonical compare predicates. InstSimplify can't rely on canonicalization to have occurred.

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

Modified:
    llvm/trunk/lib/Analysis/CmpInstAnalysis.cpp
    llvm/trunk/test/Transforms/InstSimplify/select.ll

Modified: llvm/trunk/lib/Analysis/CmpInstAnalysis.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/CmpInstAnalysis.cpp?rev=310893&r1=310892&r2=310893&view=diff
==============================================================================
--- llvm/trunk/lib/Analysis/CmpInstAnalysis.cpp (original)
+++ llvm/trunk/lib/Analysis/CmpInstAnalysis.cpp Mon Aug 14 15:11:43 2017
@@ -81,6 +81,13 @@ bool llvm::decomposeBitTestICmp(Value *L
     Mask = APInt::getSignMask(C->getBitWidth());
     Pred = ICmpInst::ICMP_NE;
     break;
+  case ICmpInst::ICMP_SLE:
+    // X <= -1 is equivalent to (X & SignMask) != 0.
+    if (!C->isAllOnesValue())
+      return false;
+    Mask = APInt::getSignMask(C->getBitWidth());
+    Pred = ICmpInst::ICMP_NE;
+    break;
   case ICmpInst::ICMP_SGT:
     // X > -1 is equivalent to (X & SignMask) == 0.
     if (!C->isAllOnesValue())
@@ -88,6 +95,13 @@ bool llvm::decomposeBitTestICmp(Value *L
     Mask = APInt::getSignMask(C->getBitWidth());
     Pred = ICmpInst::ICMP_EQ;
     break;
+  case ICmpInst::ICMP_SGE:
+    // X >= 0 is equivalent to (X & SignMask) == 0.
+    if (!C->isNullValue())
+      return false;
+    Mask = APInt::getSignMask(C->getBitWidth());
+    Pred = ICmpInst::ICMP_EQ;
+    break;
   case ICmpInst::ICMP_ULT:
     // X <u 2^n is equivalent to (X & ~(2^n-1)) == 0.
     if (!C->isPowerOf2())
@@ -95,6 +109,13 @@ bool llvm::decomposeBitTestICmp(Value *L
     Mask = -*C;
     Pred = ICmpInst::ICMP_EQ;
     break;
+  case ICmpInst::ICMP_ULE:
+    // X <=u 2^n-1 is equivalent to (X & ~(2^n-1)) == 0.
+    if (!(*C + 1).isPowerOf2())
+      return false;
+    Mask = ~*C;
+    Pred = ICmpInst::ICMP_EQ;
+    break;
   case ICmpInst::ICMP_UGT:
     // X >u 2^n-1 is equivalent to (X & ~(2^n-1)) != 0.
     if (!(*C + 1).isPowerOf2())
@@ -102,6 +123,13 @@ bool llvm::decomposeBitTestICmp(Value *L
     Mask = ~*C;
     Pred = ICmpInst::ICMP_NE;
     break;
+  case ICmpInst::ICMP_UGE:
+    // X >=u 2^n is equivalent to (X & ~(2^n-1)) != 0.
+    if (!C->isPowerOf2())
+      return false;
+    Mask = -*C;
+    Pred = ICmpInst::ICMP_NE;
+    break;
   }
 
   X = LHS;

Modified: llvm/trunk/test/Transforms/InstSimplify/select.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstSimplify/select.ll?rev=310893&r1=310892&r2=310893&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/InstSimplify/select.ll (original)
+++ llvm/trunk/test/Transforms/InstSimplify/select.ll Mon Aug 14 15:11:43 2017
@@ -47,13 +47,10 @@ define i32 @test4(i32 %X) {
 }
 
 ; Same as above, but the compare isn't canonical
-; TODO: we should be able to simplify this
 define i32 @test4noncanon(i32 %X) {
 ; CHECK-LABEL: @test4noncanon(
-; CHECK-NEXT:    [[CMP:%.*]] = icmp sle i32 [[X:%.*]], -1
-; CHECK-NEXT:    [[OR:%.*]] = or i32 [[X]], -2147483648
-; CHECK-NEXT:    [[COND:%.*]] = select i1 [[CMP]], i32 [[X]], i32 [[OR]]
-; CHECK-NEXT:    ret i32 [[COND]]
+; CHECK-NEXT:    [[OR:%.*]] = or i32 [[X:%.*]], -2147483648
+; CHECK-NEXT:    ret i32 [[OR]]
 ;
   %cmp = icmp sle i32 %X, -1
   %or = or i32 %X, -2147483648
@@ -114,13 +111,10 @@ define i32 @test9(i32 %X) {
 }
 
 ; Same as above, but the compare isn't canonical
-; TODO: we should be able to simplify this
 define i32 @test9noncanon(i32 %X) {
 ; CHECK-LABEL: @test9noncanon(
-; CHECK-NEXT:    [[CMP:%.*]] = icmp sge i32 [[X:%.*]], 0
-; CHECK-NEXT:    [[OR:%.*]] = or i32 [[X]], -2147483648
-; CHECK-NEXT:    [[COND:%.*]] = select i1 [[CMP]], i32 [[OR]], i32 [[X]]
-; CHECK-NEXT:    ret i32 [[COND]]
+; CHECK-NEXT:    [[OR:%.*]] = or i32 [[X:%.*]], -2147483648
+; CHECK-NEXT:    ret i32 [[OR]]
 ;
   %cmp = icmp sge i32 %X, 0
   %or = or i32 %X, -2147483648
@@ -172,13 +166,10 @@ define i32 @test12(i32 %X) {
 }
 
 ; Same as above, but the compare isn't canonical
-; TODO: we should be able to simplify this
 define i32 @test12noncanon(i32 %X) {
 ; CHECK-LABEL: @test12noncanon(
-; CHECK-NEXT:    [[CMP:%.*]] = icmp ule i32 [[X:%.*]], 3
-; CHECK-NEXT:    [[AND:%.*]] = and i32 [[X]], 3
-; CHECK-NEXT:    [[COND:%.*]] = select i1 [[CMP]], i32 [[X]], i32 [[AND]]
-; CHECK-NEXT:    ret i32 [[COND]]
+; CHECK-NEXT:    [[AND:%.*]] = and i32 [[X:%.*]], 3
+; CHECK-NEXT:    ret i32 [[AND]]
 ;
   %cmp = icmp ule i32 %X, 3
   %and = and i32 %X, 3
@@ -198,13 +189,10 @@ define i32 @test13(i32 %X) {
 }
 
 ; Same as above, but the compare isn't canonical
-; TODO: we should be able to simplify this
 define i32 @test13noncanon(i32 %X) {
 ; CHECK-LABEL: @test13noncanon(
-; CHECK-NEXT:    [[CMP:%.*]] = icmp uge i32 [[X:%.*]], 4
-; CHECK-NEXT:    [[AND:%.*]] = and i32 [[X]], 3
-; CHECK-NEXT:    [[COND:%.*]] = select i1 [[CMP]], i32 [[AND]], i32 [[X]]
-; CHECK-NEXT:    ret i32 [[COND]]
+; CHECK-NEXT:    [[AND:%.*]] = and i32 [[X:%.*]], 3
+; CHECK-NEXT:    ret i32 [[AND]]
 ;
   %cmp = icmp uge i32 %X, 4
   %and = and i32 %X, 3




More information about the llvm-commits mailing list