Skip to content

Commit 12773bf

Browse files
committed
[OwnershipLiveness] End at extend_lifetime.
When visiting consumes, also visit `extend_lifetime` instructions. These instructions are not lifetime ending, but together with the consumes, they enclose the users of a value. Add a flag to LinearLiveness to control whether these instructions are added so that the verifier can use verify that all such instructions appear outside the linear lifetime boundary (not including them).
1 parent c119f35 commit 12773bf

File tree

6 files changed

+341
-6
lines changed

6 files changed

+341
-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: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,13 @@ bool OwnershipUseVisitor<Impl>::visitLifetimeEndingUses(SILValue ssaDef) {
213213
template <typename Impl>
214214
bool OwnershipUseVisitor<Impl>::visitConsumes(SILValue ssaDef) {
215215
for (Operand *use : ssaDef->getUses()) {
216+
// extend_lifetime instructions are non-consuming but need to be visited
217+
// because together with consuming uses they enclose all users of the value.
218+
if (isa<ExtendLifetimeInst>(use->getUser())) {
219+
if (!handleUsePoint(use, UseLifetimeConstraint::NonLifetimeEnding))
220+
return false;
221+
continue;
222+
}
216223
if (use->isConsuming()) {
217224
if (PhiOperand(use) && !asImpl().handleOwnedPhi(use))
218225
return false;
@@ -245,6 +252,9 @@ bool OwnershipUseVisitor<Impl>::visitOuterBorrowScopeEnd(Operand *borrowEnd) {
245252

246253
return handleUsePoint(borrowEnd, UseLifetimeConstraint::LifetimeEnding);
247254

255+
case OperandOwnership::InstantaneousUse:
256+
assert(isa<ExtendLifetimeInst>(borrowEnd->getUser()));
257+
return handleUsePoint(borrowEnd, UseLifetimeConstraint::NonLifetimeEnding);
248258
default:
249259
llvm_unreachable("expected borrow scope end");
250260
}

lib/SIL/Utils/OwnershipLiveness.cpp

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

4040
bool handleUsePoint(Operand *use, UseLifetimeConstraint useConstraint) {
41+
if (!linearLiveness.includeExtensions &&
42+
isa<ExtendLifetimeInst>(use->getUser())) {
43+
return true;
44+
}
4145
linearLiveness.liveness.updateForUse(
4246
use->getUser(), useConstraint == UseLifetimeConstraint::LifetimeEnding);
4347
return true;
@@ -71,7 +75,9 @@ struct LinearLivenessVisitor :
7175
}
7276
};
7377

74-
LinearLiveness::LinearLiveness(SILValue def): OSSALiveness(def) {
78+
LinearLiveness::LinearLiveness(SILValue def,
79+
IncludeExtensions_t includeExtensions)
80+
: OSSALiveness(def), includeExtensions(includeExtensions) {
7581
if (def->getOwnershipKind() != OwnershipKind::Owned) {
7682
BorrowedValue borrowedValue(def);
7783
assert(borrowedValue && borrowedValue.isLocalScope());
@@ -118,7 +124,7 @@ struct InteriorLivenessVisitor :
118124

119125
bool handleUsePoint(Operand *use, UseLifetimeConstraint useConstraint) {
120126
interiorLiveness.liveness.updateForUse(
121-
use->getUser(), useConstraint == UseLifetimeConstraint::LifetimeEnding);
127+
use->getUser(), useConstraint == UseLifetimeConstraint::LifetimeEnding);
122128
return true;
123129
}
124130

@@ -302,7 +308,7 @@ struct ExtendedLinearLivenessVisitor
302308

303309
bool handleUsePoint(Operand *use, UseLifetimeConstraint useConstraint) {
304310
extendedLiveness.liveness.updateForUse(
305-
use->getUser(), useConstraint == UseLifetimeConstraint::LifetimeEnding);
311+
use->getUser(), useConstraint == UseLifetimeConstraint::LifetimeEnding);
306312
return true;
307313
}
308314

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)