@@ -3699,42 +3699,56 @@ static bool hasAffectedValue(Value *V, SmallPtrSetImpl<Value *> &Affected,
3699
3699
return false ;
3700
3700
}
3701
3701
3702
- static Value *foldSelectAddConstant (SelectInst &SI,
3703
- InstCombiner::BuilderTy &Builder) {
3704
- Value *Cmp;
3705
- Instruction *FAdd;
3706
- ConstantFP *C;
3707
-
3708
- // select((fcmp OGT/OLT, X, 0), (fadd X, C), C) => fadd((select (fcmp OGT/OLT,
3709
- // X, 0), X, 0), C)
3702
+ // This transformation enables the possibility of transforming fcmp + sel into
3703
+ // a fmaxnum/fminnum intrinsic.
3704
+ static Value *foldSelectIntoAddConstant (SelectInst &SI,
3705
+ InstCombiner::BuilderTy &Builder) {
3706
+ // Do this transformation only when select instruction gives NaN and NSZ
3707
+ // guarantee.
3708
+ auto *SIFOp = dyn_cast<FPMathOperator>(&SI);
3709
+ if (!SIFOp || !SIFOp->hasNoSignedZeros () || !SIFOp->hasNoNaNs ())
3710
+ return nullptr ;
3710
3711
3711
- // This transformation enables the possibility of transforming fcmp + sel into
3712
- // a fmax/fmin.
3712
+ // select((fcmp Pred, X, 0), (fadd X, C), C)
3713
+ // => fadd((select (fcmp Pred, X, 0), X, 0), C)
3714
+ //
3715
+ // Pred := OGT, OGE, OLT, OLE, UGT, UGE, ULT, and ULE
3716
+ Instruction *FAdd;
3717
+ Constant *C;
3718
+ Value *X, *Z;
3719
+ CmpInst::Predicate Pred;
3713
3720
3714
- // OneUse check for `Cmp` is necessary because it makes sure that other
3721
+ // Note: OneUse check for `Cmp` is necessary because it makes sure that other
3715
3722
// InstCombine folds don't undo this transformation and cause an infinite
3716
3723
// loop.
3717
- if (match (&SI, m_Select (m_OneUse (m_Value (Cmp)), m_OneUse (m_Instruction (FAdd)),
3718
- m_ConstantFP (C))) ||
3719
- match (&SI, m_Select (m_OneUse (m_Value (Cmp)), m_ConstantFP (C),
3720
- m_OneUse (m_Instruction (FAdd))))) {
3721
- Value *X;
3722
- CmpInst::Predicate Pred;
3723
- if (!match (Cmp, m_FCmp (Pred, m_Value (X), m_AnyZeroFP ())))
3724
+ if (match (&SI, m_Select (m_OneUse (m_FCmp (Pred, m_Value (X), m_Value (Z))),
3725
+ m_OneUse (m_Instruction (FAdd)), m_Constant (C))) ||
3726
+ match (&SI, m_Select (m_OneUse (m_FCmp (Pred, m_Value (X), m_Value (Z))),
3727
+ m_Constant (C), m_OneUse (m_Instruction (FAdd))))) {
3728
+ if (!match (Z, m_AnyZeroFP ()))
3724
3729
return nullptr ;
3725
3730
3726
- if (Pred != CmpInst::FCMP_OGT && Pred != CmpInst::FCMP_OLT)
3731
+ // Only these Predicates can be transformed into fmaxnum/fminnum intrinsic.
3732
+ switch (Pred) {
3733
+ default :
3727
3734
return nullptr ;
3735
+ case FCmpInst::FCMP_OGT:
3736
+ case FCmpInst::FCMP_OGE:
3737
+ case FCmpInst::FCMP_OLT:
3738
+ case FCmpInst::FCMP_OLE:
3739
+ case FCmpInst::FCMP_UGT:
3740
+ case FCmpInst::FCMP_UGE:
3741
+ case FCmpInst::FCMP_ULT:
3742
+ case FCmpInst::FCMP_ULE:
3743
+ break ;
3744
+ }
3728
3745
3729
3746
if (!match (FAdd, m_FAdd (m_Specific (X), m_Specific (C))))
3730
3747
return nullptr ;
3731
3748
3732
- FastMathFlags FMF = FAdd->getFastMathFlags ();
3733
- FMF |= SI.getFastMathFlags ();
3734
-
3735
- Value *NewSelect = Builder.CreateSelect (
3736
- Cmp, X, ConstantFP::getZero (C->getType ()), SI.getName () + " .new" , &SI);
3737
- cast<Instruction>(NewSelect)->setFastMathFlags (FMF);
3749
+ Value *NewSelect = Builder.CreateSelect (SI.getCondition (), X, Z,
3750
+ SI.getName () + " .new" , &SI);
3751
+ cast<Instruction>(NewSelect)->setFastMathFlags (SI.getFastMathFlags ());
3738
3752
3739
3753
Value *NewFAdd =
3740
3754
Builder.CreateFAddFMF (NewSelect, C, FAdd, FAdd->getName () + " .new" );
@@ -4140,9 +4154,8 @@ Instruction *InstCombinerImpl::visitSelectInst(SelectInst &SI) {
4140
4154
if (Value *V = foldRoundUpIntegerWithPow2Alignment (SI, Builder))
4141
4155
return replaceInstUsesWith (SI, V);
4142
4156
4143
- if (Value *V = foldSelectAddConstant (SI, Builder)) {
4157
+ if (Value *V = foldSelectIntoAddConstant (SI, Builder))
4144
4158
return replaceInstUsesWith (SI, V);
4145
- }
4146
4159
4147
4160
// select(mask, mload(,,mask,0), 0) -> mload(,,mask,0)
4148
4161
// Load inst is intentionally not checked for hasOneUse()
0 commit comments