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

Yingwei Zheng via llvm-commits llvm-commits at lists.llvm.org
Mon Sep 25 19:48:50 PDT 2023


https://github.com/dtcxzyw updated https://github.com/llvm/llvm-project/pull/67273

>From 4a59de712f25db1a6aec77df4ce0cb612dc49e9f Mon Sep 17 00:00:00 2001
From: Yingwei Zheng <dtcxzyw2333 at gmail.com>
Date: Mon, 25 Sep 2023 04:39:37 +0800
Subject: [PATCH 1/3] [InstCombine] Canonicalize `icmp eq/ne (A ^ C), B` to
 `icmp eq/ne (A ^ B), C`

---
 .../InstCombine/InstCombineCompares.cpp       |  9 ++++++
 .../InstCombine/icmp-equality-xor.ll          | 28 ++++++++-----------
 llvm/test/Transforms/InstCombine/icmp-or.ll   |  4 +--
 3 files changed, 23 insertions(+), 18 deletions(-)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
index 0903cd3f37b0f50..1a601ce46377e73 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
@@ -5437,6 +5437,15 @@ 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_Constant(Cst))),
+                     m_Value(B))))
+    return ICmpInst::Create(Instruction::ICmp, 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..8729f362c5bdb97 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,8 +83,8 @@ 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:    [[TMP1:%.*]] = xor i32 [[A:%.*]], [[B:%.*]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[TMP1]], 10
 ; CHECK-NEXT:    ret i1 [[CMP]]
 ;
   %c = xor i32 %a, 10
@@ -94,8 +94,8 @@ define i1 @cmpeq_xor_cst1_commuted(i32 %a, i32 %b) {
 
 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 +106,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 +119,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

>From f9ded0eb3ec62b65ba59c97c63cdedb25a66618d Mon Sep 17 00:00:00 2001
From: Yingwei Zheng <dtcxzyw2333 at gmail.com>
Date: Mon, 25 Sep 2023 15:51:33 +0800
Subject: [PATCH 2/3] fixup! [InstCombine] Canonicalize `icmp eq/ne (A ^ C), B`
 to `icmp eq/ne (A ^ B), C`

---
 llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
index 1a601ce46377e73..fa4726ed4c9ca05 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
@@ -5440,9 +5440,9 @@ Instruction *InstCombinerImpl::foldICmpEquality(ICmpInst &I) {
   // 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_Constant(Cst))),
-                     m_Value(B))))
+  if (match(&I, m_c_ICmp(PredUnused,
+                         m_OneUse(m_Xor(m_Value(A), m_ImmConstant(Cst))),
+                         m_Value(B))))
     return ICmpInst::Create(Instruction::ICmp, Pred, Builder.CreateXor(A, B),
                             Cst);
 

>From 2178fdad87e5f3996abca621a837e37116358b79 Mon Sep 17 00:00:00 2001
From: Yingwei Zheng <dtcxzyw2333 at gmail.com>
Date: Tue, 26 Sep 2023 10:35:10 +0800
Subject: [PATCH 3/3] fixup! [InstCombine] Canonicalize `icmp eq/ne (A ^ C), B`
 to `icmp eq/ne (A ^ B), C`

---
 llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp | 3 +--
 llvm/test/Transforms/InstCombine/icmp-equality-xor.ll   | 6 ++++--
 2 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
index fa4726ed4c9ca05..20d8fe6c9b51ff3 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
@@ -5443,8 +5443,7 @@ Instruction *InstCombinerImpl::foldICmpEquality(ICmpInst &I) {
   if (match(&I, m_c_ICmp(PredUnused,
                          m_OneUse(m_Xor(m_Value(A), m_ImmConstant(Cst))),
                          m_Value(B))))
-    return ICmpInst::Create(Instruction::ICmp, Pred, Builder.CreateXor(A, B),
-                            Cst);
+    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 8729f362c5bdb97..89ac2da2f6d1df5 100644
--- a/llvm/test/Transforms/InstCombine/icmp-equality-xor.ll
+++ b/llvm/test/Transforms/InstCombine/icmp-equality-xor.ll
@@ -83,12 +83,14 @@ 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:    [[TMP1:%.*]] = xor i32 [[A:%.*]], [[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
 }
 



More information about the llvm-commits mailing list