[llvm] 8075f68 - [InstCombine] add fold (X > C - 1) ^ (X < C + 1) --> X != C

Chenbing Zheng via llvm-commits llvm-commits at lists.llvm.org
Wed Jul 20 19:08:37 PDT 2022


Author: Chenbing Zheng
Date: 2022-07-21T10:08:21+08:00
New Revision: 8075f680c8fbff9d56055520ded00579b3c45ddc

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

LOG: [InstCombine] add fold (X > C - 1) ^ (X < C + 1) --> X != C

Considering the correctness of this pattern, we should avoid that C - 1
is non-negative and C + 1 is negative.

Alive2: https://alive2.llvm.org/ce/z/c_rBaq

Reviewed By: spatel

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

Added: 
    

Modified: 
    llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
    llvm/test/Transforms/InstCombine/set.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
index e45e3813947e5..fef902a46399b 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
@@ -3219,6 +3219,21 @@ Value *InstCombinerImpl::foldXorOfICmps(ICmpInst *LHS, ICmpInst *RHS,
       return TrueIfSignedL == TrueIfSignedR ? Builder.CreateIsNeg(XorLR) :
                                               Builder.CreateIsNotNeg(XorLR);
     }
+
+    // (X > C) ^ (X < C + 2) --> X != C + 1
+    // (X < C + 2) ^ (X > C) --> X != C + 1
+    // Considering the correctness of this pattern, we should avoid that C is
+    // non-negative and C + 2 is negative, although it will be matched by other
+    // patterns.
+    const APInt *C1, *C2;
+    if ((PredL == CmpInst::ICMP_SGT && match(LHS1, m_APInt(C1)) &&
+         PredR == CmpInst::ICMP_SLT && match(RHS1, m_APInt(C2))) ||
+        (PredL == CmpInst::ICMP_SLT && match(LHS1, m_APInt(C2)) &&
+         PredR == CmpInst::ICMP_SGT && match(RHS1, m_APInt(C1))))
+      if (LHS0 == RHS0 && *C1 + 2 == *C2 &&
+          (C1->isNegative() || C2->isNonNegative()))
+        return Builder.CreateICmpNE(LHS0,
+                                    ConstantInt::get(LHS0->getType(), *C1 + 1));
   }
 
   // Instead of trying to imitate the folds for and/or, decompose this 'xor'

diff  --git a/llvm/test/Transforms/InstCombine/set.ll b/llvm/test/Transforms/InstCombine/set.ll
index d98a16473b701..a54f7a5590ca0 100644
--- a/llvm/test/Transforms/InstCombine/set.ll
+++ b/llvm/test/Transforms/InstCombine/set.ll
@@ -222,14 +222,10 @@ define i1 @xor_of_icmps_commute(i64 %a) {
   ret i1 %xor
 }
 
-; FIXME: This is (a != 5).
-
 define i1 @xor_of_icmps_to_ne(i64 %a) {
 ; CHECK-LABEL: @xor_of_icmps_to_ne(
-; CHECK-NEXT:    [[B:%.*]] = icmp sgt i64 [[A:%.*]], 4
-; CHECK-NEXT:    [[C:%.*]] = icmp slt i64 [[A]], 6
-; CHECK-NEXT:    [[XOR:%.*]] = xor i1 [[B]], [[C]]
-; CHECK-NEXT:    ret i1 [[XOR]]
+; CHECK-NEXT:    [[TMP1:%.*]] = icmp ne i64 [[A:%.*]], 5
+; CHECK-NEXT:    ret i1 [[TMP1]]
 ;
   %b = icmp sgt i64 %a, 4
   %c = icmp slt i64 %a, 6
@@ -239,10 +235,8 @@ define i1 @xor_of_icmps_to_ne(i64 %a) {
 
 define i1 @xor_of_icmps_to_ne_commute(i64 %a) {
 ; CHECK-LABEL: @xor_of_icmps_to_ne_commute(
-; CHECK-NEXT:    [[C:%.*]] = icmp sgt i64 [[A:%.*]], 4
-; CHECK-NEXT:    [[B:%.*]] = icmp slt i64 [[A]], 6
-; CHECK-NEXT:    [[XOR:%.*]] = xor i1 [[B]], [[C]]
-; CHECK-NEXT:    ret i1 [[XOR]]
+; CHECK-NEXT:    [[TMP1:%.*]] = icmp ne i64 [[A:%.*]], 5
+; CHECK-NEXT:    ret i1 [[TMP1]]
 ;
   %c = icmp sgt i64 %a, 4
   %b = icmp slt i64 %a, 6
@@ -252,10 +246,8 @@ define i1 @xor_of_icmps_to_ne_commute(i64 %a) {
 
 define i1 @xor_of_icmps_neg_to_ne(i64 %a) {
 ; CHECK-LABEL: @xor_of_icmps_neg_to_ne(
-; CHECK-NEXT:    [[B:%.*]] = icmp sgt i64 [[A:%.*]], -6
-; CHECK-NEXT:    [[C:%.*]] = icmp slt i64 [[A]], -4
-; CHECK-NEXT:    [[XOR:%.*]] = xor i1 [[B]], [[C]]
-; CHECK-NEXT:    ret i1 [[XOR]]
+; CHECK-NEXT:    [[TMP1:%.*]] = icmp ne i64 [[A:%.*]], -5
+; CHECK-NEXT:    ret i1 [[TMP1]]
 ;
   %b = icmp sgt i64 %a, -6
   %c = icmp slt i64 %a, -4
@@ -265,10 +257,8 @@ define i1 @xor_of_icmps_neg_to_ne(i64 %a) {
 
 define <2 x i1> @xor_of_icmps_to_ne_vector(<2 x i64> %a) {
 ; CHECK-LABEL: @xor_of_icmps_to_ne_vector(
-; CHECK-NEXT:    [[B:%.*]] = icmp sgt <2 x i64> [[A:%.*]], <i64 4, i64 4>
-; CHECK-NEXT:    [[C:%.*]] = icmp slt <2 x i64> [[A]], <i64 6, i64 6>
-; CHECK-NEXT:    [[XOR:%.*]] = xor <2 x i1> [[B]], [[C]]
-; CHECK-NEXT:    ret <2 x i1> [[XOR]]
+; CHECK-NEXT:    [[TMP1:%.*]] = icmp ne <2 x i64> [[A:%.*]], <i64 5, i64 5>
+; CHECK-NEXT:    ret <2 x i1> [[TMP1]]
 ;
   %b = icmp sgt <2 x i64> %a, <i64 4, i64 4>
   %c = icmp slt <2 x i64> %a, <i64 6, i64 6>
@@ -292,10 +282,9 @@ define i1 @xor_of_icmps_to_ne_no_common_operand(i64 %a, i64 %z) {
 define i1 @xor_of_icmps_to_ne_extra_use_one(i64 %a) {
 ; CHECK-LABEL: @xor_of_icmps_to_ne_extra_use_one(
 ; CHECK-NEXT:    [[B:%.*]] = icmp sgt i64 [[A:%.*]], 4
-; CHECK-NEXT:    [[C:%.*]] = icmp slt i64 [[A]], 6
 ; CHECK-NEXT:    call void @use(i1 [[B]])
-; CHECK-NEXT:    [[XOR:%.*]] = xor i1 [[B]], [[C]]
-; CHECK-NEXT:    ret i1 [[XOR]]
+; CHECK-NEXT:    [[TMP1:%.*]] = icmp ne i64 [[A]], 5
+; CHECK-NEXT:    ret i1 [[TMP1]]
 ;
   %b = icmp sgt i64 %a, 4
   %c = icmp slt i64 %a, 6


        


More information about the llvm-commits mailing list