Skip to content

Commit 78d50ef

Browse files
committed
[SIL] Add end_linear_lifetime instruction.
It marks the end of a value's "linear lifetime". The boundary formed by all consuming uses together with these instructions will encompass all uses of the value.
1 parent 77dd568 commit 78d50ef

File tree

22 files changed

+117
-2
lines changed

22 files changed

+117
-2
lines changed

SwiftCompilerSources/Sources/SIL/Instruction.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -505,6 +505,8 @@ final public class DestroyAddrInst : Instruction, UnaryInstruction {
505505

506506
final public class EndLifetimeInst : Instruction, UnaryInstruction {}
507507

508+
final public class ExtendLifetimeInst : Instruction, UnaryInstruction {}
509+
508510
final public class InjectEnumAddrInst : Instruction, UnaryInstruction, EnumInstruction {
509511
public var `enum`: Value { operand.value }
510512
public var caseIndex: Int { bridged.InjectEnumAddrInst_caseIndex() }

SwiftCompilerSources/Sources/SIL/Registration.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ public func registerSILClasses() {
7878
register(DestroyValueInst.self)
7979
register(DestroyAddrInst.self)
8080
register(EndLifetimeInst.self)
81+
register(ExtendLifetimeInst.self)
8182
register(StrongCopyUnownedValueInst.self)
8283
register(StrongCopyUnmanagedValueInst.self)
8384
register(StrongCopyWeakValueInst.self)

docs/SIL.rst

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4682,6 +4682,22 @@ The instruction accepts an object or address type.
46824682
This instruction is valid only in OSSA and is lowered to a no-op when lowering
46834683
to non-OSSA.
46844684

4685+
extend_lifetime
4686+
```````````````
4687+
4688+
::
4689+
4690+
sil-instruction ::= 'extend_lifetime' sil-operand
4691+
4692+
// Indicate that %0's linear lifetime extends to this point
4693+
extend_lifetime %0 : $X
4694+
4695+
Indicates that a value's linear lifetime extends to this point. Inserted by
4696+
OSSALifetimeCompletion(AvailabilityBoundary) in order to provide the invariant
4697+
that a value is either consumed OR has an `extend_lifetime` user on all paths
4698+
and furthermore that all uses are within the boundary defined by that set of
4699+
instructions (the consumes and the `extend_lifetime`s).
4700+
46854701
assign
46864702
``````
46874703
::

include/swift/SIL/SILBuilder.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2292,6 +2292,11 @@ class SILBuilder {
22922292
EndLifetimeInst(getSILDebugLocation(Loc), Operand));
22932293
}
22942294

2295+
ExtendLifetimeInst *createExtendLifetime(SILLocation Loc, SILValue Operand) {
2296+
return insert(new (getModule())
2297+
ExtendLifetimeInst(getSILDebugLocation(Loc), Operand));
2298+
}
2299+
22952300
UncheckedOwnershipConversionInst *
22962301
createUncheckedOwnershipConversion(SILLocation Loc, SILValue Operand,
22972302
ValueOwnershipKind Kind) {

include/swift/SIL/SILCloner.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3019,6 +3019,18 @@ void SILCloner<ImplClass>::visitEndLifetimeInst(EndLifetimeInst *Inst) {
30193019
getOpValue(Inst->getOperand())));
30203020
}
30213021

3022+
template <typename ImplClass>
3023+
void SILCloner<ImplClass>::visitExtendLifetimeInst(ExtendLifetimeInst *Inst) {
3024+
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
3025+
3026+
if (!getBuilder().hasOwnership())
3027+
return;
3028+
3029+
recordClonedInstruction(
3030+
Inst, getBuilder().createExtendLifetime(getOpLocation(Inst->getLoc()),
3031+
getOpValue(Inst->getOperand())));
3032+
}
3033+
30223034
template <typename ImplClass>
30233035
void SILCloner<ImplClass>::visitUncheckedOwnershipConversionInst(
30243036
UncheckedOwnershipConversionInst *Inst) {

include/swift/SIL/SILInstruction.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8519,6 +8519,16 @@ class EndLifetimeInst
85198519
: UnaryInstructionBase(DebugLoc, Operand) {}
85208520
};
85218521

8522+
/// Mark the end of the linear live range of a value without destroying it.
8523+
class ExtendLifetimeInst
8524+
: public UnaryInstructionBase<SILInstructionKind::ExtendLifetimeInst,
8525+
NonValueInstruction> {
8526+
friend SILBuilder;
8527+
8528+
ExtendLifetimeInst(SILDebugLocation loc, SILValue operand)
8529+
: UnaryInstructionBase(loc, operand) {}
8530+
};
8531+
85228532
/// An unsafe conversion in between ownership kinds.
85238533
///
85248534
/// This is used today in destructors where due to Objective-C legacy

include/swift/SIL/SILNodes.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -864,6 +864,8 @@ NON_VALUE_INST(DestroyAddrInst, destroy_addr,
864864
SILInstruction, MayHaveSideEffects, MayRelease)
865865
NON_VALUE_INST(EndLifetimeInst, end_lifetime,
866866
SILInstruction, MayHaveSideEffects, MayRelease)
867+
NON_VALUE_INST(ExtendLifetimeInst, extend_lifetime,
868+
SILInstruction, None, DoesNotRelease)
867869
NON_VALUE_INST(InjectEnumAddrInst, inject_enum_addr,
868870
SILInstruction, MayWrite, DoesNotRelease)
869871
NON_VALUE_INST(DeinitExistentialAddrInst, deinit_existential_addr,

lib/IRGen/IRGenSIL.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1350,6 +1350,9 @@ class IRGenSILFunction :
13501350
void visitEndLifetimeInst(EndLifetimeInst *i) {
13511351
llvm_unreachable("unimplemented");
13521352
}
1353+
void visitExtendLifetimeInst(ExtendLifetimeInst *i) {
1354+
llvm_unreachable("should not exist after ownership lowering!?");
1355+
}
13531356
void
13541357
visitUncheckedOwnershipConversionInst(UncheckedOwnershipConversionInst *i) {
13551358
llvm_unreachable("unimplemented");

lib/SIL/IR/OperandOwnership.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,7 @@ OPERAND_OWNERSHIP(InstantaneousUse, SuperMethod)
225225
OPERAND_OWNERSHIP(InstantaneousUse, ClassifyBridgeObject)
226226
OPERAND_OWNERSHIP(InstantaneousUse, UnownedCopyValue)
227227
OPERAND_OWNERSHIP(InstantaneousUse, WeakCopyValue)
228+
OPERAND_OWNERSHIP(InstantaneousUse, ExtendLifetime)
228229
#define REF_STORAGE(Name, ...) \
229230
OPERAND_OWNERSHIP(InstantaneousUse, StrongCopy##Name##Value)
230231
#include "swift/AST/ReferenceStorage.def"

lib/SIL/IR/SILPrinter.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2565,6 +2565,9 @@ class SILPrinter : public SILInstructionVisitor<SILPrinter> {
25652565
void visitEndLifetimeInst(EndLifetimeInst *ELI) {
25662566
*this << getIDAndType(ELI->getOperand());
25672567
}
2568+
void visitExtendLifetimeInst(ExtendLifetimeInst *ELLI) {
2569+
*this << getIDAndType(ELLI->getOperand());
2570+
}
25682571
void visitValueToBridgeObjectInst(ValueToBridgeObjectInst *VBOI) {
25692572
*this << getIDAndType(VBOI->getOperand());
25702573
}

lib/SIL/Parser/ParseSIL.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3308,6 +3308,7 @@ bool SILParser::parseSpecificSILInstruction(SILBuilder &B,
33083308
UNARY_INSTRUCTION(ValueToBridgeObject)
33093309
UNARY_INSTRUCTION(FixLifetime)
33103310
UNARY_INSTRUCTION(EndLifetime)
3311+
UNARY_INSTRUCTION(ExtendLifetime)
33113312
UNARY_INSTRUCTION(CopyBlock)
33123313
UNARY_INSTRUCTION(IsUnique)
33133314
UNARY_INSTRUCTION(DestroyAddr)

lib/SIL/Utils/InstructionUtils.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -551,6 +551,7 @@ RuntimeEffect swift::getRuntimeEffect(SILInstruction *inst, SILType &impactType)
551551
case SILInstructionKind::AssignOrInitInst:
552552
case SILInstructionKind::MarkFunctionEscapeInst:
553553
case SILInstructionKind::EndLifetimeInst:
554+
case SILInstructionKind::ExtendLifetimeInst:
554555
case SILInstructionKind::EndApplyInst:
555556
case SILInstructionKind::AbortApplyInst:
556557
case SILInstructionKind::CondFailInst:

lib/SILOptimizer/Analysis/RegionAnalysis.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2497,6 +2497,7 @@ CONSTANT_TRANSLATION(DestroyValueInst, Ignored)
24972497
CONSTANT_TRANSLATION(EndAccessInst, Ignored)
24982498
CONSTANT_TRANSLATION(EndBorrowInst, Ignored)
24992499
CONSTANT_TRANSLATION(EndLifetimeInst, Ignored)
2500+
CONSTANT_TRANSLATION(ExtendLifetimeInst, Ignored)
25002501
CONSTANT_TRANSLATION(EndUnpairedAccessInst, Ignored)
25012502
CONSTANT_TRANSLATION(HopToExecutorInst, Ignored)
25022503
CONSTANT_TRANSLATION(InjectEnumAddrInst, Ignored)

lib/SILOptimizer/Mandatory/OwnershipModelEliminator.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,10 @@ struct OwnershipModelEliminatorVisitor
164164
eraseInstruction(eli);
165165
return true;
166166
}
167+
bool visitExtendLifetimeInst(ExtendLifetimeInst *eli) {
168+
eraseInstruction(eli);
169+
return true;
170+
}
167171
bool visitUncheckedOwnershipConversionInst(
168172
UncheckedOwnershipConversionInst *uoci) {
169173
eraseInstructionAndRAUW(uoci, uoci->getOperand());

lib/SILOptimizer/UtilityPasses/SerializeSILPass.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -301,6 +301,7 @@ static bool hasOpaqueArchetype(TypeExpansionContext context,
301301
case SILInstructionKind::MarkUnresolvedMoveAddrInst:
302302
case SILInstructionKind::DestroyAddrInst:
303303
case SILInstructionKind::EndLifetimeInst:
304+
case SILInstructionKind::ExtendLifetimeInst:
304305
case SILInstructionKind::InjectEnumAddrInst:
305306
case SILInstructionKind::DeinitExistentialAddrInst:
306307
case SILInstructionKind::DeinitExistentialValueInst:

lib/SILOptimizer/Utils/SILInliner.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -858,6 +858,7 @@ InlineCost swift::instructionInlineCost(SILInstruction &I) {
858858
case SILInstructionKind::GlobalAddrInst:
859859
case SILInstructionKind::BaseAddrForOffsetInst:
860860
case SILInstructionKind::EndLifetimeInst:
861+
case SILInstructionKind::ExtendLifetimeInst:
861862
case SILInstructionKind::UncheckedOwnershipConversionInst:
862863
case SILInstructionKind::BindMemoryInst:
863864
case SILInstructionKind::RebindMemoryInst:

lib/Serialization/DeserializeSIL.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2272,6 +2272,7 @@ bool SILDeserializer::readSILInstruction(SILFunction *Fn,
22722272
UNARY_INSTRUCTION(ValueToBridgeObject)
22732273
UNARY_INSTRUCTION(FixLifetime)
22742274
UNARY_INSTRUCTION(EndLifetime)
2275+
UNARY_INSTRUCTION(ExtendLifetime)
22752276
UNARY_INSTRUCTION(CopyBlock)
22762277
UNARY_INSTRUCTION(LoadBorrow)
22772278
UNARY_INSTRUCTION(EndInitLetRef)

lib/Serialization/ModuleFormat.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,7 @@ const uint16_t SWIFTMODULE_VERSION_MAJOR = 0;
5858
/// describe what change you made. The content of this comment isn't important;
5959
/// it just ensures a conflict if two people change the module format.
6060
/// Don't worry about adhering to the 80-column limit for this line.
61-
const uint16_t SWIFTMODULE_VERSION_MINOR =
62-
875; // Add package field to SerializedKind_t
61+
const uint16_t SWIFTMODULE_VERSION_MINOR = 876; // extend_lifetime instruction
6362

6463
/// A standard hash seed used for all string hashes in a serialized module.
6564
///

lib/Serialization/SerializeSIL.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1544,6 +1544,7 @@ void SILSerializer::writeSILInstruction(const SILInstruction &SI) {
15441544
case SILInstructionKind::ValueToBridgeObjectInst:
15451545
case SILInstructionKind::FixLifetimeInst:
15461546
case SILInstructionKind::EndLifetimeInst:
1547+
case SILInstructionKind::ExtendLifetimeInst:
15471548
case SILInstructionKind::CopyBlockInst:
15481549
case SILInstructionKind::StrongReleaseInst:
15491550
case SILInstructionKind::StrongRetainInst:

test/SIL/Parser/basic2.sil

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -332,3 +332,18 @@ bb0(%0 : @guaranteed $Klass):
332332
%9999 = tuple()
333333
return %9999 : $()
334334
}
335+
336+
// CHECK-LABEL: sil [ossa] @test_extend_lifetime : {{.*}} {
337+
// CHECK: bb0([[K:%[^,]+]] :
338+
// CHECK: br [[LOOP:bb[0-9]+]]
339+
// CHECK: [[LOOP]]:
340+
// CHECK: extend_lifetime [[K]]
341+
// CHECK: br [[LOOP]]
342+
// CHECK-LABEL: } // end sil function 'test_extend_lifetime'
343+
sil [ossa] @test_extend_lifetime : $@convention(thin) (@owned Klass) -> () {
344+
entry(%k : @owned $Klass):
345+
br bb1
346+
bb1:
347+
extend_lifetime %k : $Klass
348+
br bb1
349+
}

test/SIL/Serialization/basic2.sil

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,21 @@ bb0(%0 : @owned $Builtin.NativeObject):
8989
return %9999 : $()
9090
}
9191

92+
// CHECK-LABEL: sil [ossa] @test_extend_lifetime : {{.*}} {
93+
// CHECK: bb0([[K:%[^,]+]] :
94+
// CHECK: br [[LOOP:bb[0-9]+]]
95+
// CHECK: [[LOOP]]:
96+
// CHECK: extend_lifetime [[K]]
97+
// CHECK: br [[LOOP]]
98+
// CHECK-LABEL: } // end sil function 'test_extend_lifetime'
99+
sil [ossa] @test_extend_lifetime : $@convention(thin) (@owned Builtin.NativeObject) -> () {
100+
entry(%k : @owned $Builtin.NativeObject):
101+
br bb1
102+
bb1:
103+
extend_lifetime %k : $Builtin.NativeObject
104+
br bb1
105+
}
106+
92107
// CHECK-LABEL: sil [ossa] @test_mark_dependence : $@convention(thin) (@owned Builtin.NativeObject, @owned Builtin.NativeObject) -> () {
93108
// CHECK: [[MD1:%.*]] = mark_dependence %1 : $Builtin.NativeObject on %0 : $Builtin.NativeObject
94109
// CHECK: [[MD2:%.*]] = mark_dependence [nonescaping] [[MD1]] : $Builtin.NativeObject on %0 : $Builtin.NativeObject

test/SIL/cloning.sil

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,3 +206,23 @@ sil [ossa] @caller_specify_test : $@convention(thin) () -> () {
206206
%retval = apply %callee() : $@convention(thin) () -> ()
207207
return %retval : $()
208208
}
209+
210+
211+
// CHECK-LABEL: sil [ossa] @caller_extend_lifetime : {{.*}} {
212+
// CHECK: bb0([[O:%[^,]+]] :
213+
// CHECK: extend_lifetime [[O]]
214+
// CHECK-LABEL: } // end sil function 'caller_extend_lifetime'
215+
sil [always_inline] [ossa] @callee_extend_lifetime : $@convention(thin) (@owned Builtin.NativeObject) -> () {
216+
entry(%o : @owned $Builtin.NativeObject):
217+
br loop
218+
loop:
219+
extend_lifetime %o : $Builtin.NativeObject
220+
br loop
221+
}
222+
223+
sil [ossa] @caller_extend_lifetime : $@convention(thin) (@owned Builtin.NativeObject) -> () {
224+
entry(%o : @owned $Builtin.NativeObject):
225+
%callee = function_ref @callee_extend_lifetime : $@convention(thin) (@owned Builtin.NativeObject) -> ()
226+
%retval = apply %callee(%o) : $@convention(thin) (@owned Builtin.NativeObject) -> ()
227+
return %retval : $()
228+
}

0 commit comments

Comments
 (0)