Skip to content

Commit 7107113

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 7107113

File tree

2 files changed

+33
-18
lines changed

2 files changed

+33
-18
lines changed

llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4693,7 +4693,20 @@ 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+
// (X | Y) ^ M -> (X ^ M) ^ Y
4699+
// (X | Y) ^ M -> (Y ^ M) ^ X
4700+
if (match(&I, m_c_Xor(m_OneUse(m_DisjointOr(m_Value(X), m_Value(Y))),
4701+
m_Value(M)))) {
4702+
if (Value *XorAC =
4703+
simplifyBinOp(Instruction::Xor, X, M, SQ.getWithInstruction(&I)))
4704+
return BinaryOperator::CreateXor(XorAC, Y);
4705+
4706+
if (Value *XorBC = simplifyBinOp(Instruction::Xor, Y, M, SQ))
4707+
return BinaryOperator::CreateXor(XorBC, X);
4708+
}
4709+
46974710
if (match(&I, m_c_Xor(m_c_And(m_Not(m_Value(M)), m_Value()),
46984711
m_c_And(m_Deferred(M), m_Value())))) {
46994712
if (isGuaranteedNotToBeUndef(M))
@@ -4705,7 +4718,6 @@ Instruction *InstCombinerImpl::visitXor(BinaryOperator &I) {
47054718
if (Instruction *Xor = visitMaskedMerge(I, Builder))
47064719
return Xor;
47074720

4708-
Value *X, *Y;
47094721
Constant *C1;
47104722
if (match(Op1, m_Constant(C1))) {
47114723
Constant *C2;

llvm/test/Transforms/InstCombine/xor.ll

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1489,48 +1489,51 @@ 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
14981496
%xor = xor i32 %or, %a
14991497
ret i32 %xor
15001498
}
15011499

1502-
define i32 @xor_with_or_disjoint(i32 %a, i32 %b, i32 %c) {
1503-
; CHECK-LABEL: @xor_with_or_disjoint(
1500+
define i32 @xor_with_or_disjoint_ab(i32 %a, i32 %b) {
1501+
; CHECK-LABEL: @xor_with_or_disjoint_ab(
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
15111507
%xor = xor i32 %a, %or
15121508
ret i32 %xor
15131509
}
15141510

1515-
define <2 x i32> @or_disjoint_with_xor_vec(<2 x i32> %a, < 2 x i32> %b, <2 x i32> %c) {
1511+
define i32 @xor_with_or_disjoint_ba(i32 %a, i32 %b) {
1512+
; CHECK-LABEL: @xor_with_or_disjoint_ba(
1513+
; CHECK-NEXT: entry:
1514+
; CHECK-NEXT: ret i32 [[B:%.*]]
1515+
;
1516+
entry:
1517+
%or = or disjoint i32 %b, %a
1518+
%xor = xor i32 %b, %or
1519+
ret i32 %xor
1520+
}
1521+
1522+
define <2 x i32> @or_disjoint_with_xor_vec(<2 x i32> %a, < 2 x i32> %b) {
15161523
; CHECK-LABEL: @or_disjoint_with_xor_vec(
15171524
; 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]]
1525+
; CHECK-NEXT: ret <2 x i32> [[B:%.*]]
15211526
;
15221527
entry:
15231528
%or = or disjoint <2 x i32> %a, %b
15241529
%xor = xor <2 x i32> %or, %a
15251530
ret <2 x i32> %xor
15261531
}
15271532

1528-
define <2 x i32> @xor_with_or_disjoint_vec(<2 x i32> %a, < 2 x i32> %b, <2 x i32> %c) {
1533+
define <2 x i32> @xor_with_or_disjoint_vec(<2 x i32> %a, < 2 x i32> %b) {
15291534
; CHECK-LABEL: @xor_with_or_disjoint_vec(
15301535
; 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]]
1536+
; CHECK-NEXT: ret <2 x i32> [[B:%.*]]
15341537
;
15351538
entry:
15361539
%or = or disjoint <2 x i32> %a, %b

0 commit comments

Comments
 (0)