@@ -40,9 +40,6 @@ import SIL
40
40
/// destruct this data structure, e.g. in a `defer {}` block.
41
41
struct InstructionRange : CustomStringConvertible , NoReflectionChildren {
42
42
43
- /// The dominating begin instruction.
44
- let begin : Instruction
45
-
46
43
/// The underlying block range.
47
44
private( set) var blockRange : BasicBlockRange
48
45
@@ -52,10 +49,7 @@ struct InstructionRange : CustomStringConvertible, NoReflectionChildren {
52
49
private var inExclusiveRange : InstructionSet
53
50
54
51
init ( begin beginInst: Instruction , _ context: some Context ) {
55
- self . begin = beginInst
56
- self . blockRange = BasicBlockRange ( begin: beginInst. parentBlock, context)
57
- self . insertedInsts = InstructionSet ( context)
58
- self . inExclusiveRange = InstructionSet ( context)
52
+ self = InstructionRange ( beginBlock: beginInst. parentBlock, context)
59
53
self . inExclusiveRange. insert ( beginInst)
60
54
}
61
55
@@ -65,28 +59,32 @@ struct InstructionRange : CustomStringConvertible, NoReflectionChildren {
65
59
}
66
60
67
61
init ( for value: Value , _ context: some Context ) {
68
- self = InstructionRange ( begin: InstructionRange . beginningInstruction ( for: value) , context)
62
+ if let inst = value. definingInstruction {
63
+ self = InstructionRange ( begin: inst, context)
64
+ } else if let arg = value as? Argument {
65
+ self = InstructionRange ( beginBlock: arg. parentBlock, context)
66
+ } else {
67
+ fatalError ( " cannot build an instruction range for \( value) " )
68
+ }
69
69
}
70
70
71
- static func beginningInstruction( for value: Value ) -> Instruction {
72
- if let def = value. definingInstructionOrTerminator {
73
- return def
74
- }
75
- assert ( Phi ( value) != nil || value is FunctionArgument )
76
- return value. parentBlock. instructions. first!
71
+ private init ( beginBlock: BasicBlock , _ context: some Context ) {
72
+ self . blockRange = BasicBlockRange ( begin: beginBlock, context)
73
+ self . insertedInsts = InstructionSet ( context)
74
+ self . inExclusiveRange = InstructionSet ( context)
77
75
}
78
76
79
77
/// Insert a potential end instruction.
80
78
mutating func insert( _ inst: Instruction ) {
81
79
insertedInsts. insert ( inst)
82
80
insertIntoRange ( instructions: ReverseInstructionList ( first: inst. previous) )
83
81
blockRange. insert ( inst. parentBlock)
84
- if inst. parentBlock != begin . parentBlock {
82
+ if inst. parentBlock != blockRange . begin {
85
83
// The first time an instruction is inserted in another block than the begin-block we need to insert
86
84
// instructions from the begin instruction to the end of the begin block.
87
85
// For subsequent insertions this is a no-op: `insertIntoRange` will return immediately because those
88
86
// instruction are already inserted.
89
- insertIntoRange ( instructions: begin . parentBlock . instructions. reversed ( ) )
87
+ insertIntoRange ( instructions: blockRange . begin . instructions. reversed ( ) )
90
88
}
91
89
}
92
90
@@ -103,22 +101,14 @@ struct InstructionRange : CustomStringConvertible, NoReflectionChildren {
103
101
return true
104
102
}
105
103
let block = inst. parentBlock
106
- return block != begin . parentBlock && blockRange. contains ( block)
104
+ return block != blockRange . begin && blockRange. contains ( block)
107
105
}
108
106
109
107
/// Returns true if the inclusive range contains `inst`.
110
108
func inclusiveRangeContains ( _ inst: Instruction ) -> Bool {
111
109
contains ( inst) || insertedInsts. contains ( inst)
112
110
}
113
111
114
- /// Returns true if the range is valid and that's iff the begin instruction
115
- /// dominates all instructions of the range.
116
- var isValid : Bool {
117
- blockRange. isValid &&
118
- // Check if there are any inserted instructions before the begin instruction in its block.
119
- !ReverseInstructionList( first: begin) . dropFirst ( ) . contains { insertedInsts. contains ( $0) }
120
- }
121
-
122
112
/// Returns the end instructions.
123
113
///
124
114
/// Warning: this returns `begin` if no instructions were inserted.
@@ -160,6 +150,10 @@ struct InstructionRange : CustomStringConvertible, NoReflectionChildren {
160
150
}
161
151
}
162
152
153
+ var begin : Instruction ? {
154
+ blockRange. begin. instructions. first ( where: inExclusiveRange. contains)
155
+ }
156
+
163
157
private mutating func insertIntoRange( instructions: ReverseInstructionList ) {
164
158
for inst in instructions {
165
159
if !inExclusiveRange. insert ( inst) {
@@ -169,9 +163,9 @@ struct InstructionRange : CustomStringConvertible, NoReflectionChildren {
169
163
}
170
164
171
165
var description : String {
172
- return ( isValid ? " " : " <invalid> \n " ) +
166
+ return ( blockRange . isValid ? " " : " <invalid> \n " ) +
173
167
"""
174
- begin: \( begin)
168
+ begin: \( begin? . description ?? blockRange . begin . name )
175
169
ends: \( ends. map { $0. description } . joined ( separator: " \n " ) )
176
170
exits: \( exits. map { $0. description } . joined ( separator: " \n " ) )
177
171
interiors: \( interiors. map { $0. description } . joined ( separator: " \n " ) )
0 commit comments