@@ -18871,6 +18871,37 @@ SDValue DAGCombiner::visitFPOW(SDNode *N) {
1887118871
1887218872 return SDValue();
1887318873}
18874+ /// Check if a use of a floating-point operation doesn't care about the sign of
18875+ /// zero. This allows us to optimize (sitofp (fptosi x)) -> ftrunc(x) even
18876+ /// without NoSignedZerosFPMath, as long as all uses are sign-insensitive.
18877+ static bool isSignInsensitiveUse(SDNode *Use, unsigned OperandNo,
18878+ SelectionDAG &DAG) {
18879+ switch (Use->getOpcode()) {
18880+ case ISD::SETCC:
18881+ // Comparisons: IEEE 754 specifies +0.0 == -0.0.
18882+ case ISD::FABS:
18883+ // fabs always produces +0.0.
18884+ return true;
18885+ case ISD::FADD:
18886+ case ISD::FSUB: {
18887+ // Arithmetic with non-zero constants fixes the uncertainty around the sign
18888+ // bit.
18889+ SDValue Other = Use->getOperand(1 - OperandNo);
18890+ return DAG.isKnownNeverZeroFloat(Other);
18891+ }
18892+ default:
18893+ return false;
18894+ }
18895+ }
18896+
18897+ /// Check if all uses of a value are insensitive to the sign of zero.
18898+ static bool allUsesSignInsensitive(SDValue V, SelectionDAG &DAG) {
18899+ return all_of(V->uses(), [&](SDUse &Use) {
18900+ SDNode *User = Use.getUser();
18901+ unsigned OperandNo = Use.getOperandNo();
18902+ return isSignInsensitiveUse(User, OperandNo, DAG);
18903+ });
18904+ }
1887418905
1887518906static SDValue foldFPToIntToFP(SDNode *N, const SDLoc &DL, SelectionDAG &DAG,
1887618907 const TargetLowering &TLI) {
@@ -18892,12 +18923,13 @@ static SDValue foldFPToIntToFP(SDNode *N, const SDLoc &DL, SelectionDAG &DAG,
1889218923 bool IsSigned = N->getOpcode() == ISD::SINT_TO_FP;
1889318924 assert(IsSigned || IsUnsigned);
1889418925
18895- bool IsSignedZeroSafe = DAG.getTarget().Options.NoSignedZerosFPMath;
18926+ bool IsSignedZeroSafe = DAG.getTarget().Options.NoSignedZerosFPMath ||
18927+ allUsesSignInsensitive(SDValue(N, 0), DAG);
1889618928 // For signed conversions: The optimization changes signed zero behavior.
1889718929 if (IsSigned && !IsSignedZeroSafe)
1889818930 return SDValue();
1889918931 // For unsigned conversions, we need FABS to canonicalize -0.0 to +0.0
18900- // (unless NoSignedZerosFPMath is set ).
18932+ // (unless outputting a signed zero is OK ).
1890118933 if (IsUnsigned && !IsSignedZeroSafe && !TLI.isFAbsFree(VT))
1890218934 return SDValue();
1890318935
@@ -19376,10 +19408,17 @@ SDValue DAGCombiner::visitFNEG(SDNode *N) {
1937619408 // FIXME: This is duplicated in getNegatibleCost, but getNegatibleCost doesn't
1937719409 // know it was called from a context with a nsz flag if the input fsub does
1937819410 // not.
19379- if (N0.getOpcode() == ISD::FSUB && N->getFlags().hasNoSignedZeros() &&
19380- N0.hasOneUse()) {
19381- return DAG.getNode(ISD::FSUB, SDLoc(N), VT, N0.getOperand(1),
19382- N0.getOperand(0));
19411+ if (N0.getOpcode() == ISD::FSUB && N0.hasOneUse()) {
19412+ SDValue X = N0.getOperand(0);
19413+ SDValue Y = N0.getOperand(1);
19414+
19415+ // Safe if NoSignedZeros, or if we can prove X != Y (avoiding the -0.0 vs
19416+ // +0.0 issue) For now, we use a conservative check: if either operand is
19417+ // known never zero, then X - Y can't produce a signed zero from X == Y.
19418+ if (N->getFlags().hasNoSignedZeros() || DAG.isKnownNeverZeroFloat(X) ||
19419+ DAG.isKnownNeverZeroFloat(Y)) {
19420+ return DAG.getNode(ISD::FSUB, SDLoc(N), VT, Y, X);
19421+ }
1938319422 }
1938419423
1938519424 if (SimplifyDemandedBits(SDValue(N, 0)))
0 commit comments