@@ -822,7 +822,7 @@ bool PrunedLiveRange<LivenessWithDefs>::areUsesOutsideBoundary(
822822
823823template <typename LivenessWithDefs>
824824void PrunedLiveRange<LivenessWithDefs>::computeBoundary(
825- PrunedLivenessBoundary &boundary) const {
825+ AnyPrunedLivenessBoundary &boundary) const {
826826 assert (asImpl ().isInitialized ());
827827
828828 for (SILBasicBlock *block : getDiscoveredBlocks ()) {
@@ -896,50 +896,60 @@ template class PrunedLiveRange<MultiDefPrunedLiveness>;
896896// ===----------------------------------------------------------------------===//
897897
898898// / Given live-within (non-live-out) \p block, find the last user.
899- void findBoundaryInNonDefBlock (SILBasicBlock *block,
900- PrunedLivenessBoundary &boundary,
901- const PrunedLiveness &liveness) {
899+ void PrunedLivenessBoundary::findBoundaryInNonDefBlock (
900+ SILBasicBlock *block, const PrunedLiveness &liveness) {
902901 assert (liveness.getBlockLiveness (block) == PrunedLiveBlocks::LiveWithin);
903902
904903 for (SILInstruction &inst : llvm::reverse (*block)) {
905904 if (liveness.isInterestingUser (&inst)) {
906- boundary. lastUsers .push_back (&inst);
905+ lastUsers.push_back (&inst);
907906 return ;
908907 }
909908 }
910909 llvm_unreachable (" live-within block must contain an interesting use" );
911910}
912911
912+ void PrunedLivenessBlockBoundary::findBoundaryInNonDefBlock (
913+ SILBasicBlock *block, const PrunedLiveness &liveness) {
914+ assert (liveness.getBlockLiveness (block) == PrunedLiveBlocks::LiveWithin);
915+
916+ endBlocks.push_back (block);
917+ }
918+
913919// / Given a live-within \p block that contains an SSA definition, and knowledge
914920// / that all live uses are dominated by that single definition, find either the
915921// / last user or a dead def.
916922// /
917923// / A live range with a single definition cannot have any uses above that
918924// / definition in the same block. This even holds for unreachable self-loops.
919- void findBoundaryInSSADefBlock (SILNode *ssaDef,
920- PrunedLivenessBoundary &boundary,
921- const PrunedLiveness &liveness) {
925+ void PrunedLivenessBoundary::findBoundaryInSSADefBlock (
926+ SILNode *ssaDef, const PrunedLiveness &liveness) {
922927 // defInst is null for argument defs.
923928 SILInstruction *defInst = dyn_cast<SILInstruction>(ssaDef);
924929 for (SILInstruction &inst : llvm::reverse (*ssaDef->getParentBlock ())) {
925930 if (&inst == defInst) {
926- boundary. deadDefs .push_back (cast<SILNode>(&inst));
931+ deadDefs.push_back (cast<SILNode>(&inst));
927932 return ;
928933 }
929934 if (liveness.isInterestingUser (&inst)) {
930- boundary. lastUsers .push_back (&inst);
935+ lastUsers.push_back (&inst);
931936 return ;
932937 }
933938 }
934939 auto *deadArg = dyn_cast<SILArgument>(ssaDef);
935940 assert (deadArg
936941 && " findBoundariesInBlock must be called on a live block" );
937- boundary.deadDefs .push_back (deadArg);
942+ deadDefs.push_back (deadArg);
943+ }
944+
945+ void PrunedLivenessBlockBoundary::findBoundaryInSSADefBlock (
946+ SILNode *ssaDef, const PrunedLiveness &liveness) {
947+ endBlocks.push_back (ssaDef->getParentBlock ());
938948}
939949
940950void SSAPrunedLiveness::findBoundariesInBlock (
941951 SILBasicBlock *block, bool isLiveOut,
942- PrunedLivenessBoundary &boundary) const {
952+ AnyPrunedLivenessBoundary &boundary) const {
943953 assert (isInitialized ());
944954
945955 // For SSA, a live-out block cannot have a boundary.
@@ -948,13 +958,13 @@ void SSAPrunedLiveness::findBoundariesInBlock(
948958
949959 // Handle live-within block
950960 if (!isDefBlock (block)) {
951- findBoundaryInNonDefBlock (block, boundary , *this );
961+ boundary. findBoundaryInNonDefBlock (block, *this );
952962 return ;
953963 }
954964 // Find either the last user or a dead def
955965 auto *defInst = def->getDefiningInstruction ();
956966 SILNode *defNode = defInst ? cast<SILNode>(defInst) : cast<SILArgument>(def);
957- findBoundaryInSSADefBlock (defNode, boundary , *this );
967+ boundary. findBoundaryInSSADefBlock (defNode, *this );
958968}
959969
960970// ===----------------------------------------------------------------------===//
@@ -1045,13 +1055,13 @@ static FunctionTest MultiDefUseLivenessTest(
10451055
10461056void MultiDefPrunedLiveness::findBoundariesInBlock (
10471057 SILBasicBlock *block, bool isLiveOut,
1048- PrunedLivenessBoundary &boundary) const {
1058+ AnyPrunedLivenessBoundary &boundary) const {
10491059 assert (isInitialized ());
10501060
10511061 if (!isDefBlock (block)) {
10521062 // A live-out block with no defs cannot have a boundary.
10531063 if (!isLiveOut) {
1054- findBoundaryInNonDefBlock (block, boundary , *this );
1064+ boundary. findBoundaryInNonDefBlock (block, *this );
10551065 }
10561066 return ;
10571067 }
@@ -1061,48 +1071,89 @@ void MultiDefPrunedLiveness::findBoundariesInBlock(
10611071 if (++defs.begin () == defs.end ()) {
10621072 // For SSA, a live-out block cannot have a boundary.
10631073 if (!isLiveOut) {
1064- findBoundaryInSSADefBlock (*defs.begin (), boundary , *this );
1074+ boundary. findBoundaryInSSADefBlock (*defs.begin (), *this );
10651075 }
10661076 return ;
10671077 }
1078+ boundary.findBoundaryInMultiDefBlock (block, isLiveOut, *this );
1079+ }
1080+
1081+ void PrunedLivenessBoundary::findBoundaryInMultiDefBlock (
1082+ SILBasicBlock *block, bool isLiveOut,
1083+ const MultiDefPrunedLiveness &liveness) {
10681084 // Handle a live-out or live-within block with potentially multiple defs
1069- unsigned prevCount = boundary. deadDefs .size () + boundary. lastUsers .size ();
1085+ unsigned prevCount = deadDefs.size () + lastUsers.size ();
10701086 (void )prevCount;
10711087
10721088 bool isLive = isLiveOut;
10731089 for (auto &inst : llvm::reverse (*block)) {
10741090 // Check if the instruction is a def before checking whether it is a
10751091 // use. The same instruction can be both a dead def and boundary use.
1076- if (isDef (&inst)) {
1092+ if (liveness. isDef (&inst)) {
10771093 if (!isLive) {
1078- boundary. deadDefs .push_back (cast<SILNode>(&inst));
1094+ deadDefs.push_back (cast<SILNode>(&inst));
10791095 }
10801096 isLive = false ;
10811097 }
10821098 // Note: the same instruction could potentially be both a dead def and last
10831099 // user. The liveness boundary supports this, although it won't happen in
10841100 // any context where we care about inserting code on the boundary.
1085- if (!isLive && isInterestingUser (&inst)) {
1086- boundary. lastUsers .push_back (&inst);
1101+ if (!isLive && liveness. isInterestingUser (&inst)) {
1102+ lastUsers.push_back (&inst);
10871103 isLive = true ;
10881104 }
10891105 }
10901106 if (!isLive) {
10911107 for (SILArgument *deadArg : block->getArguments ()) {
1092- if (defs.contains (deadArg)) {
1093- boundary. deadDefs .push_back (deadArg);
1108+ if (liveness. defs .contains (deadArg)) {
1109+ deadDefs.push_back (deadArg);
10941110 }
10951111 }
10961112 if (auto *predBB = block->getSinglePredecessorBlock ()) {
1097- if (getBlockLiveness (predBB) == PrunedLiveBlocks::LiveOut) {
1098- boundary. boundaryEdges .push_back (block);
1113+ if (liveness. getBlockLiveness (predBB) == PrunedLiveBlocks::LiveOut) {
1114+ boundaryEdges.push_back (block);
10991115 }
11001116 }
11011117 }
11021118 // All live-within blocks must contain a boundary.
1103- assert (isLiveOut
1104- || (prevCount < boundary.deadDefs .size () + boundary.lastUsers .size ())
1105- && " findBoundariesInBlock must be called on a live block" );
1119+ assert (isLiveOut ||
1120+ (prevCount < deadDefs.size () + lastUsers.size ()) &&
1121+ " findBoundariesInBlock must be called on a live block" );
1122+ }
1123+
1124+ void PrunedLivenessBlockBoundary::findBoundaryInMultiDefBlock (
1125+ SILBasicBlock *block, bool isLiveOut,
1126+ const MultiDefPrunedLiveness &liveness) {
1127+ bool isLive = isLiveOut;
1128+ for (auto &inst : llvm::reverse (*block)) {
1129+ // Check if the instruction is a def before checking whether it is a
1130+ // use. The same instruction can be both a dead def and boundary use.
1131+ if (liveness.isDef (&inst)) {
1132+ if (!isLive) {
1133+ endBlocks.push_back (block);
1134+ return ;
1135+ }
1136+ isLive = false ;
1137+ }
1138+ if (!isLive && liveness.isInterestingUser (&inst)) {
1139+ endBlocks.push_back (block);
1140+ return ;
1141+ }
1142+ }
1143+ if (!isLive) {
1144+ for (SILArgument *deadArg : block->getArguments ()) {
1145+ if (liveness.defs .contains (deadArg)) {
1146+ endBlocks.push_back (block);
1147+ return ;
1148+ }
1149+ }
1150+ if (auto *predBB = block->getSinglePredecessorBlock ()) {
1151+ if (liveness.getBlockLiveness (predBB) == PrunedLiveBlocks::LiveOut) {
1152+ boundaryEdges.push_back (block);
1153+ return ;
1154+ }
1155+ }
1156+ }
11061157}
11071158
11081159LiveRangeSummary MultiDefPrunedLiveness::computeSimple () {
0 commit comments