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
Reproducer: https://godbolt.org/z/sqYqK8vd9
When
%1is -0.0, the former returns +0.0 while the latter returns -0.0.SelectionDAGBuilder::visitSelectincorrectly refined the select (always returns +0.0 when the input is -0.0) intoISD::FMINNUM(returns either 0.0 or -0.0).Related code:
llvm-project/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
Lines 3718 to 3754 in a4a4366
cc @topperc @arsenm