[llvm] 1376301 - [InstCombine] Canonicalize range test idiom

Nikita Popov via llvm-commits llvm-commits at lists.llvm.org
Mon Nov 8 12:15:52 PST 2021


Author: Nikita Popov
Date: 2021-11-08T21:15:46+01:00
New Revision: 1376301c87274bccf5565eb892173442782b1de3

URL: https://github.com/llvm/llvm-project/commit/1376301c87274bccf5565eb892173442782b1de3
DIFF: https://github.com/llvm/llvm-project/commit/1376301c87274bccf5565eb892173442782b1de3.diff

LOG: [InstCombine] Canonicalize range test idiom

InstCombine converts range tests of the form (X > C1 && X < C2) or
(X < C1 || X > C2) into checks of the form (X + C3 < C4) or
(X + C3 > C4). It is possible to express all range tests in either
of these forms (with different choices of constants), but currently
neither of them is considered canonical. We may have equivalent
range tests using either ult or ugt.

This proposes to canonicalize all range tests to use ult. An
alternative would be to canonicalize to either ult or ugt depending
on the specific constants involved -- e.g. in practice we currently
generate ult for && style ranges and ugt for || style ranges when
going through the insertRangeTest() helper. In fact, the "clamp like"
fold was relying on this, which is why I had to tweak it to not
assume whether inversion is needed based on just the predicate.

Proof: https://alive2.llvm.org/ce/z/_SP_rQ

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

Added: 
    

Modified: 
    llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
    llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
    llvm/test/CodeGen/BPF/adjust-opt-icmp1.ll
    llvm/test/CodeGen/BPF/adjust-opt-icmp2.ll
    llvm/test/Transforms/InstCombine/2006-12-15-Range-Test.ll
    llvm/test/Transforms/InstCombine/2007-03-21-SignedRangeTest.ll
    llvm/test/Transforms/InstCombine/2008-08-05-And.ll
    llvm/test/Transforms/InstCombine/and-or-icmps.ll
    llvm/test/Transforms/InstCombine/canonicalize-signed-truncation-check.ll
    llvm/test/Transforms/InstCombine/icmp-add.ll
    llvm/test/Transforms/InstCombine/icmp-sub.ll
    llvm/test/Transforms/InstCombine/icmp-topbitssame.ll
    llvm/test/Transforms/InstCombine/load-cmp.ll
    llvm/test/Transforms/InstCombine/minmax-fold.ll
    llvm/test/Transforms/InstCombine/or.ll
    llvm/test/Transforms/InstCombine/overflow.ll
    llvm/test/Transforms/InstCombine/smulo.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
index 5dad6b9940c61..b697ddd37aa03 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
@@ -2748,6 +2748,14 @@ Instruction *InstCombinerImpl::foldICmpAddConstant(ICmpInst &Cmp,
     return new ICmpInst(ICmpInst::ICMP_NE, Builder.CreateAnd(X, ~C),
                         ConstantExpr::getNeg(cast<Constant>(Y)));
 
+  // The range test idiom can use either ult or ugt. Arbitrarily canonicalize
+  // to the ult form.
+  // X+C2 >u C -> X+(C2-C-1) <u ~C
+  if (Pred == ICmpInst::ICMP_UGT)
+    return new ICmpInst(ICmpInst::ICMP_ULT,
+                        Builder.CreateAdd(X, ConstantInt::get(Ty, *C2 - C - 1)),
+                        ConstantInt::get(Ty, ~C));
+
   return nullptr;
 }
 

diff  --git a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
index 6ce4dc941c5a2..4a1e82ae9c1d0 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
@@ -1298,15 +1298,23 @@ static Value *canonicalizeClampLike(SelectInst &Sel0, ICmpInst &Cmp0,
   // Said condition must be one-use.
   if (!Cmp0.hasOneUse())
     return nullptr;
+  ICmpInst::Predicate Pred0 = Cmp0.getPredicate();
   Value *Cmp00 = Cmp0.getOperand(0);
   Constant *C0;
   if (!match(Cmp0.getOperand(1),
              m_CombineAnd(m_AnyIntegralConstant(), m_Constant(C0))))
     return nullptr;
-  // Canonicalize Cmp0 into the form we expect.
+
+  if (!isa<SelectInst>(Sel1)) {
+    Pred0 = ICmpInst::getInversePredicate(Pred0);
+    std::swap(X, Sel1);
+  }
+
+  // Canonicalize Cmp0 into ult or uge.
   // FIXME: we shouldn't care about lanes that are 'undef' in the end?
-  switch (Cmp0.getPredicate()) {
+  switch (Pred0) {
   case ICmpInst::Predicate::ICMP_ULT:
+  case ICmpInst::Predicate::ICMP_UGE:
     // Although icmp ult %x, 0 is an unusual thing to try and should generally
     // have been simplified, it does not verify with undef inputs so ensure we
     // are not in a strange state.
@@ -1316,25 +1324,16 @@ static Value *canonicalizeClampLike(SelectInst &Sel0, ICmpInst &Cmp0,
       return nullptr;
     break; // Great!
   case ICmpInst::Predicate::ICMP_ULE:
-    // We'd have to increment C0 by one, and for that it must not have all-ones
-    // element, but then it would have been canonicalized to 'ult' before
-    // we get here. So we can't do anything useful with 'ule'.
-    return nullptr;
   case ICmpInst::Predicate::ICMP_UGT:
-    // We want to canonicalize it to 'ult', so we'll need to increment C0,
-    // which again means it must not have any all-ones elements.
+    // We want to canonicalize it to 'ult' or 'uge', so we'll need to increment
+    // C0, which again means it must not have any all-ones elements.
     if (!match(C0,
                m_SpecificInt_ICMP(
                    ICmpInst::Predicate::ICMP_NE,
                    APInt::getAllOnes(C0->getType()->getScalarSizeInBits()))))
       return nullptr; // Can't do, have all-ones element[s].
     C0 = InstCombiner::AddOne(C0);
-    std::swap(X, Sel1);
     break;
-  case ICmpInst::Predicate::ICMP_UGE:
-    // The only way we'd get this predicate if this `icmp` has extra uses,
-    // but then we won't be able to do this fold.
-    return nullptr;
   default:
     return nullptr; // Unknown predicate.
   }
@@ -1407,6 +1406,8 @@ static Value *canonicalizeClampLike(SelectInst &Sel0, ICmpInst &Cmp0,
   // The thresholds of this clamp-like pattern.
   auto *ThresholdLowIncl = ConstantExpr::getNeg(C1);
   auto *ThresholdHighExcl = ConstantExpr::getSub(C0, C1);
+  if (Pred0 == ICmpInst::Predicate::ICMP_UGE)
+    std::swap(ThresholdLowIncl, ThresholdHighExcl);
 
   // The fold has a precondition 1: C2 s>= ThresholdLow
   auto *Precond1 = ConstantExpr::getICmp(ICmpInst::Predicate::ICMP_SGE, C2,

diff  --git a/llvm/test/CodeGen/BPF/adjust-opt-icmp1.ll b/llvm/test/CodeGen/BPF/adjust-opt-icmp1.ll
index 6eea4d2f4618c..a2e1b03b711ab 100644
--- a/llvm/test/CodeGen/BPF/adjust-opt-icmp1.ll
+++ b/llvm/test/CodeGen/BPF/adjust-opt-icmp1.ll
@@ -39,10 +39,11 @@ entry:
 ; CHECK:         if [[REG2]] s> [[REG1]] goto
 ; CHECK:         if [[REG1]] s> 7 goto
 
-; CHECK-DISABLE: [[REG1:r[0-9]+]] += -1
+; CHECK-DISABLE: [[REG1:r[0-9]+]] += -8
 ; CHECK-DISABLE: [[REG1]] <<= 32
 ; CHECK-DISABLE: [[REG1]] >>= 32
-; CHECK-DISABLE: if [[REG1]] > 6 goto
+; CHECK-DISABLE: [[REG2:r[0-9]+]] = 4294967289
+; CHECK-DISABLE: if [[REG2]] > [[REG1]] goto
 
 lor.lhs.false:                                    ; preds = %entry
   %2 = load i32, i32* %ret, align 4, !tbaa !2

diff  --git a/llvm/test/CodeGen/BPF/adjust-opt-icmp2.ll b/llvm/test/CodeGen/BPF/adjust-opt-icmp2.ll
index a264422d2b762..61071f50d8506 100644
--- a/llvm/test/CodeGen/BPF/adjust-opt-icmp2.ll
+++ b/llvm/test/CodeGen/BPF/adjust-opt-icmp2.ll
@@ -37,10 +37,11 @@ entry:
 ; CHECK:         if [[REG2]] s> [[REG1]] goto
 ; CHECK:         if [[REG1]] s> 7 goto
 
-; CHECK-DISABLE: [[REG1:r[0-9]+]] += -1
+; CHECK-DISABLE: [[REG1:r[0-9]+]] += -8
 ; CHECK-DISABLE: [[REG1]] <<= 32
 ; CHECK-DISABLE: [[REG1]] >>= 32
-; CHECK-DISABLE: if [[REG1]] > 6 goto
+; CHECK-DISABLE: [[REG2:r[0-9]+]] = 4294967289
+; CHECK-DISABLE: if [[REG2]] > [[REG1]] goto
 
 if.then:                                          ; preds = %entry
   store i32 0, i32* %retval, align 4

diff  --git a/llvm/test/Transforms/InstCombine/2006-12-15-Range-Test.ll b/llvm/test/Transforms/InstCombine/2006-12-15-Range-Test.ll
index 3d08ae5e4012a..6b83408ed7e09 100644
--- a/llvm/test/Transforms/InstCombine/2006-12-15-Range-Test.ll
+++ b/llvm/test/Transforms/InstCombine/2006-12-15-Range-Test.ll
@@ -18,9 +18,9 @@ define i1 @print_pgm_cond_true(i32 %tmp12.reload, i32* %tmp16.out) {
 ; CHECK:       cond_true:
 ; CHECK-NEXT:    [[TMP15:%.*]] = getelementptr [17 x i32], [17 x i32]* @r, i32 0, i32 [[TMP12_RELOAD:%.*]]
 ; CHECK-NEXT:    [[TMP16]] = load i32, i32* [[TMP15]], align 4
-; CHECK-NEXT:    [[TMP16_OFF:%.*]] = add i32 [[TMP16]], 31
-; CHECK-NEXT:    [[TMP0:%.*]] = icmp ugt i32 [[TMP16_OFF]], 62
-; CHECK-NEXT:    br i1 [[TMP0]], label [[BB27_EXITSTUB:%.*]], label [[COND_NEXT23_EXITSTUB:%.*]]
+; CHECK-NEXT:    [[TMP0:%.*]] = add i32 [[TMP16]], -32
+; CHECK-NEXT:    [[TMP1:%.*]] = icmp ult i32 [[TMP0]], -63
+; CHECK-NEXT:    br i1 [[TMP1]], label [[BB27_EXITSTUB:%.*]], label [[COND_NEXT23_EXITSTUB:%.*]]
 ;
 newFuncRoot:
   br label %cond_true
@@ -55,9 +55,9 @@ define i1 @print_pgm_cond_true_logical(i32 %tmp12.reload, i32* %tmp16.out) {
 ; CHECK:       cond_true:
 ; CHECK-NEXT:    [[TMP15:%.*]] = getelementptr [17 x i32], [17 x i32]* @r, i32 0, i32 [[TMP12_RELOAD:%.*]]
 ; CHECK-NEXT:    [[TMP16]] = load i32, i32* [[TMP15]], align 4
-; CHECK-NEXT:    [[TMP16_OFF:%.*]] = add i32 [[TMP16]], 31
-; CHECK-NEXT:    [[TMP0:%.*]] = icmp ugt i32 [[TMP16_OFF]], 62
-; CHECK-NEXT:    br i1 [[TMP0]], label [[BB27_EXITSTUB:%.*]], label [[COND_NEXT23_EXITSTUB:%.*]]
+; CHECK-NEXT:    [[TMP0:%.*]] = add i32 [[TMP16]], -32
+; CHECK-NEXT:    [[TMP1:%.*]] = icmp ult i32 [[TMP0]], -63
+; CHECK-NEXT:    br i1 [[TMP1]], label [[BB27_EXITSTUB:%.*]], label [[COND_NEXT23_EXITSTUB:%.*]]
 ;
 newFuncRoot:
   br label %cond_true

diff  --git a/llvm/test/Transforms/InstCombine/2007-03-21-SignedRangeTest.ll b/llvm/test/Transforms/InstCombine/2007-03-21-SignedRangeTest.ll
index ffcfe2683cf1d..a7040bbaa0c9b 100644
--- a/llvm/test/Transforms/InstCombine/2007-03-21-SignedRangeTest.ll
+++ b/llvm/test/Transforms/InstCombine/2007-03-21-SignedRangeTest.ll
@@ -5,9 +5,9 @@
 
 define i1 @test(i32 %tmp6) {
 ; CHECK-LABEL: @test(
-; CHECK-NEXT:    [[TMP6_OFF:%.*]] = add i32 %tmp6, 83
-; CHECK-NEXT:    [[TMP1:%.*]] = icmp ugt i32 [[TMP6_OFF]], 11
-; CHECK-NEXT:    ret i1 [[TMP1]]
+; CHECK-NEXT:    [[TMP1:%.*]] = add i32 [[TMP6:%.*]], 71
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp ult i32 [[TMP1]], -12
+; CHECK-NEXT:    ret i1 [[TMP2]]
 ;
   %tmp7 = sdiv i32 %tmp6, 12
   icmp ne i32 %tmp7, -6
@@ -16,9 +16,9 @@ define i1 @test(i32 %tmp6) {
 
 define <2 x i1> @test_vec(<2 x i32> %tmp6) {
 ; CHECK-LABEL: @test_vec(
-; CHECK-NEXT:    [[TMP6_OFF:%.*]] = add <2 x i32> %tmp6, <i32 83, i32 83>
-; CHECK-NEXT:    [[TMP1:%.*]] = icmp ugt <2 x i32> [[TMP6_OFF]], <i32 11, i32 11>
-; CHECK-NEXT:    ret <2 x i1> [[TMP1]]
+; CHECK-NEXT:    [[TMP1:%.*]] = add <2 x i32> [[TMP6:%.*]], <i32 71, i32 71>
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp ult <2 x i32> [[TMP1]], <i32 -12, i32 -12>
+; CHECK-NEXT:    ret <2 x i1> [[TMP2]]
 ;
   %tmp7 = sdiv <2 x i32> %tmp6, <i32 12, i32 12>
   icmp ne <2 x i32> %tmp7, <i32 -6, i32 -6>

diff  --git a/llvm/test/Transforms/InstCombine/2008-08-05-And.ll b/llvm/test/Transforms/InstCombine/2008-08-05-And.ll
index bec055a2ee7cf..f5a6df2ab80f5 100644
--- a/llvm/test/Transforms/InstCombine/2008-08-05-And.ll
+++ b/llvm/test/Transforms/InstCombine/2008-08-05-And.ll
@@ -8,10 +8,10 @@ define void @f(i8* %x) nounwind  {
 ; CHECK-NEXT:    br label [[BB:%.*]]
 ; CHECK:       bb:
 ; CHECK-NEXT:    [[L1:%.*]] = load i8, i8* [[X:%.*]], align 1
-; CHECK-NEXT:    [[S1:%.*]] = add i8 [[L1]], -6
-; CHECK-NEXT:    [[C1:%.*]] = icmp ugt i8 [[S1]], 2
-; CHECK-NEXT:    [[S2:%.*]] = add i8 [[L1]], -10
-; CHECK-NEXT:    [[C2:%.*]] = icmp ugt i8 [[S2]], 2
+; CHECK-NEXT:    [[TMP0:%.*]] = add i8 [[L1]], -9
+; CHECK-NEXT:    [[C1:%.*]] = icmp ult i8 [[TMP0]], -3
+; CHECK-NEXT:    [[TMP1:%.*]] = add i8 [[L1]], -13
+; CHECK-NEXT:    [[C2:%.*]] = icmp ult i8 [[TMP1]], -3
 ; CHECK-NEXT:    [[A1:%.*]] = and i1 [[C1]], [[C2]]
 ; CHECK-NEXT:    br i1 [[A1]], label [[INCOMPATIBLE:%.*]], label [[OKAY:%.*]]
 ; CHECK:       okay:
@@ -45,10 +45,10 @@ define void @f_logical(i8* %x) nounwind  {
 ; CHECK-NEXT:    br label [[BB:%.*]]
 ; CHECK:       bb:
 ; CHECK-NEXT:    [[L1:%.*]] = load i8, i8* [[X:%.*]], align 1
-; CHECK-NEXT:    [[S1:%.*]] = add i8 [[L1]], -6
-; CHECK-NEXT:    [[C1:%.*]] = icmp ugt i8 [[S1]], 2
-; CHECK-NEXT:    [[S2:%.*]] = add i8 [[L1]], -10
-; CHECK-NEXT:    [[C2:%.*]] = icmp ugt i8 [[S2]], 2
+; CHECK-NEXT:    [[TMP0:%.*]] = add i8 [[L1]], -9
+; CHECK-NEXT:    [[C1:%.*]] = icmp ult i8 [[TMP0]], -3
+; CHECK-NEXT:    [[TMP1:%.*]] = add i8 [[L1]], -13
+; CHECK-NEXT:    [[C2:%.*]] = icmp ult i8 [[TMP1]], -3
 ; CHECK-NEXT:    [[A1:%.*]] = and i1 [[C1]], [[C2]]
 ; CHECK-NEXT:    br i1 [[A1]], label [[INCOMPATIBLE:%.*]], label [[OKAY:%.*]]
 ; CHECK:       okay:

diff  --git a/llvm/test/Transforms/InstCombine/and-or-icmps.ll b/llvm/test/Transforms/InstCombine/and-or-icmps.ll
index 00a720b1da265..a9c5d2b1c1b81 100644
--- a/llvm/test/Transforms/InstCombine/and-or-icmps.ll
+++ b/llvm/test/Transforms/InstCombine/and-or-icmps.ll
@@ -257,8 +257,8 @@ define i1 @or_eq_with_
diff _one_logical(i8 %x) {
 
 define i1 @and_ne_with_
diff _one(i32 %x) {
 ; CHECK-LABEL: @and_ne_with_
diff _one(
-; CHECK-NEXT:    [[TMP1:%.*]] = add i32 [[X:%.*]], -39
-; CHECK-NEXT:    [[TMP2:%.*]] = icmp ugt i32 [[TMP1]], 1
+; CHECK-NEXT:    [[TMP1:%.*]] = add i32 [[X:%.*]], -41
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp ult i32 [[TMP1]], -2
 ; CHECK-NEXT:    ret i1 [[TMP2]]
 ;
   %cmp1 = icmp ne i32 %x, 40
@@ -269,8 +269,8 @@ define i1 @and_ne_with_
diff _one(i32 %x) {
 
 define i1 @and_ne_with_
diff _one_logical(i32 %x) {
 ; CHECK-LABEL: @and_ne_with_
diff _one_logical(
-; CHECK-NEXT:    [[TMP1:%.*]] = add i32 [[X:%.*]], -39
-; CHECK-NEXT:    [[TMP2:%.*]] = icmp ugt i32 [[TMP1]], 1
+; CHECK-NEXT:    [[TMP1:%.*]] = add i32 [[X:%.*]], -41
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp ult i32 [[TMP1]], -2
 ; CHECK-NEXT:    ret i1 [[TMP2]]
 ;
   %cmp1 = icmp ne i32 %x, 40
@@ -308,8 +308,8 @@ define i1 @or_eq_with_
diff _one_signed_logical(i32 %x) {
 
 define i1 @and_ne_with_
diff _one_signed(i64 %x) {
 ; CHECK-LABEL: @and_ne_with_
diff _one_signed(
-; CHECK-NEXT:    [[TMP1:%.*]] = add i64 [[X:%.*]], 1
-; CHECK-NEXT:    [[TMP2:%.*]] = icmp ugt i64 [[TMP1]], 1
+; CHECK-NEXT:    [[TMP1:%.*]] = add i64 [[X:%.*]], -1
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp ult i64 [[TMP1]], -2
 ; CHECK-NEXT:    ret i1 [[TMP2]]
 ;
   %cmp1 = icmp ne i64 %x, -1
@@ -320,8 +320,8 @@ define i1 @and_ne_with_
diff _one_signed(i64 %x) {
 
 define i1 @and_ne_with_
diff _one_signed_logical(i64 %x) {
 ; CHECK-LABEL: @and_ne_with_
diff _one_signed_logical(
-; CHECK-NEXT:    [[TMP1:%.*]] = add i64 [[X:%.*]], 1
-; CHECK-NEXT:    [[TMP2:%.*]] = icmp ugt i64 [[TMP1]], 1
+; CHECK-NEXT:    [[TMP1:%.*]] = add i64 [[X:%.*]], -1
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp ult i64 [[TMP1]], -2
 ; CHECK-NEXT:    ret i1 [[TMP2]]
 ;
   %cmp1 = icmp ne i64 %x, -1
@@ -346,8 +346,8 @@ define <2 x i1> @or_eq_with_one_bit_
diff _constants2_splatvec(<2 x i32> %x) {
 
 define <2 x i1> @and_ne_with_
diff _one_splatvec(<2 x i32> %x) {
 ; CHECK-LABEL: @and_ne_with_
diff _one_splatvec(
-; CHECK-NEXT:    [[TMP1:%.*]] = add <2 x i32> [[X:%.*]], <i32 -39, i32 -39>
-; CHECK-NEXT:    [[TMP2:%.*]] = icmp ugt <2 x i32> [[TMP1]], <i32 1, i32 1>
+; CHECK-NEXT:    [[TMP1:%.*]] = add <2 x i32> [[X:%.*]], <i32 -41, i32 -41>
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp ult <2 x i32> [[TMP1]], <i32 -2, i32 -2>
 ; CHECK-NEXT:    ret <2 x i1> [[TMP2]]
 ;
   %cmp1 = icmp ne <2 x i32> %x, <i32 40, i32 40>
@@ -508,9 +508,9 @@ define i1 @PR42691_4_logical(i32 %x) {
 
 define i1 @PR42691_5(i32 %x) {
 ; CHECK-LABEL: @PR42691_5(
-; CHECK-NEXT:    [[X_OFF:%.*]] = add i32 [[X:%.*]], -1
-; CHECK-NEXT:    [[TMP1:%.*]] = icmp ugt i32 [[X_OFF]], 2147483645
-; CHECK-NEXT:    ret i1 [[TMP1]]
+; CHECK-NEXT:    [[TMP1:%.*]] = add i32 [[X:%.*]], -2147483647
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp ult i32 [[TMP1]], -2147483646
+; CHECK-NEXT:    ret i1 [[TMP2]]
 ;
   %c1 = icmp slt i32 %x, 1
   %c2 = icmp eq i32 %x, 2147483647
@@ -520,9 +520,9 @@ define i1 @PR42691_5(i32 %x) {
 
 define i1 @PR42691_5_logical(i32 %x) {
 ; CHECK-LABEL: @PR42691_5_logical(
-; CHECK-NEXT:    [[X_OFF:%.*]] = add i32 [[X:%.*]], -1
-; CHECK-NEXT:    [[TMP1:%.*]] = icmp ugt i32 [[X_OFF]], 2147483645
-; CHECK-NEXT:    ret i1 [[TMP1]]
+; CHECK-NEXT:    [[TMP1:%.*]] = add i32 [[X:%.*]], -2147483647
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp ult i32 [[TMP1]], -2147483646
+; CHECK-NEXT:    ret i1 [[TMP2]]
 ;
   %c1 = icmp slt i32 %x, 1
   %c2 = icmp eq i32 %x, 2147483647
@@ -532,9 +532,9 @@ define i1 @PR42691_5_logical(i32 %x) {
 
 define i1 @PR42691_6(i32 %x) {
 ; CHECK-LABEL: @PR42691_6(
-; CHECK-NEXT:    [[X_OFF:%.*]] = add i32 [[X:%.*]], 2147483647
-; CHECK-NEXT:    [[TMP1:%.*]] = icmp ugt i32 [[X_OFF]], 2147483645
-; CHECK-NEXT:    ret i1 [[TMP1]]
+; CHECK-NEXT:    [[TMP1:%.*]] = add i32 [[X:%.*]], 1
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp ult i32 [[TMP1]], -2147483646
+; CHECK-NEXT:    ret i1 [[TMP2]]
 ;
   %c1 = icmp ult i32 %x, 2147483649
   %c2 = icmp eq i32 %x, 4294967295
@@ -544,9 +544,9 @@ define i1 @PR42691_6(i32 %x) {
 
 define i1 @PR42691_6_logical(i32 %x) {
 ; CHECK-LABEL: @PR42691_6_logical(
-; CHECK-NEXT:    [[X_OFF:%.*]] = add i32 [[X:%.*]], 2147483647
-; CHECK-NEXT:    [[TMP1:%.*]] = icmp ugt i32 [[X_OFF]], 2147483645
-; CHECK-NEXT:    ret i1 [[TMP1]]
+; CHECK-NEXT:    [[TMP1:%.*]] = add i32 [[X:%.*]], 1
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp ult i32 [[TMP1]], -2147483646
+; CHECK-NEXT:    ret i1 [[TMP2]]
 ;
   %c1 = icmp ult i32 %x, 2147483649
   %c2 = icmp eq i32 %x, 4294967295

diff  --git a/llvm/test/Transforms/InstCombine/canonicalize-signed-truncation-check.ll b/llvm/test/Transforms/InstCombine/canonicalize-signed-truncation-check.ll
index 90d19be434f25..8e8152a520a6d 100644
--- a/llvm/test/Transforms/InstCombine/canonicalize-signed-truncation-check.ll
+++ b/llvm/test/Transforms/InstCombine/canonicalize-signed-truncation-check.ll
@@ -15,8 +15,8 @@
 
 define i1 @p0(i8 %x) {
 ; CHECK-LABEL: @p0(
-; CHECK-NEXT:    [[TMP1:%.*]] = add i8 [[X:%.*]], 4
-; CHECK-NEXT:    [[TMP2:%.*]] = icmp ugt i8 [[TMP1]], 7
+; CHECK-NEXT:    [[TMP1:%.*]] = add i8 [[X:%.*]], -4
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp ult i8 [[TMP1]], -8
 ; CHECK-NEXT:    ret i1 [[TMP2]]
 ;
   %tmp0 = shl i8 %x, 5
@@ -44,8 +44,8 @@ define i1 @pb(i65 %x) {
 
 define <2 x i1> @p1_vec_splat(<2 x i8> %x) {
 ; CHECK-LABEL: @p1_vec_splat(
-; CHECK-NEXT:    [[TMP1:%.*]] = add <2 x i8> [[X:%.*]], <i8 4, i8 4>
-; CHECK-NEXT:    [[TMP2:%.*]] = icmp ugt <2 x i8> [[TMP1]], <i8 7, i8 7>
+; CHECK-NEXT:    [[TMP1:%.*]] = add <2 x i8> [[X:%.*]], <i8 -4, i8 -4>
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp ult <2 x i8> [[TMP1]], <i8 -8, i8 -8>
 ; CHECK-NEXT:    ret <2 x i1> [[TMP2]]
 ;
   %tmp0 = shl <2 x i8> %x, <i8 5, i8 5>
@@ -115,8 +115,8 @@ declare i8 @gen8()
 define i1 @c0() {
 ; CHECK-LABEL: @c0(
 ; CHECK-NEXT:    [[X:%.*]] = call i8 @gen8()
-; CHECK-NEXT:    [[TMP1:%.*]] = add i8 [[X]], 4
-; CHECK-NEXT:    [[TMP2:%.*]] = icmp ugt i8 [[TMP1]], 7
+; CHECK-NEXT:    [[TMP1:%.*]] = add i8 [[X]], -4
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp ult i8 [[TMP1]], -8
 ; CHECK-NEXT:    ret i1 [[TMP2]]
 ;
   %x = call i8 @gen8()
@@ -136,8 +136,8 @@ define i1 @n_oneuse0(i8 %x) {
 ; CHECK-LABEL: @n_oneuse0(
 ; CHECK-NEXT:    [[TMP0:%.*]] = shl i8 [[X:%.*]], 5
 ; CHECK-NEXT:    call void @use8(i8 [[TMP0]])
-; CHECK-NEXT:    [[TMP1:%.*]] = add i8 [[X]], 4
-; CHECK-NEXT:    [[TMP2:%.*]] = icmp ugt i8 [[TMP1]], 7
+; CHECK-NEXT:    [[TMP1:%.*]] = add i8 [[X]], -4
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp ult i8 [[TMP1]], -8
 ; CHECK-NEXT:    ret i1 [[TMP2]]
 ;
   %tmp0 = shl i8 %x, 5

diff  --git a/llvm/test/Transforms/InstCombine/icmp-add.ll b/llvm/test/Transforms/InstCombine/icmp-add.ll
index 1750b5685c50d..eb2f1945dc4d5 100644
--- a/llvm/test/Transforms/InstCombine/icmp-add.ll
+++ b/llvm/test/Transforms/InstCombine/icmp-add.ll
@@ -363,8 +363,8 @@ define i1 @ult_add_nonuw(i8 %in) {
 
 define i1 @uge_add_nonuw(i32 %in) {
 ; CHECK-LABEL: @uge_add_nonuw(
-; CHECK-NEXT:    [[A6:%.*]] = add i32 [[IN:%.*]], 3
-; CHECK-NEXT:    [[A18:%.*]] = icmp ugt i32 [[A6]], 11
+; CHECK-NEXT:    [[TMP1:%.*]] = add i32 [[IN:%.*]], -9
+; CHECK-NEXT:    [[A18:%.*]] = icmp ult i32 [[TMP1]], -12
 ; CHECK-NEXT:    ret i1 [[A18]]
 ;
   %a6 = add i32 %in, 3
@@ -785,8 +785,8 @@ define <2 x i1> @ugt_offset_splat(<2 x i5> %a) {
 
 define i1 @ugt_wrong_offset(i8 %a) {
 ; CHECK-LABEL: @ugt_wrong_offset(
-; CHECK-NEXT:    [[T:%.*]] = add i8 [[A:%.*]], 123
-; CHECK-NEXT:    [[OV:%.*]] = icmp ugt i8 [[T]], -5
+; CHECK-NEXT:    [[TMP1:%.*]] = add i8 [[A:%.*]], 127
+; CHECK-NEXT:    [[OV:%.*]] = icmp ult i8 [[TMP1]], 4
 ; CHECK-NEXT:    ret i1 [[OV]]
 ;
   %t = add i8 %a, 123

diff  --git a/llvm/test/Transforms/InstCombine/icmp-sub.ll b/llvm/test/Transforms/InstCombine/icmp-sub.ll
index 17a6800a7a79b..40447559bbb80 100644
--- a/llvm/test/Transforms/InstCombine/icmp-sub.ll
+++ b/llvm/test/Transforms/InstCombine/icmp-sub.ll
@@ -57,8 +57,8 @@ define i1 @test_negative_nuw_and_signed_pred(i64 %x) {
 
 define i1 @test_negative_nsw_and_unsigned_pred(i64 %x) {
 ; CHECK-LABEL: @test_negative_nsw_and_unsigned_pred(
-; CHECK-NEXT:    [[NOTSUB:%.*]] = add nsw i64 [[X:%.*]], -11
-; CHECK-NEXT:    [[Z:%.*]] = icmp ugt i64 [[NOTSUB]], -4
+; CHECK-NEXT:    [[TMP1:%.*]] = add i64 [[X:%.*]], -8
+; CHECK-NEXT:    [[Z:%.*]] = icmp ult i64 [[TMP1]], 3
 ; CHECK-NEXT:    ret i1 [[Z]]
 ;
   %y = sub nsw i64 10, %x

diff  --git a/llvm/test/Transforms/InstCombine/icmp-topbitssame.ll b/llvm/test/Transforms/InstCombine/icmp-topbitssame.ll
index 80344391ae7f3..61107cd15d6de 100644
--- a/llvm/test/Transforms/InstCombine/icmp-topbitssame.ll
+++ b/llvm/test/Transforms/InstCombine/icmp-topbitssame.ll
@@ -35,8 +35,8 @@ define i1 @testi16i8_com(i16 %add) {
 
 define i1 @testi16i8_ne(i16 %add) {
 ; CHECK-LABEL: @testi16i8_ne(
-; CHECK-NEXT:    [[TMP1:%.*]] = add i16 [[ADD:%.*]], 128
-; CHECK-NEXT:    [[CMP_NOT_I:%.*]] = icmp ugt i16 [[TMP1]], 255
+; CHECK-NEXT:    [[TMP1:%.*]] = add i16 [[ADD:%.*]], -128
+; CHECK-NEXT:    [[CMP_NOT_I:%.*]] = icmp ult i16 [[TMP1]], -256
 ; CHECK-NEXT:    ret i1 [[CMP_NOT_I]]
 ;
   %sh = lshr i16 %add, 8
@@ -49,8 +49,8 @@ define i1 @testi16i8_ne(i16 %add) {
 
 define i1 @testi16i8_ne_com(i16 %add) {
 ; CHECK-LABEL: @testi16i8_ne_com(
-; CHECK-NEXT:    [[TMP1:%.*]] = add i16 [[ADD:%.*]], 128
-; CHECK-NEXT:    [[CMP_NOT_I:%.*]] = icmp ugt i16 [[TMP1]], 255
+; CHECK-NEXT:    [[TMP1:%.*]] = add i16 [[ADD:%.*]], -128
+; CHECK-NEXT:    [[CMP_NOT_I:%.*]] = icmp ult i16 [[TMP1]], -256
 ; CHECK-NEXT:    ret i1 [[CMP_NOT_I]]
 ;
   %sh = lshr i16 %add, 8
@@ -77,8 +77,8 @@ define i1 @testi64i32(i64 %add) {
 
 define i1 @testi64i32_ne(i64 %add) {
 ; CHECK-LABEL: @testi64i32_ne(
-; CHECK-NEXT:    [[TMP1:%.*]] = add i64 [[ADD:%.*]], 2147483648
-; CHECK-NEXT:    [[CMP_NOT_I:%.*]] = icmp ugt i64 [[TMP1]], 4294967295
+; CHECK-NEXT:    [[TMP1:%.*]] = add i64 [[ADD:%.*]], -2147483648
+; CHECK-NEXT:    [[CMP_NOT_I:%.*]] = icmp ult i64 [[TMP1]], -4294967296
 ; CHECK-NEXT:    ret i1 [[CMP_NOT_I]]
 ;
   %sh = lshr i64 %add, 32

diff  --git a/llvm/test/Transforms/InstCombine/load-cmp.ll b/llvm/test/Transforms/InstCombine/load-cmp.ll
index 92bf377d016c8..0176093e31f47 100644
--- a/llvm/test/Transforms/InstCombine/load-cmp.ll
+++ b/llvm/test/Transforms/InstCombine/load-cmp.ll
@@ -145,8 +145,8 @@ define i1 @test6(i32 %X) {
 
 define i1 @test7(i32 %X) {
 ; CHECK-LABEL: @test7(
-; CHECK-NEXT:    [[TMP1:%.*]] = add i32 [[X:%.*]], -1
-; CHECK-NEXT:    [[R:%.*]] = icmp ugt i32 [[TMP1]], 2
+; CHECK-NEXT:    [[TMP1:%.*]] = add i32 [[X:%.*]], -4
+; CHECK-NEXT:    [[R:%.*]] = icmp ult i32 [[TMP1]], -3
 ; CHECK-NEXT:    ret i1 [[R]]
 ;
   %P = getelementptr inbounds [6 x double], [6 x double]* @GD, i32 0, i32 %X

diff  --git a/llvm/test/Transforms/InstCombine/minmax-fold.ll b/llvm/test/Transforms/InstCombine/minmax-fold.ll
index 03500298dbf7e..82c3ba8c3c29c 100644
--- a/llvm/test/Transforms/InstCombine/minmax-fold.ll
+++ b/llvm/test/Transforms/InstCombine/minmax-fold.ll
@@ -1120,6 +1120,10 @@ define i32 @add_umax_wrong_pred(i32 %x) {
 
 ; Negative test
 
+; Without the nuw that would allow pushing the add through the umax, the
+; add + icmp ugt combination can be interpreted as a range check, and would
+; normally be canonicalized to use ult instead. However, this is not done when
+; used as part of a umax to avoid breaking the SPF pattern.
 define i32 @add_umax_wrong_wrap(i32 %x) {
 ; CHECK-LABEL: @add_umax_wrong_wrap(
 ; CHECK-NEXT:    [[A:%.*]] = add nsw i32 [[X:%.*]], 15

diff  --git a/llvm/test/Transforms/InstCombine/or.ll b/llvm/test/Transforms/InstCombine/or.ll
index ef76fb0d58b44..9ed333325819d 100644
--- a/llvm/test/Transforms/InstCombine/or.ll
+++ b/llvm/test/Transforms/InstCombine/or.ll
@@ -99,9 +99,9 @@ define i32 @test17(i32 %A) {
 
 define i1 @test18(i32 %A) {
 ; CHECK-LABEL: @test18(
-; CHECK-NEXT:    [[A_OFF:%.*]] = add i32 [[A:%.*]], -50
-; CHECK-NEXT:    [[TMP1:%.*]] = icmp ugt i32 [[A_OFF]], 49
-; CHECK-NEXT:    ret i1 [[TMP1]]
+; CHECK-NEXT:    [[TMP1:%.*]] = add i32 [[A:%.*]], -100
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp ult i32 [[TMP1]], -50
+; CHECK-NEXT:    ret i1 [[TMP2]]
 ;
   %B = icmp sge i32 %A, 100
   %C = icmp slt i32 %A, 50
@@ -111,9 +111,9 @@ define i1 @test18(i32 %A) {
 
 define i1 @test18_logical(i32 %A) {
 ; CHECK-LABEL: @test18_logical(
-; CHECK-NEXT:    [[A_OFF:%.*]] = add i32 [[A:%.*]], -50
-; CHECK-NEXT:    [[TMP1:%.*]] = icmp ugt i32 [[A_OFF]], 49
-; CHECK-NEXT:    ret i1 [[TMP1]]
+; CHECK-NEXT:    [[TMP1:%.*]] = add i32 [[A:%.*]], -100
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp ult i32 [[TMP1]], -50
+; CHECK-NEXT:    ret i1 [[TMP2]]
 ;
   %B = icmp sge i32 %A, 100
   %C = icmp slt i32 %A, 50

diff  --git a/llvm/test/Transforms/InstCombine/overflow.ll b/llvm/test/Transforms/InstCombine/overflow.ll
index 6205a02776cce..153522ef6704b 100644
--- a/llvm/test/Transforms/InstCombine/overflow.ll
+++ b/llvm/test/Transforms/InstCombine/overflow.ll
@@ -11,7 +11,7 @@ define i32 @test1(i32 %a, i32 %b) nounwind ssp {
 ; CHECK-NEXT:    [[TMP0:%.*]] = extractvalue { i32, i1 } [[SADD]], 1
 ; CHECK-NEXT:    br i1 [[TMP0]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
 ; CHECK:       if.then:
-; CHECK-NEXT:    tail call void @throwAnExceptionOrWhatever() #2
+; CHECK-NEXT:    tail call void @throwAnExceptionOrWhatever() #[[ATTR2:[0-9]+]]
 ; CHECK-NEXT:    br label [[IF_END]]
 ; CHECK:       if.end:
 ; CHECK-NEXT:    [[SADD_RESULT:%.*]] = extractvalue { i32, i1 } [[SADD]], 0
@@ -49,7 +49,7 @@ define i32 @test2(i32 %a, i32 %b, i64* %P) nounwind ssp {
 ; CHECK-NEXT:    [[TMP0:%.*]] = icmp ugt i64 [[ADD_OFF]], 4294967295
 ; CHECK-NEXT:    br i1 [[TMP0]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
 ; CHECK:       if.then:
-; CHECK-NEXT:    tail call void @throwAnExceptionOrWhatever() #2
+; CHECK-NEXT:    tail call void @throwAnExceptionOrWhatever() #[[ATTR2]]
 ; CHECK-NEXT:    br label [[IF_END]]
 ; CHECK:       if.end:
 ; CHECK-NEXT:    [[CONV9:%.*]] = trunc i64 [[ADD]] to i32
@@ -82,11 +82,11 @@ define i64 @test3(i32 %a, i32 %b) nounwind ssp {
 ; CHECK-NEXT:    [[CONV:%.*]] = sext i32 [[A:%.*]] to i64
 ; CHECK-NEXT:    [[CONV2:%.*]] = sext i32 [[B:%.*]] to i64
 ; CHECK-NEXT:    [[ADD:%.*]] = add nsw i64 [[CONV2]], [[CONV]]
-; CHECK-NEXT:    [[ADD_OFF:%.*]] = add nsw i64 [[ADD]], 2147483648
-; CHECK-NEXT:    [[TMP0:%.*]] = icmp ugt i64 [[ADD_OFF]], 4294967295
-; CHECK-NEXT:    br i1 [[TMP0]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
+; CHECK-NEXT:    [[TMP0:%.*]] = add nsw i64 [[ADD]], -2147483648
+; CHECK-NEXT:    [[TMP1:%.*]] = icmp ult i64 [[TMP0]], -4294967296
+; CHECK-NEXT:    br i1 [[TMP1]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
 ; CHECK:       if.then:
-; CHECK-NEXT:    tail call void @throwAnExceptionOrWhatever() #2
+; CHECK-NEXT:    tail call void @throwAnExceptionOrWhatever() #[[ATTR2]]
 ; CHECK-NEXT:    br label [[IF_END]]
 ; CHECK:       if.end:
 ; CHECK-NEXT:    ret i64 [[ADD]]
@@ -116,7 +116,7 @@ define zeroext i8 @test4(i8 signext %a, i8 signext %b) nounwind ssp {
 ; CHECK-NEXT:    [[CMP:%.*]] = extractvalue { i8, i1 } [[SADD]], 1
 ; CHECK-NEXT:    br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
 ; CHECK:       if.then:
-; CHECK-NEXT:    tail call void @throwAnExceptionOrWhatever() #2
+; CHECK-NEXT:    tail call void @throwAnExceptionOrWhatever() #[[ATTR2]]
 ; CHECK-NEXT:    unreachable
 ; CHECK:       if.end:
 ; CHECK-NEXT:    [[SADD_RESULT:%.*]] = extractvalue { i8, i1 } [[SADD]], 0
@@ -146,11 +146,11 @@ define i32 @test8(i64 %a, i64 %b) nounwind ssp {
 ; CHECK-LABEL: @test8(
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    [[ADD:%.*]] = add i64 [[A:%.*]], [[B:%.*]]
-; CHECK-NEXT:    [[ADD_OFF:%.*]] = add i64 [[ADD]], 2147483648
-; CHECK-NEXT:    [[TMP0:%.*]] = icmp ugt i64 [[ADD_OFF]], 4294967295
-; CHECK-NEXT:    br i1 [[TMP0]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
+; CHECK-NEXT:    [[TMP0:%.*]] = add i64 [[ADD]], -2147483648
+; CHECK-NEXT:    [[TMP1:%.*]] = icmp ult i64 [[TMP0]], -4294967296
+; CHECK-NEXT:    br i1 [[TMP1]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
 ; CHECK:       if.then:
-; CHECK-NEXT:    tail call void @throwAnExceptionOrWhatever() #2
+; CHECK-NEXT:    tail call void @throwAnExceptionOrWhatever() #[[ATTR2]]
 ; CHECK-NEXT:    br label [[IF_END]]
 ; CHECK:       if.end:
 ; CHECK-NEXT:    [[CONV9:%.*]] = trunc i64 [[ADD]] to i32

diff  --git a/llvm/test/Transforms/InstCombine/smulo.ll b/llvm/test/Transforms/InstCombine/smulo.ll
index c909ed1d45ae3..42ca6d7f2b5a3 100644
--- a/llvm/test/Transforms/InstCombine/smulo.ll
+++ b/llvm/test/Transforms/InstCombine/smulo.ll
@@ -46,8 +46,8 @@ define i1 @test_constant2(i8 %a) {
 
 define i1 @test_constant3(i8 %a) {
 ; CHECK-LABEL: @test_constant3(
-; CHECK-NEXT:    [[TMP1:%.*]] = add i8 [[A:%.*]], 42
-; CHECK-NEXT:    [[OVERFLOW:%.*]] = icmp ugt i8 [[TMP1]], 84
+; CHECK-NEXT:    [[TMP1:%.*]] = add i8 [[A:%.*]], -43
+; CHECK-NEXT:    [[OVERFLOW:%.*]] = icmp ult i8 [[TMP1]], -85
 ; CHECK-NEXT:    ret i1 [[OVERFLOW]]
 ;
   %res = tail call { i8, i1 } @llvm.smul.with.overflow.i8(i8 %a, i8 3)
@@ -57,8 +57,8 @@ define i1 @test_constant3(i8 %a) {
 
 define i1 @test_constant4(i8 %a) {
 ; CHECK-LABEL: @test_constant4(
-; CHECK-NEXT:    [[TMP1:%.*]] = add i8 [[A:%.*]], 32
-; CHECK-NEXT:    [[OVERFLOW:%.*]] = icmp ugt i8 [[TMP1]], 63
+; CHECK-NEXT:    [[TMP1:%.*]] = add i8 [[A:%.*]], -32
+; CHECK-NEXT:    [[OVERFLOW:%.*]] = icmp ult i8 [[TMP1]], -64
 ; CHECK-NEXT:    ret i1 [[OVERFLOW]]
 ;
   %res = tail call { i8, i1 } @llvm.smul.with.overflow.i8(i8 %a, i8 4)
@@ -69,8 +69,8 @@ define i1 @test_constant4(i8 %a) {
 
 define i1 @test_constant127(i8 %a) {
 ; CHECK-LABEL: @test_constant127(
-; CHECK-NEXT:    [[TMP1:%.*]] = add i8 [[A:%.*]], 1
-; CHECK-NEXT:    [[OVERFLOW:%.*]] = icmp ugt i8 [[TMP1]], 2
+; CHECK-NEXT:    [[TMP1:%.*]] = add i8 [[A:%.*]], -2
+; CHECK-NEXT:    [[OVERFLOW:%.*]] = icmp ult i8 [[TMP1]], -3
 ; CHECK-NEXT:    ret i1 [[OVERFLOW]]
 ;
   %res = tail call { i8, i1 } @llvm.smul.with.overflow.i8(i8 %a, i8 127)


        


More information about the llvm-commits mailing list