]> granicus.if.org Git - llvm/commitdiff
[InstSimplify] try to eliminate icmp Pred (add nsw X, C1), C2
authorSanjay Patel <spatel@rotateright.com>
Tue, 24 Jan 2017 17:03:24 +0000 (17:03 +0000)
committerSanjay Patel <spatel@rotateright.com>
Tue, 24 Jan 2017 17:03:24 +0000 (17:03 +0000)
I was surprised to see that we're missing icmp folds based on 'add nsw' in InstCombine,
but we should handle the InstSimplify cases first because that could make the InstCombine
code simpler.

Here are Alive-based proofs for the logic:

Name: add_neg_constant
Pre: C1 < 0 && (C2 > ((1<<(width(C1)-1)) + C1))
%a = add nsw i7 %x, C1
%b = icmp sgt %a, C2
  =>
%b = false

Name: add_pos_constant
Pre: C1 > 0 && (C2 < ((1<<(width(C1)-1)) + C1 - 1))
%a = add nsw i6 %x, C1
%b = icmp slt %a, C2
  =>
%b = false

Name: nuw
Pre: C1 u>= C2
%a = add nuw i11 %x, C1
%b = icmp ult %a, C2
  =>
%b = false

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

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

lib/Analysis/InstructionSimplify.cpp
test/Transforms/InstSimplify/icmp-constant.ll

index 5245b4914de9084e41623b847a935c4e3b53971c..fc0b86aaa395973a55ebc80deea7329b76a24f29 100644 (file)
@@ -2385,9 +2385,23 @@ static void setLimitsForBinOp(BinaryOperator &BO, APInt &Lower, APInt &Upper) {
   const APInt *C;
   switch (BO.getOpcode()) {
   case Instruction::Add:
-    if (BO.hasNoUnsignedWrap() && match(BO.getOperand(1), m_APInt(C)))
-      // 'add nuw x, C' produces [C, UINT_MAX].
-      Lower = *C;
+    if (match(BO.getOperand(1), m_APInt(C)) && *C != 0) {
+      // FIXME: If we have both nuw and nsw, we should reduce the range further.
+      if (BO.hasNoUnsignedWrap()) {
+        // 'add nuw x, C' produces [C, UINT_MAX].
+        Lower = *C;
+      } else if (BO.hasNoSignedWrap()) {
+        if (C->isNegative()) {
+          // 'add nsw x, -C' produces [SINT_MIN, SINT_MAX - C].
+          Lower = APInt::getSignedMinValue(Width);
+          Upper = APInt::getSignedMaxValue(Width) + *C + 1;
+        } else {
+          // 'add nsw x, +C' produces [SINT_MIN + C, SINT_MAX].
+          Lower = APInt::getSignedMinValue(Width) + *C;
+          Upper = APInt::getSignedMaxValue(Width) + 1;
+        }
+      }
+    }
     break;
 
   case Instruction::And:
index 3df8425035a476daf57102d8039e9336e49997b2..918722299b592776d8ea7be013208c0566160154 100644 (file)
@@ -420,9 +420,7 @@ define <2 x i1> @tautological9_vec(<2 x i32> %x) {
 
 define i1 @add_nsw_neg_const1(i32 %x) {
 ; CHECK-LABEL: @add_nsw_neg_const1(
-; CHECK-NEXT:    [[ADD:%.*]] = add nsw i32 %x, -2147483647
-; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[ADD]], 0
-; CHECK-NEXT:    ret i1 [[CMP]]
+; CHECK-NEXT:    ret i1 false
 ;
   %add = add nsw i32 %x, -2147483647
   %cmp = icmp sgt i32 %add, 0
@@ -446,9 +444,7 @@ define i1 @add_nsw_neg_const2(i32 %x) {
 
 define i1 @add_nsw_neg_const3(i32 %x) {
 ; CHECK-LABEL: @add_nsw_neg_const3(
-; CHECK-NEXT:    [[ADD:%.*]] = add nsw i32 %x, -2147483646
-; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[ADD]], 1
-; CHECK-NEXT:    ret i1 [[CMP]]
+; CHECK-NEXT:    ret i1 false
 ;
   %add = add nsw i32 %x, -2147483646
   %cmp = icmp sgt i32 %add, 1
@@ -472,9 +468,7 @@ define i1 @add_nsw_neg_const4(i32 %x) {
 
 define i1 @add_nsw_neg_const5(i32 %x) {
 ; CHECK-LABEL: @add_nsw_neg_const5(
-; CHECK-NEXT:    [[ADD:%.*]] = add nsw i32 %x, -42
-; CHECK-NEXT:    [[CMP:%.*]] = icmp ne i32 [[ADD]], 2147483606
-; CHECK-NEXT:    ret i1 [[CMP]]
+; CHECK-NEXT:    ret i1 true
 ;
   %add = add nsw i32 %x, -42
   %cmp = icmp ne i32 %add, 2147483606
@@ -498,9 +492,7 @@ define i1 @add_nsw_neg_const6(i32 %x) {
 
 define i1 @add_nsw_pos_const1(i32 %x) {
 ; CHECK-LABEL: @add_nsw_pos_const1(
-; CHECK-NEXT:    [[ADD:%.*]] = add nsw i32 %x, 2147483647
-; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[ADD]], -1
-; CHECK-NEXT:    ret i1 [[CMP]]
+; CHECK-NEXT:    ret i1 false
 ;
   %add = add nsw i32 %x, 2147483647
   %cmp = icmp slt i32 %add, -1
@@ -524,9 +516,7 @@ define i1 @add_nsw_pos_const2(i32 %x) {
 
 define i1 @add_nsw_pos_const3(i32 %x) {
 ; CHECK-LABEL: @add_nsw_pos_const3(
-; CHECK-NEXT:    [[ADD:%.*]] = add nsw i32 %x, 2147483646
-; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[ADD]], -2
-; CHECK-NEXT:    ret i1 [[CMP]]
+; CHECK-NEXT:    ret i1 false
 ;
   %add = add nsw i32 %x, 2147483646
   %cmp = icmp slt i32 %add, -2
@@ -550,9 +540,7 @@ define i1 @add_nsw_pos_const4(i32 %x) {
 
 define i1 @add_nsw_pos_const5(i32 %x) {
 ; CHECK-LABEL: @add_nsw_pos_const5(
-; CHECK-NEXT:    [[ADD:%.*]] = add nsw i32 %x, 42
-; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[ADD]], -2147483607
-; CHECK-NEXT:    ret i1 [[CMP]]
+; CHECK-NEXT:    ret i1 false
 ;
   %add = add nsw i32 %x, 42
   %cmp = icmp eq i32 %add, -2147483607
@@ -576,9 +564,7 @@ define i1 @add_nsw_pos_const6(i32 %x) {
 
 define <2 x i1> @add_nsw_pos_const5_splat_vec(<2 x i32> %x) {
 ; CHECK-LABEL: @add_nsw_pos_const5_splat_vec(
-; CHECK-NEXT:    [[ADD:%.*]] = add nsw <2 x i32> %x, <i32 42, i32 42>
-; CHECK-NEXT:    [[CMP:%.*]] = icmp ne <2 x i32> [[ADD]], <i32 -2147483607, i32 -2147483607>
-; CHECK-NEXT:    ret <2 x i1> [[CMP]]
+; CHECK-NEXT:    ret <2 x i1> <i1 true, i1 true>
 ;
   %add = add nsw <2 x i32> %x, <i32 42, i32 42>
   %cmp = icmp ne <2 x i32> %add, <i32 -2147483607, i32 -2147483607>