Skip to content

Commit 53745e6

Browse files
authored
Merge pull request #8961 from swiftix/open-archtypes-tracker-fixes
[sil-opened-archetype-tracker] Improve tracking of archetypes in SILBuilder
2 parents 9712830 + 202de40 commit 53745e6

File tree

6 files changed

+163
-16
lines changed

6 files changed

+163
-16
lines changed

include/swift/SIL/SILBuilder.h

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -153,8 +153,7 @@ class SILBuilder {
153153
if (InsertPt == BB->end())
154154
return;
155155
// Set the opened archetype context from the instruction.
156-
this->getOpenedArchetypes().addOpenedArchetypeOperands(
157-
InsertPt->getTypeDependentOperands());
156+
addOpenedArchetypeOperands(&*InsertPt);
158157
}
159158

160159
/// setInsertionPoint - Set the insertion point to insert before the specified
@@ -200,10 +199,7 @@ class SILBuilder {
200199
//===--------------------------------------------------------------------===//
201200
// Opened archetypes handling
202201
//===--------------------------------------------------------------------===//
203-
void addOpenedArchetypeOperands(SILInstruction *I) {
204-
getOpenedArchetypes().addOpenedArchetypeOperands(
205-
I->getTypeDependentOperands());
206-
}
202+
void addOpenedArchetypeOperands(SILInstruction *I);
207203

208204
//===--------------------------------------------------------------------===//
209205
// Type remapping

include/swift/SIL/SILOpenedArchetypesTracker.h

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -78,16 +78,19 @@ class SILOpenedArchetypesTracker : public DeleteNotificationHandler {
7878
// Can be used to incrementally populate the mapping, e.g.
7979
// if it is done when performing a scan of all instructions
8080
// inside a function.
81-
void registerOpenedArchetypes(const SILInstruction *I);
81+
// Returns true if any opened archetypes were registered.
82+
bool registerOpenedArchetypes(const SILInstruction *I);
8283

8384
// Register opened archetypes whose definitions are referenced by
8485
// the typedef operands of this instruction.
85-
void registerUsedOpenedArchetypes(const SILInstruction *I);
86+
// Returns true if any opened archetypes were registered.
87+
bool registerUsedOpenedArchetypes(const SILInstruction *I);
8688

8789
// Register opened archetypes referenced by this type, if they
8890
// are not registered yet. Create placeholders representing forward
8991
// definitions of these opened archetypes.
90-
void registerUsedOpenedArchetypes(CanType Ty);
92+
// Returns true if any opened archetypes were registered.
93+
bool registerUsedOpenedArchetypes(CanType Ty);
9194

9295
// Unregister archetypes opened by a given instruction.
9396
// Should be only called when this instruction is to be removed.

lib/SIL/SILBuilder.cpp

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -344,3 +344,40 @@ SILValue SILBuilder::emitObjCToThickMetatype(SILLocation Loc, SILValue Op,
344344
// Just create the objc_to_thick_metatype instruction.
345345
return createObjCToThickMetatype(Loc, Op, Ty);
346346
}
347+
348+
/// Add opned archetypes defined or used by the current instruction.
349+
/// If there are no such opened archetypes in the current instruction
350+
/// and it is an instruction with just one operand, try to perform
351+
/// the same action for the instruction defining an operand, because
352+
/// it may have some opened archetypes used or defined.
353+
void SILBuilder::addOpenedArchetypeOperands(SILInstruction *I) {
354+
// The list of archetypes from the previous instruction needs
355+
// to be replaced, because it may reference a removed instruction.
356+
OpenedArchetypes.addOpenedArchetypeOperands(I->getTypeDependentOperands());
357+
if (I && I->getNumTypeDependentOperands() > 0)
358+
return;
359+
360+
while (I && I->getNumOperands() == 1 &&
361+
I->getNumTypeDependentOperands() == 0) {
362+
I = dyn_cast<SILInstruction>(I->getOperand(0));
363+
if (!I)
364+
return;
365+
// If it is a definition of an opened archetype,
366+
// register it and exit.
367+
auto Archetype = getOpenedArchetypeOf(I);
368+
if (!Archetype)
369+
continue;
370+
auto Def = OpenedArchetypes.getOpenedArchetypeDef(Archetype);
371+
// Return if it is a known open archetype.
372+
if (Def)
373+
return;
374+
// Otherwise register it and return.
375+
if (OpenedArchetypesTracker)
376+
OpenedArchetypesTracker->addOpenedArchetypeDef(Archetype, I);
377+
return;
378+
}
379+
380+
if (I && I->getNumTypeDependentOperands() > 0) {
381+
OpenedArchetypes.addOpenedArchetypeOperands(I->getTypeDependentOperands());
382+
}
383+
}

lib/SIL/SILOpenedArchetypesTracker.cpp

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -39,10 +39,11 @@ bool SILOpenedArchetypesTracker::hasUnresolvedOpenedArchetypeDefinitions() {
3939
return false;
4040
}
4141

42-
void SILOpenedArchetypesTracker::registerUsedOpenedArchetypes(CanType Ty) {
42+
bool SILOpenedArchetypesTracker::registerUsedOpenedArchetypes(CanType Ty) {
43+
bool Registered = false;
4344
// Nothing else to be done if the type does not contain an opened archetype.
4445
if (!Ty || !Ty->hasOpenedExistential())
45-
return;
46+
return Registered;
4647

4748
// Find all opened existentials used by this type and check if their
4849
// definitions are known.
@@ -64,33 +65,39 @@ void SILOpenedArchetypesTracker::registerUsedOpenedArchetypes(CanType Ty) {
6465
// archetype can be constructed.
6566
addOpenedArchetypeDef(archetypeTy, Placeholder);
6667
});
68+
return Registered;
6769
}
6870

6971
// Register archetypes opened by a given instruction.
7072
// Can be used to incrementally populate the mapping, e.g.
7173
// if it is done when performing a scan of all instructions
7274
// inside a function.
73-
void SILOpenedArchetypesTracker::registerOpenedArchetypes(
75+
bool SILOpenedArchetypesTracker::registerOpenedArchetypes(
7476
const SILInstruction *I) {
7577
assert((!I->getParent() || I->getFunction() == &F) &&
7678
"Instruction does not belong to a proper SILFunction");
7779
auto Archetype = getOpenedArchetypeOf(I);
78-
if (Archetype)
79-
addOpenedArchetypeDef(Archetype, I);
80+
if (!Archetype)
81+
return false;
82+
addOpenedArchetypeDef(Archetype, I);
83+
return true;
8084
}
8185

8286
// Register opened archetypes whose definitions are referenced by
8387
// the typedef operands of this instruction.
84-
void SILOpenedArchetypesTracker::registerUsedOpenedArchetypes(
88+
bool SILOpenedArchetypesTracker::registerUsedOpenedArchetypes(
8589
const SILInstruction *I) {
8690
assert((!I->getParent() || I->getFunction() == &F) &&
8791
"Instruction does not belong to a proper SILFunction");
92+
bool Registered = false;
8893
for (auto &Op : I->getTypeDependentOperands()) {
8994
auto OpenedArchetypeDef = Op.get();
9095
if (auto *DefInst = dyn_cast<SILInstruction>(OpenedArchetypeDef)) {
9196
addOpenedArchetypeDef(getOpenedArchetypeOf(DefInst), OpenedArchetypeDef);
97+
Registered = true;
9298
}
9399
}
100+
return Registered;
94101
}
95102

96103
// Unregister archetypes opened by a given instruction.

lib/SILOptimizer/Transforms/OwnershipModelEliminator.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,13 @@ namespace {
3939
struct OwnershipModelEliminatorVisitor
4040
: SILInstructionVisitor<OwnershipModelEliminatorVisitor, bool> {
4141
SILBuilder &B;
42+
SILOpenedArchetypesTracker OpenedArchetypesTracker;
43+
44+
OwnershipModelEliminatorVisitor(SILBuilder &B)
45+
: B(B), OpenedArchetypesTracker(B.getFunction()) {
46+
B.setOpenedArchetypesTracker(&OpenedArchetypesTracker);
47+
}
4248

43-
OwnershipModelEliminatorVisitor(SILBuilder &B) : B(B) {}
4449
void beforeVisit(ValueBase *V) {
4550
auto *I = cast<SILInstruction>(V);
4651
B.setInsertionPoint(I);

test/SILOptimizer/opened_archetype_operands_tracking.sil

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,3 +130,102 @@ bb0(%0 : $*View, %1 : $@thin DynamicItem.Type):
130130
dealloc_stack %2 : $*DynamicItem
131131
return %9 : $DynamicItem
132132
}
133+
134+
func use<T>(_ t: T)
135+
136+
final class Foo<T> where T : P {
137+
init(_ x: T)
138+
@sil_stored final var x: T { get set }
139+
@sil_stored final var y: T { get set }
140+
deinit
141+
}
142+
143+
extension P {
144+
@inline(__always) func foo()
145+
}
146+
147+
public func bar(_ p: P)
148+
149+
// Foo.__allocating_init(_:)
150+
sil @Foo_alloc_init : $@convention(method) <T where T : P> (@in T, @thick Foo<T>.Type) -> @owned Foo<T> {
151+
bb0(%0 : $*T, %1 : $@thick Foo<T>.Type):
152+
%2 = alloc_ref $Foo<T>
153+
// function_ref Foo.init(_:)
154+
%3 = function_ref @Foo_init : $@convention(method) <τ_0_0 where τ_0_0 : P> (@in τ_0_0, @owned Foo<τ_0_0>) -> @owned Foo<τ_0_0>
155+
%4 = apply %3<T>(%0, %2) : $@convention(method) <τ_0_0 where τ_0_0 : P> (@in τ_0_0, @owned Foo<τ_0_0>) -> @owned Foo<τ_0_0>
156+
return %4 : $Foo<T>
157+
} // end sil function 'Foo_alloc_init'
158+
159+
// Foo.init(_:)
160+
sil @Foo_init : $@convention(method) <T where T : P> (@in T, @owned Foo<T>) -> @owned Foo<T> {
161+
bb0(%0 : $*T, %1 : $Foo<T>):
162+
%4 = alloc_stack $T
163+
copy_addr %0 to [initialization] %4 : $*T
164+
%6 = ref_element_addr %1 : $Foo<T>, #Foo.x
165+
copy_addr [take] %4 to [initialization] %6 : $*T
166+
dealloc_stack %4 : $*T
167+
%9 = alloc_stack $T
168+
copy_addr %0 to [initialization] %9 : $*T
169+
%11 = ref_element_addr %1 : $Foo<T>, #Foo.y
170+
copy_addr [take] %9 to [initialization] %11 : $*T
171+
dealloc_stack %9 : $*T
172+
destroy_addr %0 : $*T
173+
return %1 : $Foo<T>
174+
} // end sil function 'Foo_init'
175+
176+
// P.foo()
177+
sil [always_inline] @P_foo : $@convention(method) <Self where Self : P> (@in_guaranteed Self) -> () {
178+
bb0(%0 : $*Self):
179+
// function_ref Foo.__allocating_init(_:)
180+
%2 = function_ref @Foo_alloc_init : $@convention(method) <τ_0_0 where τ_0_0 : P> (@in τ_0_0, @thick Foo<τ_0_0>.Type) -> @owned Foo<τ_0_0>
181+
%3 = metatype $@thick Foo<Self>.Type
182+
%4 = alloc_stack $Self
183+
copy_addr %0 to [initialization] %4 : $*Self
184+
%6 = apply %2<Self>(%4, %3) : $@convention(method) <τ_0_0 where τ_0_0 : P> (@in τ_0_0, @thick Foo<τ_0_0>.Type) -> @owned Foo<τ_0_0>
185+
dealloc_stack %4 : $*Self
186+
// function_ref use
187+
%9 = function_ref @use : $@convention(thin) <τ_0_0> (@in τ_0_0) -> ()
188+
%10 = ref_element_addr %6 : $Foo<Self>, #Foo.x
189+
%11 = alloc_stack $Self
190+
copy_addr %10 to [initialization] %11 : $*Self
191+
%13 = apply %9<Self>(%11) : $@convention(thin) <τ_0_0> (@in τ_0_0) -> ()
192+
dealloc_stack %11 : $*Self
193+
// function_ref use
194+
%15 = function_ref @use : $@convention(thin) <τ_0_0> (@in τ_0_0) -> ()
195+
%16 = ref_element_addr %6 : $Foo<Self>, #Foo.y
196+
%17 = alloc_stack $Self
197+
copy_addr %16 to [initialization] %17 : $*Self
198+
%19 = apply %15<Self>(%17) : $@convention(thin) <τ_0_0> (@in τ_0_0) -> ()
199+
dealloc_stack %17 : $*Self
200+
strong_release %6 : $Foo<Self>
201+
%22 = tuple ()
202+
return %22 : $()
203+
} // end sil function 'P_foo'
204+
205+
// use
206+
sil hidden_external @use : $@convention(thin) <τ_0_0> (@in τ_0_0) -> ()
207+
208+
// Check that everything besides the external function use is inlined into bar.
209+
// It should contain alloc_ref and alloc_stack instructions using opened archetypes.
210+
// CHECK-LABEL: sil @bar
211+
// CHECK: open_existential{{.*}}C08045E0-2779-11E7-970E-A45E60E99281
212+
// CHECK: alloc_ref{{.*}}C08045E0-2779-11E7-970E-A45E60E99281
213+
// CHECK: alloc_stack{{.*}}C08045E0-2779-11E7-970E-A45E60E99281
214+
// CHECK-NOT: function_ref @use
215+
// CHECK: function_ref @use
216+
// CHECK-NOT: function_ref
217+
// CHECK: dealloc_stack{{.*}}C08045E0-2779-11E7-970E-A45E60E99281
218+
// CHECK: strong_release{{.*}}C08045E0-2779-11E7-970E-A45E60E99281
219+
// CHECK: dealloc_ref{{.*}}C08045E0-2779-11E7-970E-A45E60E99281
220+
// CHECK: end sil function 'bar'
221+
sil @bar : $@convention(thin) (@in P) -> () {
222+
bb0(%0 : $*P):
223+
%2 = open_existential_addr immutable_access %0 : $*P to $*@opened("C08045E0-2779-11E7-970E-A45E60E99281") P
224+
// function_ref P.foo()
225+
%3 = function_ref @P_foo : $@convention(method) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> ()
226+
%4 = apply %3<@opened("C08045E0-2779-11E7-970E-A45E60E99281") P>(%2) : $@convention(method) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> ()
227+
destroy_addr %0 : $*P
228+
%6 = tuple ()
229+
return %6 : $()
230+
} // end sil function 'bar'
231+

0 commit comments

Comments
 (0)