Skip to content

Commit d1ec1e6

Browse files
committed
[IRGen] Dealloc metadata packs on dom frontier.
Deallocate dynamic allocas done for metadata/wtable packs. These stackrestore calls are inserted on the dominance frontier and then stack nesting is fixed up. That was achieved as follows: Added a new IRGen pass PackMetadataMarkerInserter; it - determines if there are any instructions which might allocate on-stack pack metadata - if there aren't, no changes are made - if there are, alloc_pack_metadata just before instructions that could allocate pack metadata on the stack and dealloc_pack_metadata on the dominance frontier of those instructions - fixup stack nesting During IRGen, the allocations done for metadata/wtable packs are recorded and IRGenSILFunction associates them with the instruction that lowered. It must be the instruction after some alloc_pack_metadata instruction. Then, when visiting the dealloc_pack_metadata instructions corresponding to that alloc_pack_metadata, deallocate those packs.
1 parent 172be49 commit d1ec1e6

File tree

12 files changed

+616
-21
lines changed

12 files changed

+616
-21
lines changed

Diff for: include/swift/IRGen/IRGenSILPasses.h

+1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ namespace irgen {
1919
/// Create a pass to hoist alloc_stack instructions with non-fixed size.
2020
SILTransform *createAllocStackHoisting();
2121
SILTransform *createLoadableByAddress();
22+
SILTransform *createPackMetadataMarkerInserter();
2223

2324
} // end namespace irgen
2425
} // end namespace swift

Diff for: include/swift/SILOptimizer/PassManager/Passes.def

+2
Original file line numberDiff line numberDiff line change
@@ -353,6 +353,8 @@ IRGEN_PASS(LoadableByAddress, "loadable-address",
353353
"SIL Large Loadable type by-address lowering.")
354354
PASS(MandatorySILLinker, "mandatory-linker",
355355
"Deserialize all referenced SIL functions that are shared or transparent")
356+
IRGEN_PASS(PackMetadataMarkerInserter, "pack-metadata-marker-inserter",
357+
"Insert markers where pack metadata might be de/allocated.")
356358
PASS(PerformanceSILLinker, "performance-linker",
357359
"Deserialize all referenced SIL functions")
358360
PASS(RawSILInstLowering, "raw-sil-inst-lowering",

Diff for: lib/IRGen/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ add_swift_host_library(swiftIRGen STATIC
5959
MetadataLayout.cpp
6060
MetadataRequest.cpp
6161
Outlining.cpp
62+
PackMetadataMarkerInserter.cpp
6263
StructLayout.cpp
6364
SwiftTargetInfo.cpp
6465
TBDGen.cpp

Diff for: lib/IRGen/GenPack.cpp

+75-4
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,11 @@
3535
using namespace swift;
3636
using namespace irgen;
3737

38+
static void cleanupTypeMetadataPackImpl(IRGenFunction &IGF, StackAddress pack,
39+
llvm::Value *shape);
40+
static void cleanupWitnessTablePackImpl(IRGenFunction &IGF, StackAddress pack,
41+
llvm::Value *shape);
42+
3843
static CanPackArchetypeType
3944
getForwardedPackArchetypeType(CanPackType packType) {
4045
if (auto expansion = packType.unwrapSingletonPackExpansion())
@@ -454,6 +459,7 @@ irgen::emitTypeMetadataPack(IRGenFunction &IGF, CanPackType packType,
454459
assert(packType->getNumElements() == constantInt->getValue());
455460
auto pack =
456461
StackAddress(emitFixedSizeMetadataPackRef(IGF, packType, request));
462+
IGF.recordStackPackMetadataAlloc(pack, constantInt);
457463
return {pack, constantInt};
458464
}
459465

@@ -488,6 +494,7 @@ irgen::emitTypeMetadataPack(IRGenFunction &IGF, CanPackType packType,
488494
};
489495

490496
visitPackExplosion(IGF, packType, visitFn);
497+
IGF.recordStackPackMetadataAlloc(pack, shape);
491498

492499
return {pack, shape};
493500
}
@@ -599,6 +606,7 @@ irgen::emitWitnessTablePack(IRGenFunction &IGF, CanPackType packType,
599606
assert(packType->getNumElements() == constantInt->getValue());
600607
auto pack = StackAddress(
601608
emitFixedSizeWitnessTablePack(IGF, packType, packConformance));
609+
IGF.recordStackPackWitnessTableAlloc(pack, constantInt);
602610
return {pack, constantInt};
603611
}
604612

@@ -635,12 +643,14 @@ irgen::emitWitnessTablePack(IRGenFunction &IGF, CanPackType packType,
635643
};
636644

637645
visitPackExplosion(IGF, packType, visitFn);
646+
IGF.recordStackPackWitnessTableAlloc(pack, shape);
638647

639648
return {pack, shape};
640649
}
641650

642-
void irgen::cleanupWitnessTablePack(IRGenFunction &IGF, StackAddress pack,
643-
llvm::Value *shape) {
651+
static void cleanupWitnessTablePackImpl(IRGenFunction &IGF, StackAddress pack,
652+
llvm::Value *shape) {
653+
644654
if (pack.getExtraInfo()) {
645655
IGF.emitDeallocateDynamicAlloca(pack);
646656
} else if (auto count = countForShape(shape)) {
@@ -649,6 +659,61 @@ void irgen::cleanupWitnessTablePack(IRGenFunction &IGF, StackAddress pack,
649659
}
650660
}
651661

662+
void irgen::cleanupWitnessTablePack(IRGenFunction &IGF, StackAddress pack,
663+
llvm::Value *shape) {
664+
cleanupWitnessTablePackImpl(IGF, pack, shape);
665+
IGF.eraseStackPackWitnessTableAlloc(pack, shape);
666+
}
667+
668+
void irgen::cleanupStackAllocPacks(IRGenFunction &IGF,
669+
ArrayRef<StackPackAlloc> allocs) {
670+
for (auto alloc : llvm::reverse(allocs)) {
671+
StackAddress addr;
672+
uint8_t kind;
673+
llvm::Value *shape;
674+
std::tie(addr, shape, kind) = alloc;
675+
676+
switch ((GenericRequirement::Kind)kind) {
677+
case GenericRequirement::Kind::MetadataPack:
678+
cleanupTypeMetadataPackImpl(IGF, addr, shape);
679+
break;
680+
case GenericRequirement::Kind::WitnessTablePack:
681+
cleanupWitnessTablePackImpl(IGF, addr, shape);
682+
break;
683+
default:
684+
llvm_unreachable("bad requirement in stack pack alloc");
685+
}
686+
}
687+
}
688+
689+
void IRGenFunction::recordStackPackMetadataAlloc(StackAddress addr,
690+
llvm::Value *shape) {
691+
OutstandingStackPackAllocs.insert(
692+
{addr, shape, (uint8_t)GenericRequirement::Kind::MetadataPack});
693+
}
694+
695+
void IRGenFunction::eraseStackPackMetadataAlloc(StackAddress addr,
696+
llvm::Value *shape) {
697+
auto removed = OutstandingStackPackAllocs.remove(
698+
{addr, shape, (uint8_t)GenericRequirement::Kind::MetadataPack});
699+
assert(removed && "erased stack pack metadata addr that wasn't recorded!?");
700+
(void)removed;
701+
}
702+
703+
void IRGenFunction::recordStackPackWitnessTableAlloc(StackAddress addr,
704+
llvm::Value *shape) {
705+
OutstandingStackPackAllocs.insert(
706+
{addr, shape, (uint8_t)GenericRequirement::Kind::WitnessTablePack});
707+
}
708+
709+
void IRGenFunction::eraseStackPackWitnessTableAlloc(StackAddress addr,
710+
llvm::Value *shape) {
711+
auto removed = OutstandingStackPackAllocs.remove(
712+
{addr, shape, (uint8_t)GenericRequirement::Kind::WitnessTablePack});
713+
assert(removed && "erased stack pack metadata addr that wasn't recorded!?");
714+
(void)removed;
715+
}
716+
652717
llvm::Value *irgen::emitWitnessTablePackRef(IRGenFunction &IGF,
653718
CanPackType packType,
654719
PackConformance *conformance) {
@@ -1045,8 +1110,8 @@ void irgen::bindOpenedElementArchetypesAtIndex(IRGenFunction &IGF,
10451110
}
10461111
}
10471112

1048-
void irgen::cleanupTypeMetadataPack(IRGenFunction &IGF, StackAddress pack,
1049-
llvm::Value *shape) {
1113+
static void cleanupTypeMetadataPackImpl(IRGenFunction &IGF, StackAddress pack,
1114+
llvm::Value *shape) {
10501115
if (pack.getExtraInfo()) {
10511116
IGF.emitDeallocateDynamicAlloca(pack);
10521117
} else if (auto count = countForShape(shape)) {
@@ -1055,6 +1120,12 @@ void irgen::cleanupTypeMetadataPack(IRGenFunction &IGF, StackAddress pack,
10551120
}
10561121
}
10571122

1123+
void irgen::cleanupTypeMetadataPack(IRGenFunction &IGF, StackAddress pack,
1124+
llvm::Value *shape) {
1125+
cleanupTypeMetadataPackImpl(IGF, pack, shape);
1126+
IGF.eraseStackPackMetadataAlloc(pack, shape);
1127+
}
1128+
10581129
Address irgen::emitStorageAddressOfPackElement(IRGenFunction &IGF, Address pack,
10591130
llvm::Value *index,
10601131
SILType elementType,

Diff for: lib/IRGen/GenPack.h

+12
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,18 @@ llvm::Value *emitWitnessTablePackRef(IRGenFunction &IGF, CanPackType packType,
8080
void cleanupWitnessTablePack(IRGenFunction &IGF, StackAddress pack,
8181
llvm::Value *shape);
8282

83+
/// An on-stack pack metadata/wtable allocation.
84+
///
85+
/// Includes the stack address, the element count, and the kind of requirement
86+
/// (a GenericRequirement::Kind represented as a raw uint8_t).
87+
using StackPackAlloc =
88+
std::tuple<StackAddress, /*shape*/ llvm::Value *, /*kind*/ uint8_t>;
89+
90+
/// Emits cleanups for an array of on-stack pack metadata/wtable allocations in
91+
/// reverse order.
92+
void cleanupStackAllocPacks(IRGenFunction &IGF,
93+
ArrayRef<StackPackAlloc> allocs);
94+
8395
/// Emit the dynamic index of a particular structural component
8496
/// of the given pack type. If the component is a pack expansion, this
8597
/// is the index of the first element of the pack (or where it would be

Diff for: lib/IRGen/IRGenFunction.cpp

+2
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,8 @@ IRGenFunction::~IRGenFunction() {
6767

6868
// Tear down any side-table data structures.
6969
if (LocalTypeData) destroyLocalTypeData();
70+
71+
// All dynamically allocated metadata should have been cleaned up.
7072
}
7173

7274
OptimizationMode IRGenFunction::getEffectiveOptimizationMode() const {

Diff for: lib/IRGen/IRGenFunction.h

+15-5
Original file line numberDiff line numberDiff line change
@@ -18,16 +18,17 @@
1818
#ifndef SWIFT_IRGEN_IRGENFUNCTION_H
1919
#define SWIFT_IRGEN_IRGENFUNCTION_H
2020

21-
#include "swift/Basic/LLVM.h"
22-
#include "swift/AST/Type.h"
21+
#include "DominancePoint.h"
22+
#include "GenPack.h"
23+
#include "IRBuilder.h"
24+
#include "LocalTypeDataKind.h"
2325
#include "swift/AST/ReferenceCounting.h"
26+
#include "swift/AST/Type.h"
27+
#include "swift/Basic/LLVM.h"
2428
#include "swift/SIL/SILLocation.h"
2529
#include "swift/SIL/SILType.h"
2630
#include "llvm/ADT/DenseMap.h"
2731
#include "llvm/IR/CallingConv.h"
28-
#include "IRBuilder.h"
29-
#include "LocalTypeDataKind.h"
30-
#include "DominancePoint.h"
3132

3233
namespace llvm {
3334
class AllocaInst;
@@ -206,6 +207,9 @@ class IRGenFunction {
206207
// particular.
207208
bool packMetadataStackPromotionDisabled = false;
208209

210+
/// The on-stack pack metadata allocations emitted so far awaiting cleanup.
211+
llvm::SmallSetVector<StackPackAlloc, 2> OutstandingStackPackAllocs;
212+
209213
private:
210214
Address asyncContextLocation;
211215

@@ -381,6 +385,12 @@ class IRGenFunction {
381385

382386
llvm::Value *emitPackShapeExpression(CanType type);
383387

388+
void recordStackPackMetadataAlloc(StackAddress addr, llvm::Value *shape);
389+
void eraseStackPackMetadataAlloc(StackAddress addr, llvm::Value *shape);
390+
391+
void recordStackPackWitnessTableAlloc(StackAddress addr, llvm::Value *shape);
392+
void eraseStackPackWitnessTableAlloc(StackAddress addr, llvm::Value *shape);
393+
384394
/// Emit a load of a reference to the given Objective-C selector.
385395
llvm::Value *emitObjCSelectorRefLoad(StringRef selector);
386396

Diff for: lib/IRGen/IRGenSIL.cpp

+23-2
Original file line numberDiff line numberDiff line change
@@ -441,7 +441,15 @@ class IRGenSILFunction :
441441

442442
// A cached dominance analysis.
443443
std::unique_ptr<DominanceInfo> Dominance;
444-
444+
445+
/// For each instruction which did allocate pack metadata on-stack, the stack
446+
/// locations at which they were allocated.
447+
///
448+
/// Used to emit cleanups for those allocations in
449+
/// emitDeallocateDynamicPackMetadataAllocas.
450+
llvm::DenseMap<SILInstruction *, llvm::SmallVector<StackPackAlloc, 2>>
451+
StackPackAllocs;
452+
445453
IRGenSILFunction(IRGenModule &IGM, SILFunction *f);
446454
~IRGenSILFunction();
447455

@@ -1479,7 +1487,6 @@ class IRGenSILFunction :
14791487
LOADABLE_REF_STORAGE_HELPER(Name)
14801488
#include "swift/AST/ReferenceStorage.def"
14811489
#undef LOADABLE_REF_STORAGE_HELPER
1482-
14831490
};
14841491

14851492
} // end anonymous namespace
@@ -2549,8 +2556,18 @@ void IRGenSILFunction::visitSILBasicBlock(SILBasicBlock *BB) {
25492556
IGM.emittedRuntimeFuncs.clear();
25502557
#endif
25512558

2559+
assert(OutstandingStackPackAllocs.empty());
2560+
25522561
visit(&I);
25532562

2563+
// Record the on-stack pack allocations emitted on behalf of this SIL
2564+
// instruction. They will be cleaned up when visiting the corresponding
2565+
// cleanup markers.
2566+
for (auto pair : OutstandingStackPackAllocs) {
2567+
StackPackAllocs[&I].push_back(pair);
2568+
}
2569+
OutstandingStackPackAllocs.clear();
2570+
25542571
#ifdef CHECK_RUNTIME_EFFECT_ANALYSIS
25552572
if (!isa<DebugValueInst>(&I)) {
25562573
SILType impactType;
@@ -5698,6 +5715,10 @@ void IRGenSILFunction::visitDeallocPackInst(swift::DeallocPackInst *i) {
56985715

56995716
void IRGenSILFunction::visitDeallocPackMetadataInst(
57005717
DeallocPackMetadataInst *i) {
5718+
auto iter = StackPackAllocs.find(i->getIntroducer());
5719+
if (iter == StackPackAllocs.end())
5720+
return;
5721+
cleanupStackAllocPacks(*this, iter->getSecond());
57015722
}
57025723

57035724
void IRGenSILFunction::visitDeallocRefInst(swift::DeallocRefInst *i) {

0 commit comments

Comments
 (0)