Skip to content

Commit 91d659b

Browse files
Merge pull request #66344 from nate-chandler/cherrypick/release/5.9/dealloc-on-stack-packs
5.9: [IRGen] Dealloc on-stack metadata/wtable packs on the dominance frontier.
2 parents 2338480 + a76af6d commit 91d659b

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+1256
-98
lines changed

docs/SIL.rst

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3797,7 +3797,21 @@ address of the allocated memory.
37973797

37983798
``alloc_pack`` is a stack allocation instruction. See the section above
37993799
on stack discipline. The corresponding stack deallocation instruction is
3800-
``dealloc_stack``.
3800+
``dealloc_pack``.
3801+
3802+
alloc_pack_metadata
3803+
```````````````````
3804+
3805+
::
3806+
3807+
sil-instruction ::= 'alloc_pack_metadata' $()
3808+
3809+
Inserted as the last SIL lowering pass of IRGen, indicates that the next instruction
3810+
may have on-stack pack metadata allocated on its behalf.
3811+
3812+
Notionally, ``alloc_pack_metadata`` is a stack allocation instruction. See the
3813+
section above on stack discipline. The corresponding stack deallocation
3814+
instruction is ``dealloc_pack_metadata``.
38013815

38023816
alloc_ref
38033817
`````````
@@ -4056,6 +4070,23 @@ prior to being deallocated.
40564070
on Stack Discipline above. The operand must be an ``alloc_pack``
40574071
instruction.
40584072

4073+
dealloc_pack_metadata
4074+
`````````````````````
4075+
4076+
::
4077+
4078+
sil-instruction ::= 'dealloc_pack_metadata' sil-operand
4079+
4080+
dealloc_pack_metadata $0 : $*()
4081+
4082+
Inserted as the last SIL lowering pass of IRGen, indicates that the on-stack
4083+
pack metadata emitted on behalf of its operand (actually on behalf of the
4084+
instruction after its operand) must be cleaned up here.
4085+
4086+
``dealloc_pack_metadata`` is a stack deallocation instruction. See the section
4087+
on Stack Discipline above. The operand must be an ``alloc_pack_metadata``
4088+
instruction.
4089+
40594090
dealloc_box
40604091
```````````
40614092
::

include/swift/AST/SILOptions.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,12 @@ class SILOptions {
176176
/// Require linear OSSA lifetimes after SILGen
177177
bool OSSACompleteLifetimes = false;
178178

179+
/// Enable pack metadata stack "promotion".
180+
///
181+
/// More accurately, enable skipping mandatory heapification of pack metadata
182+
/// when possible.
183+
bool EnablePackMetadataStackPromotion = true;
184+
179185
// The kind of function bodies to skip emitting.
180186
FunctionBodySkipping SkipFunctionBodies = FunctionBodySkipping::None;
181187

include/swift/AST/Types.h

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,10 @@ class RecursiveTypeProperties {
173173
/// This type contains an ElementArchetype.
174174
HasElementArchetype = 0x4000,
175175

176-
Last_Property = HasElementArchetype
176+
/// This type contains a concrete pack.
177+
HasConcretePack = 0x8000,
178+
179+
Last_Property = HasConcretePack
177180
};
178181
enum { BitWidth = countBitsUsed(Property::Last_Property) };
179182

@@ -243,6 +246,8 @@ class RecursiveTypeProperties {
243246

244247
bool hasParameterPack() const { return Bits & HasParameterPack; }
245248

249+
bool hasConcretePack() const { return Bits & HasConcretePack; }
250+
246251
/// Does a type with these properties structurally contain a
247252
/// parameterized existential type?
248253
bool hasParameterizedExistential() const {
@@ -670,6 +675,13 @@ class alignas(1 << TypeAlignInBits) TypeBase
670675
return getRecursiveProperties().hasParameterPack();
671676
}
672677

678+
bool hasConcretePack() const {
679+
return getRecursiveProperties().hasConcretePack();
680+
}
681+
682+
/// Whether the type has some flavor of pack.
683+
bool hasPack() const { return hasParameterPack() || hasConcretePack(); }
684+
673685
/// Determine whether the type involves a parameterized existential type.
674686
bool hasParameterizedExistential() const {
675687
return getRecursiveProperties().hasParameterizedExistential();

include/swift/IRGen/IRGenSILPasses.h

Lines changed: 1 addition & 0 deletions
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

include/swift/Option/FrontendOptions.td

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1021,6 +1021,16 @@ def force_struct_type_layouts : Flag<["-"], "force-struct-type-layouts">,
10211021
def enable_layout_string_value_witnesses : Flag<["-"], "enable-layout-string-value-witnesses">,
10221022
HelpText<"Enable layout string based value witnesses">;
10231023

1024+
let Flags = [FrontendOption, NoDriverOption, HelpHidden, ModuleInterfaceOptionIgnorable] in {
1025+
def enable_pack_metadata_stack_promotion :
1026+
Joined<["-"], "enable-pack-metadata-stack-promotion=">,
1027+
HelpText<"Whether to skip heapifying stack metadata packs when possible.">,
1028+
MetaVarName<"true|false">;
1029+
def enable_pack_metadata_stack_promotion_noArg :
1030+
Flag<["-"], "enable-pack-metadata-stack-promotion">,
1031+
HelpText<"Skip heapifying stack metadata packs when possible.">;
1032+
}
1033+
10241034
def disable_layout_string_value_witnesses : Flag<["-"], "disable-layout-string-value-witnesses">,
10251035
HelpText<"Disable layout string based value witnesses">;
10261036

include/swift/SIL/Dominance.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ class DominanceInfo : public DominatorTreeBase {
9494

9595
/// Compute a single block's dominance frontier.
9696
///
97-
/// Precondition: no critical edges (OSSA)
97+
/// Precondition: no critical edges
9898
///
9999
/// Postcondition: each block in \p boundary is dominated by \p root and either
100100
/// exits the function or has a single successor which has a predecessor that is

include/swift/SIL/SILBuilder.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -443,6 +443,15 @@ class SILBuilder {
443443
return insert(AllocPackInst::create(getSILDebugLocation(loc), packType,
444444
getFunction()));
445445
}
446+
AllocPackMetadataInst *
447+
createAllocPackMetadata(SILLocation loc,
448+
Optional<SILType> elementType = llvm::None) {
449+
return insert(new (getModule()) AllocPackMetadataInst(
450+
getSILDebugLocation(loc),
451+
elementType.value_or(
452+
SILType::getEmptyTupleType(getModule().getASTContext())
453+
.getAddressType())));
454+
}
446455

447456
AllocRefInst *createAllocRef(SILLocation Loc, SILType ObjectType,
448457
bool objc, bool canAllocOnStack,
@@ -2215,6 +2224,11 @@ class SILBuilder {
22152224
return insert(new (getModule())
22162225
DeallocPackInst(getSILDebugLocation(loc), operand));
22172226
}
2227+
DeallocPackMetadataInst *createDeallocPackMetadata(SILLocation loc,
2228+
SILValue alloc) {
2229+
return insert(new (getModule())
2230+
DeallocPackMetadataInst(getSILDebugLocation(loc), alloc));
2231+
}
22182232
DeallocStackRefInst *createDeallocStackRef(SILLocation Loc,
22192233
SILValue operand) {
22202234
return insert(new (getModule())

include/swift/SIL/SILCloner.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -891,6 +891,14 @@ SILCloner<ImplClass>::visitAllocStackInst(AllocStackInst *Inst) {
891891
recordClonedInstruction(Inst, NewInst);
892892
}
893893

894+
template <typename ImplClass>
895+
void SILCloner<ImplClass>::visitAllocPackMetadataInst(
896+
AllocPackMetadataInst *Inst) {
897+
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
898+
recordClonedInstruction(Inst, getBuilder().createAllocPackMetadata(
899+
getOpLocation(Inst->getLoc())));
900+
}
901+
894902
template<typename ImplClass>
895903
void
896904
SILCloner<ImplClass>::visitAllocPackInst(AllocPackInst *Inst) {
@@ -2844,6 +2852,15 @@ SILCloner<ImplClass>::visitDeallocPackInst(DeallocPackInst *Inst) {
28442852
getOpValue(Inst->getOperand())));
28452853
}
28462854

2855+
template <typename ImplClass>
2856+
void SILCloner<ImplClass>::visitDeallocPackMetadataInst(
2857+
DeallocPackMetadataInst *Inst) {
2858+
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
2859+
recordClonedInstruction(
2860+
Inst, getBuilder().createDeallocPackMetadata(
2861+
getOpLocation(Inst->getLoc()), Inst->getOperand()));
2862+
}
2863+
28472864
template<typename ImplClass>
28482865
void
28492866
SILCloner<ImplClass>::visitDeallocRefInst(DeallocRefInst *Inst) {

include/swift/SIL/SILFunction.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,11 @@ enum ForceEnableLexicalLifetimes_t {
7575
DoForceEnableLexicalLifetimes
7676
};
7777

78+
enum UseStackForPackMetadata_t {
79+
DoNotUseStackForPackMetadata,
80+
DoUseStackForPackMetadata,
81+
};
82+
7883
enum class PerformanceConstraints : uint8_t {
7984
None = 0,
8085
NoAllocation = 1,
@@ -411,6 +416,10 @@ class SILFunction
411416
/// If true, the function has lexical lifetimes even if the module does not.
412417
unsigned ForceEnableLexicalLifetimes : 1;
413418

419+
/// If true, the function contains an instruction that prevents stack nesting
420+
/// from running with pack metadata markers in place.
421+
unsigned UseStackForPackMetadata : 1;
422+
414423
static void
415424
validateSubclassScope(SubclassScope scope, IsThunk_t isThunk,
416425
const GenericSpecializationInformation *genericInfo) {
@@ -686,6 +695,14 @@ class SILFunction
686695
ForceEnableLexicalLifetimes = value;
687696
}
688697

698+
UseStackForPackMetadata_t useStackForPackMetadata() const {
699+
return UseStackForPackMetadata_t(UseStackForPackMetadata);
700+
}
701+
702+
void setUseStackForPackMetadata(UseStackForPackMetadata_t value) {
703+
UseStackForPackMetadata = value;
704+
}
705+
689706
/// Returns true if this is a reabstraction thunk of escaping function type
690707
/// whose single argument is a potentially non-escaping closure. i.e. the
691708
/// thunks' function argument may itself have @inout_aliasable parameters.

include/swift/SIL/SILInstruction.h

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -821,6 +821,10 @@ class SILInstruction : public llvm::ilist_node<SILInstruction> {
821821
/// The first operand must be the allocating instruction.
822822
bool isDeallocatingStack() const;
823823

824+
/// Whether IRGen lowering of this instruction may result in emitting packs of
825+
/// metadata or witness tables.
826+
bool mayRequirePackMetadata() const;
827+
824828
/// Create a new copy of this instruction, which retains all of the operands
825829
/// and other information of this one. If an insertion point is specified,
826830
/// then the new instruction is inserted before the specified point, otherwise
@@ -2275,6 +2279,27 @@ class AllocPackInst final
22752279
}
22762280
};
22772281

2282+
/// AllocPackMetadataInst - Marker instruction indicating that the next
2283+
/// instruction might allocate on-stack pack metadata
2284+
/// during IRGen.
2285+
///
2286+
/// Only valid in lowered SIL.
2287+
class AllocPackMetadataInst final
2288+
: public NullaryInstructionWithTypeDependentOperandsBase<
2289+
SILInstructionKind::AllocPackMetadataInst, AllocPackMetadataInst,
2290+
AllocationInst> {
2291+
friend SILBuilder;
2292+
2293+
AllocPackMetadataInst(SILDebugLocation loc, SILType elementType)
2294+
: NullaryInstructionWithTypeDependentOperandsBase(
2295+
loc, {}, elementType.getAddressType()) {}
2296+
2297+
public:
2298+
/// The instruction which may trigger on-stack pack metadata when IRGen
2299+
/// lowering.
2300+
SILInstruction *getIntroducer() { return getNextInstruction(); }
2301+
};
2302+
22782303
/// The base class for AllocRefInst and AllocRefDynamicInst.
22792304
///
22802305
/// The first NumTailTypes operands are counts for the tail allocated
@@ -8642,6 +8667,27 @@ class DeallocPackInst :
86428667
: UnaryInstructionBase(debugLoc, operand) {}
86438668
};
86448669

8670+
/// DeallocPackMetadataInst - Deallocate stack memory allocated on behalf of the
8671+
/// operand by IRGen.
8672+
///
8673+
/// Only valid in lowered SIL.
8674+
class DeallocPackMetadataInst final
8675+
: public UnaryInstructionBase<SILInstructionKind::DeallocPackMetadataInst,
8676+
DeallocationInst> {
8677+
friend SILBuilder;
8678+
8679+
DeallocPackMetadataInst(SILDebugLocation debugLoc, SILValue alloc)
8680+
: UnaryInstructionBase(debugLoc, alloc) {}
8681+
8682+
public:
8683+
AllocPackMetadataInst *getAllocation() {
8684+
return cast<AllocPackMetadataInst>(getOperand().getDefiningInstruction());
8685+
}
8686+
/// The instruction which may trigger on-stack pack metadata when IRGen
8687+
/// lowering.
8688+
SILInstruction *getIntroducer() { return getAllocation()->getIntroducer(); }
8689+
};
8690+
86458691
/// Like DeallocStackInst, but for `alloc_ref [stack]`.
86468692
class DeallocStackRefInst
86478693
: public UnaryInstructionBase<SILInstructionKind::DeallocStackRefInst,

0 commit comments

Comments
 (0)