[clang] [llvm] [CaptureTracking][FunctionAttrs] Add support for CaptureInfo (PR #125880)

Nikita Popov via llvm-commits llvm-commits at lists.llvm.org
Fri Feb 7 11:59:41 PST 2025


================
@@ -358,49 +360,64 @@ UseCaptureKind llvm::DetermineUseCaptureKind(
     // Volatile stores make the address observable.
     auto *ACXI = cast<AtomicCmpXchgInst>(I);
     if (U.getOperandNo() == 1 || U.getOperandNo() == 2 || ACXI->isVolatile())
-      return UseCaptureKind::MAY_CAPTURE;
-    return UseCaptureKind::NO_CAPTURE;
+      return CaptureInfo::otherOnly();
+    return CaptureInfo::none();
   }
   case Instruction::GetElementPtr:
     // AA does not support pointers of vectors, so GEP vector splats need to
     // be considered as captures.
     if (I->getType()->isVectorTy())
-      return UseCaptureKind::MAY_CAPTURE;
-    return UseCaptureKind::PASSTHROUGH;
+      return CaptureInfo::otherOnly();
+    return CaptureInfo::retOnly();
   case Instruction::BitCast:
   case Instruction::PHI:
   case Instruction::Select:
   case Instruction::AddrSpaceCast:
     // The original value is not captured via this if the new value isn't.
-    return UseCaptureKind::PASSTHROUGH;
+    return CaptureInfo::retOnly();
   case Instruction::ICmp: {
     unsigned Idx = U.getOperandNo();
     unsigned OtherIdx = 1 - Idx;
-    if (auto *CPN = dyn_cast<ConstantPointerNull>(I->getOperand(OtherIdx))) {
+    if (isa<ConstantPointerNull>(I->getOperand(OtherIdx)) &&
+        cast<ICmpInst>(I)->isEquality()) {
+      // TODO(captures): Remove these special cases once we make use of
+      // captures(address_is_null).
+
       // Don't count comparisons of a no-alias return value against null as
       // captures. This allows us to ignore comparisons of malloc results
       // with null, for example.
-      if (CPN->getType()->getAddressSpace() == 0)
+      if (U->getType()->getPointerAddressSpace() == 0)
         if (isNoAliasCall(U.get()->stripPointerCasts()))
-          return UseCaptureKind::NO_CAPTURE;
+          return CaptureInfo::none();
       if (!I->getFunction()->nullPointerIsDefined()) {
         auto *O = I->getOperand(Idx)->stripPointerCastsSameRepresentation();
         // Comparing a dereferenceable_or_null pointer against null cannot
         // lead to pointer escapes, because if it is not null it must be a
         // valid (in-bounds) pointer.
         const DataLayout &DL = I->getDataLayout();
         if (IsDereferenceableOrNull && IsDereferenceableOrNull(O, DL))
-          return UseCaptureKind::NO_CAPTURE;
+          return CaptureInfo::none();
       }
+
+      // Check whether this is a comparison of the base pointer against
+      // null. We can also strip inbounds GEPs, as inbounds preserves
+      // the null-ness of the pointer.
+      Value *Stripped = U.get();
+      if (!NullPointerIsDefined(I->getFunction(),
+                                U->getType()->getPointerAddressSpace()))
+        Stripped = Stripped->stripInBoundsOffsets();
+      if (Stripped == Base)
----------------
nikic wrote:

Yeah, I wasn't sure about that. I've dropped it for now. We can add it back if it's useful for phase ordering reasons.

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


More information about the llvm-commits mailing list