Skip to content

Commit ec78f0d

Browse files
committed
[X86] combineAndNotOrIntoAndNotAnd - don't attempt with constant operands
Don't fold AND(X,OR(NOT(Z),C)) -> AND(X,NOT(AND(Z,C'))) as DAGCombiner will invert it back again. Fixes #112347
1 parent 30deb76 commit ec78f0d

File tree

2 files changed

+29
-8
lines changed

2 files changed

+29
-8
lines changed

llvm/lib/Target/X86/X86ISelLowering.cpp

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -50049,12 +50049,15 @@ static SDValue combineAndNotOrIntoAndNotAnd(SDNode *N, SelectionDAG &DAG) {
5004950049
return SDValue();
5005050050

5005150051
SDValue X, Y, Z;
50052-
if (sd_match(
50053-
N, m_And(m_Value(X), m_OneUse(m_Or(m_Value(Y), m_Not(m_Value(Z)))))))
50054-
return DAG.getNode(
50055-
ISD::AND, DL, VT, X,
50056-
DAG.getNOT(DL, DAG.getNode(ISD::AND, DL, VT, DAG.getNOT(DL, Y, VT), Z),
50057-
VT));
50052+
if (sd_match(N, m_And(m_Value(X),
50053+
m_OneUse(m_Or(m_Value(Y), m_Not(m_Value(Z))))))) {
50054+
// Don't fold if Y is a constant to prevent infinite loops.
50055+
if (!isa<ConstantSDNode>(Y))
50056+
return DAG.getNode(
50057+
ISD::AND, DL, VT, X,
50058+
DAG.getNOT(
50059+
DL, DAG.getNode(ISD::AND, DL, VT, DAG.getNOT(DL, Y, VT), Z), VT));
50060+
}
5005850061

5005950062
return SDValue();
5006050063
}

llvm/test/CodeGen/X86/pr108731.ll

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,5 +57,23 @@ Entry:
5757
%and3 = and <16 x i8> %and2, %or1
5858
ret <16 x i8> %and3
5959
}
60-
;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
61-
; CHECK: {{.*}}
60+
61+
; PR112347 - don't fold if we'd be inverting a constant, as demorgan normalisation will invert it back again.
62+
define void @PR112347(ptr %p0, ptr %p1, ptr %p2) {
63+
; CHECK-LABEL: PR112347:
64+
; CHECK: # %bb.0:
65+
; CHECK-NEXT: movl (%rdi), %eax
66+
; CHECK-NEXT: notl %eax
67+
; CHECK-NEXT: orl $-16777204, %eax # imm = 0xFF00000C
68+
; CHECK-NEXT: andl (%rsi), %eax
69+
; CHECK-NEXT: movl %eax, (%rdx)
70+
; CHECK-NEXT: retq
71+
%load0 = load i32, ptr %p0, align 1
72+
%load1 = load i32, ptr %p1, align 4
73+
%not = xor i32 %load0, -1
74+
%top = or i32 %not, -16777204
75+
%mask = and i32 %load1, %top
76+
store i32 %mask, ptr %p2, align 4
77+
ret void
78+
}
79+

0 commit comments

Comments
 (0)