@@ -390,6 +390,11 @@ class LazyValueInfoImpl {
390
390
// push additional values to the worklist and return nullopt. If
391
391
// UseBlockValue is false, it will never return nullopt.
392
392
393
+ std::optional<ValueLatticeElement>
394
+ getValueFromICmpBitIntrinsic (ICmpInst::Predicate Pred, unsigned ValBitWidth,
395
+ Intrinsic::ID IID, Value *RHS, Instruction *CtxI,
396
+ bool UseBlockValue);
397
+
393
398
std::optional<ValueLatticeElement>
394
399
getValueFromSimpleICmpCondition (CmpInst::Predicate Pred, Value *RHS,
395
400
const APInt &Offset, Instruction *CxtI,
@@ -1159,6 +1164,67 @@ getRangeViaSLT(CmpInst::Predicate Pred, APInt RHS,
1159
1164
return std::nullopt;
1160
1165
}
1161
1166
1167
+ static bool matchBitIntrinsic (Value *LHS, Value *Val, Intrinsic::ID &IID) {
1168
+ auto *II = dyn_cast<IntrinsicInst>(LHS);
1169
+ if (!II)
1170
+ return false ;
1171
+ auto ID = II->getIntrinsicID ();
1172
+ switch (ID) {
1173
+ case Intrinsic::ctpop:
1174
+ case Intrinsic::ctlz:
1175
+ case Intrinsic::cttz:
1176
+ break ;
1177
+ default :
1178
+ return false ;
1179
+ }
1180
+ if (II->getArgOperand (0 ) != Val)
1181
+ return false ;
1182
+ IID = ID;
1183
+ return true ;
1184
+ }
1185
+
1186
+ // / Get value range for a "intrinsic(Val) Pred RHS" condition, where intrinsic
1187
+ // / can be one of ctpop, ctlz, and cttz.
1188
+ std::optional<ValueLatticeElement>
1189
+ LazyValueInfoImpl::getValueFromICmpBitIntrinsic (ICmpInst::Predicate Pred,
1190
+ unsigned ValBitWidth,
1191
+ Intrinsic::ID IID, Value *RHS,
1192
+ Instruction *CtxI,
1193
+ bool UseBlockValue) {
1194
+ unsigned BitWidth = ValBitWidth;
1195
+ auto Offset = APInt::getZero (BitWidth);
1196
+
1197
+ auto ResValLattice =
1198
+ getValueFromSimpleICmpCondition (Pred, RHS, Offset, CtxI, UseBlockValue);
1199
+ if (!ResValLattice)
1200
+ return std::nullopt;
1201
+ if (ResValLattice->isOverdefined ())
1202
+ return ValueLatticeElement::getOverdefined ();
1203
+ auto &ResValRange = ResValLattice->getConstantRange ();
1204
+
1205
+ unsigned ResMin = ResValRange.getUnsignedMin ().getLimitedValue (BitWidth);
1206
+ unsigned ResMax = ResValRange.getUnsignedMax ().getLimitedValue (BitWidth);
1207
+
1208
+ APInt ValMin, ValMax;
1209
+ APInt AllOnes = APInt::getAllOnes (BitWidth);
1210
+ switch (IID) {
1211
+ case Intrinsic::ctpop:
1212
+ ValMin = AllOnes.lshr (BitWidth - ResMin);
1213
+ ValMax = AllOnes.shl (BitWidth - ResMax);
1214
+ break ;
1215
+ case Intrinsic::ctlz:
1216
+ ValMin = ResMax == BitWidth ? APInt (BitWidth, 0 )
1217
+ : APInt (BitWidth, 1 ).shl (BitWidth - ResMax - 1 );
1218
+ ValMax = AllOnes.lshr (ResMin);
1219
+ break ;
1220
+ case Intrinsic::cttz:
1221
+ ValMin = APInt (BitWidth, 1 ).shl (ResMin);
1222
+ ValMax = AllOnes.shl (ResMin);
1223
+ break ;
1224
+ }
1225
+ return ValueLatticeElement::getRange (ConstantRange{ValMin, ValMax + 1 });
1226
+ }
1227
+
1162
1228
std::optional<ValueLatticeElement> LazyValueInfoImpl::getValueFromICmpCondition (
1163
1229
Value *Val, ICmpInst *ICI, bool isTrueDest, bool UseBlockValue) {
1164
1230
Value *LHS = ICI->getOperand (0 );
@@ -1191,6 +1257,13 @@ std::optional<ValueLatticeElement> LazyValueInfoImpl::getValueFromICmpCondition(
1191
1257
if (matchICmpOperand (Offset, RHS, Val, SwappedPred))
1192
1258
return getValueFromSimpleICmpCondition (SwappedPred, LHS, Offset, ICI,
1193
1259
UseBlockValue);
1260
+ Intrinsic::ID IID;
1261
+ if (matchBitIntrinsic (LHS, Val, IID))
1262
+ return getValueFromICmpBitIntrinsic (EdgePred, BitWidth, IID, RHS, ICI,
1263
+ UseBlockValue);
1264
+ if (matchBitIntrinsic (RHS, Val, IID))
1265
+ return getValueFromICmpBitIntrinsic (SwappedPred, BitWidth, IID, LHS, ICI,
1266
+ UseBlockValue);
1194
1267
1195
1268
const APInt *Mask, *C;
1196
1269
if (match (LHS, m_And (m_Specific (Val), m_APInt (Mask))) &&
0 commit comments