@@ -8002,6 +8002,53 @@ static Instruction *foldFCmpFNegCommonOp(FCmpInst &I) {
8002
8002
return new FCmpInst (Pred, Op0, Zero, " " , &I);
8003
8003
}
8004
8004
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
+
8005
8052
Instruction *InstCombinerImpl::visitFCmpInst (FCmpInst &I) {
8006
8053
bool Changed = false ;
8007
8054
@@ -8172,6 +8219,11 @@ Instruction *InstCombinerImpl::visitFCmpInst(FCmpInst &I) {
8172
8219
if (Instruction *NV = FoldOpIntoSelect (I, cast<SelectInst>(LHSI)))
8173
8220
return NV;
8174
8221
break ;
8222
+ case Instruction::FSub:
8223
+ if (LHSI->hasOneUse ())
8224
+ if (Instruction *NV = foldFCmpFSubIntoFCmp (I, LHSI, RHSC, *this ))
8225
+ return NV;
8226
+ break ;
8175
8227
case Instruction::PHI:
8176
8228
if (Instruction *NV = foldOpIntoPhi (I, cast<PHINode>(LHSI)))
8177
8229
return NV;
0 commit comments