Skip to content

SDAG doesn't handle signed zero correctly when folding select -> {min|max}num #93414

@dtcxzyw

Description

@dtcxzyw

Reproducer: https://godbolt.org/z/sqYqK8vd9

; llc -mtriple=riscv64 -mattr=+f test.ll -o -
define float @test(float %1) {
entry:
  %2 = fcmp olt float %1, 0.000000
  %3 = select i1 %2, float %1, float 0.000000
  ret float %3
}
test:                                   # @test
        fmv.w.x fa5, zero
        fmin.s  fa0, fa0, fa5
        ret

When %1 is -0.0, the former returns +0.0 while the latter returns -0.0.
SelectionDAGBuilder::visitSelect incorrectly refined the select (always returns +0.0 when the input is -0.0) into ISD::FMINNUM (returns either 0.0 or -0.0).
Related code:

// ValueTracking's select pattern matching does not account for -0.0,
// so we can't lower to FMINIMUM/FMAXIMUM because those nodes specify that
// -0.0 is less than +0.0.
Value *LHS, *RHS;
auto SPR = matchSelectPattern(const_cast<User*>(&I), LHS, RHS);
ISD::NodeType Opc = ISD::DELETED_NODE;
switch (SPR.Flavor) {
case SPF_UMAX: Opc = ISD::UMAX; break;
case SPF_UMIN: Opc = ISD::UMIN; break;
case SPF_SMAX: Opc = ISD::SMAX; break;
case SPF_SMIN: Opc = ISD::SMIN; break;
case SPF_FMINNUM:
switch (SPR.NaNBehavior) {
case SPNB_NA: llvm_unreachable("No NaN behavior for FP op?");
case SPNB_RETURNS_NAN: break;
case SPNB_RETURNS_OTHER: Opc = ISD::FMINNUM; break;
case SPNB_RETURNS_ANY:
if (TLI.isOperationLegalOrCustom(ISD::FMINNUM, VT) ||
(UseScalarMinMax &&
TLI.isOperationLegalOrCustom(ISD::FMINNUM, VT.getScalarType())))
Opc = ISD::FMINNUM;
break;
}
break;
case SPF_FMAXNUM:
switch (SPR.NaNBehavior) {
case SPNB_NA: llvm_unreachable("No NaN behavior for FP op?");
case SPNB_RETURNS_NAN: break;
case SPNB_RETURNS_OTHER: Opc = ISD::FMAXNUM; break;
case SPNB_RETURNS_ANY:
if (TLI.isOperationLegalOrCustom(ISD::FMAXNUM, VT) ||
(UseScalarMinMax &&
TLI.isOperationLegalOrCustom(ISD::FMAXNUM, VT.getScalarType())))
Opc = ISD::FMAXNUM;
break;
}
break;

cc @topperc @arsenm

Metadata

Metadata

Assignees

No one assigned

    Type

    No fields configured for Bug.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions