@@ -3661,42 +3661,56 @@ static bool hasAffectedValue(Value *V, SmallPtrSetImpl<Value *> &Affected,
3661
3661
return false ;
3662
3662
}
3663
3663
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 ;
3672
3673
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;
3675
3682
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
3677
3684
// InstCombine folds don't undo this transformation and cause an infinite
3678
3685
// 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 ()))
3686
3691
return nullptr ;
3687
3692
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 :
3689
3696
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
+ }
3690
3707
3691
3708
if (!match (FAdd, m_FAdd (m_Specific (X), m_Specific (C))))
3692
3709
return nullptr ;
3693
3710
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 ());
3700
3714
3701
3715
Value *NewFAdd =
3702
3716
Builder.CreateFAddFMF (NewSelect, C, FAdd, FAdd->getName () + " .new" );
@@ -4102,9 +4116,8 @@ Instruction *InstCombinerImpl::visitSelectInst(SelectInst &SI) {
4102
4116
if (Value *V = foldRoundUpIntegerWithPow2Alignment (SI, Builder))
4103
4117
return replaceInstUsesWith (SI, V);
4104
4118
4105
- if (Value *V = foldSelectAddConstant (SI, Builder)) {
4119
+ if (Value *V = foldSelectIntoAddConstant (SI, Builder))
4106
4120
return replaceInstUsesWith (SI, V);
4107
- }
4108
4121
4109
4122
// select(mask, mload(,,mask,0), 0) -> mload(,,mask,0)
4110
4123
// Load inst is intentionally not checked for hasOneUse()
0 commit comments