@@ -8002,6 +8002,53 @@ static Instruction *foldFCmpFNegCommonOp(FCmpInst &I) {
80028002 return new FCmpInst (Pred, Op0, Zero, " " , &I);
80038003}
80048004
8005+ static Instruction *foldFCmpFSubIntoFCmp (FCmpInst &I, Instruction *LHSI,
8006+ Constant *RHSC, InstCombinerImpl &CI) {
8007+ const CmpInst::Predicate Pred = I.getPredicate ();
8008+ Value *X = LHSI->getOperand (0 );
8009+ Value *Y = LHSI->getOperand (1 );
8010+ switch (Pred) {
8011+ default :
8012+ break ;
8013+ case FCmpInst::FCMP_UGT:
8014+ case FCmpInst::FCMP_ULT:
8015+ case FCmpInst::FCMP_UNE:
8016+ case FCmpInst::FCMP_OEQ:
8017+ case FCmpInst::FCMP_OGE:
8018+ case FCmpInst::FCMP_OLE:
8019+ // The optimization is not valid if X and Y are infinities of the same
8020+ // sign, i.e. the inf - inf = nan case. If the fsub has the ninf or nnan
8021+ // flag then we can assume we do not have that case. Otherwise we might be
8022+ // able to prove that either X or Y is not infinity.
8023+ if (!LHSI->hasNoNaNs () && !LHSI->hasNoInfs () &&
8024+ !isKnownNeverInfinity (Y, /* Depth=*/ 0 ,
8025+ CI.getSimplifyQuery ().getWithInstruction (&I)) &&
8026+ !isKnownNeverInfinity (X, /* Depth=*/ 0 ,
8027+ CI.getSimplifyQuery ().getWithInstruction (&I)))
8028+ break ;
8029+
8030+ [[fallthrough]];
8031+ case FCmpInst::FCMP_OGT:
8032+ case FCmpInst::FCMP_OLT:
8033+ case FCmpInst::FCMP_ONE:
8034+ case FCmpInst::FCMP_UEQ:
8035+ case FCmpInst::FCMP_UGE:
8036+ case FCmpInst::FCMP_ULE:
8037+ // fcmp pred (x - y), 0 --> fcmp pred x, y
8038+ if (match (RHSC, m_AnyZeroFP ()) &&
8039+ I.getFunction ()->getDenormalMode (
8040+ LHSI->getType ()->getScalarType ()->getFltSemantics ()) ==
8041+ DenormalMode::getIEEE ()) {
8042+ CI.replaceOperand (I, 0 , X);
8043+ CI.replaceOperand (I, 1 , Y);
8044+ return &I;
8045+ }
8046+ break ;
8047+ }
8048+
8049+ return nullptr ;
8050+ }
8051+
80058052Instruction *InstCombinerImpl::visitFCmpInst (FCmpInst &I) {
80068053 bool Changed = false ;
80078054
@@ -8172,6 +8219,11 @@ Instruction *InstCombinerImpl::visitFCmpInst(FCmpInst &I) {
81728219 if (Instruction *NV = FoldOpIntoSelect (I, cast<SelectInst>(LHSI)))
81738220 return NV;
81748221 break ;
8222+ case Instruction::FSub:
8223+ if (LHSI->hasOneUse ())
8224+ if (Instruction *NV = foldFCmpFSubIntoFCmp (I, LHSI, RHSC, *this ))
8225+ return NV;
8226+ break ;
81758227 case Instruction::PHI:
81768228 if (Instruction *NV = foldOpIntoPhi (I, cast<PHINode>(LHSI)))
81778229 return NV;
0 commit comments