[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 03:46:37 PDT 2026


================
@@ -484,13 +581,78 @@ 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;
+          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.
+            uint64_t Alignment = getUInt64NonPoison(getValue(GetBundleArg(1)));
+            if (OBU.Inputs.size() == 3)
+              Alignment = MinAlign(
+                  Alignment, getUInt64NonPoison(getValue(GetBundleArg(2))));
+            if (!isPowerOf2_64(Alignment)) {
+              if (!WasOn.asPointer().address().isZero())
+                reportImmediateUB() << "Assume on nonnull pointer " << WasOn
+                                    << " with a "
+                                       "non-power-of-two alignment "
+                                    << Alignment << '.';
+              break;
+            }
+            if (WasOnPtr.address().countr_zero() < Log2_64(Alignment))
+              reportImmediateUB()
+                  << "The pointer " << WasOn << " violates align(" << Alignment
+                  << ") assumption.";
+            break;
+          }
+          case Attribute::NonNull:
+            if (WasOnPtr.address().isZero())
+              reportImmediateUB()
+                  << "The pointer " << WasOn << " violates nonnull assumption.";
+            break;
+          case Attribute::Dereferenceable:
+          case Attribute::DereferenceableOrNull: {
+            uint64_t DereferenceableBytes =
+                getUInt64NonPoison(getValue(GetBundleArg(1)));
+            if (applyDereferenceableBytesAttr(
+                    WasOn, DereferenceableBytes,
+                    Kind == Attribute::DereferenceableOrNull))
----------------
nikic wrote:

I think this will incorrectly handle dereferenceable 0?

> Only n > 0 implies that the pointer is dereferenceable.

I believe the applyDereferenceableBytesAttr implementation still checks some things for 0.

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


More information about the llvm-commits mailing list