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