@@ -274,6 +274,37 @@ bool CanonicalizeOSSALifetime::computeCanonicalLiveness() {
274274 return true ;
275275}
276276
277+ // / Extend liveness to the availability boundary of currentDef. Even if a copy
278+ // / is consumed on a path to the dead-end, if the def stays live through to the
279+ // / dead-end, its lifetime must not be shrunk back from it (eventually we'll
280+ // / support shrinking it back to deinit barriers).
281+ // /
282+ // / Example:
283+ // / %def is lexical
284+ // / %copy = copy_value %def
285+ // / consume %copy
286+ // / apply %foo() // deinit barrier
287+ // / // Must extend lifetime of %def up to this point per language rules.
288+ // / unreachable
289+ void CanonicalizeOSSALifetime::extendLexicalLivenessToDeadEnds () {
290+ // TODO: OSSALifetimeCompletion: Once lifetimes are always complete, delete
291+ // this method.
292+ SmallVector<SILBasicBlock *, 32 > directDiscoverdBlocks;
293+ SSAPrunedLiveness directLiveness (function, &directDiscoverdBlocks);
294+ directLiveness.initializeDef (getCurrentDef ());
295+ directLiveness.computeSimple ();
296+ OSSALifetimeCompletion::visitAvailabilityBoundary (
297+ getCurrentDef (), directLiveness, [&](auto *unreachable, auto end) {
298+ if (end == OSSALifetimeCompletion::LifetimeEnd::Boundary) {
299+ recordUnreachableLifetimeEnd (unreachable);
300+ }
301+ unreachable->visitPriorInstructions ([&](auto *inst) {
302+ liveness->extendToNonUse (inst);
303+ return true ;
304+ });
305+ });
306+ }
307+
277308// / Extend liveness to the copy-extended availability boundary of currentDef.
278309// / Prevents destroys from being inserted between borrows of (copies of) the
279310// / def and dead-ends.
@@ -1368,6 +1399,9 @@ bool CanonicalizeOSSALifetime::computeLiveness() {
13681399 clear ();
13691400 return false ;
13701401 }
1402+ if (respectsDeinitBarriers ()) {
1403+ extendLexicalLivenessToDeadEnds ();
1404+ }
13711405 extendLivenessToDeadEnds ();
13721406 if (respectsDeinitBarriers ()) {
13731407 extendLivenessToDeinitBarriers ();
0 commit comments