@@ -3633,42 +3633,56 @@ static bool hasAffectedValue(Value *V, SmallPtrSetImpl<Value *> &Affected,
36333633 return false ;
36343634}
36353635
3636- static Value *foldSelectAddConstant (SelectInst &SI,
3637- InstCombiner::BuilderTy &Builder) {
3638- Value *Cmp;
3639- Instruction *FAdd;
3640- ConstantFP *C;
3641-
3642- // select((fcmp OGT/OLT, X, 0), (fadd X, C), C) => fadd((select (fcmp OGT/OLT,
3643- // X, 0), X, 0), C)
3636+ // This transformation enables the possibility of transforming fcmp + sel into
3637+ // a fmaxnum/fminnum intrinsic.
3638+ static Value *foldSelectIntoAddConstant (SelectInst &SI,
3639+ InstCombiner::BuilderTy &Builder) {
3640+ // Do this transformation only when select instruction gives NaN and NSZ
3641+ // guarantee.
3642+ auto *SIFOp = dyn_cast<FPMathOperator>(&SI);
3643+ if (!SIFOp || !SIFOp->hasNoSignedZeros () || !SIFOp->hasNoNaNs ())
3644+ return nullptr ;
36443645
3645- // This transformation enables the possibility of transforming fcmp + sel into
3646- // a fmax/fmin.
3646+ // select((fcmp Pred, X, 0), (fadd X, C), C)
3647+ // => fadd((select (fcmp Pred, X, 0), X, 0), C)
3648+ //
3649+ // Pred := OGT, OGE, OLT, OLE, UGT, UGE, ULT, and ULE
3650+ Instruction *FAdd;
3651+ Constant *C;
3652+ Value *X, *Z;
3653+ CmpInst::Predicate Pred;
36473654
3648- // OneUse check for `Cmp` is necessary because it makes sure that other
3655+ // Note: OneUse check for `Cmp` is necessary because it makes sure that other
36493656 // InstCombine folds don't undo this transformation and cause an infinite
36503657 // loop.
3651- if (match (&SI, m_Select (m_OneUse (m_Value (Cmp)), m_OneUse (m_Instruction (FAdd)),
3652- m_ConstantFP (C))) ||
3653- match (&SI, m_Select (m_OneUse (m_Value (Cmp)), m_ConstantFP (C),
3654- m_OneUse (m_Instruction (FAdd))))) {
3655- Value *X;
3656- CmpInst::Predicate Pred;
3657- if (!match (Cmp, m_FCmp (Pred, m_Value (X), m_AnyZeroFP ())))
3658+ if (match (&SI, m_Select (m_OneUse (m_FCmp (Pred, m_Value (X), m_Value (Z))),
3659+ m_OneUse (m_Instruction (FAdd)), m_Constant (C))) ||
3660+ match (&SI, m_Select (m_OneUse (m_FCmp (Pred, m_Value (X), m_Value (Z))),
3661+ m_Constant (C), m_OneUse (m_Instruction (FAdd))))) {
3662+ if (!match (Z, m_AnyZeroFP ()))
36583663 return nullptr ;
36593664
3660- if (Pred != CmpInst::FCMP_OGT && Pred != CmpInst::FCMP_OLT)
3665+ // Only these Predicates can be transformed into fmaxnum/fminnum intrinsic.
3666+ switch (Pred) {
3667+ default :
36613668 return nullptr ;
3669+ case FCmpInst::FCMP_OGT:
3670+ case FCmpInst::FCMP_OGE:
3671+ case FCmpInst::FCMP_OLT:
3672+ case FCmpInst::FCMP_OLE:
3673+ case FCmpInst::FCMP_UGT:
3674+ case FCmpInst::FCMP_UGE:
3675+ case FCmpInst::FCMP_ULT:
3676+ case FCmpInst::FCMP_ULE:
3677+ break ;
3678+ }
36623679
36633680 if (!match (FAdd, m_FAdd (m_Specific (X), m_Specific (C))))
36643681 return nullptr ;
36653682
3666- FastMathFlags FMF = FAdd->getFastMathFlags ();
3667- FMF |= SI.getFastMathFlags ();
3668-
3669- Value *NewSelect = Builder.CreateSelect (
3670- Cmp, X, ConstantFP::getZero (C->getType ()), SI.getName () + " .new" , &SI);
3671- cast<Instruction>(NewSelect)->setFastMathFlags (FMF);
3683+ Value *NewSelect = Builder.CreateSelect (SI.getCondition (), X, Z,
3684+ SI.getName () + " .new" , &SI);
3685+ cast<Instruction>(NewSelect)->setFastMathFlags (SI.getFastMathFlags ());
36723686
36733687 Value *NewFAdd =
36743688 Builder.CreateFAddFMF (NewSelect, C, FAdd, FAdd->getName () + " .new" );
@@ -4074,9 +4088,8 @@ Instruction *InstCombinerImpl::visitSelectInst(SelectInst &SI) {
40744088 if (Value *V = foldRoundUpIntegerWithPow2Alignment (SI, Builder))
40754089 return replaceInstUsesWith (SI, V);
40764090
4077- if (Value *V = foldSelectAddConstant (SI, Builder)) {
4091+ if (Value *V = foldSelectIntoAddConstant (SI, Builder))
40784092 return replaceInstUsesWith (SI, V);
4079- }
40804093
40814094 // select(mask, mload(,,mask,0), 0) -> mload(,,mask,0)
40824095 // Load inst is intentionally not checked for hasOneUse()
0 commit comments