Skip to content

Commit d73a081

Browse files
committed
Add pointer escape and dependent use tracking to InteriorLiveness
Rig TransitiveAddressWalker to keep track of enough information for passes to correctly check for pointer escapes and dependence uses. Requires for precise bail-outs and asserts.
1 parent 974767e commit d73a081

File tree

5 files changed

+28
-10
lines changed

5 files changed

+28
-10
lines changed

include/swift/SIL/AddressUseKind.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515

1616
namespace swift {
1717

18-
enum class AddressUseKind { NonEscaping, PointerEscape, Unknown };
18+
enum class AddressUseKind { NonEscaping, Dependent, PointerEscape, Unknown };
1919

2020
inline AddressUseKind meet(AddressUseKind lhs, AddressUseKind rhs) {
2121
return (lhs > rhs) ? lhs : rhs;

include/swift/SIL/AddressWalker.h

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ class TransitiveAddressWalker {
4848
/// Whether we could tell if this address use didn't escape, did have a
4949
/// pointer escape, or unknown if we failed to understand something.
5050
AddressUseKind result = AddressUseKind::NonEscaping;
51+
Operand *escapingUse = nullptr;
5152

5253
unsigned didInvalidate = false;
5354

@@ -83,6 +84,11 @@ class TransitiveAddressWalker {
8384
result = swift::meet(result, other);
8485
}
8586

87+
void recordEscape(Operand *op, AddressUseKind kind = AddressUseKind::PointerEscape) {
88+
meet(kind);
89+
escapingUse = op;
90+
}
91+
8692
private:
8793
/// Shim that actually calls visitUse and changes early exit.
8894
void callVisitUse(Operand *use) {
@@ -92,12 +98,16 @@ class TransitiveAddressWalker {
9298
}
9399

94100
public:
95-
AddressUseKind walk(SILValue address) &&;
101+
AddressUseKind walk(SILValue address);
102+
103+
// If the result of walk() is not NonEscaping, this returns a non-null
104+
// operand that caused the escape or unknown use.
105+
Operand *getEscapingUse() const { return escapingUse; }
96106
};
97107

98108
template <typename Impl>
99109
inline AddressUseKind
100-
TransitiveAddressWalker<Impl>::walk(SILValue projectedAddress) && {
110+
TransitiveAddressWalker<Impl>::walk(SILValue projectedAddress) {
101111
assert(!didInvalidate);
102112

103113
// When we exit, set the result to be invalidated so we can't use this again.
@@ -155,7 +165,7 @@ TransitiveAddressWalker<Impl>::walk(SILValue projectedAddress) && {
155165
case TermKind::CondBranchInst:
156166
// We could have an address phi. To be conservative, just treat this as
157167
// a point escape.
158-
meet(AddressUseKind::PointerEscape);
168+
recordEscape(op);
159169
for (auto succBlockArgList : ti->getSuccessorBlockArgumentLists()) {
160170
auto *succ = succBlockArgList[op->getOperandNumber()];
161171
for (auto *use : succ->getUses())
@@ -185,10 +195,13 @@ TransitiveAddressWalker<Impl>::walk(SILValue projectedAddress) && {
185195
}
186196
}
187197

188-
// TODO: Partial apply should be NonEscaping, but then we need to consider
189-
// the apply to be a use point.
190-
if (isa<PartialApplyInst>(user) || isa<AddressToPointerInst>(user)) {
191-
meet(AddressUseKind::PointerEscape);
198+
if (isa<PartialApplyInst>(user)) {
199+
recordEscape(op, AddressUseKind::Dependent);
200+
callVisitUse(op);
201+
continue;
202+
}
203+
if (isa<AddressToPointerInst>(user)) {
204+
recordEscape(op);
192205
callVisitUse(op);
193206
continue;
194207
}
@@ -297,7 +310,7 @@ TransitiveAddressWalker<Impl>::walk(SILValue projectedAddress) && {
297310
// address. See AddressUtils.swift. Until that is implemented, this must
298311
// be considered a pointer escape.
299312
if (op->get() == mdi->getBase()) {
300-
meet(AddressUseKind::PointerEscape);
313+
recordEscape(op, AddressUseKind::Dependent);
301314
callVisitUse(op);
302315
continue;
303316
}

include/swift/SIL/OwnershipLiveness.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,7 @@ class InteriorLiveness : public OSSALiveness {
241241
public:
242242
// Summarize address uses
243243
AddressUseKind addressUseKind = AddressUseKind::Unknown;
244+
Operand *escapingUse = nullptr;
244245

245246
public:
246247
InteriorLiveness(SILValue def): OSSALiveness(def) {}

include/swift/SIL/OwnershipUseVisitor.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -494,7 +494,7 @@ bool OwnershipUseVisitor<Impl>::visitInteriorPointerUses(Operand *use) {
494494
// just assumes that all scopes are incomplete.
495495
SmallVector<Operand *, 8> interiorUses;
496496
auto useKind = InteriorPointerOperand(use).findTransitiveUses(&interiorUses);
497-
if (useKind == AddressUseKind::PointerEscape) {
497+
if (useKind != AddressUseKind::NonEscaping) {
498498
if (!asImpl().handlePointerEscape(use))
499499
return false;
500500
}

lib/SIL/Utils/OwnershipLiveness.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,7 @@ struct InteriorLivenessVisitor :
150150

151151
bool handlePointerEscape(Operand *use) {
152152
interiorLiveness.addressUseKind = AddressUseKind::PointerEscape;
153+
interiorLiveness.escapingUse = use;
153154
if (!handleUsePoint(use, UseLifetimeConstraint::NonLifetimeEnding))
154155
return false;
155156

@@ -198,6 +199,9 @@ void InteriorLiveness::print(llvm::raw_ostream &OS) const {
198199
case AddressUseKind::PointerEscape:
199200
OS << "Incomplete liveness: Escaping address\n";
200201
break;
202+
case AddressUseKind::Dependent:
203+
OS << "Incomplete liveness: Dependent value\n";
204+
break;
201205
case AddressUseKind::Unknown:
202206
OS << "Incomplete liveness: Unknown address use\n";
203207
break;

0 commit comments

Comments
 (0)