@@ -204,11 +204,47 @@ class ConsumedArgToEpilogueReleaseMatcher {
204
204
ExitKind Kind;
205
205
ArrayRef<SILArgumentConvention> ArgumentConventions;
206
206
207
- using InstListTy = TinyPtrVector<SILInstruction *>;
208
- llvm::SmallMapVector<SILArgument *, InstListTy, 8 > ArgInstMap;
207
+ class ArgumentState {
208
+ // / The list of releases associated with this argument.
209
+ TinyPtrVector<SILInstruction *> releases;
209
210
210
- // / Set to true if we found some releases but not all for the argument.
211
- llvm::DenseSet<SILArgument *> FoundSomeReleases;
211
+ // / If this is set to true, then we know that we were able to find
212
+ // / a set of releases.
213
+ bool jointPostDominatingReleaseSet;
214
+
215
+ public:
216
+ ArgumentState (ArrayRef<SILInstruction *> releases)
217
+ : releases(releases), jointPostDominatingReleaseSet(false ) {}
218
+
219
+ void addRelease (SILInstruction *release) { releases.push_back (release); }
220
+ void setHasJointPostDominatingReleaseSet () {
221
+ jointPostDominatingReleaseSet = true ;
222
+ }
223
+
224
+ bool foundSomeButNotAllReleases () const {
225
+ return releases.size () && !jointPostDominatingReleaseSet;
226
+ }
227
+
228
+ // / If we were able to find a set of releases for this argument that joint
229
+ // / post-dominate the argument, return our release set.
230
+ Optional<ArrayRef<SILInstruction *>> getFullyPostDomReleases () const {
231
+ if (releases.empty () || foundSomeButNotAllReleases ())
232
+ return None;
233
+ return {releases};
234
+ }
235
+
236
+ // / If we were able to find a set of releases for this argument, but those
237
+ // / releases do not joint post-dominate the argument, return our release
238
+ // / set.
239
+ // /
240
+ // / *NOTE* This returns none if we did not find any releases.
241
+ Optional<ArrayRef<SILInstruction *>> getPartiallyPostDomReleases () const {
242
+ if (releases.empty () || !foundSomeButNotAllReleases ())
243
+ return None;
244
+ return ArrayRef<SILInstruction *>(releases);
245
+ }
246
+ };
247
+ llvm::SmallMapVector<SILArgument *, ArgumentState, 8 > ArgInstMap;
212
248
213
249
// / Eventually this will be used in place of HasBlock.
214
250
SILBasicBlock *ProcessedBlock;
@@ -227,95 +263,97 @@ class ConsumedArgToEpilogueReleaseMatcher {
227
263
228
264
bool hasBlock () const { return ProcessedBlock != nullptr ; }
229
265
230
- bool isEpilogueRelease (SILInstruction *I ) const {
266
+ bool isEpilogueRelease (SILInstruction *i ) const {
231
267
// This is not a release instruction in the epilogue block.
232
- if (I ->getParent () != ProcessedBlock)
268
+ if (i ->getParent () != ProcessedBlock)
233
269
return false ;
234
- for (auto &X : ArgInstMap) {
235
- // Either did not find epilogue release or found exploded epilogue
236
- // releases.
237
- if (X.second .size () != 1 )
238
- continue ;
239
- if (*X.second .begin () == I)
240
- return true ;
241
- }
242
- return false ;
270
+
271
+ using PairTy = const std::pair<SILArgument *, ArgumentState>;
272
+ return llvm::any_of (ArgInstMap, [&i](PairTy &p) {
273
+ auto completeList = p.second .getFullyPostDomReleases ();
274
+ // If we did not have a complete post dominating release set, then we do
275
+ // not want to treat any releases from p as epilogue releases.
276
+ if (!completeList)
277
+ return false ;
278
+
279
+ // Then make sure that we either found an epilogue release or found
280
+ // exploded epilogue releases. We rely on our callers to split up exploded
281
+ // parameters.
282
+ return completeList->size () == 1 && *completeList->begin () == i;
283
+ });
243
284
}
244
285
245
286
// / Return true if we've found some epilogue releases for the argument
246
287
// / but not all.
247
- bool hasSomeReleasesForArgument (SILArgument *Arg) {
248
- return FoundSomeReleases.find (Arg) != FoundSomeReleases.end ();
288
+ bool hasSomeReleasesForArgument (SILArgument *arg) const {
289
+ auto iter = ArgInstMap.find (arg);
290
+ if (iter == ArgInstMap.end ())
291
+ return false ;
292
+ return iter->second .foundSomeButNotAllReleases ();
249
293
}
250
294
251
- bool isSingleRelease (SILArgument *Arg) const {
252
- auto Iter = ArgInstMap.find (Arg);
253
- assert (Iter != ArgInstMap.end () && " Failed to get release list for argument" );
254
- return Iter->second .size () == 1 ;
295
+ bool isSingleRelease (SILArgument *arg) const {
296
+ auto iter = ArgInstMap.find (arg);
297
+ assert (iter != ArgInstMap.end () &&
298
+ " Failed to get release list for argument" );
299
+
300
+ // If we do not have a fully post dominating release set bail.
301
+ auto completeList = iter->second .getFullyPostDomReleases ();
302
+ if (!completeList)
303
+ return false ;
304
+
305
+ return completeList->size () == 1 ;
255
306
}
256
307
257
- SILInstruction *getSingleReleaseForArgument (SILArgument *Arg) {
258
- auto I = ArgInstMap.find (Arg);
259
- if (I == ArgInstMap.end ())
308
+ SILInstruction *getSingleReleaseForArgument (SILArgument *arg) const {
309
+ auto iter = ArgInstMap.find (arg);
310
+ if (iter == ArgInstMap.end ())
311
+ return nullptr ;
312
+ if (!isSingleRelease (arg))
260
313
return nullptr ;
261
- if (!isSingleRelease (Arg))
314
+ auto completeList = iter->second .getFullyPostDomReleases ();
315
+ if (!completeList)
262
316
return nullptr ;
263
- return *I-> second . begin ();
317
+ return *completeList-> begin ();
264
318
}
265
319
266
- SILInstruction *getSingleReleaseForArgument (SILValue V) {
267
- auto *Arg = dyn_cast<SILArgument>(V );
268
- if (!Arg )
320
+ SILInstruction *getSingleReleaseForArgument (SILValue value) const {
321
+ auto *arg = dyn_cast<SILArgument>(value );
322
+ if (!arg )
269
323
return nullptr ;
270
- return getSingleReleaseForArgument (Arg );
324
+ return getSingleReleaseForArgument (arg );
271
325
}
272
326
273
- ArrayRef<SILInstruction *> getReleasesForArgument (SILArgument *Arg) {
274
- auto I = ArgInstMap.find (Arg);
275
- if (I == ArgInstMap.end ())
327
+ ArrayRef<SILInstruction *> getReleasesForArgument (SILArgument *arg) const {
328
+ auto iter = ArgInstMap.find (arg);
329
+ if (iter == ArgInstMap.end ())
330
+ return {};
331
+ auto completeList = iter->second .getFullyPostDomReleases ();
332
+ if (!completeList)
276
333
return {};
277
- return I-> second ;
334
+ return completeList. getValue () ;
278
335
}
279
336
280
- ArrayRef<SILInstruction *> getReleasesForArgument (SILValue V) {
281
- auto *Arg = dyn_cast<SILArgument>(V );
282
- if (!Arg )
337
+ ArrayRef<SILInstruction *> getReleasesForArgument (SILValue value) const {
338
+ auto *arg = dyn_cast<SILArgument>(value );
339
+ if (!arg )
283
340
return {};
284
- return getReleasesForArgument (Arg );
341
+ return getReleasesForArgument (arg );
285
342
}
286
343
287
344
// / Recompute the mapping from argument to consumed arg.
288
345
void recompute ();
289
346
290
- bool isSingleReleaseMatchedToArgument (SILInstruction *Inst) {
291
- return count_if (
292
- ArgInstMap,
293
- [&Inst](const std::pair<SILArgument *, ArrayRef<SILInstruction *>> &P)
294
- -> bool {
295
- if (P.second .size () > 1 )
296
- return false ;
297
- return *P.second .begin () == Inst;
298
- });
347
+ bool isSingleReleaseMatchedToArgument (SILInstruction *inst) {
348
+ using PairTy = const std::pair<SILArgument *, ArgumentState>;
349
+ return count_if (ArgInstMap, [&inst](PairTy &p) {
350
+ auto completeList = p.second .getFullyPostDomReleases ();
351
+ if (!completeList || completeList->size () > 1 )
352
+ return false ;
353
+ return *completeList->begin () == inst;
354
+ });
299
355
}
300
356
301
- using iterator = decltype (ArgInstMap)::iterator;
302
- using const_iterator = decltype (ArgInstMap)::const_iterator;
303
- iterator begin () { return ArgInstMap.begin (); }
304
- iterator end () { return ArgInstMap.end (); }
305
- const_iterator begin () const { return ArgInstMap.begin (); }
306
- const_iterator end () const { return ArgInstMap.end (); }
307
-
308
- using reverse_iterator = decltype (ArgInstMap)::reverse_iterator;
309
- using const_reverse_iterator = decltype (ArgInstMap)::const_reverse_iterator;
310
- reverse_iterator rbegin () { return ArgInstMap.rbegin (); }
311
- reverse_iterator rend () { return ArgInstMap.rend (); }
312
- const_reverse_iterator rbegin () const { return ArgInstMap.rbegin (); }
313
- const_reverse_iterator rend () const { return ArgInstMap.rend (); }
314
-
315
- unsigned size () const { return ArgInstMap.size (); }
316
-
317
- iterator_range<iterator> getRange () { return swift::make_range (begin (), end ()); }
318
-
319
357
private:
320
358
// / Return true if we have seen releases to part or all of \p Derived in
321
359
// / \p Insts.
0 commit comments