@@ -1012,10 +1012,9 @@ static Value *canonicalizeSaturatedSubtract(const ICmpInst *ICI,
10121012 return Result;
10131013}
10141014
1015- static Value *canonicalizeSaturatedAdd (ICmpInst *Cmp, Value *TVal, Value *FVal,
1016- InstCombiner::BuilderTy &Builder) {
1017- if (!Cmp->hasOneUse ())
1018- return nullptr ;
1015+ static Value *
1016+ canonicalizeSaturatedAddUnsigned (ICmpInst *Cmp, Value *TVal, Value *FVal,
1017+ InstCombiner::BuilderTy &Builder) {
10191018
10201019 // Match unsigned saturated add with constant.
10211020 Value *Cmp0 = Cmp->getOperand (0 );
@@ -1037,8 +1036,7 @@ static Value *canonicalizeSaturatedAdd(ICmpInst *Cmp, Value *TVal, Value *FVal,
10371036 // uge -1 is canonicalized to eq -1 and requires special handling
10381037 // (a == -1) ? -1 : a + 1 -> uadd.sat(a, 1)
10391038 if (Pred == ICmpInst::ICMP_EQ) {
1040- if (match (FVal, m_Add (m_Specific (Cmp0), m_One ())) &&
1041- match (Cmp1, m_AllOnes ())) {
1039+ if (match (FVal, m_Add (m_Specific (Cmp0), m_One ())) && Cmp1 == TVal) {
10421040 return Builder.CreateBinaryIntrinsic (
10431041 Intrinsic::uadd_sat, Cmp0, ConstantInt::get (Cmp0->getType (), 1 ));
10441042 }
@@ -1115,6 +1113,107 @@ static Value *canonicalizeSaturatedAdd(ICmpInst *Cmp, Value *TVal, Value *FVal,
11151113 return nullptr ;
11161114}
11171115
1116+ static Value *canonicalizeSaturatedAddSigned (ICmpInst *Cmp, Value *TVal,
1117+ Value *FVal,
1118+ InstCombiner::BuilderTy &Builder) {
1119+ // Match saturated add with constant.
1120+ Value *Cmp0 = Cmp->getOperand (0 );
1121+ Value *Cmp1 = Cmp->getOperand (1 );
1122+ ICmpInst::Predicate Pred = Cmp->getPredicate ();
1123+ Value *X, *Y;
1124+ const APInt *C;
1125+
1126+ // Canonicalize INT_MAX to true value of the select.
1127+ if (match (FVal, m_MaxSignedValue ())) {
1128+ std::swap (TVal, FVal);
1129+ Pred = CmpInst::getInversePredicate (Pred);
1130+ }
1131+ if (!match (TVal, m_MaxSignedValue ()))
1132+ return nullptr ;
1133+
1134+ // sge maximum signed value is canonicalized to eq minimum signed value and
1135+ // requires special handling (a == INT_MAX) ? INT_MAX : a + 1 -> sadd.sat(a,
1136+ // 1)
1137+ if (Pred == ICmpInst::ICMP_EQ) {
1138+ if (match (FVal, m_Add (m_Specific (Cmp0), m_One ())) && Cmp1 == TVal) {
1139+ return Builder.CreateBinaryIntrinsic (
1140+ Intrinsic::sadd_sat, Cmp0, ConstantInt::get (Cmp0->getType (), 1 ));
1141+ }
1142+ return nullptr ;
1143+ }
1144+
1145+ if ((Pred == ICmpInst::ICMP_SGE || Pred == ICmpInst::ICMP_SGT) &&
1146+ match (FVal, m_Add (m_Specific (Cmp0), m_APIntAllowPoison (C))) &&
1147+ match (Cmp1, m_SpecificIntAllowPoison (
1148+ APInt::getSignedMaxValue (
1149+ Cmp1->getType ()->getScalarSizeInBits ()) -
1150+ *C)) &&
1151+ !C->isNegative ()) {
1152+ // (X > INT_MAX - C) ? INT_MAX : (X + C) --> sadd.sat(X, C)
1153+ // (X >= INT_MAX - C) ? INT_MAX : (X + C) --> sadd.sat(X, C)
1154+ return Builder.CreateBinaryIntrinsic (Intrinsic::sadd_sat, Cmp0,
1155+ ConstantInt::get (Cmp0->getType (), *C));
1156+ }
1157+
1158+ if (Pred == ICmpInst::ICMP_SGT &&
1159+ match (FVal, m_Add (m_Specific (Cmp0), m_APIntAllowPoison (C))) &&
1160+ match (Cmp1, m_SpecificIntAllowPoison (
1161+ APInt::getSignedMaxValue (
1162+ Cmp1->getType ()->getScalarSizeInBits ()) -
1163+ *C - 1 )) &&
1164+ !C->isNegative ()) {
1165+ // (X > INT_MAX - C - 1) ? INT_MAX : (X + C) --> sadd.sat(X, C)
1166+ return Builder.CreateBinaryIntrinsic (Intrinsic::sadd_sat, Cmp0,
1167+ ConstantInt::get (Cmp0->getType (), *C));
1168+ }
1169+
1170+ // This does not work with 0, or negative numbers as
1171+ // (X >= INT_MIN + 0 + 1) ? INT_MAX : (X + 0) is not a saturated add.
1172+ if (Pred == ICmpInst::ICMP_SGE &&
1173+ match (FVal, m_Add (m_Specific (Cmp0), m_APIntAllowPoison (C))) &&
1174+ match (Cmp1, m_SpecificIntAllowPoison (
1175+ APInt::getSignedMinValue (
1176+ Cmp1->getType ()->getScalarSizeInBits ()) -
1177+ *C + 1 )) &&
1178+ C->isStrictlyPositive ()) {
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+ // Canonicalize predicate to less-than or less-or-equal-than.
1185+ if (Pred == ICmpInst::ICMP_SGT || Pred == ICmpInst::ICMP_SGE) {
1186+ std::swap (Cmp0, Cmp1);
1187+ Pred = CmpInst::getSwappedPredicate (Pred);
1188+ }
1189+
1190+ if (Pred != ICmpInst::ICMP_SLT && Pred != ICmpInst::ICMP_SLE)
1191+ return nullptr ;
1192+
1193+ if (match (Cmp0, m_NSWSub (m_MaxSignedValue (), m_Value (X))) &&
1194+ match (FVal, m_c_Add (m_Specific (X), m_Value (Y))) && Y == Cmp1) {
1195+ // (INT_MAX - X s< Y) ? INT_MAX : (X + Y) --> sadd.sat(X, Y)
1196+ // (INT_MAX - X s< Y) ? INT_MAX : (Y + X) --> sadd.sat(X, Y)
1197+ return Builder.CreateBinaryIntrinsic (Intrinsic::sadd_sat, X, Y);
1198+ }
1199+
1200+ return nullptr ;
1201+ }
1202+
1203+ static Value *canonicalizeSaturatedAdd (ICmpInst *Cmp, Value *TVal, Value *FVal,
1204+ InstCombiner::BuilderTy &Builder) {
1205+ if (!Cmp->hasOneUse ())
1206+ return nullptr ;
1207+
1208+ if (Value *V = canonicalizeSaturatedAddUnsigned (Cmp, TVal, FVal, Builder))
1209+ return V;
1210+
1211+ if (Value *V = canonicalizeSaturatedAddSigned (Cmp, TVal, FVal, Builder))
1212+ return V;
1213+
1214+ return nullptr ;
1215+ }
1216+
11181217// / Try to match patterns with select and subtract as absolute difference.
11191218static Value *foldAbsDiff (ICmpInst *Cmp, Value *TVal, Value *FVal,
11201219 InstCombiner::BuilderTy &Builder) {
0 commit comments