@@ -82,20 +82,38 @@ bool StackNesting::solve() {
82
82
bool isNested = false ;
83
83
BitVector Bits (StackLocs.size ());
84
84
85
+ StackList<SILBasicBlock *> deadEndWorklist (BlockInfos.getFunction ());
86
+
85
87
// Initialize all bit fields to 1s, expect 0s for the entry block.
86
88
bool initVal = false ;
87
89
for (auto bd : BlockInfos) {
88
90
bd.data .AliveStackLocsAtEntry .resize (StackLocs.size (), initVal);
89
91
initVal = true ;
92
+
93
+ bd.data .isDeadEnd = !bd.block .getTerminator ()->isFunctionExiting ();
94
+ if (!bd.data .isDeadEnd )
95
+ deadEndWorklist.push_back (&bd.block );
96
+ }
97
+
98
+ // Calculate the isDeadEnd block flags.
99
+ while (!deadEndWorklist.empty ()) {
100
+ SILBasicBlock *b = deadEndWorklist.pop_back_val ();
101
+ for (SILBasicBlock *pred : b->getPredecessorBlocks ()) {
102
+ BlockInfo &bi = BlockInfos[pred];
103
+ if (bi.isDeadEnd ) {
104
+ bi.isDeadEnd = false ;
105
+ deadEndWorklist.push_back (pred);
106
+ }
107
+ }
90
108
}
91
109
92
110
// First step: do a forward dataflow analysis to get the live stack locations
93
111
// at the block exits.
94
- // This is necessary to get the live locations at blocks which end in
95
- // unreachable instructions (otherwise the backward data flow would be
96
- // sufficient). The special thing about unreachable- blocks is that it's
97
- // okay to have alive locations at that point, i.e. locations which are never
98
- // dealloced. We cannot get such locations with a purly backward dataflow.
112
+ // This is necessary to get the live locations at dead- end blocks (otherwise
113
+ // the backward data flow would be sufficient).
114
+ // The special thing about dead-end blocks is that it's okay to have alive
115
+ // locations at that point (e.g. at an `unreachable`) i.e. locations which are
116
+ // never dealloced. We cannot get such locations with a purly backward dataflow.
99
117
do {
100
118
changed = false ;
101
119
@@ -124,7 +142,7 @@ bool StackNesting::solve() {
124
142
do {
125
143
changed = false ;
126
144
127
- for (auto bd : llvm::reverse (BlockInfos)) {
145
+ for (auto bd : llvm::reverse (BlockInfos)) {
128
146
// Collect the alive-bits (at the block exit) from the successor blocks.
129
147
for (SILBasicBlock *SuccBB : bd.block .getSuccessorBlocks ()) {
130
148
bd.data .AliveStackLocsAtExit |= BlockInfos[SuccBB].AliveStackLocsAtEntry ;
@@ -134,14 +152,18 @@ bool StackNesting::solve() {
134
152
&& Bits.any ())
135
153
&& " stack location is missing dealloc" );
136
154
137
- if (isa<UnreachableInst>(bd.block .getTerminator ())) {
138
- // We treat unreachable as an implicit deallocation for all locations
139
- // which are still alive at this point.
155
+ if (bd.data .isDeadEnd ) {
156
+ // We treat `unreachable` as an implicit deallocation for all locations
157
+ // which are still alive at this point. The same is true for dead-end
158
+ // CFG regions due to an infinite loop.
140
159
for (int BitNr = Bits.find_first (); BitNr >= 0 ;
141
160
BitNr = Bits.find_next (BitNr)) {
142
161
// For each alive location extend the lifetime of all locations which
143
162
// are alive at the allocation point. This is the same as we do for
144
163
// a "real" deallocation instruction (see below).
164
+ // In dead-end CFG regions we have to do that for all blocks (because
165
+ // of potential infinite loops), whereas in "normal" CFG regions it's
166
+ // sufficient to do it at deallocation instructions.
145
167
Bits |= StackLocs[BitNr].AliveLocs ;
146
168
}
147
169
bd.data .AliveStackLocsAtExit = Bits;
@@ -336,6 +358,8 @@ StackNesting::Changes StackNesting::fixNesting(SILFunction *F) {
336
358
void StackNesting::dump () const {
337
359
for (auto bd : BlockInfos) {
338
360
llvm::dbgs () << " Block " << bd.block .getDebugID ();
361
+ if (bd.data .isDeadEnd )
362
+ llvm::dbgs () << " (deadend)" ;
339
363
llvm::dbgs () << " : entry-bits=" ;
340
364
dumpBits (bd.data .AliveStackLocsAtEntry );
341
365
llvm::dbgs () << " : exit-bits=" ;
0 commit comments