Skip to content

Commit 904ac6f

Browse files
marcaubererhuihzhang
authored andcommitted
[InstCombine] Fold ((A&B)^A)|((A&B)^B) to A^B
Depends on D159379 ((A & B) ^ A) | ((A & B) ^ B) -> A ^ B (A ^ (A & B)) | (B ^ (A & B)) -> A ^ B ((A & B) ^ B) | ((A & B) ^ A) -> A ^ B (B ^ (A & B)) | (A ^ (A & B)) -> A ^ B Alive2: https://alive2.llvm.org/ce/z/i44xmq Baseline tests: https://reviews.llvm.org/D159379 Reviewed By: huihuiz Differential Revision: https://reviews.llvm.org/D159380
1 parent 04a6dc2 commit 904ac6f

File tree

2 files changed

+28
-29
lines changed

2 files changed

+28
-29
lines changed

llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp

+21
Original file line numberDiff line numberDiff line change
@@ -3650,6 +3650,27 @@ Instruction *InstCombinerImpl::visitOr(BinaryOperator &I) {
36503650
}
36513651
}
36523652

3653+
{
3654+
// ((A & B) ^ A) | ((A & B) ^ B) -> A ^ B
3655+
// (A ^ (A & B)) | (B ^ (A & B)) -> A ^ B
3656+
// ((A & B) ^ B) | ((A & B) ^ A) -> A ^ B
3657+
// (B ^ (A & B)) | (A ^ (A & B)) -> A ^ B
3658+
const auto TryXorOpt = [&](Value *Lhs, Value *Rhs) -> Instruction * {
3659+
if (match(Lhs, m_OneUse(m_c_Xor(m_And(m_Value(A), m_Value(B)),
3660+
m_Deferred(A)))) &&
3661+
match(Rhs, m_OneUse(m_c_Xor(m_And(m_Specific(A), m_Specific(B)),
3662+
m_Deferred(B))))) {
3663+
return BinaryOperator::CreateXor(A, B);
3664+
}
3665+
return nullptr;
3666+
};
3667+
3668+
if (Instruction *Result = TryXorOpt(Op0, Op1))
3669+
return Result;
3670+
if (Instruction *Result = TryXorOpt(Op1, Op0))
3671+
return Result;
3672+
}
3673+
36533674
if (Instruction *V =
36543675
canonicalizeCondSignextOfHighBitExtractToSignextHighBitExtract(I))
36553676
return V;

llvm/test/Transforms/InstCombine/or-xor-xor.ll

+7-29
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,7 @@ declare void @use.i32(i5)
77

88
define i1 @or_xor_xor_normal_variant1(i1 %a, i1 %b) {
99
; CHECK-LABEL: @or_xor_xor_normal_variant1(
10-
; CHECK-NEXT: [[AND:%.*]] = and i1 [[A:%.*]], [[B:%.*]]
11-
; CHECK-NEXT: [[XOR1:%.*]] = xor i1 [[AND]], [[A]]
12-
; CHECK-NEXT: [[XOR2:%.*]] = xor i1 [[AND]], [[B]]
13-
; CHECK-NEXT: [[OR:%.*]] = or i1 [[XOR1]], [[XOR2]]
10+
; CHECK-NEXT: [[OR:%.*]] = xor i1 [[A:%.*]], [[B:%.*]]
1411
; CHECK-NEXT: ret i1 [[OR]]
1512
;
1613
%and = and i1 %a, %b
@@ -22,10 +19,7 @@ define i1 @or_xor_xor_normal_variant1(i1 %a, i1 %b) {
2219

2320
define i8 @or_xor_xor_normal_variant2(i8 %a, i8 %b) {
2421
; CHECK-LABEL: @or_xor_xor_normal_variant2(
25-
; CHECK-NEXT: [[AND:%.*]] = and i8 [[A:%.*]], [[B:%.*]]
26-
; CHECK-NEXT: [[XOR1:%.*]] = xor i8 [[AND]], [[B]]
27-
; CHECK-NEXT: [[XOR2:%.*]] = xor i8 [[AND]], [[A]]
28-
; CHECK-NEXT: [[OR:%.*]] = or i8 [[XOR1]], [[XOR2]]
22+
; CHECK-NEXT: [[OR:%.*]] = xor i8 [[A:%.*]], [[B:%.*]]
2923
; CHECK-NEXT: ret i8 [[OR]]
3024
;
3125
%and = and i8 %a, %b
@@ -37,10 +31,7 @@ define i8 @or_xor_xor_normal_variant2(i8 %a, i8 %b) {
3731

3832
define i16 @or_xor_xor_normal_variant3(i16 %a, i16 %b) {
3933
; CHECK-LABEL: @or_xor_xor_normal_variant3(
40-
; CHECK-NEXT: [[AND:%.*]] = and i16 [[B:%.*]], [[A:%.*]]
41-
; CHECK-NEXT: [[XOR1:%.*]] = xor i16 [[AND]], [[B]]
42-
; CHECK-NEXT: [[XOR2:%.*]] = xor i16 [[AND]], [[A]]
43-
; CHECK-NEXT: [[OR:%.*]] = or i16 [[XOR1]], [[XOR2]]
34+
; CHECK-NEXT: [[OR:%.*]] = xor i16 [[B:%.*]], [[A:%.*]]
4435
; CHECK-NEXT: ret i16 [[OR]]
4536
;
4637
%and = and i16 %b, %a
@@ -52,10 +43,7 @@ define i16 @or_xor_xor_normal_variant3(i16 %a, i16 %b) {
5243

5344
define i64 @or_xor_xor_normal_variant4(i64 %a, i64 %b) {
5445
; CHECK-LABEL: @or_xor_xor_normal_variant4(
55-
; CHECK-NEXT: [[AND:%.*]] = and i64 [[B:%.*]], [[A:%.*]]
56-
; CHECK-NEXT: [[XOR1:%.*]] = xor i64 [[AND]], [[B]]
57-
; CHECK-NEXT: [[XOR2:%.*]] = xor i64 [[AND]], [[A]]
58-
; CHECK-NEXT: [[OR:%.*]] = or i64 [[XOR1]], [[XOR2]]
46+
; CHECK-NEXT: [[OR:%.*]] = xor i64 [[B:%.*]], [[A:%.*]]
5947
; CHECK-NEXT: ret i64 [[OR]]
6048
;
6149
%and = and i64 %b, %a
@@ -67,12 +55,7 @@ define i64 @or_xor_xor_normal_variant4(i64 %a, i64 %b) {
6755

6856
define i32 @or_xor_xor_normal_binops(i32 %aa, i32 %bb, i32 %cc) {
6957
; CHECK-LABEL: @or_xor_xor_normal_binops(
70-
; CHECK-NEXT: [[A:%.*]] = xor i32 [[AA:%.*]], [[CC:%.*]]
71-
; CHECK-NEXT: [[B:%.*]] = xor i32 [[BB:%.*]], [[CC]]
72-
; CHECK-NEXT: [[AND:%.*]] = and i32 [[B]], [[A]]
73-
; CHECK-NEXT: [[XOR1:%.*]] = xor i32 [[B]], [[AND]]
74-
; CHECK-NEXT: [[XOR2:%.*]] = xor i32 [[A]], [[AND]]
75-
; CHECK-NEXT: [[OR:%.*]] = or i32 [[XOR1]], [[XOR2]]
58+
; CHECK-NEXT: [[OR:%.*]] = xor i32 [[BB:%.*]], [[AA:%.*]]
7659
; CHECK-NEXT: ret i32 [[OR]]
7760
;
7861
%a = xor i32 %aa, %cc
@@ -87,10 +70,7 @@ define i32 @or_xor_xor_normal_binops(i32 %aa, i32 %bb, i32 %cc) {
8770

8871
define <3 x i1> @or_xor_xor_normal_vector(<3 x i1> %a, <3 x i1> %b) {
8972
; CHECK-LABEL: @or_xor_xor_normal_vector(
90-
; CHECK-NEXT: [[AND:%.*]] = and <3 x i1> [[A:%.*]], [[B:%.*]]
91-
; CHECK-NEXT: [[XOR1:%.*]] = xor <3 x i1> [[AND]], [[B]]
92-
; CHECK-NEXT: [[XOR2:%.*]] = xor <3 x i1> [[AND]], [[A]]
93-
; CHECK-NEXT: [[OR:%.*]] = or <3 x i1> [[XOR1]], [[XOR2]]
73+
; CHECK-NEXT: [[OR:%.*]] = xor <3 x i1> [[A:%.*]], [[B:%.*]]
9474
; CHECK-NEXT: ret <3 x i1> [[OR]]
9575
;
9676
%and = and <3 x i1> %a, %b
@@ -104,9 +84,7 @@ define i3 @or_xor_xor_normal_multiple_uses_and(i3 %a, i3 %b) {
10484
; CHECK-LABEL: @or_xor_xor_normal_multiple_uses_and(
10585
; CHECK-NEXT: [[AND:%.*]] = and i3 [[A:%.*]], [[B:%.*]]
10686
; CHECK-NEXT: call void @use.i3(i3 [[AND]])
107-
; CHECK-NEXT: [[XOR1:%.*]] = xor i3 [[AND]], [[B]]
108-
; CHECK-NEXT: [[XOR2:%.*]] = xor i3 [[AND]], [[A]]
109-
; CHECK-NEXT: [[OR:%.*]] = or i3 [[XOR1]], [[XOR2]]
87+
; CHECK-NEXT: [[OR:%.*]] = xor i3 [[A]], [[B]]
11088
; CHECK-NEXT: ret i3 [[OR]]
11189
;
11290
%and = and i3 %a, %b

0 commit comments

Comments
 (0)