[llvm] [InstCombine] Fold (A & B) - (A & ~B) => B - (A ^ B) (PR #79717)
via llvm-commits
llvm-commits at lists.llvm.org
Sat Jan 27 16:49:27 PST 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-llvm-transforms
Author: AtariDreams (AtariDreams)
<details>
<summary>Changes</summary>
---
Full diff: https://github.com/llvm/llvm-project/pull/79717.diff
2 Files Affected:
- (modified) llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp (+18)
- (modified) llvm/test/Transforms/InstCombine/sub.ll (+26)
``````````diff
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
index 8a00b75a1f7404..aceb178263811c 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
@@ -2371,6 +2371,24 @@ Instruction *InstCombinerImpl::visitSub(BinaryOperator &I) {
return BinaryOperator::CreateNeg(Y);
}
+ {
+ Value *A, *B;
+ // (A & ~B) - (A & B) => (A ^ B) - B
+ if (match(Op0, m_c_And(m_Value(A), m_Not(m_Value(B)))) &&
+ match(Op1, m_c_And(m_Specific(A), m_Specific(B)))) {
+ return BinaryOperator::CreateSub(Builder.CreateXor(A, B), B);
+ }
+ }
+
+ {
+ Value *A, *B;
+ // (A & B) - (A & ~B) => B - (A ^ B)
+ if (match(Op1, m_c_And(m_Value(A), m_Not(m_Value(B)))) &&
+ match(Op0, m_c_And(m_Specific(A), m_Specific(B)))) {
+ return BinaryOperator::CreateSub(Builder.CreateXor(A, B), B);
+ }
+ }
+
// (sub (or A, B) (and A, B)) --> (xor A, B)
{
Value *A, *B;
diff --git a/llvm/test/Transforms/InstCombine/sub.ll b/llvm/test/Transforms/InstCombine/sub.ll
index 494cdf62c7975e..65142d4e200633 100644
--- a/llvm/test/Transforms/InstCombine/sub.ll
+++ b/llvm/test/Transforms/InstCombine/sub.ll
@@ -2626,3 +2626,29 @@ define i8 @sub_of_adds_2xc(i8 %x, i8 %y) {
%r = sub i8 %xc, %yc
ret i8 %r
}
+
+define i32 @sub_and_xor(i32 %A, i32 %B) {
+; CHECK-LABEL: @sub_and_xor(
+; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[A:%.*]], [[B:%.*]]
+; CHECK-NEXT: [[RES:%.*]] = sub i32 [[TMP1]], [[B]]
+; CHECK-NEXT: ret i32 [[RES]]
+;
+ %xor = xor i32 %B, -1
+ %and1 = and i32 %xor, %A
+ %and2 = and i32 %B, %A
+ %res = sub nsw i32 %and1, %and2
+ ret i32 %res
+}
+
+define i32 @sub_xor_and(i32 %A, i32 %B) {
+; CHECK-LABEL: @sub_xor_and(
+; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[A:%.*]], [[B:%.*]]
+; CHECK-NEXT: [[RES:%.*]] = sub i32 [[TMP1]], [[B]]
+; CHECK-NEXT: ret i32 [[RES]]
+;
+ %and1 = and i32 %B, %A
+ %xor = xor i32 %B, -1
+ %and2 = and i32 %xor, %A
+ %res = sub nsw i32 %and1, %and2
+ ret i32 %res
+}
``````````
</details>
https://github.com/llvm/llvm-project/pull/79717
More information about the llvm-commits
mailing list