@@ -73,28 +73,32 @@ bool CaptureTracker::isDereferenceableOrNull(Value *O, const DataLayout &DL) {
73
73
74
74
namespace {
75
75
struct 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) {}
78
79
79
80
void tooManyUses () override {
80
81
LLVM_DEBUG (dbgs () << " Captured due to too many uses\n " );
81
- Captured = true ;
82
+ CC = Mask ;
82
83
}
83
84
84
85
Action captured (const Use *U, UseCaptureInfo CI) override {
85
- // TODO(captures): Use UseCaptureInfo.
86
86
if (isa<ReturnInst>(U->getUser ()) && !ReturnCaptures)
87
87
return ContinueIgnoringReturn;
88
88
89
- LLVM_DEBUG (dbgs () << " Captured by: " << *U->getUser () << " \n " );
89
+ if (capturesNothing (CI.UseCC & Mask))
90
+ return Continue;
90
91
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;
93
95
}
94
96
95
97
bool ReturnCaptures;
98
+ CaptureComponents Mask;
99
+ function_ref<bool (CaptureComponents)> StopFn;
96
100
97
- bool Captured = false ;
101
+ CaptureComponents CC = CaptureComponents::None ;
98
102
};
99
103
100
104
// / Only find pointer captures which happen before the given instruction. Uses
@@ -104,11 +108,13 @@ struct SimpleCaptureTracker : public CaptureTracker {
104
108
struct CapturesBefore : public CaptureTracker {
105
109
106
110
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)
108
114
: BeforeHere(I), DT(DT), ReturnCaptures(ReturnCaptures),
109
- IncludeI (IncludeI), LI(LI) {}
115
+ IncludeI (IncludeI), LI(LI), Mask(Mask), StopFn(StopFn) {}
110
116
111
- void tooManyUses () override { Captured = true ; }
117
+ void tooManyUses () override { CC = Mask ; }
112
118
113
119
bool isSafeToPrune (Instruction *I) {
114
120
if (BeforeHere == I)
@@ -124,7 +130,6 @@ struct CapturesBefore : public CaptureTracker {
124
130
}
125
131
126
132
Action captured (const Use *U, UseCaptureInfo CI) override {
127
- // TODO(captures): Use UseCaptureInfo.
128
133
Instruction *I = cast<Instruction>(U->getUser ());
129
134
if (isa<ReturnInst>(I) && !ReturnCaptures)
130
135
return ContinueIgnoringReturn;
@@ -136,8 +141,11 @@ struct CapturesBefore : public CaptureTracker {
136
141
// If the use is not reachable, the instruction result isn't either.
137
142
return ContinueIgnoringReturn;
138
143
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;
141
149
}
142
150
143
151
const Instruction *BeforeHere;
@@ -146,9 +154,11 @@ struct CapturesBefore : public CaptureTracker {
146
154
bool ReturnCaptures;
147
155
bool IncludeI;
148
156
149
- bool Captured = false ;
157
+ CaptureComponents CC = CaptureComponents::None ;
150
158
151
159
const LoopInfo *LI;
160
+ CaptureComponents Mask;
161
+ function_ref<bool (CaptureComponents)> StopFn;
152
162
};
153
163
154
164
// / Find the 'earliest' instruction before which the pointer is known not to
@@ -161,104 +171,110 @@ struct CapturesBefore : public CaptureTracker {
161
171
// escape are not in a cycle.
162
172
struct EarliestCaptures : public CaptureTracker {
163
173
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) {}
166
177
167
178
void tooManyUses () override {
168
- Captured = true ;
179
+ CC = Mask ;
169
180
EarliestCapture = &*F.getEntryBlock ().begin ();
170
181
}
171
182
172
183
Action captured (const Use *U, UseCaptureInfo CI) override {
173
- // TODO(captures): Use UseCaptureInfo.
174
184
Instruction *I = cast<Instruction>(U->getUser ());
175
185
if (isa<ReturnInst>(I) && !ReturnCaptures)
176
186
return ContinueIgnoringReturn;
177
187
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
+ }
183
195
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;
188
198
}
189
199
190
- Instruction *EarliestCapture = nullptr ;
191
-
192
200
const DominatorTree &DT;
193
-
194
201
bool ReturnCaptures;
195
-
196
- bool Captured = false ;
197
-
198
202
Function &F;
203
+ CaptureComponents Mask;
204
+
205
+ Instruction *EarliestCapture = nullptr ;
206
+ CaptureComponents CC = CaptureComponents::None;
199
207
};
200
208
} // namespace
201
209
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) {
209
213
assert (!isa<GlobalValue>(V) &&
210
214
" It doesn't make sense to ask whether a global is captured." );
211
215
212
216
LLVM_DEBUG (dbgs () << " Captured?: " << *V << " = " );
213
217
214
- SimpleCaptureTracker SCT (ReturnCaptures);
218
+ SimpleCaptureTracker SCT (ReturnCaptures, Mask, StopFn );
215
219
PointerMayBeCaptured (V, &SCT, MaxUsesToExplore);
216
- if (SCT.Captured )
220
+ if (capturesAnything ( SCT.CC ) )
217
221
++NumCaptured;
218
222
else {
219
223
++NumNotCaptured;
220
224
LLVM_DEBUG (dbgs () << " not captured\n " );
221
225
}
222
- return SCT.Captured ;
226
+ return SCT.CC ;
223
227
}
224
228
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 ) {
237
241
assert (!isa<GlobalValue>(V) &&
238
242
" It doesn't make sense to ask whether a global is captured." );
239
243
240
244
if (!DT)
241
- return PointerMayBeCaptured (V, ReturnCaptures, MaxUsesToExplore);
245
+ return PointerMayBeCaptured (V, ReturnCaptures, Mask, StopFn,
246
+ MaxUsesToExplore);
242
247
243
- CapturesBefore CB (ReturnCaptures, I, DT, IncludeI, LI);
248
+ CapturesBefore CB (ReturnCaptures, I, DT, IncludeI, LI, Mask, StopFn );
244
249
PointerMayBeCaptured (V, &CB, MaxUsesToExplore);
245
- if (CB.Captured )
250
+ if (capturesAnything ( CB.CC ) )
246
251
++NumCapturedBefore;
247
252
else
248
253
++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));
250
265
}
251
266
252
267
Instruction *llvm::FindEarliestCapture (const Value *V, Function &F,
253
268
bool ReturnCaptures,
254
269
const DominatorTree &DT,
270
+ CaptureComponents Mask,
255
271
unsigned MaxUsesToExplore) {
256
272
assert (!isa<GlobalValue>(V) &&
257
273
" It doesn't make sense to ask whether a global is captured." );
258
274
259
- EarliestCaptures CB (ReturnCaptures, F, DT);
275
+ EarliestCaptures CB (ReturnCaptures, F, DT, Mask );
260
276
PointerMayBeCaptured (V, &CB, MaxUsesToExplore);
261
- if (CB.Captured )
277
+ if (capturesAnything ( CB.CC ) )
262
278
++NumCapturedBefore;
263
279
else
264
280
++NumNotCapturedBefore;
@@ -473,8 +489,10 @@ bool llvm::isNonEscapingLocalObject(
473
489
}
474
490
475
491
// If this is an identified function-local object, check to see if it escapes.
492
+ // We only care about provenance here, not address capture.
476
493
if (isIdentifiedFunctionLocal (V)) {
477
- auto Ret = !PointerMayBeCaptured (V, /* ReturnCaptures=*/ false );
494
+ bool Ret = !capturesAnything (PointerMayBeCaptured (
495
+ V, /* ReturnCaptures=*/ false , CaptureComponents::Provenance));
478
496
if (IsCapturedCache)
479
497
CacheIt->second = Ret;
480
498
return Ret;
0 commit comments