@@ -3633,42 +3633,56 @@ static bool hasAffectedValue(Value *V, SmallPtrSetImpl<Value *> &Affected,
3633
3633
return false ;
3634
3634
}
3635
3635
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 ;
3644
3645
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;
3647
3654
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
3649
3656
// InstCombine folds don't undo this transformation and cause an infinite
3650
3657
// 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 ()))
3658
3663
return nullptr ;
3659
3664
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 :
3661
3668
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
+ }
3662
3679
3663
3680
if (!match (FAdd, m_FAdd (m_Specific (X), m_Specific (C))))
3664
3681
return nullptr ;
3665
3682
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 ());
3672
3686
3673
3687
Value *NewFAdd =
3674
3688
Builder.CreateFAddFMF (NewSelect, C, FAdd, FAdd->getName () + " .new" );
@@ -4074,9 +4088,8 @@ Instruction *InstCombinerImpl::visitSelectInst(SelectInst &SI) {
4074
4088
if (Value *V = foldRoundUpIntegerWithPow2Alignment (SI, Builder))
4075
4089
return replaceInstUsesWith (SI, V);
4076
4090
4077
- if (Value *V = foldSelectAddConstant (SI, Builder)) {
4091
+ if (Value *V = foldSelectIntoAddConstant (SI, Builder))
4078
4092
return replaceInstUsesWith (SI, V);
4079
- }
4080
4093
4081
4094
// select(mask, mload(,,mask,0), 0) -> mload(,,mask,0)
4082
4095
// Load inst is intentionally not checked for hasOneUse()
0 commit comments