Skip to content

Commit c119f35

Browse files
committed
[SIL] Add extend_lifetime instruction.
It indicates that the value's lifetime continues to at least this point. The boundary formed by all consuming uses together with these instructions will encompass all uses of the value.
1 parent 9385d36 commit c119f35

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)