@@ -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, *Y;
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+ if (!match (TVal, m_MaxSignedValue ()))
1147+ return nullptr ;
1148+
1149+ // sge maximum signed value is canonicalized to eq minimum signed value and
1150+ // requires special handling (a == INT_MAX) ? INT_MAX : a + 1 -> sadd.sat(a,
1151+ // 1)
1152+ if (Pred == ICmpInst::ICMP_EQ) {
1153+ if (match (FVal, m_Add (m_Specific (Cmp0), m_One ())) && Cmp1 == TVal) {
1154+ return Builder.CreateBinaryIntrinsic (
1155+ Intrinsic::sadd_sat, Cmp0, ConstantInt::get (Cmp0->getType (), 1 ));
1156+ }
1157+ return nullptr ;
1158+ }
1159+
1160+ if ((Pred == ICmpInst::ICMP_SGE || Pred == ICmpInst::ICMP_SGT) &&
1161+ match (FVal, m_Add (m_Specific (Cmp0), m_APIntAllowPoison (C))) &&
1162+ match (Cmp1, m_SpecificIntAllowPoison (
1163+ APInt::getSignedMaxValue (
1164+ Cmp1->getType ()->getScalarSizeInBits ()) -
1165+ *C)) &&
1166+ !C->isNegative ()) {
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_APIntAllowPoison (C))) &&
1175+ match (Cmp1, m_SpecificIntAllowPoison (
1176+ APInt::getSignedMaxValue (
1177+ Cmp1->getType ()->getScalarSizeInBits ()) -
1178+ *C - 1 )) &&
1179+ !C->isNegative ()) {
1180+ // (X > INT_MAX - C - 1) ? INT_MAX : (X + C) --> sadd.sat(X, C)
1181+ return Builder.CreateBinaryIntrinsic (Intrinsic::sadd_sat, Cmp0,
1182+ ConstantInt::get (Cmp0->getType (), *C));
1183+ }
1184+
1185+ // This does not work with 0, or negative numbers as
1186+ // (X >= INT_MIN + 0 + 1) ? INT_MAX : (X + 0) is not a saturated add.
1187+ if (Pred == ICmpInst::ICMP_SGE &&
1188+ match (FVal, m_Add (m_Specific (Cmp0), m_APIntAllowPoison (C))) &&
1189+ match (Cmp1, m_SpecificIntAllowPoison (
1190+ APInt::getSignedMinValue (
1191+ Cmp1->getType ()->getScalarSizeInBits ()) -
1192+ *C + 1 )) &&
1193+ C->isStrictlyPositive ()) {
1194+ // (X >= INT_MAX - C + 1) ? INT_MAX : (X + C) --> sadd.sat(X, C)
1195+ return Builder.CreateBinaryIntrinsic (Intrinsic::sadd_sat, Cmp0,
1196+ ConstantInt::get (Cmp0->getType (), *C));
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, Y);
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