Skip to content

Commit 29a2b20

Browse files
committed
[SDAG] simplify FP binops to undef
As discussed in the commit thread for rGa253a2a and D73978, we can do more undef folding for FP ops. The nnan and ninf fast-math-flags specify that if an operand is the disallowed value, the result is poison, so we can produce an undef result. But this doesn't work as expected (the undef operand cases remain) because of a Flags propagation problem in SelectionDAGBuilder. I've added DAGCombiner calls to enable these for the other cases because we've shown in other patches that (because of the limited way that SDAG iterates), it is possible to miss simplifications like this if they are done only at node creation time. Several potential follow-ups to expand on this patch are possible. Differential Revision: https://reviews.llvm.org/D75576
1 parent aff6bf4 commit 29a2b20

File tree

4 files changed

+56
-16
lines changed

4 files changed

+56
-16
lines changed

llvm/include/llvm/CodeGen/SelectionDAG.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1077,7 +1077,8 @@ class SelectionDAG {
10771077

10781078
/// Try to simplify a floating-point binary operation into 1 of its operands
10791079
/// or a constant.
1080-
SDValue simplifyFPBinop(unsigned Opcode, SDValue X, SDValue Y);
1080+
SDValue simplifyFPBinop(unsigned Opcode, SDValue X, SDValue Y,
1081+
SDNodeFlags Flags);
10811082

10821083
/// VAArg produces a result and token chain, and takes a pointer
10831084
/// and a source value as input.

llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12220,6 +12220,9 @@ SDValue DAGCombiner::visitFADD(SDNode *N) {
1222012220
const TargetOptions &Options = DAG.getTarget().Options;
1222112221
const SDNodeFlags Flags = N->getFlags();
1222212222

12223+
if (SDValue R = DAG.simplifyFPBinop(N->getOpcode(), N0, N1, Flags))
12224+
return R;
12225+
1222312226
// fold vector ops
1222412227
if (VT.isVector())
1222512228
if (SDValue FoldedVOp = SimplifyVBinOp(N))
@@ -12401,6 +12404,9 @@ SDValue DAGCombiner::visitFSUB(SDNode *N) {
1240112404
const TargetOptions &Options = DAG.getTarget().Options;
1240212405
const SDNodeFlags Flags = N->getFlags();
1240312406

12407+
if (SDValue R = DAG.simplifyFPBinop(N->getOpcode(), N0, N1, Flags))
12408+
return R;
12409+
1240412410
// fold vector ops
1240512411
if (VT.isVector())
1240612412
if (SDValue FoldedVOp = SimplifyVBinOp(N))
@@ -12499,6 +12505,9 @@ SDValue DAGCombiner::visitFMUL(SDNode *N) {
1249912505
const TargetOptions &Options = DAG.getTarget().Options;
1250012506
const SDNodeFlags Flags = N->getFlags();
1250112507

12508+
if (SDValue R = DAG.simplifyFPBinop(N->getOpcode(), N0, N1, Flags))
12509+
return R;
12510+
1250212511
// fold vector ops
1250312512
if (VT.isVector()) {
1250412513
// This just handles C1 * C2 for vectors. Other vector folds are below.
@@ -12831,6 +12840,9 @@ SDValue DAGCombiner::visitFDIV(SDNode *N) {
1283112840
const TargetOptions &Options = DAG.getTarget().Options;
1283212841
SDNodeFlags Flags = N->getFlags();
1283312842

12843+
if (SDValue R = DAG.simplifyFPBinop(N->getOpcode(), N0, N1, Flags))
12844+
return R;
12845+
1283412846
// fold vector ops
1283512847
if (VT.isVector())
1283612848
if (SDValue FoldedVOp = SimplifyVBinOp(N))
@@ -12931,6 +12943,10 @@ SDValue DAGCombiner::visitFREM(SDNode *N) {
1293112943
ConstantFPSDNode *N0CFP = dyn_cast<ConstantFPSDNode>(N0);
1293212944
ConstantFPSDNode *N1CFP = dyn_cast<ConstantFPSDNode>(N1);
1293312945
EVT VT = N->getValueType(0);
12946+
SDNodeFlags Flags = N->getFlags();
12947+
12948+
if (SDValue R = DAG.simplifyFPBinop(N->getOpcode(), N0, N1, Flags))
12949+
return R;
1293412950

1293512951
// fold (frem c1, c2) -> fmod(c1,c2)
1293612952
if (N0CFP && N1CFP)

llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5229,7 +5229,7 @@ SDValue SelectionDAG::getNode(unsigned Opcode, const SDLoc &DL, EVT VT,
52295229
assert(VT.isFloatingPoint() && "This operator only applies to FP types!");
52305230
assert(N1.getValueType() == N2.getValueType() &&
52315231
N1.getValueType() == VT && "Binary operator types must match!");
5232-
if (SDValue V = simplifyFPBinop(Opcode, N1, N2))
5232+
if (SDValue V = simplifyFPBinop(Opcode, N1, N2, Flags))
52335233
return V;
52345234
break;
52355235
case ISD::FCOPYSIGN: // N1 and result must match. N1/N2 need not match.
@@ -7301,9 +7301,24 @@ SDValue SelectionDAG::simplifyShift(SDValue X, SDValue Y) {
73017301
return SDValue();
73027302
}
73037303

7304-
// TODO: Use fast-math-flags to enable more simplifications.
7305-
SDValue SelectionDAG::simplifyFPBinop(unsigned Opcode, SDValue X, SDValue Y) {
7304+
SDValue SelectionDAG::simplifyFPBinop(unsigned Opcode, SDValue X, SDValue Y,
7305+
SDNodeFlags Flags) {
7306+
// If this operation has 'nnan' or 'ninf' and at least 1 disallowed operand
7307+
// (an undef operand can be chosen to be Nan/Inf), then the result of this
7308+
// operation is poison. That result can be relaxed to undef.
7309+
ConstantFPSDNode *XC = isConstOrConstSplatFP(X, /* AllowUndefs */ true);
73067310
ConstantFPSDNode *YC = isConstOrConstSplatFP(Y, /* AllowUndefs */ true);
7311+
bool HasNan = (XC && XC->getValueAPF().isNaN()) ||
7312+
(YC && YC->getValueAPF().isNaN());
7313+
bool HasInf = (XC && XC->getValueAPF().isInfinity()) ||
7314+
(YC && YC->getValueAPF().isInfinity());
7315+
7316+
if (Flags.hasNoNaNs() && (HasNan || X.isUndef() || Y.isUndef()))
7317+
return getUNDEF(X.getValueType());
7318+
7319+
if (Flags.hasNoInfs() && (HasInf || X.isUndef() || Y.isUndef()))
7320+
return getUNDEF(X.getValueType());
7321+
73077322
if (!YC)
73087323
return SDValue();
73097324

llvm/test/CodeGen/AArch64/fp-const-fold.ll

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -76,9 +76,6 @@ define double @constant_fold_fma_nan(double* %p) {
7676
define double @fdiv_nnan_nan_op0(double %x) {
7777
; CHECK-LABEL: fdiv_nnan_nan_op0:
7878
; CHECK: // %bb.0:
79-
; CHECK-NEXT: mov x8, #-2251799813685248
80-
; CHECK-NEXT: fmov d1, x8
81-
; CHECK-NEXT: fdiv d0, d1, d0
8279
; CHECK-NEXT: ret
8380
%r = fdiv nnan double 0xfff8000000000000, %x
8481
ret double %r
@@ -87,14 +84,14 @@ define double @fdiv_nnan_nan_op0(double %x) {
8784
define double @fmul_nnan_nan_op1(double %x) {
8885
; CHECK-LABEL: fmul_nnan_nan_op1:
8986
; CHECK: // %bb.0:
90-
; CHECK-NEXT: mov x8, #9221120237041090560
91-
; CHECK-NEXT: fmov d1, x8
92-
; CHECK-NEXT: fmul d0, d0, d1
9387
; CHECK-NEXT: ret
9488
%r = fmul nnan double %x, 0x7ff8000000000000
9589
ret double %r
9690
}
9791

92+
; Negative test - nan is ok.
93+
; TODO: Should simplify to nan.
94+
9895
define double @fdiv_ninf_nan_op0(double %x) {
9996
; CHECK-LABEL: fdiv_ninf_nan_op0:
10097
; CHECK: // %bb.0:
@@ -106,6 +103,9 @@ define double @fdiv_ninf_nan_op0(double %x) {
106103
ret double %r
107104
}
108105

106+
; Negative test - nan is ok.
107+
; TODO: Should simplify to nan.
108+
109109
define double @fadd_ninf_nan_op1(double %x) {
110110
; CHECK-LABEL: fadd_ninf_nan_op1:
111111
; CHECK: // %bb.0:
@@ -120,9 +120,6 @@ define double @fadd_ninf_nan_op1(double %x) {
120120
define double @fdiv_ninf_inf_op0(double %x) {
121121
; CHECK-LABEL: fdiv_ninf_inf_op0:
122122
; CHECK: // %bb.0:
123-
; CHECK-NEXT: mov x8, #9218868437227405312
124-
; CHECK-NEXT: fmov d1, x8
125-
; CHECK-NEXT: fdiv d0, d1, d0
126123
; CHECK-NEXT: ret
127124
%r = fdiv ninf double 0x7ff0000000000000, %x
128125
ret double %r
@@ -131,14 +128,14 @@ define double @fdiv_ninf_inf_op0(double %x) {
131128
define double @fadd_ninf_inf_op1(double %x) {
132129
; CHECK-LABEL: fadd_ninf_inf_op1:
133130
; CHECK: // %bb.0:
134-
; CHECK-NEXT: mov x8, #-4503599627370496
135-
; CHECK-NEXT: fmov d1, x8
136-
; CHECK-NEXT: fadd d0, d0, d1
137131
; CHECK-NEXT: ret
138132
%r = fadd ninf double %x, 0xfff0000000000000
139133
ret double %r
140134
}
141135

136+
; Negative test - inf is ok.
137+
; TODO: Should simplify to inf.
138+
142139
define double @fsub_nnan_inf_op0(double %x) {
143140
; CHECK-LABEL: fsub_nnan_inf_op0:
144141
; CHECK: // %bb.0:
@@ -150,6 +147,9 @@ define double @fsub_nnan_inf_op0(double %x) {
150147
ret double %r
151148
}
152149

150+
; Negative test - inf is ok.
151+
; TODO: Should simplify to -inf.
152+
153153
define double @fmul_nnan_inf_op1(double %x) {
154154
; CHECK-LABEL: fmul_nnan_inf_op1:
155155
; CHECK: // %bb.0:
@@ -161,6 +161,8 @@ define double @fmul_nnan_inf_op1(double %x) {
161161
ret double %r
162162
}
163163

164+
; TODO: Should simplify to undef
165+
164166
define double @fdiv_nnan_undef_op0(double %x) {
165167
; CHECK-LABEL: fdiv_nnan_undef_op0:
166168
; CHECK: // %bb.0:
@@ -171,6 +173,8 @@ define double @fdiv_nnan_undef_op0(double %x) {
171173
ret double %r
172174
}
173175

176+
; TODO: Should simplify to undef
177+
174178
define double @fdiv_nnan_undef_op1(double %x) {
175179
; CHECK-LABEL: fdiv_nnan_undef_op1:
176180
; CHECK: // %bb.0:
@@ -181,6 +185,8 @@ define double @fdiv_nnan_undef_op1(double %x) {
181185
ret double %r
182186
}
183187

188+
; TODO: Should simplify to undef
189+
184190
define double @fdiv_ninf_undef_op0(double %x) {
185191
; CHECK-LABEL: fdiv_ninf_undef_op0:
186192
; CHECK: // %bb.0:
@@ -191,6 +197,8 @@ define double @fdiv_ninf_undef_op0(double %x) {
191197
ret double %r
192198
}
193199

200+
; TODO: Should simplify to undef
201+
194202
define double @fdiv_ninf_undef_op1(double %x) {
195203
; CHECK-LABEL: fdiv_ninf_undef_op1:
196204
; CHECK: // %bb.0:

0 commit comments

Comments
 (0)