@@ -48,40 +48,45 @@ struct InstructionRange : CustomStringConvertible, NoReflectionChildren {
48
48
49
49
private var insertedInsts : InstructionSet
50
50
51
+ // For efficiency, this set does not include instructions in blocks which are not the begin or any end block.
52
+ private var inExclusiveRange : InstructionSet
53
+
51
54
init ( begin beginInst: Instruction , _ context: some Context ) {
52
55
self . begin = beginInst
53
56
self . blockRange = BasicBlockRange ( begin: beginInst. parentBlock, context)
54
57
self . insertedInsts = InstructionSet ( context)
58
+ self . inExclusiveRange = InstructionSet ( context)
59
+ self . inExclusiveRange. insert ( beginInst)
55
60
}
56
61
57
62
/// Insert a potential end instruction.
58
63
mutating func insert( _ inst: Instruction ) {
59
64
insertedInsts. insert ( inst)
65
+ insertIntoRange ( instructions: ReverseInstructionList ( first: inst. previous) )
60
66
blockRange. insert ( inst. parentBlock)
67
+ if inst. parentBlock != begin. parentBlock {
68
+ // The first time an instruction is inserted in another block than the begin-block we need to insert
69
+ // instructions from the begin instruction to the end of the begin block.
70
+ // For subsequent insertions this is a no-op: `insertIntoRange` will return immediately because those
71
+ // instruction are already inserted.
72
+ insertIntoRange ( instructions: begin. parentBlock. instructions. reversed ( ) )
73
+ }
61
74
}
62
75
63
76
/// Insert a sequence of potential end instructions.
64
- mutating func insert< S: Sequence > ( contentsOf other: S ) where S. Element == Instruction {
77
+ mutating func insert< S: Sequence > ( contentsOf other: S ) where S. Element: Instruction {
65
78
for inst in other {
66
79
insert ( inst)
67
80
}
68
81
}
69
82
70
83
/// Returns true if the exclusive range contains `inst`.
71
84
func contains( _ inst: Instruction ) -> Bool {
72
- let block = inst. parentBlock
73
- if !blockRange. inclusiveRangeContains ( block) { return false }
74
- var inRange = false
75
- if blockRange. contains ( block) {
76
- if block != blockRange. begin { return true }
77
- inRange = true
85
+ if inExclusiveRange. contains ( inst) {
86
+ return true
78
87
}
79
- for i in block. instructions. reversed ( ) {
80
- if i == inst { return inRange }
81
- if insertedInsts. contains ( i) { inRange = true }
82
- if i == begin { return false }
83
- }
84
- fatalError ( " didn't find instruction in its block " )
88
+ let block = inst. parentBlock
89
+ return block != begin. parentBlock && blockRange. contains ( block)
85
90
}
86
91
87
92
/// Returns true if the inclusive range contains `inst`.
@@ -129,6 +134,14 @@ struct InstructionRange : CustomStringConvertible, NoReflectionChildren {
129
134
}
130
135
}
131
136
137
+ private mutating func insertIntoRange( instructions: ReverseInstructionList ) {
138
+ for inst in instructions {
139
+ if !inExclusiveRange. insert ( inst) {
140
+ return
141
+ }
142
+ }
143
+ }
144
+
132
145
var description : String {
133
146
return ( isValid ? " " : " <invalid> \n " ) +
134
147
"""
@@ -141,6 +154,7 @@ struct InstructionRange : CustomStringConvertible, NoReflectionChildren {
141
154
142
155
/// TODO: once we have move-only types, make this a real deinit.
143
156
mutating func deinitialize( ) {
157
+ inExclusiveRange. deinitialize ( )
144
158
insertedInsts. deinitialize ( )
145
159
blockRange. deinitialize ( )
146
160
}
0 commit comments