[llvm] [CaptureTracking] Compute results with and without return capture (PR #195857)

Nikita Popov via llvm-commits llvm-commits at lists.llvm.org
Thu May 7 06:04:29 PDT 2026


https://github.com/nikic updated https://github.com/llvm/llvm-project/pull/195857

>From a37046c0803c4cbec27dceabb96507e7bca7d84c Mon Sep 17 00:00:00 2001
From: Nikita Popov <npopov at redhat.com>
Date: Tue, 5 May 2026 14:49:47 +0200
Subject: [PATCH 1/2] [CaptureTracking] Compute results with and without return
 capture

Currently PointerMayBeCaptured/FindEarliestEscape accept a
ReturnCaptures argument to determine whether returning the pointer
should be considered a capture. If you want to do a capture check
for both cases, you have to invoke the capture tracking API twice.

This PR instead changes the low level APIs to return a pair of
capture components, one where returns are considered non-capturing,
and one where they are considered capturing.
---
 llvm/include/llvm/Analysis/CaptureTracking.h  | 19 +++--
 llvm/lib/Analysis/BasicAliasAnalysis.cpp      | 16 ++--
 llvm/lib/Analysis/CaptureTracking.cpp         | 73 ++++++++++---------
 .../Scalar/DeadStoreElimination.cpp           |  8 +-
 llvm/lib/Transforms/Utils/SimplifyCFG.cpp     |  4 +-
 5 files changed, 65 insertions(+), 55 deletions(-)

diff --git a/llvm/include/llvm/Analysis/CaptureTracking.h b/llvm/include/llvm/Analysis/CaptureTracking.h
index e652bc5a0a5a6..ca9d1c53de3ef 100644
--- a/llvm/include/llvm/Analysis/CaptureTracking.h
+++ b/llvm/include/llvm/Analysis/CaptureTracking.h
@@ -48,6 +48,14 @@ namespace llvm {
   LLVM_ABI bool PointerMayBeCaptured(const Value *V, bool ReturnCaptures,
                                      unsigned MaxUsesToExplore = 0);
 
+  /// Result of a PointerMayBeCaptured query, which includes the captured
+  /// components for both the case where return is considered a capture, and
+  /// where it isn't.
+  struct CaptureResult {
+    CaptureComponents WithoutRet;
+    CaptureComponents WithRet;
+  };
+
   /// Return which components of the pointer may be captured. Only consider
   /// components that are part of \p Mask. Once \p StopFn on the accumulated
   /// components returns true, the traversal is aborted early. By default, this
@@ -55,8 +63,8 @@ namespace llvm {
   /// This function only considers captures of the passed value via its def-use
   /// chain, without considering captures of values it may be based on, or
   /// implicit captures such as for external globals.
-  LLVM_ABI CaptureComponents PointerMayBeCaptured(
-      const Value *V, bool ReturnCaptures, CaptureComponents Mask,
+  LLVM_ABI CaptureResult PointerMayBeCaptured(
+      const Value *V, CaptureComponents Mask,
       function_ref<bool(CaptureComponents)> StopFn = capturesAnything,
       unsigned MaxUsesToExplore = 0);
 
@@ -106,10 +114,9 @@ namespace llvm {
   // not in a cycle.
   //
   // Only consider components that are part of \p Mask.
-  LLVM_ABI std::pair<Instruction *, CaptureComponents>
-  FindEarliestCapture(const Value *V, Function &F, bool ReturnCaptures,
-                      const DominatorTree &DT, CaptureComponents Mask,
-                      unsigned MaxUsesToExplore = 0);
+  LLVM_ABI std::pair<Instruction *, CaptureResult>
+  FindEarliestCapture(const Value *V, Function &F, const DominatorTree &DT,
+                      CaptureComponents Mask, unsigned MaxUsesToExplore = 0);
 
   /// Capture information for a specific Use.
   struct UseCaptureInfo {
diff --git a/llvm/lib/Analysis/BasicAliasAnalysis.cpp b/llvm/lib/Analysis/BasicAliasAnalysis.cpp
index 8172cf29d890b..65ffa34eeb923 100644
--- a/llvm/lib/Analysis/BasicAliasAnalysis.cpp
+++ b/llvm/lib/Analysis/BasicAliasAnalysis.cpp
@@ -208,9 +208,11 @@ CaptureComponents SimpleCaptureAnalysis::getCapturesBefore(const Value *Object,
   if (!Inserted)
     return CacheIt->second;
 
-  CaptureComponents Ret = PointerMayBeCaptured(
-      Object, /*ReturnCaptures=*/false, CaptureComponents::Provenance,
-      [](CaptureComponents CC) { return capturesFullProvenance(CC); });
+  CaptureComponents Ret =
+      PointerMayBeCaptured(
+          Object, CaptureComponents::Provenance,
+          [](CaptureComponents CC) { return capturesFullProvenance(CC); })
+          .WithoutRet;
   CacheIt->second = Ret;
   return Ret;
 }
@@ -234,13 +236,13 @@ EarliestEscapeAnalysis::getCapturesBefore(const Value *Object,
 
   auto Iter = EarliestEscapes.try_emplace(Object);
   if (Iter.second) {
-    std::pair<Instruction *, CaptureComponents> EarliestCapture =
-        FindEarliestCapture(Object, *DT.getRoot()->getParent(),
-                            /*ReturnCaptures=*/false, DT,
+    std::pair<Instruction *, CaptureResult> EarliestCapture =
+        FindEarliestCapture(Object, *DT.getRoot()->getParent(), DT,
                             CaptureComponents::Provenance);
     if (EarliestCapture.first)
       Inst2Obj[EarliestCapture.first].push_back(Object);
-    Iter.first->second = EarliestCapture;
+    Iter.first->second = {EarliestCapture.first,
+                          EarliestCapture.second.WithoutRet};
   }
 
   auto IsNotCapturedBefore = [&]() {
diff --git a/llvm/lib/Analysis/CaptureTracking.cpp b/llvm/lib/Analysis/CaptureTracking.cpp
index 22229d9c26b3b..c34fde8d11704 100644
--- a/llvm/lib/Analysis/CaptureTracking.cpp
+++ b/llvm/lib/Analysis/CaptureTracking.cpp
@@ -57,32 +57,32 @@ bool CaptureTracker::shouldExplore(const Use *U) { return true; }
 
 namespace {
 struct SimpleCaptureTracker : public CaptureTracker {
-  explicit SimpleCaptureTracker(bool ReturnCaptures, CaptureComponents Mask,
+  explicit SimpleCaptureTracker(CaptureComponents Mask,
                                 function_ref<bool(CaptureComponents)> StopFn)
-      : ReturnCaptures(ReturnCaptures), Mask(Mask), StopFn(StopFn) {}
+      : Mask(Mask), StopFn(StopFn) {}
 
   void tooManyUses() override {
     LLVM_DEBUG(dbgs() << "Captured due to too many uses\n");
     CC = Mask;
+    CCWithRet = Mask;
   }
 
   Action captured(const Use *U, UseCaptureInfo CI) override {
-    if (isa<ReturnInst>(U->getUser()) && !ReturnCaptures)
-      return ContinueIgnoringReturn;
-
     if (capturesNothing(CI.UseCC & Mask))
       return Continue;
 
     LLVM_DEBUG(dbgs() << "Captured by: " << *U->getUser() << "\n");
-    CC |= CI.UseCC & Mask;
+    CCWithRet |= CI.UseCC & Mask;
+    if (!isa<ReturnInst>(U->getUser()))
+      CC |= CI.UseCC & Mask;
     return StopFn(CC) ? Stop : Continue;
   }
 
-  bool ReturnCaptures;
   CaptureComponents Mask;
   function_ref<bool(CaptureComponents)> StopFn;
 
   CaptureComponents CC = CaptureComponents::None;
+  CaptureComponents CCWithRet = CaptureComponents::None;
 };
 
 /// Only find pointer captures which happen before the given instruction. Uses
@@ -155,26 +155,26 @@ struct CapturesBefore : public CaptureTracker {
 // escape are not in a cycle.
 struct EarliestCaptures : public CaptureTracker {
 
-  EarliestCaptures(bool ReturnCaptures, Function &F, const DominatorTree &DT,
-                   CaptureComponents Mask)
-      : DT(DT), ReturnCaptures(ReturnCaptures), F(F), Mask(Mask) {}
+  EarliestCaptures(Function &F, const DominatorTree &DT, CaptureComponents Mask)
+      : DT(DT), F(F), Mask(Mask) {}
 
   void tooManyUses() override {
     CC = Mask;
+    CCWithRet = Mask;
     EarliestCapture = &*F.getEntryBlock().begin();
   }
 
   Action captured(const Use *U, UseCaptureInfo CI) override {
     Instruction *I = cast<Instruction>(U->getUser());
-    if (isa<ReturnInst>(I) && !ReturnCaptures)
-      return ContinueIgnoringReturn;
-
     if (capturesAnything(CI.UseCC & Mask)) {
-      if (!EarliestCapture)
-        EarliestCapture = I;
-      else
-        EarliestCapture = DT.findNearestCommonDominator(EarliestCapture, I);
-      CC |= CI.UseCC & Mask;
+      CCWithRet |= CI.UseCC & Mask;
+      if (!isa<ReturnInst>(I)) {
+        if (!EarliestCapture)
+          EarliestCapture = I;
+        else
+          EarliestCapture = DT.findNearestCommonDominator(EarliestCapture, I);
+        CC |= CI.UseCC & Mask;
+      }
     }
 
     // Continue analysis, as we need to see all potential captures.
@@ -182,24 +182,25 @@ struct EarliestCaptures : public CaptureTracker {
   }
 
   const DominatorTree &DT;
-  bool ReturnCaptures;
   Function &F;
   CaptureComponents Mask;
 
   Instruction *EarliestCapture = nullptr;
   CaptureComponents CC = CaptureComponents::None;
+  CaptureComponents CCWithRet = CaptureComponents::None;
 };
 } // namespace
 
-CaptureComponents llvm::PointerMayBeCaptured(
-    const Value *V, bool ReturnCaptures, CaptureComponents Mask,
-    function_ref<bool(CaptureComponents)> StopFn, unsigned MaxUsesToExplore) {
+CaptureResult
+llvm::PointerMayBeCaptured(const Value *V, CaptureComponents Mask,
+                           function_ref<bool(CaptureComponents)> StopFn,
+                           unsigned MaxUsesToExplore) {
   assert(!isa<GlobalValue>(V) &&
          "It doesn't make sense to ask whether a global is captured.");
 
   LLVM_DEBUG(dbgs() << "Captured?: " << *V << " = ");
 
-  SimpleCaptureTracker SCT(ReturnCaptures, Mask, StopFn);
+  SimpleCaptureTracker SCT(Mask, StopFn);
   PointerMayBeCaptured(V, &SCT, MaxUsesToExplore);
   if (capturesAnything(SCT.CC))
     ++NumCaptured;
@@ -207,14 +208,14 @@ CaptureComponents llvm::PointerMayBeCaptured(
     ++NumNotCaptured;
     LLVM_DEBUG(dbgs() << "not captured\n");
   }
-  return SCT.CC;
+  return {SCT.CC, SCT.CCWithRet};
 }
 
 bool llvm::PointerMayBeCaptured(const Value *V, bool ReturnCaptures,
                                 unsigned MaxUsesToExplore) {
-  return capturesAnything(
-      PointerMayBeCaptured(V, ReturnCaptures, CaptureComponents::All,
-                           capturesAnything, MaxUsesToExplore));
+  CaptureResult Res = PointerMayBeCaptured(V, CaptureComponents::All,
+                                           capturesAnything, MaxUsesToExplore);
+  return capturesAnything(ReturnCaptures ? Res.WithRet : Res.WithoutRet);
 }
 
 CaptureComponents llvm::PointerMayBeCapturedBefore(
@@ -225,9 +226,10 @@ CaptureComponents llvm::PointerMayBeCapturedBefore(
   assert(!isa<GlobalValue>(V) &&
          "It doesn't make sense to ask whether a global is captured.");
 
-  if (!DT)
-    return PointerMayBeCaptured(V, ReturnCaptures, Mask, StopFn,
-                                MaxUsesToExplore);
+  if (!DT) {
+    CaptureResult Res = PointerMayBeCaptured(V, Mask, StopFn, MaxUsesToExplore);
+    return ReturnCaptures ? Res.WithRet : Res.WithoutRet;
+  }
 
   CapturesBefore CB(ReturnCaptures, I, DT, IncludeI, LI, Mask, StopFn);
   PointerMayBeCaptured(V, &CB, MaxUsesToExplore);
@@ -248,20 +250,19 @@ bool llvm::PointerMayBeCapturedBefore(const Value *V, bool ReturnCaptures,
       capturesAnything, LI, MaxUsesToExplore));
 }
 
-std::pair<Instruction *, CaptureComponents>
-llvm::FindEarliestCapture(const Value *V, Function &F, bool ReturnCaptures,
-                          const DominatorTree &DT, CaptureComponents Mask,
-                          unsigned MaxUsesToExplore) {
+std::pair<Instruction *, CaptureResult>
+llvm::FindEarliestCapture(const Value *V, Function &F, const DominatorTree &DT,
+                          CaptureComponents Mask, unsigned MaxUsesToExplore) {
   assert(!isa<GlobalValue>(V) &&
          "It doesn't make sense to ask whether a global is captured.");
 
-  EarliestCaptures CB(ReturnCaptures, F, DT, Mask);
+  EarliestCaptures CB(F, DT, Mask);
   PointerMayBeCaptured(V, &CB, MaxUsesToExplore);
   if (capturesAnything(CB.CC))
     ++NumCapturedBefore;
   else
     ++NumNotCapturedBefore;
-  return {CB.EarliestCapture, CB.CC};
+  return {CB.EarliestCapture, {CB.CC, CB.CCWithRet}};
 }
 
 UseCaptureInfo llvm::DetermineUseCaptureKind(const Use &U, const Value *Base) {
diff --git a/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp b/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp
index 6704fd0ef86e0..056f844b3805a 100644
--- a/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp
+++ b/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp
@@ -1396,8 +1396,8 @@ bool DSEState::isInvisibleToCallerAfterRet(const Value *V, const Value *Ptr,
   }
   auto I = InvisibleToCallerAfterRet.insert({V, false});
   if (I.second && isInvisibleToCallerOnUnwind(V) && isNoAliasCall(V))
-    I.first->second = capturesNothing(PointerMayBeCaptured(
-        V, /*ReturnCaptures=*/true, CaptureComponents::Provenance));
+    I.first->second = capturesNothing(
+        PointerMayBeCaptured(V, CaptureComponents::Provenance).WithRet);
   return I.first->second;
 }
 
@@ -1414,8 +1414,8 @@ bool DSEState::isInvisibleToCallerOnUnwind(const Value *V) {
     // with the killing MemoryDef. But we refrain from doing so for now to
     // limit compile-time and this does not cause any changes to the number
     // of stores removed on a large test set in practice.
-    I.first->second = capturesAnything(PointerMayBeCaptured(
-        V, /*ReturnCaptures=*/false, CaptureComponents::Provenance));
+    I.first->second = capturesAnything(
+        PointerMayBeCaptured(V, CaptureComponents::Provenance).WithoutRet);
   return !I.first->second;
 }
 
diff --git a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
index 5bfd06affdb1f..3a98e86038904 100644
--- a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
@@ -3070,8 +3070,8 @@ static Value *isSafeToSpeculateStore(Instruction *I, BasicBlock *BrBB,
         bool ExplicitlyDereferenceableOnly;
         if (isWritableObject(Obj, ExplicitlyDereferenceableOnly) &&
             capturesNothing(
-                PointerMayBeCaptured(Obj, /*ReturnCaptures=*/false,
-                                     CaptureComponents::Provenance)) &&
+                PointerMayBeCaptured(Obj, CaptureComponents::Provenance)
+                    .WithoutRet) &&
             (!ExplicitlyDereferenceableOnly ||
              isDereferenceablePointer(StorePtr, StoreTy,
                                       LI->getDataLayout()))) {

>From cc9c5b7d922005b64830745fc31bb31bd5cdcc49 Mon Sep 17 00:00:00 2001
From: Nikita Popov <npopov at redhat.com>
Date: Thu, 7 May 2026 14:59:10 +0200
Subject: [PATCH 2/2] Implement ReturnCaptures support in CaptureAnalysis

---
 llvm/include/llvm/Analysis/AliasAnalysis.h    | 14 +++--
 llvm/lib/Analysis/BasicAliasAnalysis.cpp      | 55 +++++++++----------
 .../Scalar/DeadStoreElimination.cpp           |  4 +-
 3 files changed, 36 insertions(+), 37 deletions(-)

diff --git a/llvm/include/llvm/Analysis/AliasAnalysis.h b/llvm/include/llvm/Analysis/AliasAnalysis.h
index 845ccdbfce776..23fa20f17d92f 100644
--- a/llvm/include/llvm/Analysis/AliasAnalysis.h
+++ b/llvm/include/llvm/Analysis/AliasAnalysis.h
@@ -39,6 +39,7 @@
 
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/Analysis/CaptureTracking.h"
 #include "llvm/Analysis/MemoryLocation.h"
 #include "llvm/IR/Function.h"
 #include "llvm/IR/PassManager.h"
@@ -155,19 +156,20 @@ struct LLVM_ABI CaptureAnalysis {
   /// are also considered.
   ///
   /// If I is nullptr, then captures at any point will be considered.
-  virtual CaptureComponents
-  getCapturesBefore(const Value *Object, const Instruction *I, bool OrAt) = 0;
+  virtual CaptureComponents getCapturesBefore(const Value *Object,
+                                              const Instruction *I, bool OrAt,
+                                              bool ReturnCaptures) = 0;
 };
 
 /// Context-free CaptureAnalysis provider, which computes and caches whether an
 /// object is captured in the function at all, but does not distinguish whether
 /// it was captured before or after the context instruction.
 class LLVM_ABI SimpleCaptureAnalysis final : public CaptureAnalysis {
-  SmallDenseMap<const Value *, CaptureComponents, 8> IsCapturedCache;
+  SmallDenseMap<const Value *, CaptureResult, 8> IsCapturedCache;
 
 public:
   CaptureComponents getCapturesBefore(const Value *Object, const Instruction *I,
-                                      bool OrAt) override;
+                                      bool OrAt, bool ReturnCaptures) override;
 };
 
 /// Context-sensitive CaptureAnalysis provider, which computes and caches the
@@ -183,7 +185,7 @@ class LLVM_ABI EarliestEscapeAnalysis final : public CaptureAnalysis {
   /// that may be captured (by any instruction, not necessarily the earliest
   /// one). The "earliest" instruction may be a conservative approximation,
   /// e.g. the first instruction in the function is always a legal choice.
-  DenseMap<const Value *, std::pair<Instruction *, CaptureComponents>>
+  DenseMap<const Value *, std::pair<Instruction *, CaptureResult>>
       EarliestEscapes;
 
   /// Reverse map from instruction to the objects it is the earliest escape for.
@@ -196,7 +198,7 @@ class LLVM_ABI EarliestEscapeAnalysis final : public CaptureAnalysis {
       : DT(DT), LI(LI), CI(CI) {}
 
   CaptureComponents getCapturesBefore(const Value *Object, const Instruction *I,
-                                      bool OrAt) override;
+                                      bool OrAt, bool ReturnCaptures) override;
 
   void removeInstruction(Instruction *I);
 };
diff --git a/llvm/lib/Analysis/BasicAliasAnalysis.cpp b/llvm/lib/Analysis/BasicAliasAnalysis.cpp
index 65ffa34eeb923..41c5df99afa5d 100644
--- a/llvm/lib/Analysis/BasicAliasAnalysis.cpp
+++ b/llvm/lib/Analysis/BasicAliasAnalysis.cpp
@@ -197,24 +197,18 @@ static bool areBothVScale(const Value *V1, const Value *V2) {
 
 CaptureAnalysis::~CaptureAnalysis() = default;
 
-CaptureComponents SimpleCaptureAnalysis::getCapturesBefore(const Value *Object,
-                                                           const Instruction *I,
-                                                           bool OrAt) {
+CaptureComponents SimpleCaptureAnalysis::getCapturesBefore(
+    const Value *Object, const Instruction *I, bool OrAt, bool ReturnCaptures) {
   if (!isIdentifiedFunctionLocal(Object))
     return CaptureComponents::Provenance;
 
-  auto [CacheIt, Inserted] =
-      IsCapturedCache.insert({Object, CaptureComponents::Provenance});
-  if (!Inserted)
-    return CacheIt->second;
-
-  CaptureComponents Ret =
-      PointerMayBeCaptured(
-          Object, CaptureComponents::Provenance,
-          [](CaptureComponents CC) { return capturesFullProvenance(CC); })
-          .WithoutRet;
-  CacheIt->second = Ret;
-  return Ret;
+  auto [CacheIt, Inserted] = IsCapturedCache.try_emplace(Object);
+  if (Inserted)
+    CacheIt->second = PointerMayBeCaptured(
+        Object, CaptureComponents::Provenance,
+        [](CaptureComponents CC) { return capturesFullProvenance(CC); });
+
+  return ReturnCaptures ? CacheIt->second.WithRet : CacheIt->second.WithoutRet;
 }
 
 static bool isNotInCycle(const Instruction *I, const DominatorTree *DT,
@@ -228,9 +222,8 @@ static bool isNotInCycle(const Instruction *I, const DominatorTree *DT,
          !isPotentiallyReachableFromMany(Succs, BB, nullptr, DT, LI);
 }
 
-CaptureComponents
-EarliestEscapeAnalysis::getCapturesBefore(const Value *Object,
-                                          const Instruction *I, bool OrAt) {
+CaptureComponents EarliestEscapeAnalysis::getCapturesBefore(
+    const Value *Object, const Instruction *I, bool OrAt, bool ReturnCaptures) {
   if (!isIdentifiedFunctionLocal(Object))
     return CaptureComponents::Provenance;
 
@@ -241,8 +234,12 @@ EarliestEscapeAnalysis::getCapturesBefore(const Value *Object,
                             CaptureComponents::Provenance);
     if (EarliestCapture.first)
       Inst2Obj[EarliestCapture.first].push_back(Object);
-    Iter.first->second = {EarliestCapture.first,
-                          EarliestCapture.second.WithoutRet};
+    Iter.first->second = {EarliestCapture.first, EarliestCapture.second};
+  }
+
+  if (ReturnCaptures) {
+    assert(!I && "Context instruction not supported if ReturnCaptures");
+    return Iter.first->second.second.WithRet;
   }
 
   auto IsNotCapturedBefore = [&]() {
@@ -265,7 +262,7 @@ EarliestEscapeAnalysis::getCapturesBefore(const Value *Object,
   };
   if (IsNotCapturedBefore())
     return CaptureComponents::None;
-  return Iter.first->second.second;
+  return Iter.first->second.second.WithoutRet;
 }
 
 void EarliestEscapeAnalysis::removeInstruction(Instruction *I) {
@@ -973,8 +970,8 @@ ModRefInfo BasicAAResult::getModRefInfo(const CallBase *Call,
   // non-volatile stores for them.
   if (isModOrRefSet(OtherMR) && !isa<Constant>(Object) && Call != Object &&
       (isa<AllocaInst>(Object) || !Call->hasFnAttr(Attribute::ReturnsTwice))) {
-    CaptureComponents CC =
-        AAQI.CA->getCapturesBefore(Object, Call, /*OrAt=*/false);
+    CaptureComponents CC = AAQI.CA->getCapturesBefore(
+        Object, Call, /*OrAt=*/false, /*ReturnCaptures=*/false);
     if (capturesNothing(CC))
       OtherMR = ModRefInfo::NoModRef;
     else if (capturesReadProvenanceOnly(CC))
@@ -1668,13 +1665,13 @@ AliasResult BasicAAResult::aliasCheck(const Value *V1, LocationSize V1Size,
     // temporary store the nocapture argument's value in a temporary memory
     // location if that memory location doesn't escape. Or it may pass a
     // nocapture value to other functions as long as they don't capture it.
-    if (isEscapeSource(O1) &&
-        capturesNothing(AAQI.CA->getCapturesBefore(
-            O2, dyn_cast<Instruction>(O1), /*OrAt*/ true)))
+    if (isEscapeSource(O1) && capturesNothing(AAQI.CA->getCapturesBefore(
+                                  O2, dyn_cast<Instruction>(O1), /*OrAt=*/true,
+                                  /*ReturnCaptures=*/false)))
       return AliasResult::NoAlias;
-    if (isEscapeSource(O2) &&
-        capturesNothing(AAQI.CA->getCapturesBefore(
-            O1, dyn_cast<Instruction>(O2), /*OrAt*/ true)))
+    if (isEscapeSource(O2) && capturesNothing(AAQI.CA->getCapturesBefore(
+                                  O1, dyn_cast<Instruction>(O2), /*OrAt=*/true,
+                                  /*ReturnCaptures=*/false)))
       return AliasResult::NoAlias;
   }
 
diff --git a/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp b/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp
index 056f844b3805a..319701e7c25f0 100644
--- a/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp
+++ b/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp
@@ -1165,8 +1165,8 @@ static bool isFuncLocalAndNotCaptured(Value *Arg, const CallBase *CB,
                                       EarliestEscapeAnalysis &EA) {
   const Value *UnderlyingObj = getUnderlyingObject(Arg);
   return isIdentifiedFunctionLocal(UnderlyingObj) &&
-         capturesNothing(
-             EA.getCapturesBefore(UnderlyingObj, CB, /*OrAt*/ true));
+         capturesNothing(EA.getCapturesBefore(UnderlyingObj, CB, /*OrAt=*/true,
+                                              /*ReturnCaptures=*/false));
 }
 
 DSEState::DSEState(Function &F, AliasAnalysis &AA, MemorySSA &MSSA,



More information about the llvm-commits mailing list