[llvm] [llubi] Add support for poison-generating/UB-implying annotations (PR #195339)

Nikita Popov via llvm-commits llvm-commits at lists.llvm.org
Sun May 3 10:06:11 PDT 2026


================
@@ -484,13 +573,86 @@ class InstExecutor : public InstVisitor<InstExecutor, void>,
     case Intrinsic::assume:
       switch (Args[0].asBoolean()) {
       case BooleanKind::True:
+        for (unsigned Idx = 0; Idx < CB.getNumOperandBundles(); Idx++) {
+          OperandBundleUse OBU = CB.getOperandBundleAt(Idx);
+          auto GetBundleArg = [&](uint32_t Offset) -> Value * {
+            return OBU.Inputs[Offset];
+          };
+          if (OBU.Inputs.empty())
+            continue;
+          Value *WasOnVal = GetBundleArg(0);
+          // Bail out on unrecognized operand bundles.
+          if (!WasOnVal->getType()->isPointerTy())
+            continue;
+          unsigned AS = WasOnVal->getType()->getPointerAddressSpace();
+          const AnyValue &WasOn = getValue(WasOnVal);
+          if (WasOn.isPoison()) {
+            reportImmediateUB() << "Assume on poison pointer.";
+            break;
+          }
+          const Pointer &WasOnPtr = WasOn.asPointer();
+          Attribute::AttrKind Kind =
+              Attribute::getAttrKindFromName(OBU.getTagName());
+          switch (Kind) {
+          case Attribute::Alignment: {
+            // Alignment assumptions should have 2 or 3 arguments.
+            // If there are two integer arguments, use the largest power of 2
+            // that divides them as the alignment.
+            APInt Alignment = getIntNonPoison(getValue(GetBundleArg(1)));
+            if (OBU.Inputs.size() == 3) {
+              APInt Offset = getIntNonPoison(getValue(GetBundleArg(2)));
+              if (!Alignment.isZero() || !Offset.isZero())
+                Alignment = APInt::getOneBitSet(
+                    std::max(Alignment.getBitWidth(), Offset.getBitWidth()),
+                    std::min(Alignment.countr_zero(), Offset.countr_zero()));
+            }
+            if (!Alignment.isPowerOf2()) {
+              if (!WasOnPtr.isNullPtr(AS, DL))
+                reportImmediateUB() << "Assume on nonnull pointer " << WasOn
+                                    << " with a "
+                                       "non-power-of-two alignment "
+                                    << Alignment << '.';
+              break;
+            }
+            if (WasOnPtr.address().countr_zero() < Alignment.logBase2())
+              reportImmediateUB()
+                  << "The pointer " << WasOn << " violates align(" << Alignment
+                  << ") assumption.";
+            break;
+          }
+          case Attribute::NonNull:
+            if (WasOnPtr.isNullPtr(AS, DL))
+              reportImmediateUB()
+                  << "The pointer " << WasOn << " violates nonnull assumption.";
+            break;
+          case Attribute::Dereferenceable:
+          case Attribute::DereferenceableOrNull: {
+            APInt DereferenceableBytes =
+                getIntNonPoison(getValue(GetBundleArg(1)));
+            // Only n > 0 implies that the pointer is dereferenceable.
+            if (!DereferenceableBytes.isStrictlyPositive())
----------------
nikic wrote:

Hm, I'm pretty sure the intent here was just `!isZero()`, as the `dereferenceable` argument is unsigned.

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


More information about the llvm-commits mailing list