@@ -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 );
@@ -1130,6 +1129,94 @@ static Value *canonicalizeSaturatedAdd(ICmpInst *Cmp, Value *TVal, Value *FVal,
11301129 return nullptr ;
11311130}
11321131
1132+ static Value *canonicalizeSaturatedAddSigned (ICmpInst *Cmp, Value *TVal,
1133+ Value *FVal,
1134+ InstCombiner::BuilderTy &Builder) {
1135+ // Match saturated add with constant.
1136+ Value *Cmp0 = Cmp->getOperand (0 );
1137+ Value *Cmp1 = Cmp->getOperand (1 );
1138+ ICmpInst::Predicate Pred = Cmp->getPredicate ();
1139+ Value *X;
1140+ const APInt *C;
1141+
1142+ // Canonicalize INT_MAX to true value of the select.
1143+ if (match (FVal, m_MaxSignedValue ())) {
1144+ std::swap (TVal, FVal);
1145+ Pred = CmpInst::getInversePredicate (Pred);
1146+ }
1147+
1148+ if (!match (TVal, m_MaxSignedValue ()))
1149+ return nullptr ;
1150+
1151+ // sge maximum signed value is canonicalized to eq maximum signed value and
1152+ // requires special handling (a == INT_MAX) ? INT_MAX : a + 1 -> sadd.sat(a,
1153+ // 1)
1154+ if (Pred == ICmpInst::ICMP_EQ) {
1155+ if (match (FVal, m_Add (m_Specific (Cmp0), m_One ())) && Cmp1 == TVal) {
1156+ return Builder.CreateBinaryIntrinsic (
1157+ Intrinsic::sadd_sat, Cmp0, ConstantInt::get (Cmp0->getType (), 1 ));
1158+ }
1159+ return nullptr ;
1160+ }
1161+
1162+ // (X > Y) ? INT_MAX : (X + C) --> sadd.sat(X, C)
1163+ // (X >= Y) ? INT_MAX : (X + C) --> sadd.sat(X, C)
1164+ // where Y is INT_MAX - C or INT_MAX - C - 1, and C > 0
1165+ if ((Pred == ICmpInst::ICMP_SGT || Pred == ICmpInst::ICMP_SGE) &&
1166+ match (FVal, m_Add (m_Specific (Cmp0), m_StrictlyPositive (C)))) {
1167+ APInt IntMax =
1168+ APInt::getSignedMaxValue (Cmp1->getType ()->getScalarSizeInBits ());
1169+
1170+ // For SGE, try to flip to SGT to normalize the comparison constant.
1171+ if (Pred == ICmpInst::ICMP_SGE) {
1172+ if (auto Flipped = getFlippedStrictnessPredicateAndConstant (
1173+ Pred, cast<Constant>(Cmp1))) {
1174+ Pred = Flipped->first ;
1175+ Cmp1 = Flipped->second ;
1176+ }
1177+ }
1178+
1179+ // Check the pattern: X > INT_MAX - C or X > INT_MAX - C - 1
1180+ if (Pred == ICmpInst::ICMP_SGT &&
1181+ (match (Cmp1, m_SpecificIntAllowPoison (IntMax - *C)) ||
1182+ match (Cmp1, m_SpecificIntAllowPoison (IntMax - *C - 1 ))))
1183+ return Builder.CreateBinaryIntrinsic (
1184+ Intrinsic::sadd_sat, Cmp0, ConstantInt::get (Cmp0->getType (), *C));
1185+ }
1186+
1187+ // Canonicalize predicate to less-than or less-or-equal-than.
1188+ if (Pred == ICmpInst::ICMP_SGT || Pred == ICmpInst::ICMP_SGE) {
1189+ std::swap (Cmp0, Cmp1);
1190+ Pred = CmpInst::getSwappedPredicate (Pred);
1191+ }
1192+
1193+ if (Pred != ICmpInst::ICMP_SLT && Pred != ICmpInst::ICMP_SLE)
1194+ return nullptr ;
1195+
1196+ if (match (Cmp0, m_NSWSub (m_MaxSignedValue (), m_Value (X))) &&
1197+ match (FVal, m_c_Add (m_Specific (X), m_Specific (Cmp1)))) {
1198+ // (INT_MAX - X s< Y) ? INT_MAX : (X + Y) --> sadd.sat(X, Y)
1199+ // (INT_MAX - X s< Y) ? INT_MAX : (Y + X) --> sadd.sat(X, Y)
1200+ return Builder.CreateBinaryIntrinsic (Intrinsic::sadd_sat, X, Cmp1);
1201+ }
1202+
1203+ return nullptr ;
1204+ }
1205+
1206+ static Value *canonicalizeSaturatedAdd (ICmpInst *Cmp, Value *TVal, Value *FVal,
1207+ InstCombiner::BuilderTy &Builder) {
1208+ if (!Cmp->hasOneUse ())
1209+ return nullptr ;
1210+
1211+ if (Value *V = canonicalizeSaturatedAddUnsigned (Cmp, TVal, FVal, Builder))
1212+ return V;
1213+
1214+ if (Value *V = canonicalizeSaturatedAddSigned (Cmp, TVal, FVal, Builder))
1215+ return V;
1216+
1217+ return nullptr ;
1218+ }
1219+
11331220// / Try to match patterns with select and subtract as absolute difference.
11341221static Value *foldAbsDiff (ICmpInst *Cmp, Value *TVal, Value *FVal,
11351222 InstCombiner::BuilderTy &Builder) {
0 commit comments