Skip to content

Commit 30ea104

Browse files
committed
make InstructionRange.contains more efficient
Instead of trying to find an instruction by iterating through all instruction in the list, use an InstructionSet.
1 parent 9f61777 commit 30ea104

File tree

1 file changed

+27
-13
lines changed

1 file changed

+27
-13
lines changed

SwiftCompilerSources/Sources/Optimizer/DataStructures/InstructionRange.swift

Lines changed: 27 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -48,40 +48,45 @@ struct InstructionRange : CustomStringConvertible, NoReflectionChildren {
4848

4949
private var insertedInsts: InstructionSet
5050

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+
5154
init(begin beginInst: Instruction, _ context: some Context) {
5255
self.begin = beginInst
5356
self.blockRange = BasicBlockRange(begin: beginInst.parentBlock, context)
5457
self.insertedInsts = InstructionSet(context)
58+
self.inExclusiveRange = InstructionSet(context)
59+
self.inExclusiveRange.insert(beginInst)
5560
}
5661

5762
/// Insert a potential end instruction.
5863
mutating func insert(_ inst: Instruction) {
5964
insertedInsts.insert(inst)
65+
insertIntoRange(instructions: ReverseInstructionList(first: inst.previous))
6066
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+
}
6174
}
6275

6376
/// 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 {
6578
for inst in other {
6679
insert(inst)
6780
}
6881
}
6982

7083
/// Returns true if the exclusive range contains `inst`.
7184
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
7887
}
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)
8590
}
8691

8792
/// Returns true if the inclusive range contains `inst`.
@@ -129,6 +134,14 @@ struct InstructionRange : CustomStringConvertible, NoReflectionChildren {
129134
}
130135
}
131136

137+
private mutating func insertIntoRange(instructions: ReverseInstructionList) {
138+
for inst in instructions {
139+
if !inExclusiveRange.insert(inst) {
140+
return
141+
}
142+
}
143+
}
144+
132145
var description: String {
133146
return (isValid ? "" : "<invalid>\n") +
134147
"""
@@ -141,6 +154,7 @@ struct InstructionRange : CustomStringConvertible, NoReflectionChildren {
141154

142155
/// TODO: once we have move-only types, make this a real deinit.
143156
mutating func deinitialize() {
157+
inExclusiveRange.deinitialize()
144158
insertedInsts.deinitialize()
145159
blockRange.deinitialize()
146160
}

0 commit comments

Comments
 (0)