@@ -88,6 +88,9 @@ static bool isHoistable(AllocStackInst *Inst, irgen::IRGenModule &Mod) {
88
88
// / a set of alloc_stack instructions that can be assigned a single stack
89
89
// / location.
90
90
namespace {
91
+
92
+ using InstructionIndices = llvm::SmallDenseMap<SILInstruction *, int >;
93
+
91
94
class Partition {
92
95
public:
93
96
SmallVector<AllocStackInst *, 4 > Elts;
@@ -235,7 +238,8 @@ class Liveness {
235
238
// / If they are in the same basic block we scan the basic block to determine
236
239
// / whether one dealloc_stack dominates the other alloc_stack. If this is the
237
240
// / case the live ranges can't overlap.
238
- bool mayOverlap (AllocStackInst *A, AllocStackInst *B) {
241
+ bool mayOverlap (AllocStackInst *A, AllocStackInst *B,
242
+ const InstructionIndices &stackInstructionIndices) {
239
243
assert (A != B);
240
244
241
245
// Check that we have a single dealloc_stack user in the same block.
@@ -251,23 +255,15 @@ class Liveness {
251
255
// Different basic blocks.
252
256
if (A->getParent () != B->getParent ())
253
257
return false ;
254
- bool ALive = false ;
255
- bool BLive = false ;
256
- for (auto &Inst : *A->getParent ()) {
257
- if (A == &Inst) {
258
- ALive = true ;
259
- } else if (singleDeallocA == &Inst) {
260
- ALive = false ;
261
- } else if (B == &Inst) {
262
- BLive = true ;
263
- } else if (singleDeallocB == &Inst) {
264
- BLive = false ;
265
- }
266
258
267
- if (ALive && BLive)
268
- return true ;
269
- }
270
- return false ;
259
+ // Within the same basic block we can use the consecutive instruction indices
260
+ // to check for overlapping.
261
+ if (stackInstructionIndices.lookup (A) > stackInstructionIndices.lookup (singleDeallocB))
262
+ return false ;
263
+ if (stackInstructionIndices.lookup (B) > stackInstructionIndices.lookup (singleDeallocA))
264
+ return false ;
265
+
266
+ return true ;
271
267
}
272
268
};
273
269
} // end anonymous namespace
@@ -285,6 +281,11 @@ class MergeStackSlots {
285
281
SmallVector<Partition, 2 > PartitionByType;
286
282
// / The function exits.
287
283
SmallVectorImpl<SILInstruction *> &FunctionExits;
284
+
285
+ // / Consecutive indices for all `alloc_stack` and `dealloc_stack`
286
+ // / instructions in the function.
287
+ const InstructionIndices &stackInstructionIndices;
288
+
288
289
// / If we are merging any alloc_stack that were moved, to work around a bug in
289
290
// / SelectionDAG that sinks to llvm.dbg.addr, we need to break blocks right
290
291
// / after each llvm.dbg.addr.
@@ -295,7 +296,8 @@ class MergeStackSlots {
295
296
296
297
public:
297
298
MergeStackSlots (SmallVectorImpl<AllocStackInst *> &AllocStacks,
298
- SmallVectorImpl<SILInstruction *> &FuncExits);
299
+ SmallVectorImpl<SILInstruction *> &FuncExits,
300
+ const InstructionIndices &stackInstructionIndices);
299
301
300
302
// / Merge alloc_stack instructions if possible and hoist them to the entry
301
303
// / block.
@@ -304,8 +306,9 @@ class MergeStackSlots {
304
306
} // end anonymous namespace
305
307
306
308
MergeStackSlots::MergeStackSlots (SmallVectorImpl<AllocStackInst *> &AllocStacks,
307
- SmallVectorImpl<SILInstruction *> &FuncExits)
308
- : FunctionExits(FuncExits) {
309
+ SmallVectorImpl<SILInstruction *> &FuncExits,
310
+ const InstructionIndices &stackInstructionIndices)
311
+ : FunctionExits(FuncExits), stackInstructionIndices(stackInstructionIndices) {
309
312
// Build initial partitions based on the type.
310
313
llvm::DenseMap<SILType, unsigned > TypeToPartitionMap;
311
314
for (auto *AS : AllocStacks) {
@@ -350,7 +353,7 @@ MergeStackSlots::mergeSlots(DominanceInfo *DomToUpdate) {
350
353
// candidate partition.
351
354
bool InterferesWithCandidateP = false ;
352
355
for (auto *AllocStackInPartition : CandidateP.Elts ) {
353
- if (Live.mayOverlap (AllocStackInPartition, CurAllocStack)) {
356
+ if (Live.mayOverlap (AllocStackInPartition, CurAllocStack, stackInstructionIndices )) {
354
357
InterferesWithCandidateP = true ;
355
358
break ;
356
359
}
@@ -405,6 +408,10 @@ class HoistAllocStack {
405
408
SmallVector<AllocStackInst *, 16 > AllocStackToHoist;
406
409
SmallVector<SILInstruction *, 8 > FunctionExits;
407
410
411
+ // / Consecutive indices for all `alloc_stack` and `dealloc_stack`
412
+ // / instructions in the function.
413
+ InstructionIndices stackInstructionIndices;
414
+
408
415
llvm::Optional<SILAnalysis::InvalidationKind> InvalidationKind = llvm::None;
409
416
410
417
DominanceInfo *DomInfoToUpdate = nullptr ;
@@ -450,6 +457,8 @@ bool inhibitsAllocStackHoisting(SILInstruction *I) {
450
457
// / A generic alloc_stack could reference an opened archetype that was not
451
458
// / opened in the entry block.
452
459
void HoistAllocStack::collectHoistableInstructions () {
460
+ int stackInstructionIndex = 0 ;
461
+
453
462
for (auto &BB : *F) {
454
463
for (auto &Inst : BB) {
455
464
// Terminators that are function exits are our dealloc_stack
@@ -466,10 +475,15 @@ void HoistAllocStack::collectHoistableInstructions() {
466
475
AllocStackToHoist.clear ();
467
476
return ;
468
477
}
478
+ if (isa<DeallocStackInst>(&Inst))
479
+ stackInstructionIndices[&Inst] = stackInstructionIndex++;
480
+
469
481
auto *ASI = dyn_cast<AllocStackInst>(&Inst);
470
482
if (!ASI) {
471
483
continue ;
472
484
}
485
+ stackInstructionIndices[ASI] = stackInstructionIndex++;
486
+
473
487
if (isHoistable (ASI, IRGenMod)) {
474
488
LLVM_DEBUG (llvm::dbgs () << " Hoisting " << Inst);
475
489
AllocStackToHoist.push_back (ASI);
@@ -484,7 +498,7 @@ void HoistAllocStack::collectHoistableInstructions() {
484
498
// / dealloc_stack instructions to the function exists.
485
499
void HoistAllocStack::hoist () {
486
500
if (SILUseStackSlotMerging) {
487
- MergeStackSlots Merger (AllocStackToHoist, FunctionExits);
501
+ MergeStackSlots Merger (AllocStackToHoist, FunctionExits, stackInstructionIndices );
488
502
InvalidationKind = Merger.mergeSlots (DomInfoToUpdate);
489
503
return ;
490
504
}
0 commit comments