Skip to content

Commit f6c06b9

Browse files
committed
[InstCombine] Fold Xor with or disjoint
Implement a missing optimization to fold (A | B) ^ C to (A ^ C) ^ B
1 parent 32c42b7 commit f6c06b9

File tree

2 files changed

+17
-14
lines changed

2 files changed

+17
-14
lines changed

llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4693,7 +4693,19 @@ Instruction *InstCombinerImpl::visitXor(BinaryOperator &I) {
46934693
// calls in there are unnecessary as SimplifyDemandedInstructionBits should
46944694
// have already taken care of those cases.
46954695
Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
4696-
Value *M;
4696+
Value *X, *Y, *M;
4697+
4698+
// (A | B) ^ C -> (A ^ C) ^ B
4699+
// C ^ (A | B) -> B ^ (A ^ C)
4700+
if (match(&I, m_c_Xor(m_OneUse(m_c_DisjointOr(m_Value(X), m_Value(Y))),
4701+
m_Value(M)))) {
4702+
if (Value *XorAC = simplifyBinOp(Instruction::Xor, X, M, SQ))
4703+
return BinaryOperator::CreateXor(XorAC, Y);
4704+
4705+
if (Value *XorBC = simplifyBinOp(Instruction::Xor, Y, M, SQ))
4706+
return BinaryOperator::CreateXor(XorBC, X);
4707+
}
4708+
46974709
if (match(&I, m_c_Xor(m_c_And(m_Not(m_Value(M)), m_Value()),
46984710
m_c_And(m_Deferred(M), m_Value())))) {
46994711
if (isGuaranteedNotToBeUndef(M))
@@ -4705,7 +4717,6 @@ Instruction *InstCombinerImpl::visitXor(BinaryOperator &I) {
47054717
if (Instruction *Xor = visitMaskedMerge(I, Builder))
47064718
return Xor;
47074719

4708-
Value *X, *Y;
47094720
Constant *C1;
47104721
if (match(Op1, m_Constant(C1))) {
47114722
Constant *C2;

llvm/test/Transforms/InstCombine/xor.ll

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1489,9 +1489,7 @@ define i4 @PR96857_xor_without_noundef(i4 %val0, i4 %val1, i4 %val2) {
14891489
define i32 @or_disjoint_with_xor(i32 %a, i32 %b) {
14901490
; CHECK-LABEL: @or_disjoint_with_xor(
14911491
; CHECK-NEXT: entry:
1492-
; CHECK-NEXT: [[TMP0:%.*]] = xor i32 [[A:%.*]], -1
1493-
; CHECK-NEXT: [[XOR:%.*]] = and i32 [[B:%.*]], [[TMP0]]
1494-
; CHECK-NEXT: ret i32 [[XOR]]
1492+
; CHECK-NEXT: ret i32 [[B:%.*]]
14951493
;
14961494
entry:
14971495
%or = or disjoint i32 %a, %b
@@ -1502,9 +1500,7 @@ entry:
15021500
define i32 @xor_with_or_disjoint(i32 %a, i32 %b, i32 %c) {
15031501
; CHECK-LABEL: @xor_with_or_disjoint(
15041502
; CHECK-NEXT: entry:
1505-
; CHECK-NEXT: [[TMP0:%.*]] = xor i32 [[A:%.*]], -1
1506-
; CHECK-NEXT: [[XOR:%.*]] = and i32 [[B:%.*]], [[TMP0]]
1507-
; CHECK-NEXT: ret i32 [[XOR]]
1503+
; CHECK-NEXT: ret i32 [[B:%.*]]
15081504
;
15091505
entry:
15101506
%or = or disjoint i32 %a, %b
@@ -1515,9 +1511,7 @@ entry:
15151511
define <2 x i32> @or_disjoint_with_xor_vec(<2 x i32> %a, < 2 x i32> %b, <2 x i32> %c) {
15161512
; CHECK-LABEL: @or_disjoint_with_xor_vec(
15171513
; CHECK-NEXT: entry:
1518-
; CHECK-NEXT: [[TMP0:%.*]] = xor <2 x i32> [[A:%.*]], <i32 -1, i32 -1>
1519-
; CHECK-NEXT: [[XOR:%.*]] = and <2 x i32> [[B:%.*]], [[TMP0]]
1520-
; CHECK-NEXT: ret <2 x i32> [[XOR]]
1514+
; CHECK-NEXT: ret <2 x i32> [[B:%.*]]
15211515
;
15221516
entry:
15231517
%or = or disjoint <2 x i32> %a, %b
@@ -1528,9 +1522,7 @@ entry:
15281522
define <2 x i32> @xor_with_or_disjoint_vec(<2 x i32> %a, < 2 x i32> %b, <2 x i32> %c) {
15291523
; CHECK-LABEL: @xor_with_or_disjoint_vec(
15301524
; CHECK-NEXT: entry:
1531-
; CHECK-NEXT: [[TMP0:%.*]] = xor <2 x i32> [[A:%.*]], <i32 -1, i32 -1>
1532-
; CHECK-NEXT: [[XOR:%.*]] = and <2 x i32> [[B:%.*]], [[TMP0]]
1533-
; CHECK-NEXT: ret <2 x i32> [[XOR]]
1525+
; CHECK-NEXT: ret <2 x i32> [[B:%.*]]
15341526
;
15351527
entry:
15361528
%or = or disjoint <2 x i32> %a, %b

0 commit comments

Comments
 (0)