Skip to content

Commit 28c1fdb

Browse files
committed
SwiftCompilerSources: Add Instruction.endInstruction
To make the ScopedInstruction abstraction useful and formalize to use-points of scoped operations. This is specifically for scoped operations that use their operands up to the end of their scope. This is not for the many instructions that introduce scoped lifetimes. Allocations are not considered scoped operations. Every owned value has a scoped lifetime just like an allocation, but the scope-ending instructions are not considered use points.
1 parent 7aab3c5 commit 28c1fdb

File tree

1 file changed

+148
-80
lines changed

1 file changed

+148
-80
lines changed

SwiftCompilerSources/Sources/SIL/Instruction.swift

Lines changed: 148 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -287,8 +287,6 @@ final public class StoreInst : Instruction, StoringInstruction {
287287
final public class StoreWeakInst : Instruction, StoringInstruction { }
288288
final public class StoreUnownedInst : Instruction, StoringInstruction { }
289289

290-
final public class StoreBorrowInst : SingleValueInstruction, StoringInstruction, BorrowIntroducingInstruction { }
291-
292290
final public class AssignInst : Instruction, StoringInstruction {
293291
// must match with enum class swift::AssignOwnershipQualifier
294292
public enum AssignOwnership: Int {
@@ -341,17 +339,6 @@ final public class ExplicitCopyAddrInst : Instruction, SourceDestAddrInstruction
341339
}
342340
}
343341

344-
final public class EndAccessInst : Instruction, UnaryInstruction {
345-
public var beginAccess: BeginAccessInst {
346-
return operand.value as! BeginAccessInst
347-
}
348-
}
349-
350-
final public class BeginUnpairedAccessInst : Instruction {}
351-
final public class EndUnpairedAccessInst : Instruction {}
352-
353-
final public class EndBorrowInst : Instruction, UnaryInstruction {}
354-
355342
final public class MarkUninitializedInst : SingleValueInstruction, UnaryInstruction {
356343

357344
/// This enum captures what the mark_uninitialized instruction is designating.
@@ -449,9 +436,6 @@ final public class UnconditionalCheckedCastAddrInst : Instruction {
449436
public override var mayTrap: Bool { true }
450437
}
451438

452-
final public class EndApplyInst : Instruction, UnaryInstruction {}
453-
final public class AbortApplyInst : Instruction, UnaryInstruction {}
454-
455439
final public class BeginDeallocRefInst : SingleValueInstruction, UnaryInstruction {
456440
public var reference: Value { operands[0].value }
457441
public var allocation: AllocRefInstBase { operands[1].value as! AllocRefInstBase }
@@ -568,9 +552,6 @@ extension LoadInstruction {
568552
public var address: Value { operand.value }
569553
}
570554

571-
/// Instructions, beginning a borrow-scope which must be ended by `end_borrow`.
572-
public protocol BorrowIntroducingInstruction : SingleValueInstruction {}
573-
574555
final public class LoadInst : SingleValueInstruction, LoadInstruction {
575556
// must match with enum class LoadOwnershipQualifier
576557
public enum LoadOwnership: Int {
@@ -583,7 +564,6 @@ final public class LoadInst : SingleValueInstruction, LoadInstruction {
583564

584565
final public class LoadWeakInst : SingleValueInstruction, LoadInstruction {}
585566
final public class LoadUnownedInst : SingleValueInstruction, LoadInstruction {}
586-
final public class LoadBorrowInst : SingleValueInstruction, LoadInstruction, BorrowIntroducingInstruction {}
587567

588568
final public class BuiltinInst : SingleValueInstruction {
589569
public typealias ID = BridgedInstruction.BuiltinValueKind
@@ -983,57 +963,6 @@ final public class BridgeObjectToRefInst : SingleValueInstruction, UnaryInstruct
983963

984964
final public class BridgeObjectToWordInst : SingleValueInstruction, UnaryInstruction {}
985965

986-
// TODO: add support for begin_unpaired_access
987-
final public class BeginAccessInst : SingleValueInstruction, UnaryInstruction {
988-
// The raw values must match SILAccessKind.
989-
public enum AccessKind: Int {
990-
case `init` = 0
991-
case read = 1
992-
case modify = 2
993-
case `deinit` = 3
994-
}
995-
public var accessKind: AccessKind {
996-
AccessKind(rawValue: bridged.BeginAccessInst_getAccessKind())!
997-
}
998-
999-
public var isStatic: Bool { bridged.BeginAccessInst_isStatic() }
1000-
1001-
public var address: Value { operand.value }
1002-
}
1003-
1004-
// An instruction that is always paired with a scope ending instruction
1005-
// such as `begin_access` (ending with `end_access`) and `alloc_stack`
1006-
// (ending with `dealloc_stack`).
1007-
public protocol ScopedInstruction {
1008-
// The type of the ending instructions (while `IteratorProtocol` would be
1009-
// ideal, for performance reasons we allow the user to specify any type as return)
1010-
associatedtype EndInstructions
1011-
1012-
// The instructions that end the scope of the instruction denoted
1013-
// by `self`.
1014-
var endInstructions: EndInstructions { get }
1015-
}
1016-
1017-
extension BeginAccessInst : ScopedInstruction {
1018-
public typealias EndInstructions = LazyMapSequence<LazyFilterSequence<UseList>, EndAccessInst>
1019-
1020-
public var endInstructions: EndInstructions {
1021-
endOperands.map { $0.instruction as! EndAccessInst }
1022-
}
1023-
1024-
public var endOperands: LazyFilterSequence<UseList> {
1025-
return uses.lazy.filter { $0.instruction is EndAccessInst }
1026-
}
1027-
}
1028-
1029-
final public class BeginBorrowInst : SingleValueInstruction, UnaryInstruction, BorrowIntroducingInstruction {
1030-
public var borrowedValue: Value { operand.value }
1031-
1032-
public var isLexical: Bool { bridged.BeginBorrow_isLexical() }
1033-
1034-
public var isFromVarDecl: Bool { bridged.BeginBorrow_isFromVarDecl() }
1035-
}
1036-
1037966
final public class ProjectBoxInst : SingleValueInstruction, UnaryInstruction {
1038967
public var box: Value { operand.value }
1039968
public var fieldIndex: Int { bridged.ProjectBoxInst_fieldIndex() }
@@ -1242,23 +1171,94 @@ final public class AllocExistentialBoxInst : SingleValueInstruction, Allocation
12421171
}
12431172

12441173
//===----------------------------------------------------------------------===//
1245-
// multi-value instructions
1174+
// scoped instructions
12461175
//===----------------------------------------------------------------------===//
12471176

1248-
final public class BeginCOWMutationInst : MultipleValueInstruction, UnaryInstruction {
1249-
public var instance: Value { operand.value }
1250-
public var uniquenessResult: Value { return getResult(index: 0) }
1251-
public var instanceResult: Value { return getResult(index: 1) }
1177+
/// An instruction whose side effects extend across a scope including other instructions. These are always paired with a
1178+
/// scope ending instruction such as `begin_access` (ending with `end_access`) and `begin_borrow` (ending with
1179+
/// `end_borrow`).
1180+
public protocol ScopedInstruction {
1181+
var endOperands: LazyFilterSequence<UseList> { get }
12521182
}
12531183

1254-
final public class DestructureStructInst : MultipleValueInstruction, UnaryInstruction {
1255-
public var `struct`: Value { operand.value }
1184+
extension Instruction {
1185+
/// Return the sequence of use points of any instruction.
1186+
public var endInstructions: EndInstructions {
1187+
if let scopedInst = self as? ScopedInstruction {
1188+
return .scoped(scopedInst.endOperands.map({ $0.instruction }))
1189+
}
1190+
return .single(self)
1191+
}
12561192
}
12571193

1258-
final public class DestructureTupleInst : MultipleValueInstruction, UnaryInstruction {
1259-
public var `tuple`: Value { operand.value }
1194+
/// Instructions beginning a borrow-scope which must be ended by `end_borrow`.
1195+
public protocol BorrowIntroducingInstruction : SingleValueInstruction, ScopedInstruction {}
1196+
1197+
final public class EndBorrowInst : Instruction, UnaryInstruction {}
1198+
1199+
extension BorrowIntroducingInstruction {
1200+
public var endOperands: LazyFilterSequence<UseList> {
1201+
return uses.lazy.filter { $0.instruction is EndBorrowInst }
1202+
}
12601203
}
12611204

1205+
final public class BeginBorrowInst : SingleValueInstruction, UnaryInstruction, BorrowIntroducingInstruction {
1206+
public var borrowedValue: Value { operand.value }
1207+
1208+
public var isLexical: Bool { bridged.BeginBorrow_isLexical() }
1209+
1210+
public var isFromVarDecl: Bool { bridged.BeginBorrow_isFromVarDecl() }
1211+
1212+
public var endOperands: LazyFilterSequence<UseList> {
1213+
return uses.endingLifetime
1214+
}
1215+
}
1216+
1217+
final public class LoadBorrowInst : SingleValueInstruction, LoadInstruction, BorrowIntroducingInstruction {}
1218+
1219+
final public class StoreBorrowInst : SingleValueInstruction, StoringInstruction, BorrowIntroducingInstruction { }
1220+
1221+
final public class BeginAccessInst : SingleValueInstruction, UnaryInstruction {
1222+
// The raw values must match SILAccessKind.
1223+
public enum AccessKind: Int {
1224+
case `init` = 0
1225+
case read = 1
1226+
case modify = 2
1227+
case `deinit` = 3
1228+
}
1229+
public var accessKind: AccessKind {
1230+
AccessKind(rawValue: bridged.BeginAccessInst_getAccessKind())!
1231+
}
1232+
1233+
public var isStatic: Bool { bridged.BeginAccessInst_isStatic() }
1234+
1235+
public var address: Value { operand.value }
1236+
1237+
public typealias EndAccessInstructions = LazyMapSequence<LazyFilterSequence<UseList>, EndAccessInst>
1238+
1239+
public var endAccessInstructions: EndAccessInstructions {
1240+
endOperands.map { $0.instruction as! EndAccessInst }
1241+
}
1242+
}
1243+
1244+
final public class EndAccessInst : Instruction, UnaryInstruction {
1245+
public var beginAccess: BeginAccessInst {
1246+
return operand.value as! BeginAccessInst
1247+
}
1248+
}
1249+
1250+
extension BeginAccessInst : ScopedInstruction {
1251+
public var endOperands: LazyFilterSequence<UseList> {
1252+
return uses.lazy.filter { $0.instruction is EndAccessInst }
1253+
}
1254+
}
1255+
1256+
// Unpaired accesses do not have a static scope, are generally unsupported by the optimizer, and should be avoided.
1257+
final public class BeginUnpairedAccessInst : Instruction {}
1258+
1259+
final public class EndUnpairedAccessInst : Instruction {}
1260+
1261+
12621262
final public class BeginApplyInst : MultipleValueInstruction, FullApplySite {
12631263
public var numArguments: Int { bridged.BeginApplyInst_numArguments() }
12641264

@@ -1271,6 +1271,74 @@ final public class BeginApplyInst : MultipleValueInstruction, FullApplySite {
12711271
}
12721272
}
12731273

1274+
final public class EndApplyInst : Instruction, UnaryInstruction {}
1275+
final public class AbortApplyInst : Instruction, UnaryInstruction {}
1276+
1277+
extension BeginApplyInst : ScopedInstruction {
1278+
public var endOperands: LazyFilterSequence<UseList> {
1279+
return token.uses.lazy.filter { _ in true }
1280+
}
1281+
}
1282+
1283+
/// A sequence representing the use points of an instruction for the purpose of liveness and the general
1284+
/// nesting of scopes.
1285+
///
1286+
/// Abstracts over simple single-use instructions vs. an instruction that is always paired with scope ending
1287+
/// instructions that denote the end of the scoped operation.
1288+
public enum EndInstructions: CollectionLikeSequence {
1289+
public typealias EndScopedInstructions = LazyMapSequence<LazyFilterSequence<UseList>, Instruction>
1290+
1291+
case single(Instruction)
1292+
case scoped(EndScopedInstructions)
1293+
1294+
public enum Iterator : IteratorProtocol {
1295+
case single(Instruction?)
1296+
case scoped(EndScopedInstructions.Iterator)
1297+
1298+
public mutating func next() -> Instruction? {
1299+
switch self {
1300+
case let .single(inst):
1301+
if let result = inst {
1302+
self = .single(nil)
1303+
return result
1304+
}
1305+
return nil
1306+
case var .scoped(iter):
1307+
let result = iter.next()
1308+
self = .scoped(iter)
1309+
return result
1310+
}
1311+
}
1312+
}
1313+
1314+
public func makeIterator() -> Iterator {
1315+
switch self {
1316+
case let .single(inst):
1317+
return .single(inst)
1318+
case let .scoped(endScoped):
1319+
return .scoped(endScoped.makeIterator())
1320+
}
1321+
}
1322+
}
1323+
1324+
//===----------------------------------------------------------------------===//
1325+
// multi-value instructions
1326+
//===----------------------------------------------------------------------===//
1327+
1328+
final public class BeginCOWMutationInst : MultipleValueInstruction, UnaryInstruction {
1329+
public var instance: Value { operand.value }
1330+
public var uniquenessResult: Value { return getResult(index: 0) }
1331+
public var instanceResult: Value { return getResult(index: 1) }
1332+
}
1333+
1334+
final public class DestructureStructInst : MultipleValueInstruction, UnaryInstruction {
1335+
public var `struct`: Value { operand.value }
1336+
}
1337+
1338+
final public class DestructureTupleInst : MultipleValueInstruction, UnaryInstruction {
1339+
public var `tuple`: Value { operand.value }
1340+
}
1341+
12741342
//===----------------------------------------------------------------------===//
12751343
// terminator instructions
12761344
//===----------------------------------------------------------------------===//

0 commit comments

Comments
 (0)