Skip to content

Commit 85f89a3

Browse files
committed
[OwnershipLiveness] End at extend_lifetime.
All ownership liveness types treat `extend_lifetime` instructions as lifetime-ending (on the C++ side, there is no corresponding caching on the Swift side). As such, `LinearLiveness` adds these instructions to its backing range tracking gadget. On the C++ side, this can be disabled for the purposes of verification.
1 parent 78d50ef commit 85f89a3

File tree

6 files changed

+343
-6
lines changed

6 files changed

+343
-6
lines changed

SwiftCompilerSources/Sources/Optimizer/Utilities/OwnershipLiveness.swift

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,11 @@ func computeLinearLiveness(for definingValue: Value, _ context: Context)
6464
var range = InstructionRange(for: definingValue, context)
6565

6666
// Compute liveness.
67-
definingValue.lookThroughBorrowedFromUser.uses.endingLifetime.forEach {
68-
range.insert($0.instruction)
67+
for use in definingValue.lookThroughBorrowedFromUser.uses {
68+
let instruction = use.instruction
69+
if use.endsLifetime || instruction is ExtendLifetimeInst {
70+
range.insert(instruction)
71+
}
6972
}
7073
return range
7174
}

include/swift/SIL/OwnershipLiveness.h

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -206,9 +206,19 @@ class LinearLiveness : public OSSALiveness {
206206
friend LinearLivenessVisitor;
207207

208208
public:
209-
LinearLiveness(SILValue def);
209+
/// Whether extend_lifetime instructions should be added to the boundary.
210+
/// Used to verify extend_lifetime instructions.
211+
enum IncludeExtensions_t {
212+
DoNotIncludeExtensions = false,
213+
IncludeExtensions = true,
214+
};
215+
LinearLiveness(SILValue def,
216+
IncludeExtensions_t includeExtensions = IncludeExtensions);
210217

211218
void compute();
219+
220+
private:
221+
const IncludeExtensions_t includeExtensions;
212222
};
213223

214224
// Internal implementation

include/swift/SIL/OwnershipUseVisitor.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,11 @@ bool OwnershipUseVisitor<Impl>::visitLifetimeEndingUses(SILValue ssaDef) {
213213
template <typename Impl>
214214
bool OwnershipUseVisitor<Impl>::visitConsumes(SILValue ssaDef) {
215215
for (Operand *use : ssaDef->getUses()) {
216+
if (isa<ExtendLifetimeInst>(use->getUser())) {
217+
if (!handleUsePoint(use, UseLifetimeConstraint::LifetimeEnding))
218+
return false;
219+
continue;
220+
}
216221
if (use->isConsuming()) {
217222
if (PhiOperand(use) && !asImpl().handleOwnedPhi(use))
218223
return false;

lib/SIL/Utils/OwnershipLiveness.cpp

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,13 @@ struct LinearLivenessVisitor :
3838
linearLiveness(linearLiveness){}
3939

4040
bool handleUsePoint(Operand *use, UseLifetimeConstraint useConstraint) {
41+
if (isa<ExtendLifetimeInst>(use->getUser())) {
42+
if (linearLiveness.includeExtensions) {
43+
linearLiveness.liveness.updateForUse(use->getUser(),
44+
/*lifetimeEnding=*/true);
45+
}
46+
return true;
47+
}
4148
linearLiveness.liveness.updateForUse(
4249
use->getUser(), useConstraint == UseLifetimeConstraint::LifetimeEnding);
4350
return true;
@@ -71,7 +78,9 @@ struct LinearLivenessVisitor :
7178
}
7279
};
7380

74-
LinearLiveness::LinearLiveness(SILValue def): OSSALiveness(def) {
81+
LinearLiveness::LinearLiveness(SILValue def,
82+
IncludeExtensions_t includeExtensions)
83+
: OSSALiveness(def), includeExtensions(includeExtensions) {
7584
if (def->getOwnershipKind() != OwnershipKind::Owned) {
7685
BorrowedValue borrowedValue(def);
7786
assert(borrowedValue && borrowedValue.isLocalScope());
@@ -118,7 +127,9 @@ struct InteriorLivenessVisitor :
118127

119128
bool handleUsePoint(Operand *use, UseLifetimeConstraint useConstraint) {
120129
interiorLiveness.liveness.updateForUse(
121-
use->getUser(), useConstraint == UseLifetimeConstraint::LifetimeEnding);
130+
use->getUser(),
131+
(useConstraint == UseLifetimeConstraint::LifetimeEnding) ||
132+
isa<ExtendLifetimeInst>(use->getUser()));
122133
return true;
123134
}
124135

@@ -302,7 +313,9 @@ struct ExtendedLinearLivenessVisitor
302313

303314
bool handleUsePoint(Operand *use, UseLifetimeConstraint useConstraint) {
304315
extendedLiveness.liveness.updateForUse(
305-
use->getUser(), useConstraint == UseLifetimeConstraint::LifetimeEnding);
316+
use->getUser(),
317+
(useConstraint == UseLifetimeConstraint::LifetimeEnding) ||
318+
isa<ExtendLifetimeInst>(use->getUser()));
306319
return true;
307320
}
308321

lib/SIL/Utils/OwnershipUtils.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -950,6 +950,10 @@ bool BorrowedValue::visitLocalScopeEndingUses(
950950
case BorrowedValueKind::Phi:
951951
case BorrowedValueKind::BeginApplyToken:
952952
for (auto *use : lookThroughBorrowedFromUser(value)->getUses()) {
953+
if (isa<ExtendLifetimeInst>(use->getUser())) {
954+
if (!visitor(use))
955+
return false;
956+
}
953957
if (use->isLifetimeEnding()) {
954958
if (!visitor(use))
955959
return false;

0 commit comments

Comments
 (0)