[llvm] [LVI] Learn value ranges from ctpop/ctlz/cttz results (PR #121945)

Yingwei Zheng via llvm-commits llvm-commits at lists.llvm.org
Wed Jan 8 00:40:41 PST 2025


================
@@ -1159,6 +1164,67 @@ getRangeViaSLT(CmpInst::Predicate Pred, APInt RHS,
   return std::nullopt;
 }
 
+static bool matchBitIntrinsic(Value *LHS, Value *Val, Intrinsic::ID &IID) {
+  auto *II = dyn_cast<IntrinsicInst>(LHS);
+  if (!II)
+    return false;
+  auto ID = II->getIntrinsicID();
+  switch (ID) {
+  case Intrinsic::ctpop:
+  case Intrinsic::ctlz:
+  case Intrinsic::cttz:
+    break;
+  default:
+    return false;
+  }
+  if (II->getArgOperand(0) != Val)
+    return false;
+  IID = ID;
+  return true;
+}
+
+/// Get value range for a "intrinsic(Val) Pred RHS" condition, where intrinsic
+/// can be one of ctpop, ctlz, and cttz.
+std::optional<ValueLatticeElement>
+LazyValueInfoImpl::getValueFromICmpBitIntrinsic(ICmpInst::Predicate Pred,
+                                                unsigned ValBitWidth,
+                                                Intrinsic::ID IID, Value *RHS,
+                                                Instruction *CtxI,
+                                                bool UseBlockValue) {
+  unsigned BitWidth = ValBitWidth;
+  auto Offset = APInt::getZero(BitWidth);
+
+  auto ResValLattice =
+      getValueFromSimpleICmpCondition(Pred, RHS, Offset, CtxI, UseBlockValue);
+  if (!ResValLattice)
+    return std::nullopt;
+  if (ResValLattice->isOverdefined())
+    return ValueLatticeElement::getOverdefined();
+  auto &ResValRange = ResValLattice->getConstantRange();
+
+  unsigned ResMin = ResValRange.getUnsignedMin().getLimitedValue(BitWidth);
+  unsigned ResMax = ResValRange.getUnsignedMax().getLimitedValue(BitWidth);
+
+  APInt ValMin, ValMax;
+  APInt AllOnes = APInt::getAllOnes(BitWidth);
+  switch (IID) {
+  case Intrinsic::ctpop:
+    ValMin = AllOnes.lshr(BitWidth - ResMin);
+    ValMax = AllOnes.shl(BitWidth - ResMax);
+    break;
+  case Intrinsic::ctlz:
+    ValMin = ResMax == BitWidth ? APInt(BitWidth, 0)
+                                : APInt(BitWidth, 1).shl(BitWidth - ResMax - 1);
+    ValMax = AllOnes.lshr(ResMin);
+    break;
+  case Intrinsic::cttz:
+    ValMin = APInt(BitWidth, 1).shl(ResMin);
+    ValMax = AllOnes.shl(ResMin);
+    break;
+  }
----------------
dtcxzyw wrote:

```suggestion
    default: llvm_unreachable("Unexpected intrinsic ID");
  }
```


https://github.com/llvm/llvm-project/pull/121945


More information about the llvm-commits mailing list