@@ -1012,10 +1012,9 @@ static Value *canonicalizeSaturatedSubtract(const ICmpInst *ICI,
1012
1012
return Result;
1013
1013
}
1014
1014
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) {
1019
1018
1020
1019
// Match unsigned saturated add with constant.
1021
1020
Value *Cmp0 = Cmp->getOperand (0 );
@@ -1037,8 +1036,7 @@ static Value *canonicalizeSaturatedAdd(ICmpInst *Cmp, Value *TVal, Value *FVal,
1037
1036
// uge -1 is canonicalized to eq -1 and requires special handling
1038
1037
// (a == -1) ? -1 : a + 1 -> uadd.sat(a, 1)
1039
1038
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) {
1042
1040
return Builder.CreateBinaryIntrinsic (
1043
1041
Intrinsic::uadd_sat, Cmp0, ConstantInt::get (Cmp0->getType (), 1 ));
1044
1042
}
@@ -1115,6 +1113,107 @@ static Value *canonicalizeSaturatedAdd(ICmpInst *Cmp, Value *TVal, Value *FVal,
1115
1113
return nullptr ;
1116
1114
}
1117
1115
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
+
1118
1217
// / Try to match patterns with select and subtract as absolute difference.
1119
1218
static Value *foldAbsDiff (ICmpInst *Cmp, Value *TVal, Value *FVal,
1120
1219
InstCombiner::BuilderTy &Builder) {
0 commit comments