Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Closed
wants to merge 2 commits into from

Conversation

AtariDreams
Copy link
Contributor

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

@llvmbot
Copy link
Collaborator

llvmbot commented Jan 19, 2024

@llvm/pr-subscribers-llvm-transforms

Author: AtariDreams (AtariDreams)

Changes

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 --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

@nikic
Copy link
Contributor

nikic commented Jan 19, 2024

I believe #77231 subsumes this already.

@AtariDreams
Copy link
Contributor Author

@dtcxzyw This true?

We already have this for the OR variant, but this works for XOR as well.
@dtcxzyw
Copy link
Member

dtcxzyw commented Jan 22, 2024

@dtcxzyw This true?

Confirmed.

@AtariDreams AtariDreams deleted the xors branch January 22, 2024 17:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants