[llvm] 2bec8d6 - [InstCombine] Fold X + Y + C u< X

Nikita Popov via llvm-commits llvm-commits at lists.llvm.org
Mon Apr 25 03:53:50 PDT 2022


Author: Nikita Popov
Date: 2022-04-25T12:53:39+02:00
New Revision: 2bec8d6d59a1c90f2593040fb2b4eb339d83f8c9

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

LOG: [InstCombine] Fold X + Y + C u< X

This is a variation on the X + Y u< X fold with an extra constant.
Proof: https://alive2.llvm.org/ce/z/VNb8pY

Added: 
    

Modified: 
    llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
    llvm/test/Transforms/InstCombine/icmp-add.ll
    llvm/test/Transforms/InstCombine/result-of-add-of-negative-or-zero-is-non-zero-and-no-underflow.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
index 3e6a2f0d108a1..6c70299199c21 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
@@ -3970,6 +3970,24 @@ Instruction *InstCombinerImpl::foldICmpBinOp(ICmpInst &I,
       (Pred == ICmpInst::ICMP_UGT || Pred == ICmpInst::ICMP_ULE))
     return new ICmpInst(Pred, X, Builder.CreateNot(Op0));
 
+  {
+    // (Op1 + X) + C u</u>= Op1 --> ~C - X u</u>= Op1
+    Constant *C;
+    if (match(Op0, m_OneUse(m_Add(m_c_Add(m_Specific(Op1), m_Value(X)),
+                                  m_ImmConstant(C)))) &&
+        (Pred == ICmpInst::ICMP_ULT || Pred == ICmpInst::ICMP_UGE)) {
+      Constant *C2 = ConstantExpr::getNot(C);
+      return new ICmpInst(Pred, Builder.CreateSub(C2, X), Op1);
+    }
+    // Op0 u>/u<= (Op0 + X) + C --> Op0 u>/u<= ~C - X
+    if (match(Op1, m_OneUse(m_Add(m_c_Add(m_Specific(Op0), m_Value(X)),
+                                  m_ImmConstant(C)))) &&
+        (Pred == ICmpInst::ICMP_UGT || Pred == ICmpInst::ICMP_ULE)) {
+      Constant *C2 = ConstantExpr::getNot(C);
+      return new ICmpInst(Pred, Op0, Builder.CreateSub(C2, X));
+    }
+  }
+
   {
     // Similar to above: an unsigned overflow comparison may use offset + mask:
     // ((Op1 + C) & C) u<  Op1 --> Op1 != 0

diff  --git a/llvm/test/Transforms/InstCombine/icmp-add.ll b/llvm/test/Transforms/InstCombine/icmp-add.ll
index 308adcab05391..849946ce84af5 100644
--- a/llvm/test/Transforms/InstCombine/icmp-add.ll
+++ b/llvm/test/Transforms/InstCombine/icmp-add.ll
@@ -1027,9 +1027,8 @@ define i32 @decrement_min(i32 %x) {
 
 define i1 @icmp_add_add_C(i32 %a, i32 %b) {
 ; CHECK-LABEL: @icmp_add_add_C(
-; CHECK-NEXT:    [[ADD1:%.*]] = add i32 [[A:%.*]], [[B:%.*]]
-; CHECK-NEXT:    [[ADD2:%.*]] = add i32 [[ADD1]], -1
-; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i32 [[ADD2]], [[A]]
+; CHECK-NEXT:    [[TMP1:%.*]] = sub i32 0, [[B:%.*]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i32 [[TMP1]], [[A:%.*]]
 ; CHECK-NEXT:    ret i1 [[CMP]]
 ;
   %add1 = add i32 %a, %b
@@ -1040,9 +1039,8 @@ define i1 @icmp_add_add_C(i32 %a, i32 %b) {
 
 define i1 @icmp_add_add_C_pred(i32 %a, i32 %b) {
 ; CHECK-LABEL: @icmp_add_add_C_pred(
-; CHECK-NEXT:    [[ADD1:%.*]] = add i32 [[A:%.*]], [[B:%.*]]
-; CHECK-NEXT:    [[ADD2:%.*]] = add i32 [[ADD1]], -1
-; CHECK-NEXT:    [[CMP:%.*]] = icmp uge i32 [[ADD2]], [[A]]
+; CHECK-NEXT:    [[TMP1:%.*]] = sub i32 0, [[B:%.*]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp uge i32 [[TMP1]], [[A:%.*]]
 ; CHECK-NEXT:    ret i1 [[CMP]]
 ;
   %add1 = add i32 %a, %b
@@ -1079,9 +1077,8 @@ define i1 @icmp_add_add_C_wrong_operand(i32 %a, i32 %b, i32 %c) {
 
 define i1 @icmp_add_add_C_
diff erent_const(i32 %a, i32 %b) {
 ; CHECK-LABEL: @icmp_add_add_C_
diff erent_const(
-; CHECK-NEXT:    [[ADD1:%.*]] = add i32 [[A:%.*]], [[B:%.*]]
-; CHECK-NEXT:    [[ADD2:%.*]] = add i32 [[ADD1]], 42
-; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i32 [[ADD2]], [[A]]
+; CHECK-NEXT:    [[TMP1:%.*]] = sub i32 -43, [[B:%.*]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i32 [[TMP1]], [[A:%.*]]
 ; CHECK-NEXT:    ret i1 [[CMP]]
 ;
   %add1 = add i32 %a, %b
@@ -1092,9 +1089,8 @@ define i1 @icmp_add_add_C_
diff erent_const(i32 %a, i32 %b) {
 
 define <2 x i1> @icmp_add_add_C_vector(<2 x i8> %a, <2 x i8> %b) {
 ; CHECK-LABEL: @icmp_add_add_C_vector(
-; CHECK-NEXT:    [[ADD1:%.*]] = add <2 x i8> [[A:%.*]], [[B:%.*]]
-; CHECK-NEXT:    [[ADD2:%.*]] = add <2 x i8> [[ADD1]], <i8 10, i8 20>
-; CHECK-NEXT:    [[CMP:%.*]] = icmp ult <2 x i8> [[ADD2]], [[A]]
+; CHECK-NEXT:    [[TMP1:%.*]] = sub <2 x i8> <i8 -11, i8 -21>, [[B:%.*]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ult <2 x i8> [[TMP1]], [[A:%.*]]
 ; CHECK-NEXT:    ret <2 x i1> [[CMP]]
 ;
   %add1 = add <2 x i8> %a, %b
@@ -1105,9 +1101,8 @@ define <2 x i1> @icmp_add_add_C_vector(<2 x i8> %a, <2 x i8> %b) {
 
 define <2 x i1> @icmp_add_add_C_vector_undef(<2 x i8> %a, <2 x i8> %b) {
 ; CHECK-LABEL: @icmp_add_add_C_vector_undef(
-; CHECK-NEXT:    [[ADD1:%.*]] = add <2 x i8> [[A:%.*]], [[B:%.*]]
-; CHECK-NEXT:    [[ADD2:%.*]] = add <2 x i8> [[ADD1]], <i8 10, i8 undef>
-; CHECK-NEXT:    [[CMP:%.*]] = icmp ult <2 x i8> [[ADD2]], [[A]]
+; CHECK-NEXT:    [[TMP1:%.*]] = sub <2 x i8> <i8 -11, i8 undef>, [[B:%.*]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ult <2 x i8> [[TMP1]], [[A:%.*]]
 ; CHECK-NEXT:    ret <2 x i1> [[CMP]]
 ;
   %add1 = add <2 x i8> %a, %b
@@ -1118,9 +1113,8 @@ define <2 x i1> @icmp_add_add_C_vector_undef(<2 x i8> %a, <2 x i8> %b) {
 
 define i1 @icmp_add_add_C_comm1(i32 %a, i32 %b) {
 ; CHECK-LABEL: @icmp_add_add_C_comm1(
-; CHECK-NEXT:    [[ADD1:%.*]] = add i32 [[B:%.*]], [[A:%.*]]
-; CHECK-NEXT:    [[ADD2:%.*]] = add i32 [[ADD1]], -1
-; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i32 [[ADD2]], [[A]]
+; CHECK-NEXT:    [[TMP1:%.*]] = sub i32 0, [[B:%.*]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i32 [[TMP1]], [[A:%.*]]
 ; CHECK-NEXT:    ret i1 [[CMP]]
 ;
   %add1 = add i32 %b, %a
@@ -1132,9 +1126,8 @@ define i1 @icmp_add_add_C_comm1(i32 %a, i32 %b) {
 define i1 @icmp_add_add_C_comm2(i32 %X, i32 %b) {
 ; CHECK-LABEL: @icmp_add_add_C_comm2(
 ; CHECK-NEXT:    [[A:%.*]] = udiv i32 42, [[X:%.*]]
-; CHECK-NEXT:    [[ADD1:%.*]] = add i32 [[A]], [[B:%.*]]
-; CHECK-NEXT:    [[ADD2:%.*]] = add i32 [[ADD1]], -1
-; CHECK-NEXT:    [[CMP:%.*]] = icmp ugt i32 [[A]], [[ADD2]]
+; CHECK-NEXT:    [[TMP1:%.*]] = sub i32 0, [[B:%.*]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ugt i32 [[A]], [[TMP1]]
 ; CHECK-NEXT:    ret i1 [[CMP]]
 ;
   %a = udiv i32 42, %X ; thwart complexity-based canonicalization
@@ -1147,9 +1140,8 @@ define i1 @icmp_add_add_C_comm2(i32 %X, i32 %b) {
 define i1 @icmp_add_add_C_comm2_pred(i32 %X, i32 %b) {
 ; CHECK-LABEL: @icmp_add_add_C_comm2_pred(
 ; CHECK-NEXT:    [[A:%.*]] = udiv i32 42, [[X:%.*]]
-; CHECK-NEXT:    [[ADD1:%.*]] = add i32 [[A]], [[B:%.*]]
-; CHECK-NEXT:    [[ADD2:%.*]] = add i32 [[ADD1]], -1
-; CHECK-NEXT:    [[CMP:%.*]] = icmp ule i32 [[A]], [[ADD2]]
+; CHECK-NEXT:    [[TMP1:%.*]] = sub i32 0, [[B:%.*]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ule i32 [[A]], [[TMP1]]
 ; CHECK-NEXT:    ret i1 [[CMP]]
 ;
   %a = udiv i32 42, %X ; thwart complexity-based canonicalization
@@ -1177,9 +1169,8 @@ define i1 @icmp_add_add_C_comm2_wrong_pred(i32 %X, i32 %b) {
 define i1 @icmp_add_add_C_comm3(i32 %X, i32 %b) {
 ; CHECK-LABEL: @icmp_add_add_C_comm3(
 ; CHECK-NEXT:    [[A:%.*]] = udiv i32 42, [[X:%.*]]
-; CHECK-NEXT:    [[ADD1:%.*]] = add i32 [[A]], [[B:%.*]]
-; CHECK-NEXT:    [[ADD2:%.*]] = add i32 [[ADD1]], -1
-; CHECK-NEXT:    [[CMP:%.*]] = icmp ugt i32 [[A]], [[ADD2]]
+; CHECK-NEXT:    [[TMP1:%.*]] = sub i32 0, [[B:%.*]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ugt i32 [[A]], [[TMP1]]
 ; CHECK-NEXT:    ret i1 [[CMP]]
 ;
   %a = udiv i32 42, %X ; thwart complexity-based canonicalization
@@ -1208,8 +1199,8 @@ define i1 @icmp_add_add_C_extra_use2(i32 %a, i32 %b) {
 ; CHECK-LABEL: @icmp_add_add_C_extra_use2(
 ; CHECK-NEXT:    [[ADD1:%.*]] = add i32 [[A:%.*]], [[B:%.*]]
 ; CHECK-NEXT:    call void @use(i32 [[ADD1]])
-; CHECK-NEXT:    [[ADD2:%.*]] = add i32 [[ADD1]], -1
-; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i32 [[ADD2]], [[A]]
+; CHECK-NEXT:    [[TMP1:%.*]] = sub i32 0, [[B]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i32 [[TMP1]], [[A]]
 ; CHECK-NEXT:    ret i1 [[CMP]]
 ;
   %add1 = add i32 %a, %b

diff  --git a/llvm/test/Transforms/InstCombine/result-of-add-of-negative-or-zero-is-non-zero-and-no-underflow.ll b/llvm/test/Transforms/InstCombine/result-of-add-of-negative-or-zero-is-non-zero-and-no-underflow.ll
index 08def405c58b9..049b61eb2d81b 100644
--- a/llvm/test/Transforms/InstCombine/result-of-add-of-negative-or-zero-is-non-zero-and-no-underflow.ll
+++ b/llvm/test/Transforms/InstCombine/result-of-add-of-negative-or-zero-is-non-zero-and-no-underflow.ll
@@ -254,7 +254,7 @@ define i1 @t7(i8 %base, i8 %offset) {
 ; CHECK-LABEL: @t7(
 ; CHECK-NEXT:    [[ADJUSTED:%.*]] = add i8 [[BASE:%.*]], [[OFFSET:%.*]]
 ; CHECK-NEXT:    call void @use8(i8 [[ADJUSTED]])
-; CHECK-NEXT:    [[TMP1:%.*]] = add i8 [[ADJUSTED]], -1
+; CHECK-NEXT:    [[TMP1:%.*]] = sub i8 0, [[OFFSET]]
 ; CHECK-NEXT:    [[TMP2:%.*]] = icmp uge i8 [[TMP1]], [[BASE]]
 ; CHECK-NEXT:    ret i1 [[TMP2]]
 ;
@@ -270,7 +270,7 @@ define i1 @t7_logical(i8 %base, i8 %offset) {
 ; CHECK-LABEL: @t7_logical(
 ; CHECK-NEXT:    [[ADJUSTED:%.*]] = add i8 [[BASE:%.*]], [[OFFSET:%.*]]
 ; CHECK-NEXT:    call void @use8(i8 [[ADJUSTED]])
-; CHECK-NEXT:    [[TMP1:%.*]] = add i8 [[ADJUSTED]], -1
+; CHECK-NEXT:    [[TMP1:%.*]] = sub i8 0, [[OFFSET]]
 ; CHECK-NEXT:    [[TMP2:%.*]] = icmp uge i8 [[TMP1]], [[BASE]]
 ; CHECK-NEXT:    ret i1 [[TMP2]]
 ;


        


More information about the llvm-commits mailing list