@@ -18862,12 +18862,15 @@ SDValue DAGCombiner::visitFPOW(SDNode *N) {
1886218862
1886318863static SDValue foldFPToIntToFP(SDNode *N, const SDLoc &DL, SelectionDAG &DAG,
1886418864 const TargetLowering &TLI) {
18865- // We only do this if the target has legal ftrunc. Otherwise, we'd likely be
18866- // replacing casts with a libcall. We also must be allowed to ignore -0.0
18867- // because FTRUNC will return -0.0 for (-1.0, -0.0), but using integer
18868- // conversions would return +0.0.
18865+ // We can fold the fpto[us]i -> [us]itofp pattern into a single ftrunc.
18866+ // If NoSignedZerosFPMath is enabled, this is a direct replacement.
18867+ // Otherwise, for strict math, we must handle edge cases:
18868+ // 1. For signed conversions, clamp out-of-range values to the valid
18869+ // integer range before the trunc.
18870+ // 2. For unsigned conversions, use FABS. A negative float becomes integer 0,
18871+ // which must convert back to +0.0. FTRUNC on its own could produce -0.0.
18872+
1886918873 // FIXME: We should be able to use node-level FMF here.
18870- // TODO: If strict math, should we use FABS (+ range check for signed cast)?
1887118874 EVT VT = N->getValueType(0);
1887218875 if (!TLI.isOperationLegal(ISD::FTRUNC, VT))
1887318876 return SDValue();
@@ -18880,6 +18883,7 @@ static SDValue foldFPToIntToFP(SDNode *N, const SDLoc &DL, SelectionDAG &DAG,
1888018883 if (DAG.getTarget().Options.NoSignedZerosFPMath)
1888118884 return DAG.getNode(ISD::FTRUNC, DL, VT, N0.getOperand(0));
1888218885
18886+ // Strict math: clamp to the signed integer range before truncating.
1888318887 unsigned IntWidth = N0.getValueSizeInBits();
1888418888 APInt APMax = APInt::getSignedMaxValue(IntWidth);
1888518889 APInt APMin = APInt::getSignedMinValue(IntWidth);
@@ -18892,9 +18896,9 @@ static SDValue foldFPToIntToFP(SDNode *N, const SDLoc &DL, SelectionDAG &DAG,
1889218896 SDValue MaxFP = DAG.getConstantFP(MaxAPF, DL, VT);
1889318897 SDValue MinFP = DAG.getConstantFP(MinAPF, DL, VT);
1889418898
18895- SDValue Clamped = DAG.getNode(ISD::FMINNUM, DL, VT,
18896- DAG.getNode( ISD::FMAXNUM , DL, VT, N0->getOperand(0), MinFP) ,
18897- MaxFP);
18899+ SDValue Clamped = DAG.getNode(
18900+ ISD::FMINNUM , DL, VT,
18901+ DAG.getNode(ISD::FMAXNUM, DL, VT, N0->getOperand(0), MinFP), MaxFP);
1889818902 return DAG.getNode(ISD::FTRUNC, DL, VT, Clamped);
1889918903 }
1890018904
@@ -18903,6 +18907,7 @@ static SDValue foldFPToIntToFP(SDNode *N, const SDLoc &DL, SelectionDAG &DAG,
1890318907 if (DAG.getTarget().Options.NoSignedZerosFPMath)
1890418908 return DAG.getNode(ISD::FTRUNC, DL, VT, N0.getOperand(0));
1890518909
18910+ // Strict math: use FABS to handle negative inputs correctly.
1890618911 if (TLI.isFAbsFree(VT)) {
1890718912 SDValue Abs = DAG.getNode(ISD::FABS, DL, VT, N0.getOperand(0));
1890818913 return DAG.getNode(ISD::FTRUNC, DL, VT, Abs);
0 commit comments