@@ -73,28 +73,32 @@ bool CaptureTracker::isDereferenceableOrNull(Value *O, const DataLayout &DL) {
7373
7474namespace {
7575struct SimpleCaptureTracker : public CaptureTracker {
76- explicit SimpleCaptureTracker (bool ReturnCaptures)
77- : ReturnCaptures(ReturnCaptures) {}
76+ explicit SimpleCaptureTracker (bool ReturnCaptures, CaptureComponents Mask,
77+ function_ref<bool (CaptureComponents)> StopFn)
78+ : ReturnCaptures(ReturnCaptures), Mask(Mask), StopFn(StopFn) {}
7879
7980 void tooManyUses () override {
8081 LLVM_DEBUG (dbgs () << " Captured due to too many uses\n " );
81- Captured = true ;
82+ CC = Mask ;
8283 }
8384
8485 Action captured (const Use *U, UseCaptureInfo CI) override {
85- // TODO(captures): Use UseCaptureInfo.
8686 if (isa<ReturnInst>(U->getUser ()) && !ReturnCaptures)
8787 return ContinueIgnoringReturn;
8888
89- LLVM_DEBUG (dbgs () << " Captured by: " << *U->getUser () << " \n " );
89+ if (capturesNothing (CI.UseCC & Mask))
90+ return Continue;
9091
91- Captured = true ;
92- return Stop;
92+ LLVM_DEBUG (dbgs () << " Captured by: " << *U->getUser () << " \n " );
93+ CC |= CI.UseCC & Mask;
94+ return StopFn (CC) ? Stop : Continue;
9395 }
9496
9597 bool ReturnCaptures;
98+ CaptureComponents Mask;
99+ function_ref<bool (CaptureComponents)> StopFn;
96100
97- bool Captured = false ;
101+ CaptureComponents CC = CaptureComponents::None ;
98102};
99103
100104// / Only find pointer captures which happen before the given instruction. Uses
@@ -104,11 +108,13 @@ struct SimpleCaptureTracker : public CaptureTracker {
104108struct CapturesBefore : public CaptureTracker {
105109
106110 CapturesBefore (bool ReturnCaptures, const Instruction *I,
107- const DominatorTree *DT, bool IncludeI, const LoopInfo *LI)
111+ const DominatorTree *DT, bool IncludeI, const LoopInfo *LI,
112+ CaptureComponents Mask,
113+ function_ref<bool (CaptureComponents)> StopFn)
108114 : BeforeHere(I), DT(DT), ReturnCaptures(ReturnCaptures),
109- IncludeI (IncludeI), LI(LI) {}
115+ IncludeI (IncludeI), LI(LI), Mask(Mask), StopFn(StopFn) {}
110116
111- void tooManyUses () override { Captured = true ; }
117+ void tooManyUses () override { CC = Mask ; }
112118
113119 bool isSafeToPrune (Instruction *I) {
114120 if (BeforeHere == I)
@@ -124,7 +130,6 @@ struct CapturesBefore : public CaptureTracker {
124130 }
125131
126132 Action captured (const Use *U, UseCaptureInfo CI) override {
127- // TODO(captures): Use UseCaptureInfo.
128133 Instruction *I = cast<Instruction>(U->getUser ());
129134 if (isa<ReturnInst>(I) && !ReturnCaptures)
130135 return ContinueIgnoringReturn;
@@ -136,8 +141,11 @@ struct CapturesBefore : public CaptureTracker {
136141 // If the use is not reachable, the instruction result isn't either.
137142 return ContinueIgnoringReturn;
138143
139- Captured = true ;
140- return Stop;
144+ if (capturesNothing (CI.UseCC & Mask))
145+ return Continue;
146+
147+ CC |= CI.UseCC & Mask;
148+ return StopFn (CC) ? Stop : Continue;
141149 }
142150
143151 const Instruction *BeforeHere;
@@ -146,9 +154,11 @@ struct CapturesBefore : public CaptureTracker {
146154 bool ReturnCaptures;
147155 bool IncludeI;
148156
149- bool Captured = false ;
157+ CaptureComponents CC = CaptureComponents::None ;
150158
151159 const LoopInfo *LI;
160+ CaptureComponents Mask;
161+ function_ref<bool (CaptureComponents)> StopFn;
152162};
153163
154164// / Find the 'earliest' instruction before which the pointer is known not to
@@ -161,104 +171,110 @@ struct CapturesBefore : public CaptureTracker {
161171// escape are not in a cycle.
162172struct EarliestCaptures : public CaptureTracker {
163173
164- EarliestCaptures (bool ReturnCaptures, Function &F, const DominatorTree &DT)
165- : DT(DT), ReturnCaptures(ReturnCaptures), F(F) {}
174+ EarliestCaptures (bool ReturnCaptures, Function &F, const DominatorTree &DT,
175+ CaptureComponents Mask)
176+ : DT(DT), ReturnCaptures(ReturnCaptures), F(F), Mask(Mask) {}
166177
167178 void tooManyUses () override {
168- Captured = true ;
179+ CC = Mask ;
169180 EarliestCapture = &*F.getEntryBlock ().begin ();
170181 }
171182
172183 Action captured (const Use *U, UseCaptureInfo CI) override {
173- // TODO(captures): Use UseCaptureInfo.
174184 Instruction *I = cast<Instruction>(U->getUser ());
175185 if (isa<ReturnInst>(I) && !ReturnCaptures)
176186 return ContinueIgnoringReturn;
177187
178- if (!EarliestCapture)
179- EarliestCapture = I;
180- else
181- EarliestCapture = DT.findNearestCommonDominator (EarliestCapture, I);
182- Captured = true ;
188+ if (capturesAnything (CI.UseCC & Mask)) {
189+ if (!EarliestCapture)
190+ EarliestCapture = I;
191+ else
192+ EarliestCapture = DT.findNearestCommonDominator (EarliestCapture, I);
193+ CC |= CI.UseCC & Mask;
194+ }
183195
184- // Continue analysis, as we need to see all potential captures. However,
185- // we do not need to follow the instruction result, as this use will
186- // dominate any captures made through the instruction result.
187- return ContinueIgnoringReturn;
196+ // Continue analysis, as we need to see all potential captures.
197+ return Continue;
188198 }
189199
190- Instruction *EarliestCapture = nullptr ;
191-
192200 const DominatorTree &DT;
193-
194201 bool ReturnCaptures;
195-
196- bool Captured = false ;
197-
198202 Function &F;
203+ CaptureComponents Mask;
204+
205+ Instruction *EarliestCapture = nullptr ;
206+ CaptureComponents CC = CaptureComponents::None;
199207};
200208} // namespace
201209
202- // / PointerMayBeCaptured - Return true if this pointer value may be captured
203- // / by the enclosing function (which is required to exist). This routine can
204- // / be expensive, so consider caching the results. The boolean ReturnCaptures
205- // / specifies whether returning the value (or part of it) from the function
206- // / counts as capturing it or not.
207- bool llvm::PointerMayBeCaptured (const Value *V, bool ReturnCaptures,
208- unsigned MaxUsesToExplore) {
210+ CaptureComponents llvm::PointerMayBeCaptured (
211+ const Value *V, bool ReturnCaptures, CaptureComponents Mask,
212+ function_ref<bool (CaptureComponents)> StopFn, unsigned MaxUsesToExplore) {
209213 assert (!isa<GlobalValue>(V) &&
210214 " It doesn't make sense to ask whether a global is captured." );
211215
212216 LLVM_DEBUG (dbgs () << " Captured?: " << *V << " = " );
213217
214- SimpleCaptureTracker SCT (ReturnCaptures);
218+ SimpleCaptureTracker SCT (ReturnCaptures, Mask, StopFn );
215219 PointerMayBeCaptured (V, &SCT, MaxUsesToExplore);
216- if (SCT.Captured )
220+ if (capturesAnything ( SCT.CC ) )
217221 ++NumCaptured;
218222 else {
219223 ++NumNotCaptured;
220224 LLVM_DEBUG (dbgs () << " not captured\n " );
221225 }
222- return SCT.Captured ;
226+ return SCT.CC ;
223227}
224228
225- // / PointerMayBeCapturedBefore - Return true if this pointer value may be
226- // / captured by the enclosing function (which is required to exist). If a
227- // / DominatorTree is provided, only captures which happen before the given
228- // / instruction are considered. This routine can be expensive, so consider
229- // / caching the results. The boolean ReturnCaptures specifies whether
230- // / returning the value (or part of it) from the function counts as capturing
231- // / it or not.
232- bool llvm::PointerMayBeCapturedBefore (const Value *V, bool ReturnCaptures,
233- const Instruction *I,
234- const DominatorTree *DT, bool IncludeI,
235- unsigned MaxUsesToExplore ,
236- const LoopInfo *LI ) {
229+ bool llvm::PointerMayBeCaptured ( const Value *V, bool ReturnCaptures,
230+ unsigned MaxUsesToExplore) {
231+ return capturesAnything (
232+ PointerMayBeCaptured (V, ReturnCaptures, CaptureComponents::All,
233+ capturesAnything, MaxUsesToExplore));
234+ }
235+
236+ CaptureComponents llvm::PointerMayBeCapturedBefore (
237+ const Value *V, bool ReturnCaptures, const Instruction *I,
238+ const DominatorTree *DT, bool IncludeI, CaptureComponents Mask ,
239+ function_ref< bool (CaptureComponents)> StopFn, const LoopInfo *LI ,
240+ unsigned MaxUsesToExplore ) {
237241 assert (!isa<GlobalValue>(V) &&
238242 " It doesn't make sense to ask whether a global is captured." );
239243
240244 if (!DT)
241- return PointerMayBeCaptured (V, ReturnCaptures, MaxUsesToExplore);
245+ return PointerMayBeCaptured (V, ReturnCaptures, Mask, StopFn,
246+ MaxUsesToExplore);
242247
243- CapturesBefore CB (ReturnCaptures, I, DT, IncludeI, LI);
248+ CapturesBefore CB (ReturnCaptures, I, DT, IncludeI, LI, Mask, StopFn );
244249 PointerMayBeCaptured (V, &CB, MaxUsesToExplore);
245- if (CB.Captured )
250+ if (capturesAnything ( CB.CC ) )
246251 ++NumCapturedBefore;
247252 else
248253 ++NumNotCapturedBefore;
249- return CB.Captured ;
254+ return CB.CC ;
255+ }
256+
257+ bool llvm::PointerMayBeCapturedBefore (const Value *V, bool ReturnCaptures,
258+ const Instruction *I,
259+ const DominatorTree *DT, bool IncludeI,
260+ unsigned MaxUsesToExplore,
261+ const LoopInfo *LI) {
262+ return capturesAnything (PointerMayBeCapturedBefore (
263+ V, ReturnCaptures, I, DT, IncludeI, CaptureComponents::All,
264+ capturesAnything, LI, MaxUsesToExplore));
250265}
251266
252267Instruction *llvm::FindEarliestCapture (const Value *V, Function &F,
253268 bool ReturnCaptures,
254269 const DominatorTree &DT,
270+ CaptureComponents Mask,
255271 unsigned MaxUsesToExplore) {
256272 assert (!isa<GlobalValue>(V) &&
257273 " It doesn't make sense to ask whether a global is captured." );
258274
259- EarliestCaptures CB (ReturnCaptures, F, DT);
275+ EarliestCaptures CB (ReturnCaptures, F, DT, Mask );
260276 PointerMayBeCaptured (V, &CB, MaxUsesToExplore);
261- if (CB.Captured )
277+ if (capturesAnything ( CB.CC ) )
262278 ++NumCapturedBefore;
263279 else
264280 ++NumNotCapturedBefore;
@@ -473,8 +489,10 @@ bool llvm::isNonEscapingLocalObject(
473489 }
474490
475491 // If this is an identified function-local object, check to see if it escapes.
492+ // We only care about provenance here, not address capture.
476493 if (isIdentifiedFunctionLocal (V)) {
477- auto Ret = !PointerMayBeCaptured (V, /* ReturnCaptures=*/ false );
494+ bool Ret = !capturesAnything (PointerMayBeCaptured (
495+ V, /* ReturnCaptures=*/ false , CaptureComponents::Provenance));
478496 if (IsCapturedCache)
479497 CacheIt->second = Ret;
480498 return Ret;
0 commit comments