@@ -822,7 +822,7 @@ bool PrunedLiveRange<LivenessWithDefs>::areUsesOutsideBoundary(
822
822
823
823
template <typename LivenessWithDefs>
824
824
void PrunedLiveRange<LivenessWithDefs>::computeBoundary(
825
- PrunedLivenessBoundary &boundary) const {
825
+ AnyPrunedLivenessBoundary &boundary) const {
826
826
assert (asImpl ().isInitialized ());
827
827
828
828
for (SILBasicBlock *block : getDiscoveredBlocks ()) {
@@ -896,50 +896,60 @@ template class PrunedLiveRange<MultiDefPrunedLiveness>;
896
896
// ===----------------------------------------------------------------------===//
897
897
898
898
// / 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) {
902
901
assert (liveness.getBlockLiveness (block) == PrunedLiveBlocks::LiveWithin);
903
902
904
903
for (SILInstruction &inst : llvm::reverse (*block)) {
905
904
if (liveness.isInterestingUser (&inst)) {
906
- boundary. lastUsers .push_back (&inst);
905
+ lastUsers.push_back (&inst);
907
906
return ;
908
907
}
909
908
}
910
909
llvm_unreachable (" live-within block must contain an interesting use" );
911
910
}
912
911
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
+
913
919
// / Given a live-within \p block that contains an SSA definition, and knowledge
914
920
// / that all live uses are dominated by that single definition, find either the
915
921
// / last user or a dead def.
916
922
// /
917
923
// / A live range with a single definition cannot have any uses above that
918
924
// / 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) {
922
927
// defInst is null for argument defs.
923
928
SILInstruction *defInst = dyn_cast<SILInstruction>(ssaDef);
924
929
for (SILInstruction &inst : llvm::reverse (*ssaDef->getParentBlock ())) {
925
930
if (&inst == defInst) {
926
- boundary. deadDefs .push_back (cast<SILNode>(&inst));
931
+ deadDefs.push_back (cast<SILNode>(&inst));
927
932
return ;
928
933
}
929
934
if (liveness.isInterestingUser (&inst)) {
930
- boundary. lastUsers .push_back (&inst);
935
+ lastUsers.push_back (&inst);
931
936
return ;
932
937
}
933
938
}
934
939
auto *deadArg = dyn_cast<SILArgument>(ssaDef);
935
940
assert (deadArg
936
941
&& " 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 ());
938
948
}
939
949
940
950
void SSAPrunedLiveness::findBoundariesInBlock (
941
951
SILBasicBlock *block, bool isLiveOut,
942
- PrunedLivenessBoundary &boundary) const {
952
+ AnyPrunedLivenessBoundary &boundary) const {
943
953
assert (isInitialized ());
944
954
945
955
// For SSA, a live-out block cannot have a boundary.
@@ -948,13 +958,13 @@ void SSAPrunedLiveness::findBoundariesInBlock(
948
958
949
959
// Handle live-within block
950
960
if (!isDefBlock (block)) {
951
- findBoundaryInNonDefBlock (block, boundary , *this );
961
+ boundary. findBoundaryInNonDefBlock (block, *this );
952
962
return ;
953
963
}
954
964
// Find either the last user or a dead def
955
965
auto *defInst = def->getDefiningInstruction ();
956
966
SILNode *defNode = defInst ? cast<SILNode>(defInst) : cast<SILArgument>(def);
957
- findBoundaryInSSADefBlock (defNode, boundary , *this );
967
+ boundary. findBoundaryInSSADefBlock (defNode, *this );
958
968
}
959
969
960
970
// ===----------------------------------------------------------------------===//
@@ -1045,13 +1055,13 @@ static FunctionTest MultiDefUseLivenessTest(
1045
1055
1046
1056
void MultiDefPrunedLiveness::findBoundariesInBlock (
1047
1057
SILBasicBlock *block, bool isLiveOut,
1048
- PrunedLivenessBoundary &boundary) const {
1058
+ AnyPrunedLivenessBoundary &boundary) const {
1049
1059
assert (isInitialized ());
1050
1060
1051
1061
if (!isDefBlock (block)) {
1052
1062
// A live-out block with no defs cannot have a boundary.
1053
1063
if (!isLiveOut) {
1054
- findBoundaryInNonDefBlock (block, boundary , *this );
1064
+ boundary. findBoundaryInNonDefBlock (block, *this );
1055
1065
}
1056
1066
return ;
1057
1067
}
@@ -1061,48 +1071,89 @@ void MultiDefPrunedLiveness::findBoundariesInBlock(
1061
1071
if (++defs.begin () == defs.end ()) {
1062
1072
// For SSA, a live-out block cannot have a boundary.
1063
1073
if (!isLiveOut) {
1064
- findBoundaryInSSADefBlock (*defs.begin (), boundary , *this );
1074
+ boundary. findBoundaryInSSADefBlock (*defs.begin (), *this );
1065
1075
}
1066
1076
return ;
1067
1077
}
1078
+ boundary.findBoundaryInMultiDefBlock (block, isLiveOut, *this );
1079
+ }
1080
+
1081
+ void PrunedLivenessBoundary::findBoundaryInMultiDefBlock (
1082
+ SILBasicBlock *block, bool isLiveOut,
1083
+ const MultiDefPrunedLiveness &liveness) {
1068
1084
// 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 ();
1070
1086
(void )prevCount;
1071
1087
1072
1088
bool isLive = isLiveOut;
1073
1089
for (auto &inst : llvm::reverse (*block)) {
1074
1090
// Check if the instruction is a def before checking whether it is a
1075
1091
// use. The same instruction can be both a dead def and boundary use.
1076
- if (isDef (&inst)) {
1092
+ if (liveness. isDef (&inst)) {
1077
1093
if (!isLive) {
1078
- boundary. deadDefs .push_back (cast<SILNode>(&inst));
1094
+ deadDefs.push_back (cast<SILNode>(&inst));
1079
1095
}
1080
1096
isLive = false ;
1081
1097
}
1082
1098
// Note: the same instruction could potentially be both a dead def and last
1083
1099
// user. The liveness boundary supports this, although it won't happen in
1084
1100
// 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);
1087
1103
isLive = true ;
1088
1104
}
1089
1105
}
1090
1106
if (!isLive) {
1091
1107
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);
1094
1110
}
1095
1111
}
1096
1112
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);
1099
1115
}
1100
1116
}
1101
1117
}
1102
1118
// 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
+ }
1106
1157
}
1107
1158
1108
1159
LiveRangeSummary MultiDefPrunedLiveness::computeSimple () {
0 commit comments