@@ -24,6 +24,7 @@ void StackNesting::setup(SILFunction *F) {
24
24
25
25
// We use pointers to BlockInfo structs. Therefore it's important that the
26
26
// BlockInfos vector is never re-allocated.
27
+ BlockInfos.clear ();
27
28
BlockInfos.reserve (F->size ());
28
29
29
30
// Start with the function entry block and add blocks while walking down along
@@ -231,36 +232,26 @@ bool StackNesting::insertDeallocs(const BitVector &AliveBefore,
231
232
return changesMade;
232
233
}
233
234
234
- StackNesting::Changes StackNesting::adaptDeallocs () {
235
-
236
- bool InstChanged = false ;
237
- bool CFGChanged = false ;
238
- BitVector Bits (StackLocs.size ());
239
-
240
- // Visit all blocks. Actually the order doesn't matter, but let's to it in
241
- // the same order as in solve().
235
+ // Insert deallocations at block boundaries.
236
+ // This can be necessary for unreachable blocks. Example:
237
+ //
238
+ // %1 = alloc_stack
239
+ // %2 = alloc_stack
240
+ // cond_br %c, bb2, bb3
241
+ // bb2: <--- need to insert a dealloc_stack %2 at the begin of bb2
242
+ // dealloc_stack %1
243
+ // unreachable
244
+ // bb3:
245
+ // dealloc_stack %2
246
+ // dealloc_stack %1
247
+ StackNesting::Changes StackNesting::insertDeallocsAtBlockBoundaries () {
248
+ Changes changes = Changes::None;
242
249
for (const BlockInfo &BI : reversed (BlockInfos)) {
243
- // Collect the alive-bits (at the block exit) from the successor blocks.
244
- Bits = BI.AliveStackLocsAtExit ;
245
-
246
- // Insert deallocations at block boundaries.
247
- // This can be necessary for unreachable blocks. Example:
248
- //
249
- // %1 = alloc_stack
250
- // %2 = alloc_stack
251
- // cond_br %c, bb2, bb3
252
- // bb2: <--- need to insert a dealloc_stack %2 at the begin of bb2
253
- // dealloc_stack %1
254
- // unreachable
255
- // bb3:
256
- // dealloc_stack %2
257
- // dealloc_stack %1
258
- //
259
250
for (unsigned SuccIdx = 0 , NumSuccs = BI.Successors .size ();
260
- SuccIdx < NumSuccs; ++ SuccIdx) {
261
- BlockInfo *SuccBI = BI.Successors [SuccIdx];
251
+ SuccIdx < NumSuccs; ++SuccIdx) {
262
252
263
- if (SuccBI->AliveStackLocsAtEntry == Bits)
253
+ BlockInfo *SuccBI = BI.Successors [SuccIdx];
254
+ if (SuccBI->AliveStackLocsAtEntry == BI.AliveStackLocsAtExit )
264
255
continue ;
265
256
266
257
// Insert deallocations for all locations which are alive at the end of
@@ -271,11 +262,26 @@ StackNesting::Changes StackNesting::adaptDeallocs() {
271
262
// block, we have to insert a new block where we can add the
272
263
// deallocations.
273
264
InsertionBlock = splitEdge (BI.Block ->getTerminator (), SuccIdx);
274
- CFGChanged = true ;
265
+ changes = Changes::CFG;
266
+ }
267
+ if (insertDeallocs (BI.AliveStackLocsAtExit , SuccBI->AliveStackLocsAtEntry ,
268
+ &InsertionBlock->front (), None)) {
269
+ if (changes == Changes::None)
270
+ changes = Changes::Instructions;
275
271
}
276
- InstChanged |= insertDeallocs (Bits, SuccBI->AliveStackLocsAtEntry ,
277
- &InsertionBlock->front (), None);
278
272
}
273
+ }
274
+ return changes;
275
+ }
276
+
277
+ bool StackNesting::adaptDeallocs () {
278
+ bool InstChanged = false ;
279
+ BitVector Bits (StackLocs.size ());
280
+
281
+ // Visit all blocks. Actually the order doesn't matter, but let's to it in
282
+ // the same order as in solve().
283
+ for (const BlockInfo &BI : reversed (BlockInfos)) {
284
+ Bits = BI.AliveStackLocsAtExit ;
279
285
280
286
// Insert/remove deallocations inside blocks.
281
287
for (SILInstruction *StackInst : reversed (BI.StackInsts )) {
@@ -310,19 +316,29 @@ StackNesting::Changes StackNesting::adaptDeallocs() {
310
316
}
311
317
assert (Bits == BI.AliveStackLocsAtEntry && " dataflow didn't converge" );
312
318
}
313
- if (CFGChanged)
314
- return Changes::CFG;
315
- if (InstChanged)
316
- return Changes::Instructions;
317
- return Changes::None;
319
+ return InstChanged;
318
320
}
319
321
320
322
StackNesting::Changes StackNesting::correctStackNesting (SILFunction *F) {
321
323
setup (F);
322
- if (solve ()) {
323
- return adaptDeallocs ();
324
+ if (!solve ())
325
+ return Changes::None;
326
+
327
+ // Insert deallocs at block boundaries. This might be necessary in CFG sub
328
+ // graphs which don't reach a function exit, but only an unreachable.
329
+ Changes changes = insertDeallocsAtBlockBoundaries ();
330
+ if (changes != Changes::None) {
331
+ // Those inserted deallocs make it necessary to re-compute the analysis.
332
+ setup (F);
333
+ solve ();
334
+ }
335
+ // Do the real work: extend lifetimes by moving deallocs.
336
+ if (adaptDeallocs ()) {
337
+ if (changes == Changes::None)
338
+ changes = Changes::Instructions;
324
339
}
325
- return Changes::None;
340
+
341
+ return changes;
326
342
}
327
343
328
344
void StackNesting::dump () const {
0 commit comments