|
13 | 13 | #include "swift/SILOptimizer/Utils/ParseTestSpecification.h"
|
14 | 14 | #include "swift/SIL/SILFunction.h"
|
15 | 15 | #include "swift/SIL/SILModule.h"
|
| 16 | +#include "swift/SIL/SILSuccessor.h" |
16 | 17 | #include "swift/SILOptimizer/Utils/InstructionDeleter.h"
|
17 | 18 | #include "llvm/ADT/DenseMap.h"
|
18 | 19 | #include "llvm/ADT/SmallVector.h"
|
@@ -84,55 +85,75 @@ SILInstruction *getInstruction(SILBasicBlock *block, unsigned long index) {
|
84 | 85 | llvm_unreachable("bad index!?");
|
85 | 86 | }
|
86 | 87 |
|
| 88 | +SILBasicBlock *getNextBlock(SILBasicBlock *block) { |
| 89 | + auto next = std::next(block->getIterator()); |
| 90 | + if (next == block->getFunction()->end()) |
| 91 | + return nullptr; |
| 92 | + return &*next; |
| 93 | +} |
| 94 | + |
| 95 | +SILBasicBlock *getPreviousBlock(SILBasicBlock *block) { |
| 96 | + auto iterator = block->getIterator(); |
| 97 | + if (iterator == block->getFunction()->begin()) |
| 98 | + return nullptr; |
| 99 | + return &*std::prev(iterator); |
| 100 | +} |
| 101 | + |
| 102 | +SILInstruction *getNextInstructionIgnoringBlocks(SILInstruction *instruction) { |
| 103 | + if (auto *nextInstruction = instruction->getNextInstruction()) |
| 104 | + return nextInstruction; |
| 105 | + if (auto *nextBlock = getNextBlock(instruction->getParent())) |
| 106 | + return &nextBlock->front(); |
| 107 | + return nullptr; |
| 108 | +} |
| 109 | + |
| 110 | +SILInstruction * |
| 111 | +getPreviousInstructionIgnoringBlocks(SILInstruction *instruction) { |
| 112 | + if (auto *previousInstruction = instruction->getPreviousInstruction()) |
| 113 | + return previousInstruction; |
| 114 | + if (auto *previousBlock = getPreviousBlock(instruction->getParent())) |
| 115 | + return &previousBlock->back(); |
| 116 | + return nullptr; |
| 117 | +} |
| 118 | + |
87 | 119 | SILInstruction *getInstructionOffsetFrom(SILInstruction *base, long offset) {
|
88 | 120 | if (offset == 0) {
|
89 | 121 | return base;
|
90 | 122 | }
|
| 123 | + auto *instruction = base; |
91 | 124 | if (offset > 0) {
|
92 |
| - Optional<unsigned long> baseIndex; |
93 |
| - unsigned long index = 0; |
94 |
| - for (auto &block : *base->getFunction()) { |
95 |
| - for (auto &other : block) { |
96 |
| - if (baseIndex && index == (*baseIndex + offset)) { |
97 |
| - return &other; |
98 |
| - } |
99 |
| - if (&other == base) { |
100 |
| - baseIndex = index; |
101 |
| - } |
102 |
| - ++index; |
103 |
| - } |
104 |
| - } |
105 |
| - llvm_unreachable("positive offset outside of function!?"); |
106 |
| - } |
107 |
| - SmallVector<SILInstruction *, 64> instructions; |
108 |
| - unsigned long index = 0; |
109 |
| - for (auto &block : *base->getFunction()) { |
110 |
| - for (auto &other : block) { |
111 |
| - instructions.push_back(&other); |
112 |
| - if (&other == base) { |
113 |
| - return instructions[index + offset]; |
114 |
| - } |
115 |
| - ++index; |
| 125 | + for (auto index = 0; index < offset; ++index) { |
| 126 | + instruction = getNextInstructionIgnoringBlocks(instruction); |
| 127 | + assert(instruction && "too large an offset!?"); |
116 | 128 | }
|
| 129 | + return instruction; |
117 | 130 | }
|
118 |
| - llvm_unreachable("never found instruction in its own function!?"); |
| 131 | + // offset < 0 |
| 132 | + for (auto index = 0; index > offset; --index) { |
| 133 | + instruction = getPreviousInstructionIgnoringBlocks(instruction); |
| 134 | + assert(instruction && "too negative an offset!?"); |
| 135 | + } |
| 136 | + return instruction; |
119 | 137 | }
|
120 | 138 |
|
121 | 139 | SILBasicBlock *getBlockOffsetFrom(SILBasicBlock *base, long offset) {
|
122 | 140 | if (offset == 0)
|
123 | 141 | return base;
|
124 |
| - if (offset < 0) { |
125 |
| - auto iterator = base->getIterator(); |
126 |
| - for (auto counter = 0; counter > offset; --counter) { |
127 |
| - iterator = std::prev(iterator); |
| 142 | + if (offset > 0) { |
| 143 | + auto *block = base; |
| 144 | + for (auto counter = 0; counter < offset; ++counter) { |
| 145 | + block = getNextBlock(block); |
| 146 | + assert(block && "too large an offset!?"); |
128 | 147 | }
|
129 |
| - return &*iterator; |
| 148 | + return block; |
130 | 149 | }
|
131 |
| - auto iterator = base->getIterator(); |
132 |
| - for (auto counter = 0; counter < offset; ++counter) { |
133 |
| - iterator = std::next(iterator); |
| 150 | + // offset < 0 |
| 151 | + auto *block = base; |
| 152 | + for (auto counter = 0; counter > offset; --counter) { |
| 153 | + block = getPreviousBlock(block); |
| 154 | + assert(block && "too negative an offset!?"); |
134 | 155 | }
|
135 |
| - return &*iterator; |
| 156 | + return block; |
136 | 157 | }
|
137 | 158 |
|
138 | 159 | SILBasicBlock *getBlock(SILFunction *function, unsigned long index) {
|
|
0 commit comments