@@ -493,17 +493,21 @@ class FieldSensitivePrunedLiveBlocks {
493493 // / LiveWithin blocks have at least one use and/or def within the block, but
494494 // / are not (yet) LiveOut.
495495 // /
496+ // / DeadToLiveEdge blocks are not live within the block itself, but the value
497+ // / becomes live on one or more of the edges out.
498+ // /
496499 // / LiveOut blocks are live on at least one successor path. LiveOut blocks may
497500 // / or may not contain defs or uses.
498- // /
499- // / NOTE: The values below for Dead, LiveWithin, LiveOut were picked to ensure
500- // / that given a 2 bit representation of the value, a value is Dead if the
501- // / first bit is 0 and is LiveOut if the second bit is set.
502501 enum IsLive {
503502 Dead = 0 ,
504503 LiveWithin = 1 ,
504+ DeadToLiveEdge = 2 ,
505505 LiveOut = 3 ,
506506 };
507+
508+ static bool isDead (IsLive liveness) {
509+ return liveness == Dead || liveness == DeadToLiveEdge;
510+ }
507511
508512 // / A bit vector that stores information about liveness. This is composed
509513 // / with SmallBitVector since it contains two bits per liveness so that it
@@ -524,37 +528,27 @@ class FieldSensitivePrunedLiveBlocks {
524528 unsigned size () const { return bits.size () / 2 ; }
525529
526530 IsLive getLiveness (unsigned bitNo) const {
527- if (!bits[bitNo * 2 ])
528- return IsLive::Dead;
529- return bits[bitNo * 2 + 1 ] ? LiveOut : LiveWithin;
531+ return IsLive ((bits[bitNo * 2 + 1 ] << 1 ) | bits[bitNo * 2 ]);
530532 }
531533
532534 // / Returns the liveness in \p resultingFoundLiveness. We only return the
533535 // / bits for endBitNo - startBitNo.
534536 void getLiveness (unsigned startBitNo, unsigned endBitNo,
535537 SmallVectorImpl<IsLive> &resultingFoundLiveness) const {
536- unsigned actualStartBitNo = startBitNo * 2 ;
537- unsigned actualEndBitNo = endBitNo * 2 ;
538-
539- for (unsigned i = actualStartBitNo, e = actualEndBitNo; i != e; i += 2 ) {
540- if (!bits[i]) {
541- resultingFoundLiveness.push_back (Dead);
542- continue ;
543- }
544-
545- resultingFoundLiveness.push_back (bits[i + 1 ] ? LiveOut : LiveWithin);
538+ for (unsigned i = startBitNo, e = endBitNo; i != e; ++i) {
539+ resultingFoundLiveness.push_back (getLiveness (i));
546540 }
547541 }
548542
549- void setLiveness (unsigned startBitNo, unsigned endBitNo, IsLive isLive) {
550- for (unsigned i = startBitNo * 2 , e = endBitNo * 2 ; i != e; i += 2 ) {
551- bits[i] = isLive & 1 ;
552- bits[i + 1 ] = isLive & 2 ;
553- }
543+ void setLiveness (unsigned bitNo, IsLive isLive) {
544+ bits[bitNo * 2 ] = isLive & 1 ;
545+ bits[bitNo * 2 + 1 ] = bool (isLive & 2 );
554546 }
555547
556- void setLiveness (unsigned bitNo, IsLive isLive) {
557- setLiveness (bitNo, bitNo + 1 , isLive);
548+ void setLiveness (unsigned startBitNo, unsigned endBitNo, IsLive isLive) {
549+ for (unsigned i = startBitNo, e = endBitNo; i != e; ++i) {
550+ setLiveness (i, isLive);
551+ }
558552 }
559553 };
560554
@@ -620,9 +614,10 @@ class FieldSensitivePrunedLiveBlocks {
620614 }
621615
622616 void initializeDefBlock (SILBasicBlock *defBB, unsigned startBitNo,
623- unsigned endBitNo) {
617+ unsigned endBitNo,
618+ IsLive isLive = LiveWithin) {
624619 assert (isInitialized ());
625- markBlockLive (defBB, startBitNo, endBitNo, LiveWithin );
620+ markBlockLive (defBB, startBitNo, endBitNo, isLive );
626621 }
627622
628623 // / Update this liveness result for a single use.
@@ -632,7 +627,7 @@ class FieldSensitivePrunedLiveBlocks {
632627 auto *block = user->getParent ();
633628 if (!isUserBeforeDef) {
634629 auto liveness = getBlockLiveness (block, bitNo);
635- if (liveness != Dead )
630+ if (! isDead (liveness) )
636631 return liveness;
637632 }
638633 computeScalarUseBlockLiveness (block, bitNo);
@@ -696,6 +691,7 @@ class FieldSensitivePrunedLiveBlocks {
696691 // If we are dead, always update to the new liveness.
697692 switch (iterAndInserted.first ->getSecond ().getLiveness (bitNo)) {
698693 case Dead:
694+ case DeadToLiveEdge:
699695 iterAndInserted.first ->getSecond ().setLiveness (bitNo, bitNo + 1 ,
700696 isLive);
701697 break ;
@@ -935,10 +931,12 @@ class FieldSensitivePrunedLiveness {
935931 return UserBlockRange (getAllUsers (), op);
936932 }
937933
938- void initializeDefBlock (SILBasicBlock *defBB, TypeTreeLeafTypeRange span) {
934+ void initializeDefBlock (SILBasicBlock *defBB, TypeTreeLeafTypeRange span,
935+ FieldSensitivePrunedLiveBlocks::IsLive isLive
936+ = FieldSensitivePrunedLiveBlocks::LiveWithin) {
939937 assert (isInitialized ());
940938 liveBlocks.initializeDefBlock (defBB, span.startEltOffset ,
941- span.endEltOffset );
939+ span.endEltOffset , isLive );
942940 }
943941
944942 // / For flexibility, \p lifetimeEnding is provided by the
@@ -1303,6 +1301,14 @@ class FieldSensitiveSSAPrunedLiveRange
13031301 FieldSensitivePrunedLivenessBoundary &boundary) const ;
13041302};
13051303
1304+ static inline SILBasicBlock *getDefinedInBlock (SILNode *node) {
1305+ // try_apply defines the value only on the success edge.
1306+ if (auto ta = dyn_cast<TryApplyInst>(node)) {
1307+ return ta->getNormalBB ();
1308+ }
1309+ return node->getParentBlock ();
1310+ }
1311+
13061312// / MultiDefPrunedLiveness is computed incrementally by calling updateForUse.
13071313// /
13081314// / Defs should be initialized before calling updatingForUse on any def
@@ -1351,9 +1357,17 @@ class FieldSensitiveMultiDefPrunedLiveRange
13511357 void initializeDef (SILNode *node, TypeTreeLeafTypeRange span) {
13521358 assert (Super::isInitialized ());
13531359 defs.insert (node, span);
1354- auto *block = node->getParentBlock ();
1355- defBlocks.insert (block, span);
1356- initializeDefBlock (block, span);
1360+ auto defBlock = getDefinedInBlock (node);
1361+ defBlocks.insert (defBlock, span);
1362+ initializeDefBlock (defBlock, span);
1363+
1364+ if (auto ta = dyn_cast<TryApplyInst>(node)) {
1365+ // The value becomes live on the success edge.
1366+ // Mark the basic block the try_apply terminates as a dead-to-live
1367+ // edge.
1368+ initializeDefBlock (ta->getParent (), span,
1369+ FieldSensitivePrunedLiveBlocks::DeadToLiveEdge);
1370+ }
13571371 }
13581372
13591373 void initializeDef (SILInstruction *def, TypeTreeLeafTypeRange span) {
0 commit comments