@@ -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,106 @@ 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
+ // (X > INT_MAX - C) ? INT_MAX : (X + C) --> sadd.sat(X, C)
1152
+ // (X >= INT_MAX - C) ? INT_MAX : (X + C) --> sadd.sat(X, C)
1153
+ return Builder.CreateBinaryIntrinsic (Intrinsic::sadd_sat, Cmp0,
1154
+ ConstantInt::get (Cmp0->getType (), *C));
1155
+ }
1156
+
1157
+ if (Pred == ICmpInst::ICMP_SGT &&
1158
+ match (FVal, m_Add (m_Specific (Cmp0), m_APIntAllowPoison (C))) &&
1159
+ match (Cmp1, m_SpecificIntAllowPoison (
1160
+ APInt::getSignedMaxValue (
1161
+ Cmp1->getType ()->getScalarSizeInBits ()) -
1162
+ *C - 1 )) &&
1163
+ !C->isSignedMinValue ()) {
1164
+ // (X > INT_MAX - C - 1) ? INT_MAX : (X + C) --> sadd.sat(X, C)
1165
+ return Builder.CreateBinaryIntrinsic (Intrinsic::sadd_sat, Cmp0,
1166
+ ConstantInt::get (Cmp0->getType (), *C));
1167
+ }
1168
+
1169
+ if (Pred == ICmpInst::ICMP_SGE &&
1170
+ match (FVal, m_Add (m_Specific (Cmp0), m_APIntAllowPoison (C))) &&
1171
+ match (Cmp1, m_SpecificIntAllowPoison (
1172
+ APInt::getSignedMinValue (
1173
+ Cmp1->getType ()->getScalarSizeInBits ()) -
1174
+ *C + 1 )) &&
1175
+ !C->isZero ()) {
1176
+ // (X >= INT_MAX - C + 1) ? INT_MAX : (X + C) --> sadd.sat(X, C)
1177
+ return Builder.CreateBinaryIntrinsic (Intrinsic::sadd_sat, Cmp0,
1178
+ ConstantInt::get (Cmp0->getType (), *C));
1179
+ }
1180
+
1181
+ // Canonicalize predicate to less-than or less-or-equal-than.
1182
+ if (Pred == ICmpInst::ICMP_SGT || Pred == ICmpInst::ICMP_SGE) {
1183
+ std::swap (Cmp0, Cmp1);
1184
+ Pred = CmpInst::getSwappedPredicate (Pred);
1185
+ }
1186
+
1187
+ if (Pred != ICmpInst::ICMP_SLT && Pred != ICmpInst::ICMP_SLE)
1188
+ return nullptr ;
1189
+
1190
+ if (match (Cmp0, m_NSWSub (m_MaxSignedValue (), m_Value (X))) &&
1191
+ match (FVal, m_c_Add (m_Specific (X), m_Value (Y))) && Y == Cmp1) {
1192
+ // (INT_MAX - X s< Y) ? INT_MAX : (X + Y) --> sadd.sat(X, Y)
1193
+ // (INT_MAX - X s< Y) ? INT_MAX : (Y + X) --> sadd.sat(X, Y)
1194
+ return Builder.CreateBinaryIntrinsic (Intrinsic::sadd_sat, X, Y);
1195
+ }
1196
+
1197
+ // TODO: More cases?
1198
+
1199
+ return nullptr ;
1200
+ }
1201
+
1202
+ static Value *canonicalizeSaturatedAdd (ICmpInst *Cmp, Value *TVal, Value *FVal,
1203
+ InstCombiner::BuilderTy &Builder) {
1204
+ if (!Cmp->hasOneUse ())
1205
+ return nullptr ;
1206
+
1207
+ if (Value *V = canonicalizeSaturatedAddUnsigned (Cmp, TVal, FVal, Builder))
1208
+ return V;
1209
+
1210
+ if (Value *V = canonicalizeSaturatedAddSigned (Cmp, TVal, FVal, Builder))
1211
+ return V;
1212
+
1213
+ return nullptr ;
1214
+ }
1215
+
1118
1216
// / Try to match patterns with select and subtract as absolute difference.
1119
1217
static Value *foldAbsDiff (ICmpInst *Cmp, Value *TVal, Value *FVal,
1120
1218
InstCombiner::BuilderTy &Builder) {
0 commit comments