@@ -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,106 @@ 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+ if ((Pred == ICmpInst::ICMP_SGE || Pred == ICmpInst::ICMP_SGT) &&
1162+ match (FVal, m_Add (m_Specific (Cmp0), m_NonNegative (C))) &&
1163+ match (Cmp1, m_SpecificIntAllowPoison (
1164+ APInt::getSignedMaxValue (
1165+ Cmp1->getType ()->getScalarSizeInBits ()) -
1166+ *C))) {
1167+ // (X > INT_MAX - C) ? INT_MAX : (X + C) --> sadd.sat(X, C)
1168+ // (X >= INT_MAX - C) ? INT_MAX : (X + C) --> sadd.sat(X, C)
1169+ return Builder.CreateBinaryIntrinsic (Intrinsic::sadd_sat, Cmp0,
1170+ ConstantInt::get (Cmp0->getType (), *C));
1171+ }
1172+
1173+ if (Pred == ICmpInst::ICMP_SGT &&
1174+ match (FVal, m_Add (m_Specific (Cmp0), m_NonNegative (C))) &&
1175+ match (Cmp1, m_SpecificIntAllowPoison (
1176+ APInt::getSignedMaxValue (
1177+ Cmp1->getType ()->getScalarSizeInBits ()) -
1178+ *C - 1 ))) {
1179+ // (X > INT_MAX - C - 1) ? INT_MAX : (X + C) --> sadd.sat(X, C)
1180+ return Builder.CreateBinaryIntrinsic (Intrinsic::sadd_sat, Cmp0,
1181+ ConstantInt::get (Cmp0->getType (), *C));
1182+ }
1183+
1184+ // This does not work with 0, or negative numbers as
1185+ // (X >= INT_MIN + 0 + 1) ? INT_MAX : (X + 0) is not a saturated add.
1186+ if (Pred == ICmpInst::ICMP_SGE &&
1187+ match (FVal, m_Add (m_Specific (Cmp0), m_APIntAllowPoison (C))) &&
1188+ match (Cmp1, m_SpecificIntAllowPoison (
1189+ APInt::getSignedMinValue (
1190+ Cmp1->getType ()->getScalarSizeInBits ()) -
1191+ *C + 1 )) &&
1192+ C->isStrictlyPositive ()) {
1193+ // (X >= INT_MAX - C + 1) ? INT_MAX : (X + C) --> sadd.sat(X, C)
1194+ return Builder.CreateBinaryIntrinsic (Intrinsic::sadd_sat, Cmp0,
1195+ ConstantInt::get (Cmp0->getType (), *C));
1196+ }
1197+
1198+ // Canonicalize predicate to less-than or less-or-equal-than.
1199+ if (Pred == ICmpInst::ICMP_SGT || Pred == ICmpInst::ICMP_SGE) {
1200+ std::swap (Cmp0, Cmp1);
1201+ Pred = CmpInst::getSwappedPredicate (Pred);
1202+ }
1203+
1204+ if (Pred != ICmpInst::ICMP_SLT && Pred != ICmpInst::ICMP_SLE)
1205+ return nullptr ;
1206+
1207+ if (match (Cmp0, m_NSWSub (m_MaxSignedValue (), m_Value (X))) &&
1208+ match (FVal, m_c_Add (m_Specific (X), m_Specific (Cmp1)))) {
1209+ // (INT_MAX - X s< Y) ? INT_MAX : (X + Y) --> sadd.sat(X, Y)
1210+ // (INT_MAX - X s< Y) ? INT_MAX : (Y + X) --> sadd.sat(X, Y)
1211+ return Builder.CreateBinaryIntrinsic (Intrinsic::sadd_sat, X, Cmp1);
1212+ }
1213+
1214+ return nullptr ;
1215+ }
1216+
1217+ static Value *canonicalizeSaturatedAdd (ICmpInst *Cmp, Value *TVal, Value *FVal,
1218+ InstCombiner::BuilderTy &Builder) {
1219+ if (!Cmp->hasOneUse ())
1220+ return nullptr ;
1221+
1222+ if (Value *V = canonicalizeSaturatedAddUnsigned (Cmp, TVal, FVal, Builder))
1223+ return V;
1224+
1225+ if (Value *V = canonicalizeSaturatedAddSigned (Cmp, TVal, FVal, Builder))
1226+ return V;
1227+
1228+ return nullptr ;
1229+ }
1230+
11331231// / Try to match patterns with select and subtract as absolute difference.
11341232static Value *foldAbsDiff (ICmpInst *Cmp, Value *TVal, Value *FVal,
11351233 InstCombiner::BuilderTy &Builder) {
0 commit comments