diff options
author | Michele Scandale <michele.scandale@gmail.com> | 2024-03-19 09:47:07 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-03-19 09:47:07 -0700 |
commit | 09eb9f1136c8572c4c3f2ec46be50899c32fc881 (patch) | |
tree | 1ebefba155679c8ba95c3a3f8afb2ede47df10fc /llvm/lib | |
parent | 24f22b3f93f950348cbff35feb7ad9a5d16d916d (diff) | |
download | llvm-09eb9f1136c8572c4c3f2ec46be50899c32fc881.zip llvm-09eb9f1136c8572c4c3f2ec46be50899c32fc881.tar.gz llvm-09eb9f1136c8572c4c3f2ec46be50899c32fc881.tar.bz2 |
[InstCombine] Fix for folding `select` into floating point binary operators. (#83200)
Folding a `select` into a floating point binary operators can only be
done if the result is preserved for both case. In particular, if the
other operand of the `select` can be a NaN, then the transformation
won't preserve the result value.
Diffstat (limited to 'llvm/lib')
-rw-r--r-- | llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp | 36 |
1 files changed, 23 insertions, 13 deletions
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp index ee76a62..9ab2bd8 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp @@ -536,19 +536,29 @@ Instruction *InstCombinerImpl::foldSelectIntoOp(SelectInst &SI, Value *TrueVal, // between 0, 1 and -1. const APInt *OOpC; bool OOpIsAPInt = match(OOp, m_APInt(OOpC)); - if (!isa<Constant>(OOp) || - (OOpIsAPInt && isSelect01(C->getUniqueInteger(), *OOpC))) { - Value *NewSel = Builder.CreateSelect(SI.getCondition(), Swapped ? C : OOp, - Swapped ? OOp : C, "", &SI); - if (isa<FPMathOperator>(&SI)) - cast<Instruction>(NewSel)->setFastMathFlags(FMF); - NewSel->takeName(TVI); - BinaryOperator *BO = - BinaryOperator::Create(TVI->getOpcode(), FalseVal, NewSel); - BO->copyIRFlags(TVI); - return BO; - } - return nullptr; + if (isa<Constant>(OOp) && + (!OOpIsAPInt || !isSelect01(C->getUniqueInteger(), *OOpC))) + return nullptr; + + // If the false value is a NaN then we have that the floating point math + // operation in the transformed code may not preserve the exact NaN + // bit-pattern -- e.g. `fadd sNaN, 0.0 -> qNaN`. + // This makes the transformation incorrect since the original program would + // have preserved the exact NaN bit-pattern. + // Avoid the folding if the false value might be a NaN. + if (isa<FPMathOperator>(&SI) && + !computeKnownFPClass(FalseVal, FMF, fcNan, &SI).isKnownNeverNaN()) + return nullptr; + + Value *NewSel = Builder.CreateSelect(SI.getCondition(), Swapped ? C : OOp, + Swapped ? OOp : C, "", &SI); + if (isa<FPMathOperator>(&SI)) + cast<Instruction>(NewSel)->setFastMathFlags(FMF); + NewSel->takeName(TVI); + BinaryOperator *BO = + BinaryOperator::Create(TVI->getOpcode(), FalseVal, NewSel); + BO->copyIRFlags(TVI); + return BO; }; if (Instruction *R = TryFoldSelectIntoOp(SI, TrueVal, FalseVal, false)) |