Skip to content

Commit 436993e

Browse files
woruyuworuyu
authored andcommitted
[DAG] add (~a | x) & (a | y) -> (a & (x ^ y)) ^y for foldMaskedMerge
1 parent 977f333 commit 436993e

File tree

2 files changed

+43
-31
lines changed

2 files changed

+43
-31
lines changed

llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7206,24 +7206,30 @@ static SDValue foldLogicTreeOfShifts(SDNode *N, SDValue LeftHand,
72067206
return DAG.getNode(LogicOpcode, DL, VT, CombinedShifts, W);
72077207
}
72087208

7209-
/// Fold "masked merge" expressions like `(m & x) | (~m & y)` into the
7210-
/// equivalent `((x ^ y) & m) ^ y)` pattern.
7211-
/// This is typically a better representation for targets without a fused
7212-
/// "and-not" operation.
7209+
/// Fold "masked merge" expressions like `(m & x) | (~m & y)` and its DeMorgan
7210+
/// variant `(~m | x) & (m | y)` into the equivalent `((x ^ y) & m) ^ y)`
7211+
/// pattern. This is typically a better representation for targets without a
7212+
/// fused "and-not" operation.
72137213
static SDValue foldMaskedMerge(SDNode *Node, SelectionDAG &DAG,
72147214
const TargetLowering &TLI, const SDLoc &DL) {
72157215
// Note that masked-merge variants using XOR or ADD expressions are
7216-
// normalized to OR by InstCombine so we only check for OR.
7217-
assert(Node->getOpcode() == ISD::OR && "Must be called with ISD::OR node");
7216+
// normalized to OR by InstCombine so we only check for OR or AND.
7217+
assert(Node->getOpcode() == ISD::OR ||
7218+
Node->getOpcode() == ISD::AND &&
7219+
"Must be called with ISD::OR or ISD::AND node");
72187220

72197221
// If the target supports and-not, don't fold this.
72207222
if (TLI.hasAndNot(SDValue(Node, 0)))
72217223
return SDValue();
72227224

72237225
SDValue M, X, Y;
7226+
72247227
if (sd_match(Node,
72257228
m_Or(m_OneUse(m_And(m_OneUse(m_Not(m_Value(M))), m_Value(Y))),
7226-
m_OneUse(m_And(m_Deferred(M), m_Value(X)))))) {
7229+
m_OneUse(m_And(m_Deferred(M), m_Value(X))))) ||
7230+
sd_match(Node,
7231+
m_And(m_OneUse(m_Or(m_OneUse(m_Not(m_Value(M))), m_Value(X))),
7232+
m_OneUse(m_Or(m_Deferred(M), m_Value(Y)))))) {
72277233
EVT VT = M.getValueType();
72287234
SDValue Xor = DAG.getNode(ISD::XOR, DL, VT, X, Y);
72297235
SDValue And = DAG.getNode(ISD::AND, DL, VT, Xor, M);
@@ -7678,6 +7684,10 @@ SDValue DAGCombiner::visitAND(SDNode *N) {
76787684
if (SDValue R = foldLogicTreeOfShifts(N, N0, N1, DAG))
76797685
return R;
76807686

7687+
if (VT.isScalarInteger() && VT != MVT::i1)
7688+
if (SDValue R = foldMaskedMerge(N, DAG, TLI, DL))
7689+
return R;
7690+
76817691
return SDValue();
76827692
}
76837693

llvm/test/CodeGen/X86/fold-masked-merge-demorgan.ll

Lines changed: 26 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,10 @@
88
define i32 @masked_merge0_demorgan(i32 %a0, i32 %a1, i32 %a2) {
99
; NOBMI-LABEL: masked_merge0_demorgan:
1010
; NOBMI: # %bb.0:
11-
; NOBMI-NEXT: orl %edi, %edx
12-
; NOBMI-NEXT: movl %edi, %eax
13-
; NOBMI-NEXT: notl %eax
14-
; NOBMI-NEXT: orl %esi, %eax
15-
; NOBMI-NEXT: andl %edx, %eax
11+
; NOBMI-NEXT: movl %esi, %eax
12+
; NOBMI-NEXT: xorl %edx, %eax
13+
; NOBMI-NEXT: andl %edi, %eax
14+
; NOBMI-NEXT: xorl %edx, %eax
1615
; NOBMI-NEXT: retq
1716
;
1817
; BMI-LABEL: masked_merge0_demorgan:
@@ -29,15 +28,22 @@ define i32 @masked_merge0_demorgan(i32 %a0, i32 %a1, i32 %a2) {
2928
}
3029

3130
define i16 @masked_merge1_demorgan(i16 %a0, i16 %a1, i16 %a2) {
32-
; CHECK-LABEL: masked_merge1_demorgan:
33-
; CHECK: # %bb.0:
34-
; CHECK-NEXT: orl %edi, %edx
35-
; CHECK-NEXT: movl %edi, %eax
36-
; CHECK-NEXT: notl %eax
37-
; CHECK-NEXT: orl %esi, %eax
38-
; CHECK-NEXT: andl %edx, %eax
39-
; CHECK-NEXT: # kill: def $ax killed $ax killed $eax
40-
; CHECK-NEXT: retq
31+
; NOBMI-LABEL: masked_merge1_demorgan:
32+
; NOBMI: # %bb.0:
33+
; NOBMI-NEXT: movl %esi, %eax
34+
; NOBMI-NEXT: xorl %edx, %eax
35+
; NOBMI-NEXT: andl %edi, %eax
36+
; NOBMI-NEXT: xorl %edx, %eax
37+
; NOBMI-NEXT: # kill: def $ax killed $ax killed $eax
38+
; NOBMI-NEXT: retq
39+
;
40+
; BMI-LABEL: masked_merge1_demorgan:
41+
; BMI: # %bb.0:
42+
; BMI-NEXT: andnl %edx, %edi, %eax
43+
; BMI-NEXT: andl %edi, %esi
44+
; BMI-NEXT: orl %esi, %eax
45+
; BMI-NEXT: # kill: def $ax killed $ax killed $eax
46+
; BMI-NEXT: retq
4147
%not = xor i16 %a0, -1
4248
%or0 = or i16 %not, %a1
4349
%or1 = or i16 %a0, %a2
@@ -48,11 +54,8 @@ define i16 @masked_merge1_demorgan(i16 %a0, i16 %a1, i16 %a2) {
4854
define i8 @masked_merge2_demorgan(i8 %a0, i8 %a1, i8 %a2) {
4955
; CHECK-LABEL: masked_merge2_demorgan:
5056
; CHECK: # %bb.0:
51-
; CHECK-NEXT: movl %edi, %eax
52-
; CHECK-NEXT: notb %al
53-
; CHECK-NEXT: orb %sil, %al
54-
; CHECK-NEXT: orb %sil, %dil
55-
; CHECK-NEXT: andb %dil, %al
57+
; CHECK-NEXT: movl %esi, %eax
58+
; CHECK-NEXT: # kill: def $al killed $al killed $eax
5659
; CHECK-NEXT: retq
5760
%not = xor i8 %a0, -1
5861
%or0 = or i8 %not, %a1
@@ -64,13 +67,12 @@ define i8 @masked_merge2_demorgan(i8 %a0, i8 %a1, i8 %a2) {
6467
define i64 @masked_merge3_demorgan(i64 %a0, i64 %a1, i64 %a2) {
6568
; NOBMI-LABEL: masked_merge3_demorgan:
6669
; NOBMI: # %bb.0:
70+
; NOBMI-NEXT: movq %rsi, %rax
6771
; NOBMI-NEXT: notq %rdx
68-
; NOBMI-NEXT: orq %rdi, %rdx
69-
; NOBMI-NEXT: movq %rdi, %rax
72+
; NOBMI-NEXT: xorq %rdx, %rax
7073
; NOBMI-NEXT: notq %rax
71-
; NOBMI-NEXT: notq %rsi
72-
; NOBMI-NEXT: orq %rsi, %rax
73-
; NOBMI-NEXT: andq %rdx, %rax
74+
; NOBMI-NEXT: andq %rdi, %rax
75+
; NOBMI-NEXT: xorq %rdx, %rax
7476
; NOBMI-NEXT: retq
7577
;
7678
; BMI-LABEL: masked_merge3_demorgan:

0 commit comments

Comments
 (0)