@@ -3645,6 +3645,60 @@ static bool hasAffectedValue(Value *V, SmallPtrSetImpl<Value *> &Affected,
3645
3645
return false ;
3646
3646
}
3647
3647
3648
+ // This transformation enables the possibility of transforming fcmp + sel into
3649
+ // a fmaxnum/fminnum intrinsic.
3650
+ static Value *foldSelectIntoAddConstant (SelectInst &SI,
3651
+ InstCombiner::BuilderTy &Builder) {
3652
+ // Do this transformation only when select instruction gives NaN and NSZ
3653
+ // guarantee.
3654
+ auto *SIFOp = dyn_cast<FPMathOperator>(&SI);
3655
+ if (!SIFOp || !SIFOp->hasNoSignedZeros () || !SIFOp->hasNoNaNs ())
3656
+ return nullptr ;
3657
+
3658
+ // select((fcmp Pred, X, 0), (fadd X, C), C)
3659
+ // => fadd((select (fcmp Pred, X, 0), X, 0), C)
3660
+ //
3661
+ // Pred := OGT, OGE, OLT, OLE, UGT, UGE, ULT, and ULE
3662
+ Instruction *FAdd;
3663
+ Constant *C;
3664
+ Value *X, *Z;
3665
+ CmpInst::Predicate Pred;
3666
+
3667
+ // Note: OneUse check for `Cmp` is necessary because it makes sure that other
3668
+ // InstCombine folds don't undo this transformation and cause an infinite
3669
+ // loop. Furthermore, it could also increase the operation count.
3670
+ if (match (&SI, m_Select (m_OneUse (m_FCmp (Pred, m_Value (X), m_Value (Z))),
3671
+ m_OneUse (m_Instruction (FAdd)), m_Constant (C))) ||
3672
+ match (&SI, m_Select (m_OneUse (m_FCmp (Pred, m_Value (X), m_Value (Z))),
3673
+ m_Constant (C), m_OneUse (m_Instruction (FAdd))))) {
3674
+ // Only these relational predicates can be transformed into maxnum/minnum
3675
+ // intrinsic.
3676
+ if (!CmpInst::isRelational (Pred) || !match (Z, m_AnyZeroFP ()))
3677
+ return nullptr ;
3678
+
3679
+ if (!match (FAdd, m_FAdd (m_Specific (X), m_Specific (C))))
3680
+ return nullptr ;
3681
+
3682
+ Value *NewSelect = Builder.CreateSelect (SI.getCondition (), X, Z, " " , &SI);
3683
+ NewSelect->takeName (&SI);
3684
+
3685
+ Value *NewFAdd = Builder.CreateFAdd (NewSelect, C);
3686
+ NewFAdd->takeName (FAdd);
3687
+
3688
+ // Propagate FastMath flags
3689
+ FastMathFlags SelectFMF = SI.getFastMathFlags ();
3690
+ FastMathFlags FAddFMF = FAdd->getFastMathFlags ();
3691
+ FastMathFlags NewFMF = FastMathFlags::intersectRewrite (SelectFMF, FAddFMF) |
3692
+ FastMathFlags::unionValue (SelectFMF, FAddFMF);
3693
+ cast<Instruction>(NewFAdd)->setFastMathFlags (NewFMF);
3694
+ cast<Instruction>(NewSelect)->setFastMathFlags (NewFMF);
3695
+
3696
+ return NewFAdd;
3697
+ }
3698
+
3699
+ return nullptr ;
3700
+ }
3701
+
3648
3702
Instruction *InstCombinerImpl::visitSelectInst (SelectInst &SI) {
3649
3703
Value *CondVal = SI.getCondition ();
3650
3704
Value *TrueVal = SI.getTrueValue ();
@@ -4041,6 +4095,9 @@ Instruction *InstCombinerImpl::visitSelectInst(SelectInst &SI) {
4041
4095
if (Value *V = foldRoundUpIntegerWithPow2Alignment (SI, Builder))
4042
4096
return replaceInstUsesWith (SI, V);
4043
4097
4098
+ if (Value *V = foldSelectIntoAddConstant (SI, Builder))
4099
+ return replaceInstUsesWith (SI, V);
4100
+
4044
4101
// select(mask, mload(,,mask,0), 0) -> mload(,,mask,0)
4045
4102
// Load inst is intentionally not checked for hasOneUse()
4046
4103
if (match (FalseVal, m_Zero ()) &&
0 commit comments