@@ -1027,10 +1027,9 @@ static Value *canonicalizeSaturatedSubtract(const ICmpInst *ICI,
10271027 return Result;
10281028}
10291029
1030- static Value *canonicalizeSaturatedAdd (ICmpInst *Cmp, Value *TVal, Value *FVal,
1031- InstCombiner::BuilderTy &Builder) {
1032- if (!Cmp->hasOneUse ())
1033- return nullptr ;
1030+ static Value *
1031+ canonicalizeSaturatedAddUnsigned (ICmpInst *Cmp, Value *TVal, Value *FVal,
1032+ InstCombiner::BuilderTy &Builder) {
10341033
10351034 // Match unsigned saturated add with constant.
10361035 Value *Cmp0 = Cmp->getOperand (0 );
@@ -1052,8 +1051,7 @@ static Value *canonicalizeSaturatedAdd(ICmpInst *Cmp, Value *TVal, Value *FVal,
10521051 // uge -1 is canonicalized to eq -1 and requires special handling
10531052 // (a == -1) ? -1 : a + 1 -> uadd.sat(a, 1)
10541053 if (Pred == ICmpInst::ICMP_EQ) {
1055- if (match (FVal, m_Add (m_Specific (Cmp0), m_One ())) &&
1056- match (Cmp1, m_AllOnes ())) {
1054+ if (match (FVal, m_Add (m_Specific (Cmp0), m_One ())) && Cmp1 == TVal) {
10571055 return Builder.CreateBinaryIntrinsic (
10581056 Intrinsic::uadd_sat, Cmp0, ConstantInt::get (Cmp0->getType (), 1 ));
10591057 }
@@ -1130,6 +1128,107 @@ static Value *canonicalizeSaturatedAdd(ICmpInst *Cmp, Value *TVal, Value *FVal,
11301128 return nullptr ;
11311129}
11321130
1131+ static Value *canonicalizeSaturatedAddSigned (ICmpInst *Cmp, Value *TVal,
1132+ Value *FVal,
1133+ InstCombiner::BuilderTy &Builder) {
1134+ // Match saturated add with constant.
1135+ Value *Cmp0 = Cmp->getOperand (0 );
1136+ Value *Cmp1 = Cmp->getOperand (1 );
1137+ ICmpInst::Predicate Pred = Cmp->getPredicate ();
1138+ Value *X;
1139+ const APInt *C;
1140+
1141+ // Canonicalize INT_MAX to true value of the select.
1142+ if (match (FVal, m_MaxSignedValue ())) {
1143+ std::swap (TVal, FVal);
1144+ Pred = CmpInst::getInversePredicate (Pred);
1145+ }
1146+
1147+ if (!match (TVal, m_MaxSignedValue ()))
1148+ return nullptr ;
1149+
1150+ // sge maximum signed value is canonicalized to eq maximum signed value and
1151+ // requires special handling (a == INT_MAX) ? INT_MAX : a + 1 -> sadd.sat(a,
1152+ // 1)
1153+ if (Pred == ICmpInst::ICMP_EQ) {
1154+ if (match (FVal, m_Add (m_Specific (Cmp0), m_One ())) && Cmp1 == TVal) {
1155+ return Builder.CreateBinaryIntrinsic (
1156+ Intrinsic::sadd_sat, Cmp0, ConstantInt::get (Cmp0->getType (), 1 ));
1157+ }
1158+ return nullptr ;
1159+ }
1160+
1161+ // (X > Y) ? INT_MAX : (X + C) --> sadd.sat(X, C)
1162+ // (X >= Y) ? INT_MAX : (X + C) --> sadd.sat(X, C)
1163+ // where Y is INT_MAX - C or INT_MAX - C - 1, and C > 0
1164+ if ((Pred == ICmpInst::ICMP_SGT || Pred == ICmpInst::ICMP_SGE) &&
1165+ match (FVal, m_Add (m_Specific (Cmp0), m_APIntAllowPoison (C))) &&
1166+ C->isStrictlyPositive ()) {
1167+ APInt IntMax =
1168+ APInt::getSignedMaxValue (Cmp1->getType ()->getScalarSizeInBits ());
1169+
1170+ // For SGE, try to flip to SGT to normalize the comparison constant.
1171+ auto FlippedPredicate = Pred;
1172+ const APInt *FlippedC = nullptr ;
1173+ if (Pred == ICmpInst::ICMP_SGE) {
1174+ if (auto Flipped = getFlippedStrictnessPredicateAndConstant (
1175+ Pred, cast<Constant>(Cmp1))) {
1176+ FlippedPredicate = Flipped->first ;
1177+ if (auto *CI = dyn_cast<ConstantInt>(Flipped->second ))
1178+ FlippedC = &CI->getValue ();
1179+ }
1180+ }
1181+
1182+ // Check the pattern: X > INT_MAX - C or X > INT_MAX - C - 1
1183+ bool MatchesSGT =
1184+ (Pred == ICmpInst::ICMP_SGT &&
1185+ (match (Cmp1, m_SpecificIntAllowPoison (IntMax - *C)) ||
1186+ match (Cmp1, m_SpecificIntAllowPoison (IntMax - *C - 1 ))));
1187+
1188+ // Check if SGE can be canonicalized to match the pattern
1189+ bool MatchesSGE =
1190+ (Pred == ICmpInst::ICMP_SGE && FlippedC &&
1191+ (*FlippedC == IntMax - *C || *FlippedC == IntMax - *C - 1 ));
1192+
1193+ if (MatchesSGT || MatchesSGE) {
1194+ return Builder.CreateBinaryIntrinsic (Intrinsic::sadd_sat, Cmp0,
1195+ ConstantInt::get (Cmp0->getType (), *C));
1196+ }
1197+ }
1198+
1199+ // Canonicalize predicate to less-than or less-or-equal-than.
1200+ if (Pred == ICmpInst::ICMP_SGT || Pred == ICmpInst::ICMP_SGE) {
1201+ std::swap (Cmp0, Cmp1);
1202+ Pred = CmpInst::getSwappedPredicate (Pred);
1203+ }
1204+
1205+ if (Pred != ICmpInst::ICMP_SLT && Pred != ICmpInst::ICMP_SLE)
1206+ return nullptr ;
1207+
1208+ if (match (Cmp0, m_NSWSub (m_MaxSignedValue (), m_Value (X))) &&
1209+ match (FVal, m_c_Add (m_Specific (X), m_Specific (Cmp1)))) {
1210+ // (INT_MAX - X s< Y) ? INT_MAX : (X + Y) --> sadd.sat(X, Y)
1211+ // (INT_MAX - X s< Y) ? INT_MAX : (Y + X) --> sadd.sat(X, Y)
1212+ return Builder.CreateBinaryIntrinsic (Intrinsic::sadd_sat, X, Cmp1);
1213+ }
1214+
1215+ return nullptr ;
1216+ }
1217+
1218+ static Value *canonicalizeSaturatedAdd (ICmpInst *Cmp, Value *TVal, Value *FVal,
1219+ InstCombiner::BuilderTy &Builder) {
1220+ if (!Cmp->hasOneUse ())
1221+ return nullptr ;
1222+
1223+ if (Value *V = canonicalizeSaturatedAddUnsigned (Cmp, TVal, FVal, Builder))
1224+ return V;
1225+
1226+ if (Value *V = canonicalizeSaturatedAddSigned (Cmp, TVal, FVal, Builder))
1227+ return V;
1228+
1229+ return nullptr ;
1230+ }
1231+
11331232// / Try to match patterns with select and subtract as absolute difference.
11341233static Value *foldAbsDiff (ICmpInst *Cmp, Value *TVal, Value *FVal,
11351234 InstCombiner::BuilderTy &Builder) {
0 commit comments