Skip to content

[DAGCombiner] Remove all UnsafeFPMath references #146295

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 8 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 10 additions & 15 deletions llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16914,8 +16914,7 @@ SDValue DAGCombiner::visitFADDForFMACombine(SDNode *N) {
// fadd (G, (fma A, B, (fma (C, D, (fmul (E, F)))))) -->
// fma A, B, (fma C, D, fma (E, F, G)).
// This requires reassociation because it changes the order of operations.
bool CanReassociate =
Options.UnsafeFPMath || N->getFlags().hasAllowReassociation();
bool CanReassociate = N->getFlags().hasAllowReassociation();
if (CanReassociate) {
SDValue FMA, E;
if (isFusedOp(N0) && N0.hasOneUse()) {
Expand Down Expand Up @@ -17581,7 +17580,7 @@ SDValue DAGCombiner::visitFADD(SDNode *N) {
// If 'unsafe math' or reassoc and nsz, fold lots of things.
// TODO: break out portions of the transformations below for which Unsafe is
// considered and which do not require both nsz and reassoc
if (((Options.UnsafeFPMath && Options.NoSignedZerosFPMath) ||
if ((Options.NoSignedZerosFPMath ||
(Flags.hasAllowReassociation() && Flags.hasNoSignedZeros())) &&
AllowNewConst) {
// fadd (fadd x, c1), c2 -> fadd x, c1 + c2
Expand Down Expand Up @@ -17668,7 +17667,7 @@ SDValue DAGCombiner::visitFADD(SDNode *N) {
}
} // enable-unsafe-fp-math && AllowNewConst

if (((Options.UnsafeFPMath && Options.NoSignedZerosFPMath) ||
if ((Options.NoSignedZerosFPMath ||
(Flags.hasAllowReassociation() && Flags.hasNoSignedZeros()))) {
// Fold fadd(vecreduce(x), vecreduce(y)) -> vecreduce(fadd(x, y))
if (SDValue SD = reassociateReduction(ISD::VECREDUCE_FADD, ISD::FADD, DL,
Expand Down Expand Up @@ -17771,7 +17770,7 @@ SDValue DAGCombiner::visitFSUB(SDNode *N) {
}
}

if (((Options.UnsafeFPMath && Options.NoSignedZerosFPMath) ||
if ((Options.NoSignedZerosFPMath ||
(Flags.hasAllowReassociation() && Flags.hasNoSignedZeros())) &&
N1.getOpcode() == ISD::FADD) {
// X - (X + Y) -> -Y
Expand Down Expand Up @@ -17911,7 +17910,6 @@ SDValue DAGCombiner::visitFMUL(SDNode *N) {
ConstantFPSDNode *N1CFP = isConstOrConstSplatFP(N1, true);
EVT VT = N->getValueType(0);
SDLoc DL(N);
const TargetOptions &Options = DAG.getTarget().Options;
const SDNodeFlags Flags = N->getFlags();
SelectionDAG::FlagInserter FlagsInserter(DAG, N);

Expand All @@ -17935,7 +17933,7 @@ SDValue DAGCombiner::visitFMUL(SDNode *N) {
if (SDValue NewSel = foldBinOpIntoSelect(N))
return NewSel;

if (Options.UnsafeFPMath || Flags.hasAllowReassociation()) {
if (Flags.hasAllowReassociation()) {
// fmul (fmul X, C1), C2 -> fmul X, C1 * C2
if (DAG.isConstantFPBuildVectorOrConstantFP(N1) &&
N0.getOpcode() == ISD::FMUL) {
Expand Down Expand Up @@ -18088,8 +18086,7 @@ template <class MatchContextClass> SDValue DAGCombiner::visitFMA(SDNode *N) {
return matcher.getNode(ISD::FMA, DL, VT, NegN0, NegN1, N2);
}

// FIXME: use fast math flags instead of Options.UnsafeFPMath
// TODO: Finally migrate away from global TargetOptions.
// FIXME: Finally migrate away from global TargetOptions.
if (Options.AllowFPOpFusion == FPOpFusion::Fast ||
(Options.NoNaNsFPMath && Options.NoInfsFPMath) ||
(N->getFlags().hasNoNaNs() && N->getFlags().hasNoInfs())) {
Expand All @@ -18113,8 +18110,7 @@ template <class MatchContextClass> SDValue DAGCombiner::visitFMA(SDNode *N) {
!DAG.isConstantFPBuildVectorOrConstantFP(N1))
return matcher.getNode(ISD::FMA, DL, VT, N1, N0, N2);

bool CanReassociate =
Options.UnsafeFPMath || N->getFlags().hasAllowReassociation();
bool CanReassociate = N->getFlags().hasAllowReassociation();
if (CanReassociate) {
// (fma x, c1, (fmul x, c2)) -> (fmul x, c1+c2)
if (matcher.match(N2, ISD::FMUL) && N0 == N2.getOperand(0) &&
Expand Down Expand Up @@ -18209,9 +18205,8 @@ SDValue DAGCombiner::combineRepeatedFPDivisors(SDNode *N) {
// TODO: Limit this transform based on optsize/minsize - it always creates at
// least 1 extra instruction. But the perf win may be substantial enough
// that only minsize should restrict this.
bool UnsafeMath = DAG.getTarget().Options.UnsafeFPMath;
const SDNodeFlags Flags = N->getFlags();
if (LegalDAG || (!UnsafeMath && !Flags.hasAllowReciprocal()))
if (LegalDAG || !Flags.hasAllowReciprocal())
return SDValue();

// Skip if current node is a reciprocal/fneg-reciprocal.
Expand Down Expand Up @@ -18248,7 +18243,7 @@ SDValue DAGCombiner::combineRepeatedFPDivisors(SDNode *N) {

// This division is eligible for optimization only if global unsafe math
// is enabled or if this division allows reciprocal formation.
if (UnsafeMath || U->getFlags().hasAllowReciprocal())
if (U->getFlags().hasAllowReciprocal())
Users.insert(U);
}
}
Expand Down Expand Up @@ -18861,7 +18856,7 @@ SDValue DAGCombiner::visitFP_ROUND(SDNode *N) {
// single-step fp_round we want to fold to.
// In other words, double rounding isn't the same as rounding.
// Also, this is a value preserving truncation iff both fp_round's are.
if (DAG.getTarget().Options.UnsafeFPMath || N0IsTrunc)
if (N->getFlags().hasAllowContract() || N0IsTrunc)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is contract the proper flag here?

return DAG.getNode(
ISD::FP_ROUND, DL, VT, N0.getOperand(0),
DAG.getIntPtrConstant(NIsTrunc && N0IsTrunc, DL, /*isTarget=*/true));
Expand Down
6 changes: 5 additions & 1 deletion llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3908,11 +3908,15 @@ void SelectionDAGBuilder::visitFPTrunc(const User &I) {
// FPTrunc is never a no-op cast, no need to check
SDValue N = getValue(I.getOperand(0));
SDLoc dl = getCurSDLoc();
SDNodeFlags Flags;
if (auto *FPOp = dyn_cast<FPMathOperator>(&I))
Flags.copyFMF(*FPOp);
const TargetLowering &TLI = DAG.getTargetLoweringInfo();
EVT DestVT = TLI.getValueType(DAG.getDataLayout(), I.getType());
setValue(&I, DAG.getNode(ISD::FP_ROUND, dl, DestVT, N,
DAG.getTargetConstant(
0, dl, TLI.getPointerTy(DAG.getDataLayout()))));
0, dl, TLI.getPointerTy(DAG.getDataLayout())),
Flags));
}

void SelectionDAGBuilder::visitFPExt(const User &I) {
Expand Down
79 changes: 39 additions & 40 deletions llvm/test/CodeGen/AArch64/fdiv-combine.ll
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
; a / D; b / D; c / D;
; =>
; recip = 1.0 / D; a * recip; b * recip; c * recip;
define void @three_fdiv_float(float %D, float %a, float %b, float %c) #0 {
define void @three_fdiv_float(float %D, float %a, float %b, float %c) {
; CHECK-SD-LABEL: three_fdiv_float:
; CHECK-SD: // %bb.0:
; CHECK-SD-NEXT: fmov s4, #1.00000000
Expand All @@ -28,14 +28,14 @@ define void @three_fdiv_float(float %D, float %a, float %b, float %c) #0 {
; CHECK-GI-NEXT: fdiv s2, s3, s0
; CHECK-GI-NEXT: fmov s0, s4
; CHECK-GI-NEXT: b foo_3f
%div = fdiv float %a, %D
%div1 = fdiv float %b, %D
%div2 = fdiv float %c, %D
%div = fdiv arcp float %a, %D
%div1 = fdiv arcp float %b, %D
%div2 = fdiv arcp float %c, %D
tail call void @foo_3f(float %div, float %div1, float %div2)
ret void
}

define void @three_fdiv_double(double %D, double %a, double %b, double %c) #0 {
define void @three_fdiv_double(double %D, double %a, double %b, double %c) {
; CHECK-SD-LABEL: three_fdiv_double:
; CHECK-SD: // %bb.0:
; CHECK-SD-NEXT: fmov d4, #1.00000000
Expand All @@ -52,14 +52,14 @@ define void @three_fdiv_double(double %D, double %a, double %b, double %c) #0 {
; CHECK-GI-NEXT: fdiv d2, d3, d0
; CHECK-GI-NEXT: fmov d0, d4
; CHECK-GI-NEXT: b foo_3d
%div = fdiv double %a, %D
%div1 = fdiv double %b, %D
%div2 = fdiv double %c, %D
%div = fdiv arcp double %a, %D
%div1 = fdiv arcp double %b, %D
%div2 = fdiv arcp double %c, %D
tail call void @foo_3d(double %div, double %div1, double %div2)
ret void
}

define void @three_fdiv_4xfloat(<4 x float> %D, <4 x float> %a, <4 x float> %b, <4 x float> %c) #0 {
define void @three_fdiv_4xfloat(<4 x float> %D, <4 x float> %a, <4 x float> %b, <4 x float> %c) {
; CHECK-SD-LABEL: three_fdiv_4xfloat:
; CHECK-SD: // %bb.0:
; CHECK-SD-NEXT: fmov v4.4s, #1.00000000
Expand All @@ -76,14 +76,14 @@ define void @three_fdiv_4xfloat(<4 x float> %D, <4 x float> %a, <4 x float> %b,
; CHECK-GI-NEXT: fdiv v2.4s, v3.4s, v0.4s
; CHECK-GI-NEXT: mov v0.16b, v4.16b
; CHECK-GI-NEXT: b foo_3_4xf
%div = fdiv <4 x float> %a, %D
%div1 = fdiv <4 x float> %b, %D
%div2 = fdiv <4 x float> %c, %D
%div = fdiv arcp <4 x float> %a, %D
%div1 = fdiv arcp <4 x float> %b, %D
%div2 = fdiv arcp <4 x float> %c, %D
tail call void @foo_3_4xf(<4 x float> %div, <4 x float> %div1, <4 x float> %div2)
ret void
}

define void @three_fdiv_2xdouble(<2 x double> %D, <2 x double> %a, <2 x double> %b, <2 x double> %c) #0 {
define void @three_fdiv_2xdouble(<2 x double> %D, <2 x double> %a, <2 x double> %b, <2 x double> %c) {
; CHECK-SD-LABEL: three_fdiv_2xdouble:
; CHECK-SD: // %bb.0:
; CHECK-SD-NEXT: fmov v4.2d, #1.00000000
Expand All @@ -100,42 +100,42 @@ define void @three_fdiv_2xdouble(<2 x double> %D, <2 x double> %a, <2 x double>
; CHECK-GI-NEXT: fdiv v2.2d, v3.2d, v0.2d
; CHECK-GI-NEXT: mov v0.16b, v4.16b
; CHECK-GI-NEXT: b foo_3_2xd
%div = fdiv <2 x double> %a, %D
%div1 = fdiv <2 x double> %b, %D
%div2 = fdiv <2 x double> %c, %D
%div = fdiv arcp <2 x double> %a, %D
%div1 = fdiv arcp <2 x double> %b, %D
%div2 = fdiv arcp <2 x double> %c, %D
tail call void @foo_3_2xd(<2 x double> %div, <2 x double> %div1, <2 x double> %div2)
ret void
}

; Following test cases check we never combine two FDIVs if neither of them
; calculates a reciprocal.
define void @two_fdiv_float(float %D, float %a, float %b) #0 {
define void @two_fdiv_float(float %D, float %a, float %b) {
; CHECK-LABEL: two_fdiv_float:
; CHECK: // %bb.0:
; CHECK-NEXT: fdiv s3, s1, s0
; CHECK-NEXT: fdiv s1, s2, s0
; CHECK-NEXT: fmov s0, s3
; CHECK-NEXT: b foo_2f
%div = fdiv float %a, %D
%div1 = fdiv float %b, %D
%div = fdiv arcp float %a, %D
%div1 = fdiv arcp float %b, %D
tail call void @foo_2f(float %div, float %div1)
ret void
}

define void @two_fdiv_double(double %D, double %a, double %b) #0 {
define void @two_fdiv_double(double %D, double %a, double %b) {
; CHECK-LABEL: two_fdiv_double:
; CHECK: // %bb.0:
; CHECK-NEXT: fdiv d3, d1, d0
; CHECK-NEXT: fdiv d1, d2, d0
; CHECK-NEXT: fmov d0, d3
; CHECK-NEXT: b foo_2d
%div = fdiv double %a, %D
%div1 = fdiv double %b, %D
%div = fdiv arcp double %a, %D
%div1 = fdiv arcp double %b, %D
tail call void @foo_2d(double %div, double %div1)
ret void
}

define void @splat_three_fdiv_4xfloat(float %D, <4 x float> %a, <4 x float> %b, <4 x float> %c) #0 {
define void @splat_three_fdiv_4xfloat(float %D, <4 x float> %a, <4 x float> %b, <4 x float> %c) {
; CHECK-SD-LABEL: splat_three_fdiv_4xfloat:
; CHECK-SD: // %bb.0:
; CHECK-SD-NEXT: // kill: def $s0 killed $s0 def $q0
Expand All @@ -157,14 +157,14 @@ define void @splat_three_fdiv_4xfloat(float %D, <4 x float> %a, <4 x float> %b,
; CHECK-GI-NEXT: b foo_3_4xf
%D.ins = insertelement <4 x float> poison, float %D, i64 0
%splat = shufflevector <4 x float> %D.ins, <4 x float> poison, <4 x i32> zeroinitializer
%div = fdiv <4 x float> %a, %splat
%div1 = fdiv <4 x float> %b, %splat
%div2 = fdiv <4 x float> %c, %splat
%div = fdiv arcp <4 x float> %a, %splat
%div1 = fdiv arcp <4 x float> %b, %splat
%div2 = fdiv arcp <4 x float> %c, %splat
tail call void @foo_3_4xf(<4 x float> %div, <4 x float> %div1, <4 x float> %div2)
ret void
}

define <4 x float> @splat_fdiv_v4f32(float %D, <4 x float> %a) #1 {
define <4 x float> @splat_fdiv_v4f32(float %D, <4 x float> %a) #0 {
; CHECK-SD-LABEL: splat_fdiv_v4f32:
; CHECK-SD: // %bb.0: // %entry
; CHECK-SD-NEXT: // kill: def $s0 killed $s0 def $q0
Expand All @@ -183,11 +183,11 @@ define <4 x float> @splat_fdiv_v4f32(float %D, <4 x float> %a) #1 {
entry:
%D.ins = insertelement <4 x float> poison, float %D, i64 0
%splat = shufflevector <4 x float> %D.ins, <4 x float> poison, <4 x i32> zeroinitializer
%div = fdiv <4 x float> %a, %splat
%div = fdiv arcp <4 x float> %a, %splat
ret <4 x float> %div
}

define <vscale x 4 x float> @splat_fdiv_nxv4f32(float %D, <vscale x 4 x float> %a) #1 {
define <vscale x 4 x float> @splat_fdiv_nxv4f32(float %D, <vscale x 4 x float> %a) #0 {
; CHECK-LABEL: splat_fdiv_nxv4f32:
; CHECK: // %bb.0: // %entry
; CHECK-NEXT: fmov s2, #1.00000000
Expand All @@ -198,11 +198,11 @@ define <vscale x 4 x float> @splat_fdiv_nxv4f32(float %D, <vscale x 4 x float> %
entry:
%D.ins = insertelement <vscale x 4 x float> poison, float %D, i64 0
%splat = shufflevector <vscale x 4 x float> %D.ins, <vscale x 4 x float> poison, <vscale x 4 x i32> zeroinitializer
%div = fdiv <vscale x 4 x float> %a, %splat
%div = fdiv arcp <vscale x 4 x float> %a, %splat
ret <vscale x 4 x float> %div
}

define void @splat_three_fdiv_nxv4f32(float %D, <vscale x 4 x float> %a, <vscale x 4 x float> %b, <vscale x 4 x float> %c) #1 {
define void @splat_three_fdiv_nxv4f32(float %D, <vscale x 4 x float> %a, <vscale x 4 x float> %b, <vscale x 4 x float> %c) #0 {
; CHECK-LABEL: splat_three_fdiv_nxv4f32:
; CHECK: // %bb.0: // %entry
; CHECK-NEXT: fmov s4, #1.00000000
Expand All @@ -215,14 +215,14 @@ define void @splat_three_fdiv_nxv4f32(float %D, <vscale x 4 x float> %a, <vscale
entry:
%D.ins = insertelement <vscale x 4 x float> poison, float %D, i64 0
%splat = shufflevector <vscale x 4 x float> %D.ins, <vscale x 4 x float> poison, <vscale x 4 x i32> zeroinitializer
%div = fdiv <vscale x 4 x float> %a, %splat
%div1 = fdiv <vscale x 4 x float> %b, %splat
%div2 = fdiv <vscale x 4 x float> %c, %splat
%div = fdiv arcp <vscale x 4 x float> %a, %splat
%div1 = fdiv arcp <vscale x 4 x float> %b, %splat
%div2 = fdiv arcp <vscale x 4 x float> %c, %splat
tail call void @foo_3_nxv4f32(<vscale x 4 x float> %div, <vscale x 4 x float> %div1, <vscale x 4 x float> %div2)
ret void
}

define <vscale x 2 x double> @splat_fdiv_nxv2f64(double %D, <vscale x 2 x double> %a) #1 {
define <vscale x 2 x double> @splat_fdiv_nxv2f64(double %D, <vscale x 2 x double> %a) #0 {
; CHECK-LABEL: splat_fdiv_nxv2f64:
; CHECK: // %bb.0: // %entry
; CHECK-NEXT: // kill: def $d0 killed $d0 def $z0
Expand All @@ -237,7 +237,7 @@ entry:
ret <vscale x 2 x double> %div
}

define void @splat_two_fdiv_nxv2f64(double %D, <vscale x 2 x double> %a, <vscale x 2 x double> %b) #1 {
define void @splat_two_fdiv_nxv2f64(double %D, <vscale x 2 x double> %a, <vscale x 2 x double> %b) #0 {
; CHECK-LABEL: splat_two_fdiv_nxv2f64:
; CHECK: // %bb.0: // %entry
; CHECK-NEXT: fmov d3, #1.00000000
Expand All @@ -249,8 +249,8 @@ define void @splat_two_fdiv_nxv2f64(double %D, <vscale x 2 x double> %a, <vscale
entry:
%D.ins = insertelement <vscale x 2 x double> poison, double %D, i64 0
%splat = shufflevector <vscale x 2 x double> %D.ins, <vscale x 2 x double> poison, <vscale x 2 x i32> zeroinitializer
%div = fdiv <vscale x 2 x double> %a, %splat
%div1 = fdiv <vscale x 2 x double> %b, %splat
%div = fdiv arcp <vscale x 2 x double> %a, %splat
%div1 = fdiv arcp <vscale x 2 x double> %b, %splat
tail call void @foo_2_nxv2f64(<vscale x 2 x double> %div, <vscale x 2 x double> %div1)
ret void
}
Expand All @@ -264,5 +264,4 @@ declare void @foo_2d(double, double)
declare void @foo_3_nxv4f32(<vscale x 4 x float>, <vscale x 4 x float>, <vscale x 4 x float>)
declare void @foo_2_nxv2f64(<vscale x 2 x double>, <vscale x 2 x double>)

attributes #0 = { "unsafe-fp-math"="true" }
attributes #1 = { "unsafe-fp-math"="true" "target-features"="+sve" }
attributes #0 = { "target-features"="+sve" }
Loading
Loading