@@ -134,9 +134,6 @@ void StackNesting::setup(SILFunction *F) {
134
134
}
135
135
}
136
136
}
137
- if (BI->Block ->getTerminator ()->isFunctionExiting ())
138
- BI->ExitReachable = true ;
139
-
140
137
for (auto *SuccBB : BI->Block ->getSuccessorBlocks ()) {
141
138
BlockInfo *&SuccBI = BlockMapping[SuccBB];
142
139
if (!SuccBI) {
@@ -165,33 +162,78 @@ bool StackNesting::solve() {
165
162
bool isNested = false ;
166
163
BitVector Bits (StackLocs.size ());
167
164
168
- // Iterate until we reach a fixed-point.
165
+ // Initialize all bit fields to 1s, expect 0s for the entry block.
166
+ bool initVal = false ;
167
+ for (BlockInfo &BI : BlockInfos) {
168
+ BI.AliveStackLocsAtEntry .resize (StackLocs.size (), initVal);
169
+ initVal = false ;
170
+ }
171
+
172
+ // First step: do a forward dataflow analysis to get the live stack locations
173
+ // at the block exits.
174
+ // This is necessary to get the live locations at blocks which end in
175
+ // unreachable instructions (otherwise the backward data flow would be
176
+ // sufficient). The special thing about unreachable-blocks is that it's
177
+ // okay to have alive locations at that point, i.e. locations which are never
178
+ // dealloced. We cannot get such locations with a purly backward dataflow.
179
+ do {
180
+ changed = false ;
181
+
182
+ for (BlockInfo &BI : BlockInfos) {
183
+ Bits = BI.AliveStackLocsAtEntry ;
184
+ for (SILInstruction *StackInst : BI.StackInsts ) {
185
+ if (StackInst->isAllocatingStack ()) {
186
+ Bits.set (bitNumberForAlloc (StackInst));
187
+ } else if (StackInst->isDeallocatingStack ()) {
188
+ Bits.reset (bitNumberForDealloc (StackInst));
189
+ }
190
+ }
191
+ if (Bits != BI.AliveStackLocsAtExit ) {
192
+ BI.AliveStackLocsAtExit = Bits;
193
+ assert (!(BI.Block ->getTerminator ()->isFunctionExiting () && Bits.any ())
194
+ && " stack location is missing dealloc" );
195
+ changed = true ;
196
+ }
197
+ // Merge the bits into the successors.
198
+ for (BlockInfo *SuccBI : BI.Successors ) {
199
+ SuccBI->AliveStackLocsAtEntry &= Bits;
200
+ }
201
+ }
202
+ } while (changed);
203
+
204
+ // Second step: do a backward dataflow analysis to extend the lifetimes of
205
+ // no properly nested allocations.
169
206
do {
170
207
changed = false ;
171
208
172
209
// It's a backward dataflow problem.
173
210
for (BlockInfo &BI : reversed (BlockInfos)) {
174
211
// Collect the alive-bits (at the block exit) from the successor blocks.
175
- Bits.reset ();
176
212
for (BlockInfo *SuccBI : BI.Successors ) {
177
- Bits |= SuccBI->AliveStackLocsAtEntry ;
178
-
179
- // Also get the ExitReachable flag from the successor blocks.
180
- if (!BI.ExitReachable && SuccBI->ExitReachable ) {
181
- BI.ExitReachable = true ;
182
- changed = true ;
213
+ BI.AliveStackLocsAtExit |= SuccBI->AliveStackLocsAtEntry ;
214
+ }
215
+ Bits = BI.AliveStackLocsAtExit ;
216
+
217
+ if (isa<UnreachableInst>(BI.Block ->getTerminator ())) {
218
+ // We treat unreachable as an implicit deallocation for all locations
219
+ // which are still alive at this point.
220
+ for (int BitNr = Bits.find_first (); BitNr >= 0 ;
221
+ BitNr = Bits.find_next (BitNr)) {
222
+ // For each alive location extend the lifetime of all locations which
223
+ // are alive at the allocation point. This is the same as we do for
224
+ // a "real" deallocation instruction (see below).
225
+ Bits |= StackLocs[BitNr].AliveLocs ;
183
226
}
227
+ BI.AliveStackLocsAtExit = Bits;
184
228
}
185
229
for (SILInstruction *StackInst : reversed (BI.StackInsts )) {
186
230
if (StackInst->isAllocatingStack ()) {
187
- auto AllocInst = cast<SingleValueInstruction>(StackInst);
188
- int BitNr = StackLoc2BitNumbers[AllocInst];
231
+ int BitNr = bitNumberForAlloc (StackInst);
189
232
if (Bits != StackLocs[BitNr].AliveLocs ) {
190
233
// More locations are alive around the StackInst's location.
191
234
// Update the AlivaLocs bitset, which contains all those alive
192
235
// locations.
193
- assert ((Bits.test (BitNr) || (!BI.ExitReachable && !Bits.any ()))
194
- && " no dealloc found for alloc stack" );
236
+ assert (Bits.test (BitNr) && " no dealloc found for alloc stack" );
195
237
StackLocs[BitNr].AliveLocs = Bits;
196
238
changed = true ;
197
239
isNested = true ;
@@ -203,10 +245,7 @@ bool StackNesting::solve() {
203
245
// A stack deallocation begins the lifetime of its location (in
204
246
// reverse order). And it also begins the lifetime of all other
205
247
// locations which are alive at the allocation point.
206
- auto *AllocInst =
207
- cast<SingleValueInstruction>(StackInst->getOperand (0 ));
208
- int BitNr = StackLoc2BitNumbers[AllocInst];
209
- Bits |= StackLocs[BitNr].AliveLocs ;
248
+ Bits |= StackLocs[bitNumberForDealloc (StackInst)].AliveLocs ;
210
249
}
211
250
}
212
251
if (Bits != BI.AliveStackLocsAtEntry ) {
@@ -271,10 +310,7 @@ StackNesting::Changes StackNesting::adaptDeallocs() {
271
310
// the same order as in solve().
272
311
for (const BlockInfo &BI : reversed (BlockInfos)) {
273
312
// Collect the alive-bits (at the block exit) from the successor blocks.
274
- Bits.reset ();
275
- for (BlockInfo *SuccBI : BI.Successors ) {
276
- Bits |= SuccBI->AliveStackLocsAtEntry ;
277
- }
313
+ Bits = BI.AliveStackLocsAtExit ;
278
314
279
315
// Insert deallocations at block boundaries.
280
316
// This can be necessary for unreachable blocks. Example:
@@ -293,12 +329,6 @@ StackNesting::Changes StackNesting::adaptDeallocs() {
293
329
SuccIdx < NumSuccs; ++ SuccIdx) {
294
330
BlockInfo *SuccBI = BI.Successors [SuccIdx];
295
331
296
- // It's acceptable to not deallocate alive locations in unreachable
297
- // blocks - as long as the nesting is not violated. So if there are no
298
- // alive locations at the unreachable successor block, we can ignore it.
299
- if (!SuccBI->ExitReachable && !SuccBI->AliveStackLocsAtEntry .any ())
300
- continue ;
301
-
302
332
if (SuccBI->AliveStackLocsAtEntry == Bits)
303
333
continue ;
304
334
@@ -320,16 +350,14 @@ StackNesting::Changes StackNesting::adaptDeallocs() {
320
350
for (SILInstruction *StackInst : reversed (BI.StackInsts )) {
321
351
if (StackInst->isAllocatingStack ()) {
322
352
// For allocations we just update the bit-set.
323
- auto AllocInst = cast<SingleValueInstruction>(StackInst);
324
- int BitNr = StackLoc2BitNumbers.lookup (AllocInst);
353
+ int BitNr = bitNumberForAlloc (StackInst);
325
354
assert (Bits == StackLocs[BitNr].AliveLocs &&
326
355
" dataflow didn't converge" );
327
356
Bits.reset (BitNr);
328
357
} else if (StackInst->isDeallocatingStack ()) {
329
358
// Handle deallocations.
330
- auto *AllocInst = cast<SingleValueInstruction>(StackInst->getOperand (0 ));
331
359
SILLocation Loc = StackInst->getLoc ();
332
- int BitNr = StackLoc2BitNumbers. lookup (AllocInst );
360
+ int BitNr = bitNumberForDealloc (StackInst );
333
361
SILInstruction *InsertionPoint = &*std::next (StackInst->getIterator ());
334
362
if (Bits.test (BitNr)) {
335
363
// The location of StackInst is alive after StackInst. So we have to
@@ -372,17 +400,18 @@ void StackNesting::dump() const {
372
400
continue ;
373
401
374
402
llvm::dbgs () << " Block " << BI.Block ->getDebugID ();
375
- if (!BI.ExitReachable )
376
- llvm::dbgs () << " (unreachable exit)" ;
377
- llvm::dbgs () << " : bits=" ;
403
+ llvm::dbgs () << " : entry-bits=" ;
378
404
dumpBits (BI.AliveStackLocsAtEntry );
405
+ llvm::dbgs () << " : exit-bits=" ;
406
+ dumpBits (BI.AliveStackLocsAtExit );
407
+ llvm::dbgs () << ' \n ' ;
379
408
for (SILInstruction *StackInst : BI.StackInsts ) {
380
409
if (StackInst->isAllocatingStack ()) {
381
410
auto AllocInst = cast<SingleValueInstruction>(StackInst);
382
411
int BitNr = StackLoc2BitNumbers.lookup (AllocInst);
383
412
llvm::dbgs () << " alloc #" << BitNr << " : alive=" ;
384
413
dumpBits (StackLocs[BitNr].AliveLocs );
385
- llvm::dbgs () << " " << *StackInst;
414
+ llvm::dbgs () << " , " << *StackInst;
386
415
} else if (StackInst->isDeallocatingStack ()) {
387
416
auto *AllocInst = cast<SingleValueInstruction>(StackInst->getOperand (0 ));
388
417
int BitNr = StackLoc2BitNumbers.lookup (AllocInst);
@@ -405,6 +434,5 @@ void StackNesting::dumpBits(const BitVector &Bits) {
405
434
llvm::dbgs () << separator << Bit;
406
435
separator = " ," ;
407
436
}
408
- llvm::dbgs () << " > \n " ;
437
+ llvm::dbgs () << ' > ' ;
409
438
}
410
-
0 commit comments