[llvm] e158add - [InstCombine] Canonicalize `icmp eq/ne (A ^ C), B` to `icmp eq/ne (A ^ B), C` (#67273)

via llvm-commits llvm-commits at lists.llvm.org
Tue Sep 26 04:33:35 PDT 2023


Author: Yingwei Zheng
Date: 2023-09-26T19:33:31+08:00
New Revision: e158add121dd20cec3a363cb4e6e66b6072479d7

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

LOG: [InstCombine] Canonicalize `icmp eq/ne (A ^ C), B` to `icmp eq/ne (A ^ B), C` (#67273)

This patch canonicalizes `icmp eq/ne (A ^ Cst), B` to `icmp eq/ne (A ^ B), Cst` since the latter form exposes more optimizations.
Proof: https://alive2.llvm.org/ce/z/9DbhGc
Fixes #65968.

Added: 
    

Modified: 
    llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
    llvm/test/Transforms/InstCombine/icmp-equality-xor.ll
    llvm/test/Transforms/InstCombine/icmp-or.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
index 9aea16b80fef99f..b4b5c49a3adb696 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
@@ -5440,6 +5440,14 @@ Instruction *InstCombinerImpl::foldICmpEquality(ICmpInst &I) {
         Pred, A,
         Builder.CreateIntrinsic(Op0->getType(), Intrinsic::fshl, {A, A, B}));
 
+  // Canonicalize:
+  // icmp eq/ne OneUse(A ^ Cst), B --> icmp eq/ne (A ^ B), Cst
+  Constant *Cst;
+  if (match(&I, m_c_ICmp(PredUnused,
+                         m_OneUse(m_Xor(m_Value(A), m_ImmConstant(Cst))),
+                         m_Value(B))))
+    return new ICmpInst(Pred, Builder.CreateXor(A, B), Cst);
+
   return nullptr;
 }
 

diff  --git a/llvm/test/Transforms/InstCombine/icmp-equality-xor.ll b/llvm/test/Transforms/InstCombine/icmp-equality-xor.ll
index 4443ee40049a1ab..89ac2da2f6d1df5 100644
--- a/llvm/test/Transforms/InstCombine/icmp-equality-xor.ll
+++ b/llvm/test/Transforms/InstCombine/icmp-equality-xor.ll
@@ -4,8 +4,8 @@
 declare void @use(i32)
 define i1 @cmpeq_xor_cst1(i32 %a, i32 %b) {
 ; CHECK-LABEL: @cmpeq_xor_cst1(
-; CHECK-NEXT:    [[C:%.*]] = xor i32 [[A:%.*]], 10
-; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C]], [[B:%.*]]
+; CHECK-NEXT:    [[TMP1:%.*]] = xor i32 [[A:%.*]], [[B:%.*]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[TMP1]], 10
 ; CHECK-NEXT:    ret i1 [[CMP]]
 ;
   %c = xor i32 %a, 10
@@ -37,8 +37,8 @@ define i1 @cmpeq_xor_cst3(i32 %a, i32 %b) {
 
 define i1 @cmpne_xor_cst1(i32 %a, i32 %b) {
 ; CHECK-LABEL: @cmpne_xor_cst1(
-; CHECK-NEXT:    [[C:%.*]] = xor i32 [[A:%.*]], 10
-; CHECK-NEXT:    [[CMP:%.*]] = icmp ne i32 [[C]], [[B:%.*]]
+; CHECK-NEXT:    [[TMP1:%.*]] = xor i32 [[A:%.*]], [[B:%.*]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ne i32 [[TMP1]], 10
 ; CHECK-NEXT:    ret i1 [[CMP]]
 ;
   %c = xor i32 %a, 10
@@ -83,19 +83,21 @@ define i1 @cmpeq_xor_cst1_multiuse(i32 %a, i32 %b) {
 
 define i1 @cmpeq_xor_cst1_commuted(i32 %a, i32 %b) {
 ; CHECK-LABEL: @cmpeq_xor_cst1_commuted(
-; CHECK-NEXT:    [[C:%.*]] = xor i32 [[A:%.*]], 10
-; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C]], [[B:%.*]]
+; CHECK-NEXT:    [[B2:%.*]] = mul i32 [[B:%.*]], [[B]]
+; CHECK-NEXT:    [[TMP1:%.*]] = xor i32 [[B2]], [[A:%.*]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[TMP1]], 10
 ; CHECK-NEXT:    ret i1 [[CMP]]
 ;
+  %b2 = mul i32 %b, %b ; thwart complexity-based canonicalization
   %c = xor i32 %a, 10
-  %cmp = icmp eq i32 %b, %c
+  %cmp = icmp eq i32 %b2, %c
   ret i1 %cmp
 }
 
 define <2 x i1> @cmpeq_xor_cst1_vec(<2 x i32> %a, <2 x i32> %b) {
 ; CHECK-LABEL: @cmpeq_xor_cst1_vec(
-; CHECK-NEXT:    [[C:%.*]] = xor <2 x i32> [[A:%.*]], <i32 10, i32 11>
-; CHECK-NEXT:    [[CMP:%.*]] = icmp eq <2 x i32> [[C]], [[B:%.*]]
+; CHECK-NEXT:    [[TMP1:%.*]] = xor <2 x i32> [[A:%.*]], [[B:%.*]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq <2 x i32> [[TMP1]], <i32 10, i32 11>
 ; CHECK-NEXT:    ret <2 x i1> [[CMP]]
 ;
   %c = xor <2 x i32> %a, <i32 10, i32 11>
@@ -106,10 +108,8 @@ define <2 x i1> @cmpeq_xor_cst1_vec(<2 x i32> %a, <2 x i32> %b) {
 ; tests from PR65968
 define i1 @foo1(i32 %x, i32 %y) {
 ; CHECK-LABEL: @foo1(
-; CHECK-NEXT:    [[AND:%.*]] = and i32 [[X:%.*]], -2147483648
-; CHECK-NEXT:    [[NEG:%.*]] = and i32 [[Y:%.*]], -2147483648
-; CHECK-NEXT:    [[AND1:%.*]] = xor i32 [[NEG]], -2147483648
-; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[AND]], [[AND1]]
+; CHECK-NEXT:    [[NEG1:%.*]] = xor i32 [[Y:%.*]], [[X:%.*]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[NEG1]], 0
 ; CHECK-NEXT:    ret i1 [[CMP]]
 ;
   %and = and i32 %x, -2147483648
@@ -121,10 +121,8 @@ define i1 @foo1(i32 %x, i32 %y) {
 
 define i1 @foo2(i32 %x, i32 %y) {
 ; CHECK-LABEL: @foo2(
-; CHECK-NEXT:    [[AND:%.*]] = and i32 [[X:%.*]], -2147483648
-; CHECK-NEXT:    [[NEG:%.*]] = and i32 [[Y:%.*]], -2147483648
-; CHECK-NEXT:    [[AND1:%.*]] = xor i32 [[NEG]], -2147483648
-; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[AND]], [[AND1]]
+; CHECK-NEXT:    [[NEG1:%.*]] = xor i32 [[Y:%.*]], [[X:%.*]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[NEG1]], 0
 ; CHECK-NEXT:    ret i1 [[CMP]]
 ;
   %and = and i32 %x, -2147483648

diff  --git a/llvm/test/Transforms/InstCombine/icmp-or.ll b/llvm/test/Transforms/InstCombine/icmp-or.ll
index 6578cf753e2b9db..922845c1e7e2d82 100644
--- a/llvm/test/Transforms/InstCombine/icmp-or.ll
+++ b/llvm/test/Transforms/InstCombine/icmp-or.ll
@@ -172,8 +172,8 @@ define i1 @eq_const_mask_not_same(i8 %x, i8 %y) {
 define i1 @eq_const_mask_wrong_opcode(i8 %x, i8 %y) {
 ; CHECK-LABEL: @eq_const_mask_wrong_opcode(
 ; CHECK-NEXT:    [[B0:%.*]] = or i8 [[X:%.*]], 5
-; CHECK-NEXT:    [[B1:%.*]] = xor i8 [[Y:%.*]], 5
-; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i8 [[B0]], [[B1]]
+; CHECK-NEXT:    [[TMP1:%.*]] = xor i8 [[B0]], [[Y:%.*]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i8 [[TMP1]], 5
 ; CHECK-NEXT:    ret i1 [[CMP]]
 ;
   %b0 = or i8 %x, 5


        


More information about the llvm-commits mailing list