Skip to content

Commit d2fad71

Browse files
authored
Merge pull request #42589 from jckarter/begin-partial-apply-simplification-pass
[SIL] Initial work on PartialApplySimplification pass
2 parents d292a85 + 1f30a54 commit d2fad71

28 files changed

+1382
-45
lines changed

include/swift/AST/Attr.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ TYPE_ATTR(pseudogeneric)
8484
TYPE_ATTR(yields)
8585
TYPE_ATTR(yield_once)
8686
TYPE_ATTR(yield_many)
87+
TYPE_ATTR(captures_generics)
8788

8889
// SIL metatype attributes.
8990
TYPE_ATTR(thin)

include/swift/AST/SILLayout.h

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -89,14 +89,17 @@ class SILLayout final : public llvm::FoldingSetNode,
8989

9090
enum : unsigned {
9191
IsMutable = 0x1,
92+
CapturesGenericEnvironment = 0x2,
9293
};
9394

94-
static constexpr const unsigned NumFlags = 1;
95+
static constexpr const unsigned NumFlags = 2;
9596

96-
static unsigned getFlagsValue(bool Mutable) {
97+
static unsigned getFlagsValue(bool Mutable, bool CapturesGenerics) {
9798
unsigned flags = 0;
9899
if (Mutable)
99100
flags |= IsMutable;
101+
if (CapturesGenerics)
102+
flags |= CapturesGenericEnvironment;
100103

101104
assert(flags >> NumFlags == 0
102105
&& "more flags than flag bits?!");
@@ -109,15 +112,17 @@ class SILLayout final : public llvm::FoldingSetNode,
109112
unsigned NumFields;
110113

111114
SILLayout(CanGenericSignature Signature,
112-
ArrayRef<SILField> Fields);
115+
ArrayRef<SILField> Fields,
116+
bool CapturesGenericEnvironment);
113117

114118
SILLayout(const SILLayout &) = delete;
115119
SILLayout &operator=(const SILLayout &) = delete;
116120
public:
117121
/// Get or create a layout.
118122
static SILLayout *get(ASTContext &C,
119123
CanGenericSignature Generics,
120-
ArrayRef<SILField> Fields);
124+
ArrayRef<SILField> Fields,
125+
bool CapturesGenericEnvironment);
121126

122127
/// Get the generic signature in which this layout exists.
123128
CanGenericSignature getGenericSignature() const {
@@ -129,6 +134,12 @@ class SILLayout final : public llvm::FoldingSetNode,
129134
return GenericSigAndFlags.getInt() & IsMutable;
130135
}
131136

137+
/// True if the layout captures the generic arguments it is substituted with
138+
/// and can provide generic bindings when passed as a closure argument.
139+
bool capturesGenericEnvironment() const {
140+
return GenericSigAndFlags.getInt() & CapturesGenericEnvironment;
141+
}
142+
132143
/// Get the fields inside the layout.
133144
ArrayRef<SILField> getFields() const {
134145
return llvm::makeArrayRef(getTrailingObjects<SILField>(), NumFields);
@@ -137,11 +148,13 @@ class SILLayout final : public llvm::FoldingSetNode,
137148
/// Produce a profile of this layout, for use in a folding set.
138149
static void Profile(llvm::FoldingSetNodeID &id,
139150
CanGenericSignature Generics,
140-
ArrayRef<SILField> Fields);
151+
ArrayRef<SILField> Fields,
152+
bool CapturesGenericEnvironment);
141153

142154
/// Produce a profile of this locator, for use in a folding set.
143155
void Profile(llvm::FoldingSetNodeID &id) {
144-
Profile(id, getGenericSignature(), getFields());
156+
Profile(id, getGenericSignature(), getFields(),
157+
capturesGenericEnvironment());
145158
}
146159
};
147160

include/swift/SIL/SILBuilder.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -420,14 +420,15 @@ class SILBuilder {
420420

421421
AllocBoxInst *createAllocBox(SILLocation Loc, CanSILBoxType BoxType,
422422
Optional<SILDebugVariable> Var = None,
423-
bool hasDynamicLifetime = false) {
423+
bool hasDynamicLifetime = false,
424+
bool reflection = false) {
424425
llvm::SmallString<4> Name;
425426
Loc.markAsPrologue();
426427
assert((!dyn_cast_or_null<VarDecl>(Loc.getAsASTNode<Decl>()) || Var) &&
427428
"location is a VarDecl, but SILDebugVariable is empty");
428429
return insert(AllocBoxInst::create(getSILDebugLocation(Loc), BoxType, *F,
429430
substituteAnonymousArgs(Name, Var, Loc),
430-
hasDynamicLifetime));
431+
hasDynamicLifetime, reflection));
431432
}
432433

433434
AllocExistentialBoxInst *

include/swift/SIL/SILInstruction.h

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -461,11 +461,11 @@ class SILInstruction : public llvm::ilist_node<SILInstruction> {
461461
locationStorage = loc.storage;
462462
}
463463

464-
/// Return the next instruction or nullptr if this is the last instruction in
465-
/// its block.
464+
/// Return the previous instruction, or nullptr if this is the first
465+
/// instruction in its block.
466466
SILInstruction *getPreviousInstruction();
467467

468-
/// Return the previous instruction or nullptr if this is the first
468+
/// Return the next instruction, or nullptr if this is the final
469469
/// instruction in its block.
470470
SILInstruction *getNextInstruction();
471471

@@ -2289,30 +2289,38 @@ class AllocRefDynamicInst final
22892289
class AllocBoxInst final
22902290
: public InstructionBaseWithTrailingOperands<
22912291
SILInstructionKind::AllocBoxInst,
2292-
AllocBoxInst, AllocationInst, char> {
2292+
AllocBoxInst, AllocationInst, char>
2293+
{
22932294
friend SILBuilder;
22942295

22952296
TailAllocatedDebugVariable VarInfo;
22962297

2297-
bool dynamicLifetime = false;
2298+
unsigned HasDynamicLifetime : 1;
2299+
unsigned Reflection : 1;
22982300

22992301
AllocBoxInst(SILDebugLocation DebugLoc, CanSILBoxType BoxType,
23002302
ArrayRef<SILValue> TypeDependentOperands, SILFunction &F,
2301-
Optional<SILDebugVariable> Var, bool hasDynamicLifetime);
2303+
Optional<SILDebugVariable> Var, bool hasDynamicLifetime,
2304+
bool reflection = false);
23022305

23032306
static AllocBoxInst *create(SILDebugLocation Loc, CanSILBoxType boxType,
23042307
SILFunction &F,
23052308
Optional<SILDebugVariable> Var,
2306-
bool hasDynamicLifetime);
2309+
bool hasDynamicLifetime,
2310+
bool reflection = false);
23072311

23082312
public:
23092313
CanSILBoxType getBoxType() const {
23102314
return getType().castTo<SILBoxType>();
23112315
}
23122316

2313-
void setDynamicLifetime() { dynamicLifetime = true; }
2314-
bool hasDynamicLifetime() const { return dynamicLifetime; }
2317+
void setDynamicLifetime() { HasDynamicLifetime = true; }
2318+
bool hasDynamicLifetime() const { return HasDynamicLifetime; }
23152319

2320+
/// True if the box should be emitted with reflection metadata for its
2321+
/// contents.
2322+
bool emitReflectionMetadata() const { return Reflection; }
2323+
23162324
// Return the type of the memory stored in the alloc_box.
23172325
SILType getAddressType() const;
23182326

include/swift/SIL/SILType.h

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -427,7 +427,13 @@ class SILType {
427427

428428
/// True if the given type has at least the size and alignment of a native
429429
/// pointer.
430-
bool isPointerSizeAndAligned();
430+
bool isPointerSizeAndAligned(SILModule &M,
431+
ResilienceExpansion expansion) const;
432+
433+
/// True if the layout of the given type consists of a single native Swift-
434+
/// refcounted object reference, possibly nullable.
435+
bool isSingleSwiftRefcounted(SILModule &M,
436+
ResilienceExpansion expansion) const;
431437

432438
/// True if `operTy` can be cast by single-reference value into `resultTy`.
433439
static bool canRefCast(SILType operTy, SILType resultTy, SILModule &M);
@@ -613,6 +619,12 @@ class SILType {
613619
llvm::hash_code getHashCode() const {
614620
return llvm::hash_combine(*this);
615621
}
622+
623+
/// If a type is visibly a singleton aggregate (a tuple with one element, a
624+
/// struct with one field, or an enum with a single payload case), return the
625+
/// type of its field, which it is guaranteed to have identical layout to.
626+
SILType getSingletonAggregateFieldType(SILModule &M,
627+
ResilienceExpansion expansion) const;
616628

617629
//
618630
// Accessors for types used in SIL instructions:

include/swift/SILOptimizer/PassManager/Passes.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -446,6 +446,8 @@ PASS(MoveFunctionCanonicalization, "sil-move-function-canon",
446446
"function checking.")
447447
PASS(DebugInfoCanonicalizer, "sil-onone-debuginfo-canonicalizer",
448448
"Canonicalize debug info at -Onone by propagating debug info into coroutine funclets")
449+
PASS(PartialApplySimplification, "partial-apply-simplification",
450+
"Transform partial_apply instructions into explicit closure box constructions")
449451
PASS(PruneVTables, "prune-vtables",
450452
"Mark class methods that do not require vtable dispatch")
451453
PASS_RANGE(AllPasses, AADumper, PruneVTables)

lib/AST/ASTContext.cpp

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5374,10 +5374,17 @@ std::string ASTContext::getEntryPointFunctionName() const {
53745374

53755375
SILLayout *SILLayout::get(ASTContext &C,
53765376
CanGenericSignature Generics,
5377-
ArrayRef<SILField> Fields) {
5377+
ArrayRef<SILField> Fields,
5378+
bool CapturesGenericEnvironment) {
5379+
// The "captures generic environment" flag is meaningless if there are
5380+
// no generic arguments to capture.
5381+
if (!Generics || Generics->areAllParamsConcrete()) {
5382+
CapturesGenericEnvironment = false;
5383+
}
5384+
53785385
// Profile the layout parameters.
53795386
llvm::FoldingSetNodeID id;
5380-
Profile(id, Generics, Fields);
5387+
Profile(id, Generics, Fields, CapturesGenericEnvironment);
53815388

53825389
// Return an existing layout if there is one.
53835390
void *insertPos;
@@ -5390,7 +5397,8 @@ SILLayout *SILLayout::get(ASTContext &C,
53905397
void *memory = C.Allocate(totalSizeToAlloc<SILField>(Fields.size()),
53915398
alignof(SILLayout));
53925399

5393-
auto newLayout = ::new (memory) SILLayout(Generics, Fields);
5400+
auto newLayout = ::new (memory) SILLayout(Generics, Fields,
5401+
CapturesGenericEnvironment);
53945402
Layouts.InsertNode(newLayout, insertPos);
53955403
return newLayout;
53965404
}
@@ -5423,7 +5431,8 @@ CanSILBoxType SILBoxType::get(CanType boxedType) {
54235431
auto genericParam = singleGenericParamSignature.getGenericParams()[0];
54245432
auto layout = SILLayout::get(ctx, singleGenericParamSignature,
54255433
SILField(CanType(genericParam),
5426-
/*mutable*/ true));
5434+
/*mutable*/ true),
5435+
/*captures generic env*/ false);
54275436

54285437
auto subMap =
54295438
SubstitutionMap::get(

lib/AST/ASTDemangler.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -710,7 +710,8 @@ Type ASTBuilder::createSILBoxTypeWithLayout(
710710
silFields.emplace_back(field.getPointer()->getCanonicalType(),
711711
field.getInt());
712712
SILLayout *layout =
713-
SILLayout::get(Ctx, signature.getCanonicalSignature(), silFields);
713+
SILLayout::get(Ctx, signature.getCanonicalSignature(), silFields,
714+
/*captures generics*/ false);
714715

715716
SubstitutionMap substs;
716717
if (signature)

lib/AST/ASTPrinter.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6085,6 +6085,11 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
60856085
}
60866086

60876087
void visitSILBoxType(SILBoxType *T) {
6088+
// Print attributes.
6089+
if (T->getLayout()->capturesGenericEnvironment()) {
6090+
Printer << "@captures_generics ";
6091+
}
6092+
60886093
{
60896094
// A box layout has its own independent generic environment. Don't try
60906095
// to print it with the environment's generic params.

lib/AST/SILLayout.cpp

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,10 @@ static void verifyFields(CanGenericSignature Sig, ArrayRef<SILField> Fields) {
7272
#endif
7373

7474
SILLayout::SILLayout(CanGenericSignature Sig,
75-
ArrayRef<SILField> Fields)
76-
: GenericSigAndFlags(Sig, getFlagsValue(anyMutable(Fields))),
75+
ArrayRef<SILField> Fields,
76+
bool CapturesGenericEnvironment)
77+
: GenericSigAndFlags(Sig,
78+
getFlagsValue(anyMutable(Fields), CapturesGenericEnvironment)),
7779
NumFields(Fields.size())
7880
{
7981
#ifndef NDEBUG
@@ -87,8 +89,10 @@ SILLayout::SILLayout(CanGenericSignature Sig,
8789

8890
void SILLayout::Profile(llvm::FoldingSetNodeID &id,
8991
CanGenericSignature Generics,
90-
ArrayRef<SILField> Fields) {
92+
ArrayRef<SILField> Fields,
93+
bool CapturesGenericEnvironment) {
9194
id.AddPointer(Generics.getPointer());
95+
id.AddBoolean(CapturesGenericEnvironment);
9296
for (auto &field : Fields) {
9397
id.AddPointer(field.getLoweredType().getPointer());
9498
id.AddBoolean(field.isMutable());

0 commit comments

Comments
 (0)