[llvm] [InstCombine] Implement ((B ^ C) & A) | B -> B | (A & C) (PR #78782)

via llvm-commits llvm-commits at lists.llvm.org
Fri Jan 19 12:53:05 PST 2024


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-llvm-transforms

Author: AtariDreams (AtariDreams)

<details>
<summary>Changes</summary>

We already have this for the OR variant, but this works for XOR as well.

---
Full diff: https://github.com/llvm/llvm-project/pull/78782.diff


2 Files Affected:

- (modified) llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp (+8) 
- (modified) llvm/test/Transforms/InstCombine/or.ll (+62-4) 


``````````diff
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
index 5fd944a859ef09..3d1407062cf658 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
@@ -3544,6 +3544,14 @@ Instruction *InstCombinerImpl::visitOr(BinaryOperator &I) {
   if (match(Op1, m_c_And(m_c_Or(m_Specific(Op0), m_Value(C)), m_Value(A))))
     return BinaryOperator::CreateOr(Op0, Builder.CreateAnd(A, C));
 
+  // ((B ^ C) & A) | B -> B | (A & C)
+  if (match(Op0, m_c_And(m_c_Xor(m_Specific(Op1), m_Value(C)), m_Value(A))))
+    return BinaryOperator::CreateOr(Op1, Builder.CreateAnd(A, C));
+
+  // B | ((B ^ C) & A) -> B | (A & C)
+  if (match(Op1, m_c_And(m_c_Xor(m_Specific(Op0), m_Value(C)), m_Value(A))))
+    return BinaryOperator::CreateOr(Op0, Builder.CreateAnd(A, C));
+
   if (Instruction *DeMorgan = matchDeMorgansLaws(I, *this))
     return DeMorgan;
 
diff --git a/llvm/test/Transforms/InstCombine/or.ll b/llvm/test/Transforms/InstCombine/or.ll
index 573a11599141a7..8d13fe09cf3881 100644
--- a/llvm/test/Transforms/InstCombine/or.ll
+++ b/llvm/test/Transforms/InstCombine/or.ll
@@ -799,6 +799,64 @@ define i32 @test45_commuted3(i32 %x, i32 %y, i32 %z) {
   ret i32 %or1
 }
 
+define i32 @test45a(i32 %x, i32 %y, i32 %z) {
+; CHECK-LABEL: @test45a(
+; CHECK-NEXT:    [[TMP1:%.*]] = and i32 [[X:%.*]], [[Z:%.*]]
+; CHECK-NEXT:    [[OR:%.*]] = or i32 [[TMP1]], [[Y:%.*]]
+; CHECK-NEXT:    ret i32 [[OR]]
+;
+  %xor = xor i32 %y, %z
+  %and = and i32 %x, %xor
+  %or = or i32 %and, %y
+  ret i32 %or
+}
+
+define i32 @test45a_commuted1(i32 %x, i32 %y, i32 %z) {
+; CHECK-LABEL: @test45a_commuted1(
+; CHECK-NEXT:    [[YY:%.*]] = mul i32 [[Y:%.*]], [[Y]]
+; CHECK-NEXT:    [[TMP1:%.*]] = and i32 [[X:%.*]], [[Z:%.*]]
+; CHECK-NEXT:    [[OR:%.*]] = or i32 [[YY]], [[TMP1]]
+; CHECK-NEXT:    ret i32 [[OR]]
+;
+  %yy = mul i32 %y, %y ; thwart complexity-based ordering
+  %xor = xor i32 %yy, %z
+  %and = and i32 %xor, %x
+  %or = or i32 %yy, %and
+  ret i32 %or
+}
+
+define i32 @test45a_commuted2(i32 %x, i32 %y, i32 %z) {
+; CHECK-LABEL: @test45a_commuted2(
+; CHECK-NEXT:    [[YY:%.*]] = mul i32 [[Y:%.*]], [[Y]]
+; CHECK-NEXT:    [[XX:%.*]] = mul i32 [[X:%.*]], [[X]]
+; CHECK-NEXT:    [[TMP1:%.*]] = and i32 [[XX]], [[Z:%.*]]
+; CHECK-NEXT:    [[OR:%.*]] = or i32 [[YY]], [[TMP1]]
+; CHECK-NEXT:    ret i32 [[OR]]
+;
+  %yy = mul i32 %y, %y ; thwart complexity-based ordering
+  %xx = mul i32 %x, %x ; thwart complexity-based ordering
+  %xor = xor i32 %yy, %z
+  %and = and i32 %xx, %xor
+  %or = or i32 %and, %yy
+  ret i32 %or
+}
+
+define i32 @test45a_commuted3(i32 %x, i32 %y, i32 %z) {
+; CHECK-LABEL: @test45a_commuted3(
+; CHECK-NEXT:    [[YY:%.*]] = mul i32 [[Y:%.*]], [[Y]]
+; CHECK-NEXT:    [[ZZ:%.*]] = mul i32 [[Z:%.*]], [[Z]]
+; CHECK-NEXT:    [[TMP1:%.*]] = and i32 [[ZZ]], [[X:%.*]]
+; CHECK-NEXT:    [[OR:%.*]] = or i32 [[YY]], [[TMP1]]
+; CHECK-NEXT:    ret i32 [[OR]]
+;
+  %yy = mul i32 %y, %y ; thwart complexity-based ordering
+  %zz = mul i32 %z, %z ; thwart complexity-based ordering
+  %xor = xor i32 %zz, %yy
+  %and = and i32 %xor, %x
+  %or = or i32 %and, %yy
+  ret i32 %or
+}
+
 define i1 @test46(i8 signext %c)  {
 ; CHECK-LABEL: @test46(
 ; CHECK-NEXT:    [[TMP1:%.*]] = and i8 [[C:%.*]], -33
@@ -1242,13 +1300,13 @@ define i1 @orn_and_cmp_4_logical(i32 %a, i32 %b, i32 %c) {
 ; The constant vectors are inverses. Make sure we can turn this into a select without crashing trying to truncate the constant to 16xi1.
 define <16 x i1> @test51(<16 x i1> %arg, <16 x i1> %arg1) {
 ; CHECK-LABEL: @test51(
-; CHECK-NEXT:    [[TMP3:%.*]] = shufflevector <16 x i1> [[ARG:%.*]], <16 x i1> [[ARG1:%.*]], <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 20, i32 5, i32 6, i32 23, i32 24, i32 9, i32 10, i32 27, i32 28, i32 29, i32 30, i32 31>
-; CHECK-NEXT:    ret <16 x i1> [[TMP3]]
+; CHECK-NEXT:    [[RET:%.*]] = shufflevector <16 x i1> [[ARG:%.*]], <16 x i1> [[ARG1:%.*]], <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 20, i32 5, i32 6, i32 23, i32 24, i32 9, i32 10, i32 27, i32 28, i32 29, i32 30, i32 31>
+; CHECK-NEXT:    ret <16 x i1> [[RET]]
 ;
   %tmp = and <16 x i1> %arg, <i1 true, i1 true, i1 true, i1 true, i1 false, i1 true, i1 true, i1 false, i1 false, i1 true, i1 true, i1 false, i1 false, i1 false, i1 false, i1 false>
   %tmp2 = and <16 x i1> %arg1, <i1 false, i1 false, i1 false, i1 false, i1 true, i1 false, i1 false, i1 true, i1 true, i1 false, i1 false, i1 true, i1 true, i1 true, i1 true, i1 true>
-  %tmp3 = or <16 x i1> %tmp, %tmp2
-  ret <16 x i1> %tmp3
+  %ret = or <16 x i1> %tmp, %tmp2
+  ret <16 x i1> %ret
 }
 
 ; This would infinite loop because it reaches a transform

``````````

</details>


https://github.com/llvm/llvm-project/pull/78782


More information about the llvm-commits mailing list