@@ -2857,9 +2857,20 @@ Instruction *InstCombinerImpl::visitSub(BinaryOperator &I) {
28572857 I, Builder.CreateIntrinsic (Intrinsic::usub_sat, {Ty}, {X, Op1}));
28582858
28592859 // Op0 - umin(X, Op0) --> usub.sat(Op0, X)
2860- if (match (Op1, m_OneUse (m_c_UMin (m_Value (X), m_Specific (Op0)))))
2861- return replaceInstUsesWith (
2862- I, Builder.CreateIntrinsic (Intrinsic::usub_sat, {Ty}, {Op0, X}));
2860+ if (match (Op1, m_OneUse (m_c_UMin (m_Value (X), m_Specific (Op0))))) {
2861+ Value *USub = Builder.CreateIntrinsic (Intrinsic::usub_sat, {Ty}, {Op0, X});
2862+ if (auto *USubCall = dyn_cast<CallInst>(USub)) {
2863+ // Preserve range information implied by the nsw flag.
2864+ const APInt *C;
2865+ if (I.hasNoSignedWrap () && match (X, m_NonNegative (C))) {
2866+ ConstantRange CR = ConstantRange::makeExactNoWrapRegion (
2867+ Instruction::Sub, *C, OverflowingBinaryOperator::NoSignedWrap);
2868+ USubCall->addParamAttr (
2869+ 0 , Attribute::get (I.getContext (), Attribute::Range, CR));
2870+ }
2871+ }
2872+ return replaceInstUsesWith (I, USub);
2873+ }
28632874
28642875 // Op0 - umax(X, Op0) --> 0 - usub.sat(X, Op0)
28652876 if (match (Op1, m_OneUse (m_c_UMax (m_Value (X), m_Specific (Op0))))) {
0 commit comments