Skip to content

Commit ed1cd46

Browse files
committed
[ownership] Update devirtualization utilities for ownership.
I discovered this due to the mandatory inliner doing devirtualization. I ported all of the relevant SIL tests to increase code coverage of this code when ownership is enabled.
1 parent 87b66e7 commit ed1cd46

16 files changed

+1919
-70
lines changed

include/swift/SIL/InstructionUtils.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,10 @@ SILValue stripCasts(SILValue V);
4444
/// mark_dependence) from the current SILValue.
4545
SILValue stripCastsWithoutMarkDependence(SILValue V);
4646

47+
/// Return the underlying SILValue after stripping off all copy_value and
48+
/// begin_borrow instructions.
49+
SILValue stripOwnershipInsts(SILValue v);
50+
4751
/// Return the underlying SILValue after stripping off all upcasts from the
4852
/// current SILValue.
4953
SILValue stripUpCasts(SILValue V);

include/swift/SIL/SILBuilder.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2179,6 +2179,13 @@ class SILBuilderWithScope : public SILBuilder {
21792179
: SILBuilder(I, I->getDebugScope(), C)
21802180
{}
21812181

2182+
/// Build instructions before the given insertion point, inheriting the debug
2183+
/// location and using the context from the passed in builder.
2184+
///
2185+
/// Clients should prefer this constructor.
2186+
SILBuilderWithScope(SILInstruction *I, SILBuilder &B)
2187+
: SILBuilder(I, I->getDebugScope(), B.getBuilderContext()) {}
2188+
21822189
explicit SILBuilderWithScope(
21832190
SILInstruction *I,
21842191
SmallVectorImpl<SILInstruction *> *InsertedInstrs = nullptr)

lib/SIL/InstructionUtils.cpp

Lines changed: 72 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -22,15 +22,30 @@
2222

2323
using namespace swift;
2424

25+
SILValue swift::stripOwnershipInsts(SILValue v) {
26+
while (true) {
27+
switch (v->getKind()) {
28+
default:
29+
return v;
30+
case ValueKind::CopyValueInst:
31+
case ValueKind::BeginBorrowInst:
32+
v = cast<SingleValueInstruction>(v)->getOperand(0);
33+
}
34+
}
35+
}
36+
2537
/// Strip off casts/indexing insts/address projections from V until there is
2638
/// nothing left to strip.
2739
/// FIXME: Why don't we strip projections after stripping indexes?
28-
SILValue swift::getUnderlyingObject(SILValue V) {
40+
SILValue swift::getUnderlyingObject(SILValue v) {
2941
while (true) {
30-
SILValue V2 = stripIndexingInsts(stripAddressProjections(stripCasts(V)));
31-
if (V2 == V)
32-
return V2;
33-
V = V2;
42+
SILValue v2 = stripCasts(v);
43+
v2 = stripAddressProjections(v2);
44+
v2 = stripIndexingInsts(v2);
45+
v2 = stripOwnershipInsts(v2);
46+
if (v2 == v)
47+
return v2;
48+
v = v2;
3449
}
3550
}
3651

@@ -56,12 +71,15 @@ SILValue swift::getUnderlyingAddressRoot(SILValue V) {
5671
}
5772

5873

59-
SILValue swift::getUnderlyingObjectStopAtMarkDependence(SILValue V) {
74+
SILValue swift::getUnderlyingObjectStopAtMarkDependence(SILValue v) {
6075
while (true) {
61-
SILValue V2 = stripIndexingInsts(stripAddressProjections(stripCastsWithoutMarkDependence(V)));
62-
if (V2 == V)
63-
return V2;
64-
V = V2;
76+
SILValue v2 = stripCastsWithoutMarkDependence(v);
77+
v2 = stripAddressProjections(v2);
78+
v2 = stripIndexingInsts(v2);
79+
v2 = stripOwnershipInsts(v2);
80+
if (v2 == v)
81+
return v2;
82+
v = v2;
6583
}
6684
}
6785

@@ -138,47 +156,68 @@ SILValue swift::stripCastsWithoutMarkDependence(SILValue V) {
138156
}
139157
}
140158

141-
SILValue swift::stripCasts(SILValue V) {
159+
SILValue swift::stripCasts(SILValue v) {
142160
while (true) {
143-
V = stripSinglePredecessorArgs(V);
161+
v = stripSinglePredecessorArgs(v);
144162

145-
auto K = V->getKind();
146-
if (isRCIdentityPreservingCast(K)
147-
|| K == ValueKind::UncheckedTrivialBitCastInst
148-
|| K == ValueKind::MarkDependenceInst) {
149-
V = cast<SingleValueInstruction>(V)->getOperand(0);
163+
auto k = v->getKind();
164+
if (isRCIdentityPreservingCast(k)
165+
|| k == ValueKind::UncheckedTrivialBitCastInst
166+
|| k == ValueKind::MarkDependenceInst) {
167+
v = cast<SingleValueInstruction>(v)->getOperand(0);
150168
continue;
151169
}
152-
153-
return V;
170+
171+
SILValue v2 = stripOwnershipInsts(v);
172+
if (v2 != v) {
173+
v = v2;
174+
continue;
175+
}
176+
177+
return v;
154178
}
155179
}
156180

157-
SILValue swift::stripUpCasts(SILValue V) {
158-
assert(V->getType().isClassOrClassMetatype() &&
181+
SILValue swift::stripUpCasts(SILValue v) {
182+
assert(v->getType().isClassOrClassMetatype() &&
159183
"Expected class or class metatype!");
160184

161-
V = stripSinglePredecessorArgs(V);
162-
163-
while (auto upcast = dyn_cast<UpcastInst>(V))
164-
V = stripSinglePredecessorArgs(upcast->getOperand());
185+
v = stripSinglePredecessorArgs(v);
165186

166-
return V;
187+
while (true) {
188+
if (auto *ui = dyn_cast<UpcastInst>(v)) {
189+
v = ui->getOperand();
190+
continue;
191+
}
192+
193+
SILValue v2 = stripSinglePredecessorArgs(v);
194+
v2 = stripOwnershipInsts(v2);
195+
if (v2 == v) {
196+
return v2;
197+
}
198+
v = v2;
199+
}
167200
}
168201

169-
SILValue swift::stripClassCasts(SILValue V) {
202+
SILValue swift::stripClassCasts(SILValue v) {
170203
while (true) {
171-
if (auto *UI = dyn_cast<UpcastInst>(V)) {
172-
V = UI->getOperand();
204+
if (auto *ui = dyn_cast<UpcastInst>(v)) {
205+
v = ui->getOperand();
173206
continue;
174207
}
175208

176-
if (auto *UCCI = dyn_cast<UnconditionalCheckedCastInst>(V)) {
177-
V = UCCI->getOperand();
209+
if (auto *ucci = dyn_cast<UnconditionalCheckedCastInst>(v)) {
210+
v = ucci->getOperand();
178211
continue;
179212
}
180-
181-
return V;
213+
214+
SILValue v2 = stripOwnershipInsts(v);
215+
if (v2 != v) {
216+
v = v2;
217+
continue;
218+
}
219+
220+
return v;
182221
}
183222
}
184223

0 commit comments

Comments
 (0)