[llvm] [InstCombine] Loosen one-use restriction if common operand is constant (PR #79767)

via llvm-commits llvm-commits at lists.llvm.org
Sun Jan 28 12:45:20 PST 2024


https://github.com/AtariDreams updated https://github.com/llvm/llvm-project/pull/79767

>From 62602b0085b1c58729b2e56a9bfc50f4aa9c4879 Mon Sep 17 00:00:00 2001
From: Rose <83477269+AtariDreams at users.noreply.github.com>
Date: Sun, 28 Jan 2024 15:32:44 -0500
Subject: [PATCH 1/2] [InstCombine] pre-commit tests (NFC)

---
 llvm/test/Transforms/InstCombine/xor-and-or.ll | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/llvm/test/Transforms/InstCombine/xor-and-or.ll b/llvm/test/Transforms/InstCombine/xor-and-or.ll
index feba47912b1dac5..c78f2335f5e14d6 100644
--- a/llvm/test/Transforms/InstCombine/xor-and-or.ll
+++ b/llvm/test/Transforms/InstCombine/xor-and-or.ll
@@ -241,4 +241,19 @@ define i1 @xor_and_or_negative_oneuse(i1 %c, i1 %x, i1 %y) {
   ret i1 %r
 }
 
+define i32 @xor_and_or_constant(i32 %X, i32 %Y, i32 %Z) {
+; CHECK-LABEL: @xor_and_or_constant(
+; CHECK-NEXT:    [[TMP1:%.*]] = xor i32 [[X:%.*]], -1
+; CHECK-NEXT:    [[TMP2:%.*]] = xor i32 [[Y:%.*]], [[Z:%.*]]
+; CHECK-NEXT:    [[TMP3:%.*]] = and i32 [[TMP2]], [[TMP1]]
+; CHECK-NEXT:    ret i32 [[TMP3]]
+;
+  %1 = or i32 %X, %Y
+  %2 = or i32 %X, %Z
+  %3 = xor i32 %1, %2
+  %4 = xor i32 %X, -1
+  %5 = and i32 %3, %4
+  ret i32 %5
+}
+
 declare void @use(i1)

>From 96b47db2d1e55b923f7409fce6d73001e03e593d Mon Sep 17 00:00:00 2001
From: Rose <83477269+AtariDreams at users.noreply.github.com>
Date: Sun, 28 Jan 2024 13:30:29 -0500
Subject: [PATCH 2/2] [InstCombine] Loosen one-use restriction if common
 operand is constant

---
 .../InstCombine/InstCombineAndOrXor.cpp       | 18 +++++--------
 .../test/Transforms/InstCombine/xor-and-or.ll | 26 ++++++++++++++-----
 2 files changed, 27 insertions(+), 17 deletions(-)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
index 5fd944a859ef098..c72f3dfd4c6139e 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
@@ -4756,21 +4756,17 @@ Instruction *InstCombinerImpl::visitXor(BinaryOperator &I) {
     return BinaryOperator::CreateNot(Builder.CreateAnd(Op0, B));
 
   // (A | B) ^ (A | C) --> (B ^ C) & ~A -- There are 4 commuted variants.
-  // TODO: Loosen one-use restriction if common operand is a constant.
-  Value *D;
-  if (match(Op0, m_OneUse(m_Or(m_Value(A), m_Value(B)))) &&
-      match(Op1, m_OneUse(m_Or(m_Value(C), m_Value(D))))) {
-    if (B == C || B == D)
-      std::swap(A, B);
-    if (A == C)
-      std::swap(C, D);
-    if (A == D) {
-      Value *NotA = Builder.CreateNot(A);
-      return BinaryOperator::CreateAnd(Builder.CreateXor(B, C), NotA);
+  if (match(Op0, m_c_Or(m_Value(A), m_Value(B))) &&
+      match(Op1, m_c_Or(m_Specific(A), m_Value(C)))) {  
+    // Allow the tranformation to happen if A is one use or a constant.
+    if (A->hasOneUse() || match(A, m_ImmConstant())) {
+      return BinaryOperator::CreateAnd(Builder.CreateXor(B, C),
+                                       Builder.CreateNot(A));
     }
   }
 
   // (A & B) ^ (A | C) --> A ? ~B : C -- There are 4 commuted variants.
+  Value *D;
   if (I.getType()->isIntOrIntVectorTy(1) &&
       match(Op0, m_OneUse(m_LogicalAnd(m_Value(A), m_Value(B)))) &&
       match(Op1, m_OneUse(m_LogicalOr(m_Value(C), m_Value(D))))) {
diff --git a/llvm/test/Transforms/InstCombine/xor-and-or.ll b/llvm/test/Transforms/InstCombine/xor-and-or.ll
index c78f2335f5e14d6..234ca5ec481e8a9 100644
--- a/llvm/test/Transforms/InstCombine/xor-and-or.ll
+++ b/llvm/test/Transforms/InstCombine/xor-and-or.ll
@@ -241,11 +241,13 @@ define i1 @xor_and_or_negative_oneuse(i1 %c, i1 %x, i1 %y) {
   ret i1 %r
 }
 
-define i32 @xor_and_or_constant(i32 %X, i32 %Y, i32 %Z) {
-; CHECK-LABEL: @xor_and_or_constant(
-; CHECK-NEXT:    [[TMP1:%.*]] = xor i32 [[X:%.*]], -1
-; CHECK-NEXT:    [[TMP2:%.*]] = xor i32 [[Y:%.*]], [[Z:%.*]]
-; CHECK-NEXT:    [[TMP3:%.*]] = and i32 [[TMP2]], [[TMP1]]
+declare void @use(i1)
+
+define i32 @xor_and_or_c(i32 %X, i32 %Y, i32 %Z) {
+; CHECK-LABEL: @xor_and_or_c(
+; CHECK-NEXT:    [[TMP1:%.*]] = or i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[TMP2:%.*]] = or i32 [[X]], [[Z:%.*]]
+; CHECK-NEXT:    [[TMP3:%.*]] = xor i32 [[TMP1]], [[TMP2]]
 ; CHECK-NEXT:    ret i32 [[TMP3]]
 ;
   %1 = or i32 %X, %Y
@@ -256,4 +258,16 @@ define i32 @xor_and_or_constant(i32 %X, i32 %Y, i32 %Z) {
   ret i32 %5
 }
 
-declare void @use(i1)
+define i32 @xor_and_or_constant(i32 %Y, i32 %Z) {
+; CHECK-LABEL: @xor_and_or_constant(
+; CHECK-NEXT:    [[TMP1:%.*]] = xor i32 [[Y:%.*]], [[Z:%.*]]
+; CHECK-NEXT:    [[TMP2:%.*]] = and i32 [[TMP1]], -43
+; CHECK-NEXT:    ret i32 [[TMP2]]
+;
+  %1 = or i32 42, %Y
+  %2 = or i32 42, %Z
+  %3 = xor i32 %1, %2
+  %4 = xor i32 42, -1
+  %5 = and i32 %3, %4
+  ret i32 %5
+}



More information about the llvm-commits mailing list