7070#include " swift/SIL/NodeDatastructures.h"
7171#include " swift/SIL/OwnershipUtils.h"
7272#include " swift/SIL/PrunedLiveness.h"
73+ #include " swift/SILOptimizer/Analysis/BasicCalleeAnalysis.h"
74+ #include " swift/SILOptimizer/Analysis/Reachability.h"
7375#include " swift/SILOptimizer/Utils/CFGOptUtils.h"
7476#include " swift/SILOptimizer/Utils/DebugOptUtils.h"
7577#include " swift/SILOptimizer/Utils/InstructionDeleter.h"
@@ -232,6 +234,45 @@ bool CanonicalizeOSSALifetime::computeCanonicalLiveness() {
232234 return true ;
233235}
234236
237+ void CanonicalizeOSSALifetime::findDestroysOutsideBoundary (
238+ SmallVectorImpl<SILInstruction *> &outsideDestroys) {
239+ for (auto destroy : destroys) {
240+ if (liveness->isWithinBoundary (destroy))
241+ continue ;
242+ outsideDestroys.push_back (destroy);
243+ }
244+ }
245+
246+ void CanonicalizeOSSALifetime::extendLivenessToDeinitBarriers () {
247+ SmallVector<SILInstruction *, 4 > outsideDestroys;
248+ findDestroysOutsideBoundary (outsideDestroys);
249+
250+ auto *def = getCurrentDef ()->getDefiningInstruction ();
251+ using InitialBlocks = ArrayRef<SILBasicBlock *>;
252+ auto *defBlock = getCurrentDef ()->getParentBlock ();
253+ auto initialBlocks = defBlock ? InitialBlocks (defBlock) : InitialBlocks ();
254+ ReachableBarriers barriers;
255+ findBarriersBackward (outsideDestroys, initialBlocks,
256+ *getCurrentDef ()->getFunction (), barriers,
257+ [&](auto *inst) {
258+ if (inst == def)
259+ return true ;
260+ return isDeinitBarrier (inst, calleeAnalysis);
261+ });
262+ for (auto *barrier : barriers.instructions ) {
263+ liveness->updateForUse (barrier, /* lifetimeEnding*/ false );
264+ }
265+ for (auto *barrier : barriers.phis ) {
266+ for (auto *predecessor : barrier->getPredecessorBlocks ()) {
267+ liveness->updateForUse (predecessor->getTerminator (),
268+ /* lifetimeEnding*/ false );
269+ }
270+ }
271+ // Ignore barriers.edges. The beginning of the targets of such edges should
272+ // not be added to liveness. These edges will be rediscovered when computing
273+ // the liveness boundary.
274+ }
275+
235276// Return true if \p inst is an end_access whose access scope overlaps the end
236277// of the pruned live range. This means that a hoisted destroy might execute
237278// within the access scope which previously executed outside the access scope.
@@ -1032,9 +1073,6 @@ bool CanonicalizeOSSALifetime::computeLiveness() {
10321073 if (currentDef->getOwnershipKind () != OwnershipKind::Owned)
10331074 return false ;
10341075
1035- if (currentDef->isLexical ())
1036- return false ;
1037-
10381076 LLVM_DEBUG (llvm::dbgs () << " Canonicalizing: " << currentDef);
10391077
10401078 // Note: There is no need to register callbacks with this utility. 'onDelete'
@@ -1057,6 +1095,9 @@ bool CanonicalizeOSSALifetime::computeLiveness() {
10571095 invalidateLiveness ();
10581096 return false ;
10591097 }
1098+ if (currentDef->isLexical ()) {
1099+ extendLivenessToDeinitBarriers ();
1100+ }
10601101 if (accessBlockAnalysis) {
10611102 extendLivenessThroughOverlappingAccess ();
10621103 }
0 commit comments