Skip to content

Commit 9614f69

Browse files
authored
[InstCombine] Fold Xor with or disjoint (#105992)
Implement a missing optimization fold `(X | Y) ^ M to (X ^ M) ^ Y` and `(X | Y) ^ M to (Y ^ M) ^ X`
1 parent 2f1e04f commit 9614f69

File tree

2 files changed

+193
-2
lines changed

2 files changed

+193
-2
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: 179 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1485,3 +1485,182 @@ define i4 @PR96857_xor_without_noundef(i4 %val0, i4 %val1, i4 %val2) {
14851485
%val7 = xor i4 %val4, %val6
14861486
ret i4 %val7
14871487
}
1488+
1489+
define i32 @or_disjoint_with_xor(i32 %a, i32 %b) {
1490+
; CHECK-LABEL: @or_disjoint_with_xor(
1491+
; CHECK-NEXT: entry:
1492+
; CHECK-NEXT: ret i32 [[B:%.*]]
1493+
;
1494+
entry:
1495+
%or = or disjoint i32 %a, %b
1496+
%xor = xor i32 %or, %a
1497+
ret i32 %xor
1498+
}
1499+
1500+
define i32 @xor_with_or_disjoint_ab(i32 %a, i32 %b) {
1501+
; CHECK-LABEL: @xor_with_or_disjoint_ab(
1502+
; CHECK-NEXT: entry:
1503+
; CHECK-NEXT: ret i32 [[B:%.*]]
1504+
;
1505+
entry:
1506+
%or = or disjoint i32 %a, %b
1507+
%xor = xor i32 %a, %or
1508+
ret i32 %xor
1509+
}
1510+
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) {
1523+
; CHECK-LABEL: @or_disjoint_with_xor_vec(
1524+
; CHECK-NEXT: entry:
1525+
; CHECK-NEXT: ret <2 x i32> [[B:%.*]]
1526+
;
1527+
entry:
1528+
%or = or disjoint <2 x i32> %a, %b
1529+
%xor = xor <2 x i32> %or, %a
1530+
ret <2 x i32> %xor
1531+
}
1532+
1533+
define <2 x i32> @xor_with_or_disjoint_vec(<2 x i32> %a, < 2 x i32> %b) {
1534+
; CHECK-LABEL: @xor_with_or_disjoint_vec(
1535+
; CHECK-NEXT: entry:
1536+
; CHECK-NEXT: ret <2 x i32> [[B:%.*]]
1537+
;
1538+
entry:
1539+
%or = or disjoint <2 x i32> %a, %b
1540+
%xor = xor <2 x i32> %a, %or
1541+
ret <2 x i32> %xor
1542+
}
1543+
1544+
define i32 @select_or_disjoint_xor(i32 %a, i1 %c) {
1545+
; CHECK-LABEL: @select_or_disjoint_xor(
1546+
; CHECK-NEXT: entry:
1547+
; CHECK-NEXT: [[S:%.*]] = select i1 [[C:%.*]], i32 0, i32 4
1548+
; CHECK-NEXT: [[SHL:%.*]] = shl i32 [[A:%.*]], 4
1549+
; CHECK-NEXT: [[OR:%.*]] = or disjoint i32 [[S]], [[SHL]]
1550+
; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[OR]], 4
1551+
; CHECK-NEXT: ret i32 [[XOR]]
1552+
;
1553+
entry:
1554+
%s = select i1 %c, i32 0, i32 4
1555+
%shl = shl i32 %a, 4
1556+
%or = or disjoint i32 %s, %shl
1557+
%xor = xor i32 %or, 4
1558+
ret i32 %xor
1559+
}
1560+
1561+
define <2 x i32> @select_or_disjoint_xor_vec(<2 x i32> %a, i1 %c) {
1562+
; CHECK-LABEL: @select_or_disjoint_xor_vec(
1563+
; CHECK-NEXT: entry:
1564+
; CHECK-NEXT: [[S:%.*]] = select i1 [[C:%.*]], <2 x i32> zeroinitializer, <2 x i32> <i32 4, i32 4>
1565+
; CHECK-NEXT: [[SHL:%.*]] = shl <2 x i32> [[A:%.*]], <i32 4, i32 4>
1566+
; CHECK-NEXT: [[OR:%.*]] = or disjoint <2 x i32> [[S]], [[SHL]]
1567+
; CHECK-NEXT: [[XOR:%.*]] = xor <2 x i32> [[OR]], <i32 4, i32 4>
1568+
; CHECK-NEXT: ret <2 x i32> [[XOR]]
1569+
;
1570+
entry:
1571+
%s = select i1 %c, <2 x i32> <i32 0, i32 0>, <2 x i32> <i32 4, i32 4>
1572+
%shl = shl <2 x i32> %a, <i32 4, i32 4>
1573+
%or = or <2 x i32> %s, %shl
1574+
%xor = xor <2 x i32> %or, <i32 4, i32 4>
1575+
ret <2 x i32> %xor
1576+
}
1577+
1578+
define i32 @select_or_disjoint_or(i32 %a, i1 %c) {
1579+
; CHECK-LABEL: @select_or_disjoint_or(
1580+
; CHECK-NEXT: entry:
1581+
; CHECK-NEXT: [[S:%.*]] = select i1 [[C:%.*]], i32 0, i32 4
1582+
; CHECK-NEXT: [[SHL:%.*]] = shl i32 [[A:%.*]], 4
1583+
; CHECK-NEXT: [[OR:%.*]] = or disjoint i32 [[S]], [[SHL]]
1584+
; CHECK-NEXT: [[ADD:%.*]] = add nuw nsw i32 [[OR]], 4
1585+
; CHECK-NEXT: ret i32 [[ADD]]
1586+
;
1587+
entry:
1588+
%s = select i1 %c, i32 0, i32 4
1589+
%shl = shl i32 %a, 4
1590+
%or = or disjoint i32 %s, %shl
1591+
%add = add i32 %or, 4
1592+
ret i32 %add
1593+
}
1594+
1595+
define <2 x i32> @select_or_disjoint_or_vec(<2 x i32> %a, i1 %c) {
1596+
; CHECK-LABEL: @select_or_disjoint_or_vec(
1597+
; CHECK-NEXT: entry:
1598+
; CHECK-NEXT: [[S:%.*]] = select i1 [[C:%.*]], <2 x i32> zeroinitializer, <2 x i32> <i32 4, i32 4>
1599+
; CHECK-NEXT: [[SHL:%.*]] = shl <2 x i32> [[A:%.*]], <i32 4, i32 4>
1600+
; CHECK-NEXT: [[OR:%.*]] = or disjoint <2 x i32> [[S]], [[SHL]]
1601+
; CHECK-NEXT: [[ADD:%.*]] = add nuw nsw <2 x i32> [[OR]], <i32 4, i32 4>
1602+
; CHECK-NEXT: ret <2 x i32> [[ADD]]
1603+
;
1604+
entry:
1605+
%s = select i1 %c, <2 x i32> <i32 0, i32 0>, <2 x i32> <i32 4, i32 4>
1606+
%shl = shl <2 x i32> %a, <i32 4, i32 4>
1607+
%or = or <2 x i32> %s, %shl
1608+
%add = add <2 x i32> %or, <i32 4, i32 4>
1609+
ret <2 x i32> %add
1610+
}
1611+
1612+
define i32 @or_multi_use_disjoint_with_xor(i32 %a, i32 %b, i32 %c) {
1613+
; CHECK-LABEL: @or_multi_use_disjoint_with_xor(
1614+
; CHECK-NEXT: entry:
1615+
; CHECK-NEXT: [[OR:%.*]] = or disjoint i32 [[A:%.*]], [[B:%.*]]
1616+
; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[OR]], [[C:%.*]]
1617+
; CHECK-NEXT: [[ADD:%.*]] = add i32 [[OR]], [[XOR]]
1618+
; CHECK-NEXT: ret i32 [[ADD]]
1619+
;
1620+
entry:
1621+
%or = or disjoint i32 %a, %b
1622+
%xor = xor i32 %or, %c
1623+
%add = add i32 %or, %xor
1624+
ret i32 %add
1625+
}
1626+
1627+
define <2 x i32> @or_multi_use_disjoint_with_xor_vec(<2 x i32> %a, <2 x i32> %b, <2 x i32> %c) {
1628+
; CHECK-LABEL: @or_multi_use_disjoint_with_xor_vec(
1629+
; CHECK-NEXT: entry:
1630+
; CHECK-NEXT: [[OR:%.*]] = or disjoint <2 x i32> [[A:%.*]], [[B:%.*]]
1631+
; CHECK-NEXT: [[XOR:%.*]] = xor <2 x i32> [[OR]], [[C:%.*]]
1632+
; CHECK-NEXT: [[ADD:%.*]] = add <2 x i32> [[OR]], [[XOR]]
1633+
; CHECK-NEXT: ret <2 x i32> [[ADD]]
1634+
;
1635+
entry:
1636+
%or = or disjoint <2 x i32> %a, %b
1637+
%xor = xor <2 x i32> %or, %c
1638+
%add = add <2 x i32> %or, %xor
1639+
ret <2 x i32> %add
1640+
}
1641+
1642+
define i32 @add_with_or(i32 %a, i32 %b, i32 %c) {
1643+
; CHECK-LABEL: @add_with_or(
1644+
; CHECK-NEXT: entry:
1645+
; CHECK-NEXT: [[ADD:%.*]] = add i32 [[A:%.*]], [[B:%.*]]
1646+
; CHECK-NEXT: [[OR:%.*]] = or i32 [[ADD]], [[C:%.*]]
1647+
; CHECK-NEXT: ret i32 [[OR]]
1648+
;
1649+
entry:
1650+
%add = add i32 %a, %b
1651+
%or = or i32 %add, %c
1652+
ret i32 %or
1653+
}
1654+
1655+
define <2 x i32> @add_with_or_vec(<2 x i32> %a, <2 x i32> %b, <2 x i32> %c) {
1656+
; CHECK-LABEL: @add_with_or_vec(
1657+
; CHECK-NEXT: entry:
1658+
; CHECK-NEXT: [[ADD:%.*]] = add <2 x i32> [[A:%.*]], [[B:%.*]]
1659+
; CHECK-NEXT: [[OR:%.*]] = or <2 x i32> [[ADD]], [[C:%.*]]
1660+
; CHECK-NEXT: ret <2 x i32> [[OR]]
1661+
;
1662+
entry:
1663+
%add = add <2 x i32> %a, %b
1664+
%or = or <2 x i32> %add, %c
1665+
ret <2 x i32> %or
1666+
}

0 commit comments

Comments
 (0)