Skip to content

Commit 4ef135c

Browse files
authored
Merge pull request #66201 from nate-chandler/dealloc-on-stack-packs
[IRGen] Dealloc on-stack metadata/wtable packs on the dominance frontier.
2 parents 44a4097 + c5699c9 commit 4ef135c

Some content is hidden

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

47 files changed

+1264
-107
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
@@ -173,6 +173,12 @@ class SILOptions {
173173
/// Require linear OSSA lifetimes after SILGen
174174
bool OSSACompleteLifetimes = false;
175175

176+
/// Enable pack metadata stack "promotion".
177+
///
178+
/// More accurately, enable skipping mandatory heapification of pack metadata
179+
/// when possible.
180+
bool EnablePackMetadataStackPromotion = true;
181+
176182
// The kind of function bodies to skip emitting.
177183
FunctionBodySkipping SkipFunctionBodies = FunctionBodySkipping::None;
178184

include/swift/AST/Types.h

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,10 @@ class RecursiveTypeProperties {
179179
/// they have a type variable originator.
180180
SolverAllocated = 0x8000,
181181

182-
Last_Property = SolverAllocated
182+
/// This type contains a concrete pack.
183+
HasConcretePack = 0x10000,
184+
185+
Last_Property = HasConcretePack
183186
};
184187
enum { BitWidth = countBitsUsed(Property::Last_Property) };
185188

@@ -255,6 +258,8 @@ class RecursiveTypeProperties {
255258

256259
bool hasParameterPack() const { return Bits & HasParameterPack; }
257260

261+
bool hasConcretePack() const { return Bits & HasConcretePack; }
262+
258263
/// Does a type with these properties structurally contain a
259264
/// parameterized existential type?
260265
bool hasParameterizedExistential() const {
@@ -412,12 +417,12 @@ class alignas(1 << TypeAlignInBits) TypeBase
412417
NumProtocols : 16
413418
);
414419

415-
SWIFT_INLINE_BITFIELD_FULL(TypeVariableType, TypeBase, 7+31,
420+
SWIFT_INLINE_BITFIELD_FULL(TypeVariableType, TypeBase, 7+30,
416421
/// Type variable options.
417422
Options : 7,
418423
: NumPadBits,
419424
/// The unique number assigned to this type variable.
420-
ID : 31
425+
ID : 30
421426
);
422427

423428
SWIFT_INLINE_BITFIELD(SILFunctionType, TypeBase, NumSILExtInfoBits+1+4+1+2+1+1,
@@ -684,6 +689,13 @@ class alignas(1 << TypeAlignInBits) TypeBase
684689
return getRecursiveProperties().hasParameterPack();
685690
}
686691

692+
bool hasConcretePack() const {
693+
return getRecursiveProperties().hasConcretePack();
694+
}
695+
696+
/// Whether the type has some flavor of pack.
697+
bool hasPack() const { return hasParameterPack() || hasConcretePack(); }
698+
687699
/// Determine whether the type involves a parameterized existential type.
688700
bool hasParameterizedExistential() const {
689701
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
@@ -1028,6 +1028,16 @@ def force_struct_type_layouts : Flag<["-"], "force-struct-type-layouts">,
10281028
def enable_layout_string_value_witnesses : Flag<["-"], "enable-layout-string-value-witnesses">,
10291029
HelpText<"Enable layout string based value witnesses">;
10301030

1031+
let Flags = [FrontendOption, NoDriverOption, HelpHidden, ModuleInterfaceOptionIgnorable] in {
1032+
def enable_pack_metadata_stack_promotion :
1033+
Joined<["-"], "enable-pack-metadata-stack-promotion=">,
1034+
HelpText<"Whether to skip heapifying stack metadata packs when possible.">,
1035+
MetaVarName<"true|false">;
1036+
def enable_pack_metadata_stack_promotion_noArg :
1037+
Flag<["-"], "enable-pack-metadata-stack-promotion">,
1038+
HelpText<"Skip heapifying stack metadata packs when possible.">;
1039+
}
1040+
10311041
def disable_layout_string_value_witnesses : Flag<["-"], "disable-layout-string-value-witnesses">,
10321042
HelpText<"Disable layout string based value witnesses">;
10331043

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
@@ -436,6 +436,15 @@ class SILBuilder {
436436
return insert(AllocPackInst::create(getSILDebugLocation(loc), packType,
437437
getFunction()));
438438
}
439+
AllocPackMetadataInst *
440+
createAllocPackMetadata(SILLocation loc,
441+
Optional<SILType> elementType = llvm::None) {
442+
return insert(new (getModule()) AllocPackMetadataInst(
443+
getSILDebugLocation(loc),
444+
elementType.value_or(
445+
SILType::getEmptyTupleType(getModule().getASTContext())
446+
.getAddressType())));
447+
}
439448

440449
AllocRefInst *createAllocRef(SILLocation Loc, SILType ObjectType,
441450
bool objc, bool canAllocOnStack,
@@ -2226,6 +2235,11 @@ class SILBuilder {
22262235
return insert(new (getModule())
22272236
DeallocPackInst(getSILDebugLocation(loc), operand));
22282237
}
2238+
DeallocPackMetadataInst *createDeallocPackMetadata(SILLocation loc,
2239+
SILValue alloc) {
2240+
return insert(new (getModule())
2241+
DeallocPackMetadataInst(getSILDebugLocation(loc), alloc));
2242+
}
22292243
DeallocStackRefInst *createDeallocStackRef(SILLocation Loc,
22302244
SILValue operand) {
22312245
return insert(new (getModule())

include/swift/SIL/SILCloner.h

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

895+
template <typename ImplClass>
896+
void SILCloner<ImplClass>::visitAllocPackMetadataInst(
897+
AllocPackMetadataInst *Inst) {
898+
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
899+
recordClonedInstruction(Inst, getBuilder().createAllocPackMetadata(
900+
getOpLocation(Inst->getLoc())));
901+
}
902+
895903
template<typename ImplClass>
896904
void
897905
SILCloner<ImplClass>::visitAllocPackInst(AllocPackInst *Inst) {
@@ -2854,6 +2862,15 @@ SILCloner<ImplClass>::visitDeallocPackInst(DeallocPackInst *Inst) {
28542862
getOpValue(Inst->getOperand())));
28552863
}
28562864

2865+
template <typename ImplClass>
2866+
void SILCloner<ImplClass>::visitDeallocPackMetadataInst(
2867+
DeallocPackMetadataInst *Inst) {
2868+
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
2869+
recordClonedInstruction(
2870+
Inst, getBuilder().createDeallocPackMetadata(
2871+
getOpLocation(Inst->getLoc()), Inst->getOperand()));
2872+
}
2873+
28572874
template<typename ImplClass>
28582875
void
28592876
SILCloner<ImplClass>::visitDeallocRefInst(DeallocRefInst *Inst) {

include/swift/SIL/SILFunction.h

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

79+
enum UseStackForPackMetadata_t {
80+
DoNotUseStackForPackMetadata,
81+
DoUseStackForPackMetadata,
82+
};
83+
7984
enum class PerformanceConstraints : uint8_t {
8085
None = 0,
8186
NoAllocation = 1,
@@ -418,6 +423,10 @@ class SILFunction
418423
/// If true, the function has lexical lifetimes even if the module does not.
419424
unsigned ForceEnableLexicalLifetimes : 1;
420425

426+
/// If true, the function contains an instruction that prevents stack nesting
427+
/// from running with pack metadata markers in place.
428+
unsigned UseStackForPackMetadata : 1;
429+
421430
static void
422431
validateSubclassScope(SubclassScope scope, IsThunk_t isThunk,
423432
const GenericSpecializationInformation *genericInfo) {
@@ -693,6 +702,14 @@ class SILFunction
693702
ForceEnableLexicalLifetimes = value;
694703
}
695704

705+
UseStackForPackMetadata_t useStackForPackMetadata() const {
706+
return UseStackForPackMetadata_t(UseStackForPackMetadata);
707+
}
708+
709+
void setUseStackForPackMetadata(UseStackForPackMetadata_t value) {
710+
UseStackForPackMetadata = value;
711+
}
712+
696713
/// Returns true if this is a reabstraction thunk of escaping function type
697714
/// whose single argument is a potentially non-escaping closure. i.e. the
698715
/// 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
@@ -8685,6 +8710,27 @@ class DeallocPackInst :
86858710
: UnaryInstructionBase(debugLoc, operand) {}
86868711
};
86878712

8713+
/// DeallocPackMetadataInst - Deallocate stack memory allocated on behalf of the
8714+
/// operand by IRGen.
8715+
///
8716+
/// Only valid in lowered SIL.
8717+
class DeallocPackMetadataInst final
8718+
: public UnaryInstructionBase<SILInstructionKind::DeallocPackMetadataInst,
8719+
DeallocationInst> {
8720+
friend SILBuilder;
8721+
8722+
DeallocPackMetadataInst(SILDebugLocation debugLoc, SILValue alloc)
8723+
: UnaryInstructionBase(debugLoc, alloc) {}
8724+
8725+
public:
8726+
AllocPackMetadataInst *getAllocation() {
8727+
return cast<AllocPackMetadataInst>(getOperand().getDefiningInstruction());
8728+
}
8729+
/// The instruction which may trigger on-stack pack metadata when IRGen
8730+
/// lowering.
8731+
SILInstruction *getIntroducer() { return getAllocation()->getIntroducer(); }
8732+
};
8733+
86888734
/// Like DeallocStackInst, but for `alloc_ref [stack]`.
86898735
class DeallocStackRefInst
86908736
: public UnaryInstructionBase<SILInstructionKind::DeallocStackRefInst,

0 commit comments

Comments
 (0)