@@ -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,94 @@ 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
+ const APInt *C;
1124
+
1125
+ // Canonicalize INT_MAX to true value of the select.
1126
+ if (match (FVal, m_MaxSignedValue ())) {
1127
+ std::swap (TVal, FVal);
1128
+ Pred = CmpInst::getInversePredicate (Pred);
1129
+ }
1130
+ if (!match (TVal, m_MaxSignedValue ()))
1131
+ return nullptr ;
1132
+
1133
+ // sge maximum signed value is canonicalized to eq minimum signed value and
1134
+ // requires special handling (a == INT_MAX) ? INT_MAX : a + 1 -> sadd.sat(a,
1135
+ // 1)
1136
+ if (Pred == ICmpInst::ICMP_EQ) {
1137
+ if (match (FVal, m_Add (m_Specific (Cmp0), m_One ())) && Cmp1 == TVal) {
1138
+ return Builder.CreateBinaryIntrinsic (
1139
+ Intrinsic::sadd_sat, Cmp0, ConstantInt::get (Cmp0->getType (), 1 ));
1140
+ }
1141
+ return nullptr ;
1142
+ }
1143
+
1144
+ if ((Pred == ICmpInst::ICMP_SGE || Pred == ICmpInst::ICMP_SGT) &&
1145
+ match (FVal, m_Add (m_Specific (Cmp0), m_APIntAllowPoison (C))) &&
1146
+ match (Cmp1, m_SpecificIntAllowPoison (
1147
+ APInt::getSignedMaxValue (
1148
+ Cmp1->getType ()->getScalarSizeInBits ()) -
1149
+ *C)) &&
1150
+ !C->isNegative ()) {
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->isNegative ()) {
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)) &&
1175
+ !C->isNegative ()) {
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
+ // TODO: Try to match variables. However, due to the fact that we can only
1182
+ // fold if we know at least one is positive, we cannot fold for each and every
1183
+ // time, unlike the unsigned case, where every number is positive.
1184
+
1185
+ // TODO: Match when known negatives go towards INT_MIN.
1186
+
1187
+ return nullptr ;
1188
+ }
1189
+
1190
+ static Value *canonicalizeSaturatedAdd (ICmpInst *Cmp, Value *TVal, Value *FVal,
1191
+ InstCombiner::BuilderTy &Builder) {
1192
+ if (!Cmp->hasOneUse ())
1193
+ return nullptr ;
1194
+
1195
+ if (Value *V = canonicalizeSaturatedAddUnsigned (Cmp, TVal, FVal, Builder))
1196
+ return V;
1197
+
1198
+ if (Value *V = canonicalizeSaturatedAddSigned (Cmp, TVal, FVal, Builder))
1199
+ return V;
1200
+
1201
+ return nullptr ;
1202
+ }
1203
+
1118
1204
// / Try to match patterns with select and subtract as absolute difference.
1119
1205
static Value *foldAbsDiff (ICmpInst *Cmp, Value *TVal, Value *FVal,
1120
1206
InstCombiner::BuilderTy &Builder) {
0 commit comments