[llvm] da210f5 - [InstCombine] canonicalize "(C2 - Y) > C" as (Y + ~C2) < ~C

Sanjay Patel via llvm-commits llvm-commits at lists.llvm.org
Sun Oct 10 08:08:08 PDT 2021


Author: Sanjay Patel
Date: 2021-10-10T11:06:49-04:00
New Revision: da210f5d3425e8877ceabaf6ed3483d52cbd7448

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

LOG: [InstCombine] canonicalize "(C2 - Y) > C" as (Y + ~C2) < ~C

The test diffs show that we have better analysis/folds for 'add'
(although we should at least have the simplifications
independently, so we don't have the one-use restriction).

This is related to solving regressions that would appear in
transforms related to D111410, and that is part of a series
of enhancements that may eventually helpi solve PR34047.

https://alive2.llvm.org/ce/z/3tB9KG

  define i1 @src(i8 %x, i8 %C, i8 %C2) {
    %sub = sub nuw i8 %C2, %x
    %r = icmp slt i8 %sub, %C
    ret i1 %r
  }

  define i1 @tgt(i8 %x, i8 %C, i8 %C2) {
    %Cnot = xor i8 %C, -1
    %C2not = xor i8 %C2, -1
    %add = add nuw i8 %x, %C2not
    %r = icmp sgt i8 %add, %Cnot
    ret i1 %r
  }

Added: 
    

Modified: 
    llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
    llvm/test/Transforms/InstCombine/2007-12-18-AddSelCmpSub.ll
    llvm/test/Transforms/InstCombine/icmp-sub.ll
    llvm/test/Transforms/InstCombine/or.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
index e080e7f95168e..63be48fe352f4 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
@@ -2592,12 +2592,13 @@ Instruction *InstCombinerImpl::foldICmpSubConstant(ICmpInst &Cmp,
   // (icmp P (sub nuw|nsw C2, Y), C) -> (icmp swap(P) Y, C2-C)
   const APInt *C2;
   APInt SubResult;
+  ICmpInst::Predicate SwappedPred = Cmp.getSwappedPredicate();
+  bool HasNSW = Sub->hasNoSignedWrap();
+  bool HasNUW = Sub->hasNoUnsignedWrap();
   if (match(X, m_APInt(C2)) &&
-      ((Cmp.isUnsigned() && Sub->hasNoUnsignedWrap()) ||
-       (Cmp.isSigned() && Sub->hasNoSignedWrap())) &&
+      ((Cmp.isUnsigned() && HasNUW) || (Cmp.isSigned() && HasNSW)) &&
       !subWithOverflow(SubResult, *C2, C, Cmp.isSigned()))
-    return new ICmpInst(Cmp.getSwappedPredicate(), Y,
-                        ConstantInt::get(Ty, SubResult));
+    return new ICmpInst(SwappedPred, Y, ConstantInt::get(Ty, SubResult));
 
   // The following transforms are only worth it if the only user of the subtract
   // is the icmp.
@@ -2636,7 +2637,12 @@ Instruction *InstCombinerImpl::foldICmpSubConstant(ICmpInst &Cmp,
   if (Pred == ICmpInst::ICMP_UGT && (C + 1).isPowerOf2() && (*C2 & C) == C)
     return new ICmpInst(ICmpInst::ICMP_NE, Builder.CreateOr(Y, C), X);
 
-  return nullptr;
+  // We have handled special cases that reduce.
+  // Canonicalize any remaining sub to add as:
+  // (C2 - Y) > C --> (Y + ~C2) < ~C
+  Value *Add = Builder.CreateAdd(Y, ConstantInt::get(Ty, ~(*C2)), "notsub",
+                                 HasNUW, HasNSW);
+  return new ICmpInst(SwappedPred, Add, ConstantInt::get(Ty, ~C));
 }
 
 /// Fold icmp (add X, Y), C.

diff  --git a/llvm/test/Transforms/InstCombine/2007-12-18-AddSelCmpSub.ll b/llvm/test/Transforms/InstCombine/2007-12-18-AddSelCmpSub.ll
index 62fb4132d5de6..38721f3079a66 100644
--- a/llvm/test/Transforms/InstCombine/2007-12-18-AddSelCmpSub.ll
+++ b/llvm/test/Transforms/InstCombine/2007-12-18-AddSelCmpSub.ll
@@ -3,10 +3,10 @@
 
 define i32 @foo(i32 %a) {
 ; CHECK-LABEL: @foo(
-; CHECK-NEXT:    [[T15:%.*]] = sub i32 99, [[A:%.*]]
-; CHECK-NEXT:    [[TMP1:%.*]] = icmp sgt i32 [[T15]], 0
+; CHECK-NEXT:    [[TMP1:%.*]] = add i32 [[A:%.*]], -100
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp slt i32 [[TMP1]], -1
 ; CHECK-NEXT:    [[A_OP:%.*]] = add i32 [[A]], 1
-; CHECK-NEXT:    [[T13:%.*]] = select i1 [[TMP1]], i32 100, i32 [[A_OP]]
+; CHECK-NEXT:    [[T13:%.*]] = select i1 [[TMP2]], i32 100, i32 [[A_OP]]
 ; CHECK-NEXT:    ret i32 [[T13]]
 ;
   %t15 = sub i32 99, %a
@@ -19,9 +19,9 @@ define i32 @foo(i32 %a) {
 
 define i32 @bar(i32 %a) {
 ; CHECK-LABEL: @bar(
-; CHECK-NEXT:    [[T15:%.*]] = sub i32 99, [[A:%.*]]
-; CHECK-NEXT:    [[TMP1:%.*]] = icmp sgt i32 [[T15]], 0
-; CHECK-NEXT:    [[T12:%.*]] = select i1 [[TMP1]], i32 99, i32 [[A]]
+; CHECK-NEXT:    [[TMP1:%.*]] = add i32 [[A:%.*]], -100
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp slt i32 [[TMP1]], -1
+; CHECK-NEXT:    [[T12:%.*]] = select i1 [[TMP2]], i32 99, i32 [[A]]
 ; CHECK-NEXT:    ret i32 [[T12]]
 ;
   %t15 = sub i32 99, %a

diff  --git a/llvm/test/Transforms/InstCombine/icmp-sub.ll b/llvm/test/Transforms/InstCombine/icmp-sub.ll
index 0b62df6042585..03488a2f469a3 100644
--- a/llvm/test/Transforms/InstCombine/icmp-sub.ll
+++ b/llvm/test/Transforms/InstCombine/icmp-sub.ll
@@ -46,8 +46,8 @@ define i1 @test_nuw_nsw_and_signed_pred(i64 %x) {
 
 define i1 @test_negative_nuw_and_signed_pred(i64 %x) {
 ; CHECK-LABEL: @test_negative_nuw_and_signed_pred(
-; CHECK-NEXT:    [[Y:%.*]] = sub nuw i64 10, [[X:%.*]]
-; CHECK-NEXT:    [[Z:%.*]] = icmp slt i64 [[Y]], 3
+; CHECK-NEXT:    [[NOTSUB:%.*]] = add nuw i64 [[X:%.*]], -11
+; CHECK-NEXT:    [[Z:%.*]] = icmp sgt i64 [[NOTSUB]], -4
 ; CHECK-NEXT:    ret i1 [[Z]]
 ;
   %y = sub nuw i64 10, %x
@@ -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:    [[Y:%.*]] = sub nsw i64 10, [[X:%.*]]
-; CHECK-NEXT:    [[Z:%.*]] = icmp ult i64 [[Y]], 3
+; CHECK-NEXT:    [[NOTSUB:%.*]] = add nsw i64 [[X:%.*]], -11
+; CHECK-NEXT:    [[Z:%.*]] = icmp ugt i64 [[NOTSUB]], -4
 ; CHECK-NEXT:    ret i1 [[Z]]
 ;
   %y = sub nsw i64 10, %x
@@ -68,9 +68,7 @@ define i1 @test_negative_nsw_and_unsigned_pred(i64 %x) {
 
 define i1 @test_negative_combined_sub_unsigned_overflow(i64 %x) {
 ; CHECK-LABEL: @test_negative_combined_sub_unsigned_overflow(
-; CHECK-NEXT:    [[Y:%.*]] = sub nuw i64 10, [[X:%.*]]
-; CHECK-NEXT:    [[Z:%.*]] = icmp ult i64 [[Y]], 11
-; CHECK-NEXT:    ret i1 [[Z]]
+; CHECK-NEXT:    ret i1 true
 ;
   %y = sub nuw i64 10, %x
   %z = icmp ult i64 %y, 11
@@ -79,9 +77,7 @@ define i1 @test_negative_combined_sub_unsigned_overflow(i64 %x) {
 
 define i1 @test_negative_combined_sub_signed_overflow(i8 %x) {
 ; CHECK-LABEL: @test_negative_combined_sub_signed_overflow(
-; CHECK-NEXT:    [[Y:%.*]] = sub nsw i8 127, [[X:%.*]]
-; CHECK-NEXT:    [[Z:%.*]] = icmp slt i8 [[Y]], -1
-; CHECK-NEXT:    ret i1 [[Z]]
+; CHECK-NEXT:    ret i1 false
 ;
   %y = sub nsw i8 127, %x
   %z = icmp slt i8 %y, -1
@@ -191,8 +187,8 @@ define <2 x i1> @icmp_eq_sub_non_splat2(<2 x i32> %a) {
 
 define i1 @neg_sgt_42(i32 %x) {
 ; CHECK-LABEL: @neg_sgt_42(
-; CHECK-NEXT:    [[NEGX:%.*]] = sub i32 0, [[X:%.*]]
-; CHECK-NEXT:    [[R:%.*]] = icmp sgt i32 [[NEGX]], 42
+; CHECK-NEXT:    [[NOTSUB:%.*]] = add i32 [[X:%.*]], -1
+; CHECK-NEXT:    [[R:%.*]] = icmp slt i32 [[NOTSUB]], -43
 ; CHECK-NEXT:    ret i1 [[R]]
 ;
   %negx = sub i32 0, %x
@@ -306,8 +302,8 @@ define i1 @subC_nsw_ne(i32 %x) {
 
 define i1 @neg_slt_42(i128 %x) {
 ; CHECK-LABEL: @neg_slt_42(
-; CHECK-NEXT:    [[NEGX:%.*]] = sub i128 0, [[X:%.*]]
-; CHECK-NEXT:    [[R:%.*]] = icmp slt i128 [[NEGX]], 42
+; CHECK-NEXT:    [[NOTSUB:%.*]] = add i128 [[X:%.*]], -1
+; CHECK-NEXT:    [[R:%.*]] = icmp sgt i128 [[NOTSUB]], -43
 ; CHECK-NEXT:    ret i1 [[R]]
 ;
   %negx = sub i128 0, %x
@@ -317,8 +313,8 @@ define i1 @neg_slt_42(i128 %x) {
 
 define <2 x i1> @neg_ugt_42_splat(<2 x i7> %x) {
 ; CHECK-LABEL: @neg_ugt_42_splat(
-; CHECK-NEXT:    [[NEGX:%.*]] = sub <2 x i7> zeroinitializer, [[X:%.*]]
-; CHECK-NEXT:    [[R:%.*]] = icmp ugt <2 x i7> [[NEGX]], <i7 42, i7 42>
+; CHECK-NEXT:    [[NOTSUB:%.*]] = add <2 x i7> [[X:%.*]], <i7 -1, i7 -1>
+; CHECK-NEXT:    [[R:%.*]] = icmp ult <2 x i7> [[NOTSUB]], <i7 -43, i7 -43>
 ; CHECK-NEXT:    ret <2 x i1> [[R]]
 ;
   %negx = sub <2 x i7> zeroinitializer, %x
@@ -343,8 +339,8 @@ define i1 @neg_sgt_42_use(i32 %x) {
 
 define i1 @neg_slt_n1(i8 %x) {
 ; CHECK-LABEL: @neg_slt_n1(
-; CHECK-NEXT:    [[NEGX:%.*]] = sub i8 0, [[X:%.*]]
-; CHECK-NEXT:    [[R:%.*]] = icmp slt i8 [[NEGX]], -1
+; CHECK-NEXT:    [[NOTSUB:%.*]] = add i8 [[X:%.*]], -1
+; CHECK-NEXT:    [[R:%.*]] = icmp sgt i8 [[NOTSUB]], 0
 ; CHECK-NEXT:    ret i1 [[R]]
 ;
   %negx = sub i8 0, %x
@@ -354,8 +350,8 @@ define i1 @neg_slt_n1(i8 %x) {
 
 define i1 @neg_slt_0(i8 %x) {
 ; CHECK-LABEL: @neg_slt_0(
-; CHECK-NEXT:    [[NEGX:%.*]] = sub i8 0, [[X:%.*]]
-; CHECK-NEXT:    [[ISNEGNEG:%.*]] = icmp slt i8 [[NEGX]], 0
+; CHECK-NEXT:    [[NOTSUB:%.*]] = add i8 [[X:%.*]], -1
+; CHECK-NEXT:    [[ISNEGNEG:%.*]] = icmp sgt i8 [[NOTSUB]], -1
 ; CHECK-NEXT:    ret i1 [[ISNEGNEG]]
 ;
   %negx = sub i8 0, %x
@@ -365,8 +361,7 @@ define i1 @neg_slt_0(i8 %x) {
 
 define i1 @neg_slt_1(i8 %x) {
 ; CHECK-LABEL: @neg_slt_1(
-; CHECK-NEXT:    [[NEGX:%.*]] = sub i8 0, [[X:%.*]]
-; CHECK-NEXT:    [[R:%.*]] = icmp slt i8 [[NEGX]], 1
+; CHECK-NEXT:    [[R:%.*]] = icmp ult i8 [[X:%.*]], -127
 ; CHECK-NEXT:    ret i1 [[R]]
 ;
   %negx = sub i8 0, %x
@@ -376,8 +371,8 @@ define i1 @neg_slt_1(i8 %x) {
 
 define i1 @neg_sgt_n1(i8 %x) {
 ; CHECK-LABEL: @neg_sgt_n1(
-; CHECK-NEXT:    [[NEGX:%.*]] = sub i8 0, [[X:%.*]]
-; CHECK-NEXT:    [[R:%.*]] = icmp sgt i8 [[NEGX]], -1
+; CHECK-NEXT:    [[NOTSUB:%.*]] = add i8 [[X:%.*]], -1
+; CHECK-NEXT:    [[R:%.*]] = icmp slt i8 [[NOTSUB]], 0
 ; CHECK-NEXT:    ret i1 [[R]]
 ;
   %negx = sub i8 0, %x
@@ -387,8 +382,7 @@ define i1 @neg_sgt_n1(i8 %x) {
 
 define i1 @neg_sgt_0(i8 %x) {
 ; CHECK-LABEL: @neg_sgt_0(
-; CHECK-NEXT:    [[NEGX:%.*]] = sub i8 0, [[X:%.*]]
-; CHECK-NEXT:    [[R:%.*]] = icmp sgt i8 [[NEGX]], 0
+; CHECK-NEXT:    [[R:%.*]] = icmp ugt i8 [[X:%.*]], -128
 ; CHECK-NEXT:    ret i1 [[R]]
 ;
   %negx = sub i8 0, %x
@@ -398,8 +392,8 @@ define i1 @neg_sgt_0(i8 %x) {
 
 define i1 @neg_sgt_1(i8 %x) {
 ; CHECK-LABEL: @neg_sgt_1(
-; CHECK-NEXT:    [[NEGX:%.*]] = sub i8 0, [[X:%.*]]
-; CHECK-NEXT:    [[R:%.*]] = icmp sgt i8 [[NEGX]], 1
+; CHECK-NEXT:    [[NOTSUB:%.*]] = add i8 [[X:%.*]], -1
+; CHECK-NEXT:    [[R:%.*]] = icmp slt i8 [[NOTSUB]], -2
 ; CHECK-NEXT:    ret i1 [[R]]
 ;
   %negx = sub i8 0, %x

diff  --git a/llvm/test/Transforms/InstCombine/or.ll b/llvm/test/Transforms/InstCombine/or.ll
index 90f4f45935353..5b4bff6f0c291 100644
--- a/llvm/test/Transforms/InstCombine/or.ll
+++ b/llvm/test/Transforms/InstCombine/or.ll
@@ -1447,11 +1447,10 @@ define i8 @lshr_bitwidth_mask(i8 %x, i8 %y) {
 
 define i1 @cmp_overlap(i32 %x) {
 ; CHECK-LABEL: @cmp_overlap(
-; CHECK-NEXT:    [[ISNEG:%.*]] = icmp slt i32 [[X:%.*]], 0
-; CHECK-NEXT:    [[NEGX:%.*]] = sub i32 0, [[X]]
-; CHECK-NEXT:    [[ISNOTNEG:%.*]] = icmp sgt i32 [[NEGX]], -1
-; CHECK-NEXT:    [[R:%.*]] = or i1 [[ISNEG]], [[ISNOTNEG]]
-; CHECK-NEXT:    ret i1 [[R]]
+; CHECK-NEXT:    [[NOTSUB:%.*]] = add i32 [[X:%.*]], -1
+; CHECK-NEXT:    [[TMP1:%.*]] = or i32 [[NOTSUB]], [[X]]
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp slt i32 [[TMP1]], 0
+; CHECK-NEXT:    ret i1 [[TMP2]]
 ;
   %isneg = icmp slt i32 %x, 0
   %negx = sub i32 0, %x


        


More information about the llvm-commits mailing list