@@ -3661,42 +3661,56 @@ static bool hasAffectedValue(Value *V, SmallPtrSetImpl<Value *> &Affected,
36613661 return false ;
36623662}
36633663
3664- static Value *foldSelectAddConstant (SelectInst &SI,
3665- InstCombiner::BuilderTy &Builder) {
3666- Value *Cmp;
3667- Instruction *FAdd;
3668- ConstantFP *C;
3669-
3670- // select((fcmp OGT/OLT, X, 0), (fadd X, C), C) => fadd((select (fcmp OGT/OLT,
3671- // X, 0), X, 0), C)
3664+ // This transformation enables the possibility of transforming fcmp + sel into
3665+ // a fmaxnum/fminnum intrinsic.
3666+ static Value *foldSelectIntoAddConstant (SelectInst &SI,
3667+ InstCombiner::BuilderTy &Builder) {
3668+ // Do this transformation only when select instruction gives NaN and NSZ
3669+ // guarantee.
3670+ auto *SIFOp = dyn_cast<FPMathOperator>(&SI);
3671+ if (!SIFOp || !SIFOp->hasNoSignedZeros () || !SIFOp->hasNoNaNs ())
3672+ return nullptr ;
36723673
3673- // This transformation enables the possibility of transforming fcmp + sel into
3674- // a fmax/fmin.
3674+ // select((fcmp Pred, X, 0), (fadd X, C), C)
3675+ // => fadd((select (fcmp Pred, X, 0), X, 0), C)
3676+ //
3677+ // Pred := OGT, OGE, OLT, OLE, UGT, UGE, ULT, and ULE
3678+ Instruction *FAdd;
3679+ Constant *C;
3680+ Value *X, *Z;
3681+ CmpInst::Predicate Pred;
36753682
3676- // OneUse check for `Cmp` is necessary because it makes sure that other
3683+ // Note: OneUse check for `Cmp` is necessary because it makes sure that other
36773684 // InstCombine folds don't undo this transformation and cause an infinite
36783685 // loop.
3679- if (match (&SI, m_Select (m_OneUse (m_Value (Cmp)), m_OneUse (m_Instruction (FAdd)),
3680- m_ConstantFP (C))) ||
3681- match (&SI, m_Select (m_OneUse (m_Value (Cmp)), m_ConstantFP (C),
3682- m_OneUse (m_Instruction (FAdd))))) {
3683- Value *X;
3684- CmpInst::Predicate Pred;
3685- if (!match (Cmp, m_FCmp (Pred, m_Value (X), m_AnyZeroFP ())))
3686+ if (match (&SI, m_Select (m_OneUse (m_FCmp (Pred, m_Value (X), m_Value (Z))),
3687+ m_OneUse (m_Instruction (FAdd)), m_Constant (C))) ||
3688+ match (&SI, m_Select (m_OneUse (m_FCmp (Pred, m_Value (X), m_Value (Z))),
3689+ m_Constant (C), m_OneUse (m_Instruction (FAdd))))) {
3690+ if (!match (Z, m_AnyZeroFP ()))
36863691 return nullptr ;
36873692
3688- if (Pred != CmpInst::FCMP_OGT && Pred != CmpInst::FCMP_OLT)
3693+ // Only these Predicates can be transformed into fmaxnum/fminnum intrinsic.
3694+ switch (Pred) {
3695+ default :
36893696 return nullptr ;
3697+ case FCmpInst::FCMP_OGT:
3698+ case FCmpInst::FCMP_OGE:
3699+ case FCmpInst::FCMP_OLT:
3700+ case FCmpInst::FCMP_OLE:
3701+ case FCmpInst::FCMP_UGT:
3702+ case FCmpInst::FCMP_UGE:
3703+ case FCmpInst::FCMP_ULT:
3704+ case FCmpInst::FCMP_ULE:
3705+ break ;
3706+ }
36903707
36913708 if (!match (FAdd, m_FAdd (m_Specific (X), m_Specific (C))))
36923709 return nullptr ;
36933710
3694- FastMathFlags FMF = FAdd->getFastMathFlags ();
3695- FMF |= SI.getFastMathFlags ();
3696-
3697- Value *NewSelect = Builder.CreateSelect (
3698- Cmp, X, ConstantFP::getZero (C->getType ()), SI.getName () + " .new" , &SI);
3699- cast<Instruction>(NewSelect)->setFastMathFlags (FMF);
3711+ Value *NewSelect = Builder.CreateSelect (SI.getCondition (), X, Z,
3712+ SI.getName () + " .new" , &SI);
3713+ cast<Instruction>(NewSelect)->setFastMathFlags (SI.getFastMathFlags ());
37003714
37013715 Value *NewFAdd =
37023716 Builder.CreateFAddFMF (NewSelect, C, FAdd, FAdd->getName () + " .new" );
@@ -4102,9 +4116,8 @@ Instruction *InstCombinerImpl::visitSelectInst(SelectInst &SI) {
41024116 if (Value *V = foldRoundUpIntegerWithPow2Alignment (SI, Builder))
41034117 return replaceInstUsesWith (SI, V);
41044118
4105- if (Value *V = foldSelectAddConstant (SI, Builder)) {
4119+ if (Value *V = foldSelectIntoAddConstant (SI, Builder))
41064120 return replaceInstUsesWith (SI, V);
4107- }
41084121
41094122 // select(mask, mload(,,mask,0), 0) -> mload(,,mask,0)
41104123 // Load inst is intentionally not checked for hasOneUse()
0 commit comments