|
13 | 13 | #ifndef SWIFT_SIL_BASICBLOCKUTILS_H
|
14 | 14 | #define SWIFT_SIL_BASICBLOCKUTILS_H
|
15 | 15 |
|
16 |
| -#include "swift/SIL/SILValue.h" |
17 | 16 | #include "swift/SIL/BasicBlockBits.h"
|
| 17 | +#include "swift/SIL/BasicBlockDatastructures.h" |
| 18 | +#include "swift/SIL/SILValue.h" |
18 | 19 | #include "llvm/ADT/SetVector.h"
|
19 | 20 | #include "llvm/ADT/SmallPtrSet.h"
|
20 | 21 | #include "llvm/ADT/SmallVector.h"
|
@@ -155,6 +156,76 @@ void findJointPostDominatingSet(
|
155 | 156 | bool checkDominates(SILBasicBlock *sourceBlock, SILBasicBlock *destBlock);
|
156 | 157 | #endif
|
157 | 158 |
|
| 159 | +/// Given a region, specified via \p visitor's \p isInRegion member function, |
| 160 | +/// backwards-reachable from \r root, traverse the region backwards, depth-first |
| 161 | +/// and visit its nodes in the associated post-order. |
| 162 | +/// |
| 163 | +/// interface Visitor { |
| 164 | +/// /// Whether the indicated basic block is within the region of the graph |
| 165 | +/// /// that should be traversed. |
| 166 | +/// bool isInRegion(SILBasicBlock *) |
| 167 | +/// |
| 168 | +/// /// Visit each block in post-order. |
| 169 | +/// void visit(SILBasicBlock *) |
| 170 | +/// } |
| 171 | +template <typename Visitor> |
| 172 | +void visitPostOrderBackwards(SILFunction *function, SILBasicBlock *root, |
| 173 | + Visitor visitor) { |
| 174 | + SmallVector<std::pair<SILBasicBlock *, SILBasicBlock::pred_iterator>, 32> |
| 175 | + stack; |
| 176 | + BasicBlockSet visited(function); |
| 177 | + stack.push_back({root, root->pred_begin()}); |
| 178 | + while (!stack.empty()) { |
| 179 | + while (stack.back().second != stack.back().first->pred_end()) { |
| 180 | + auto predecessor = *stack.back().second; |
| 181 | + stack.back().second++; |
| 182 | + if (!visitor.isInRegion(predecessor)) |
| 183 | + continue; |
| 184 | + if (visited.insert(predecessor)) |
| 185 | + stack.push_back({predecessor, predecessor->pred_begin()}); |
| 186 | + } |
| 187 | + visitor.visit(stack.back().first); |
| 188 | + stack.pop_back(); |
| 189 | + } |
| 190 | +} |
| 191 | + |
| 192 | +/// Given a region, specified via \p visitor's \p isInRegion member function, |
| 193 | +/// backwards-reachable from \r roots, traverse the region in topological order. |
| 194 | +/// Node M shall be visited before node N if and only if there is an edge from |
| 195 | +/// M to N, except for backedges*. |
| 196 | +/// |
| 197 | +/// * The backedges in question are backedges according to backwards depth-first |
| 198 | +/// searches from roots. |
| 199 | +/// |
| 200 | +/// interface Visitor { |
| 201 | +/// /// Whether the indicated basic block is within the region of the graph |
| 202 | +/// /// that should be traversed. |
| 203 | +/// bool isInRegion(SILBasicBlock *) |
| 204 | +/// |
| 205 | +/// /// Visit each block in topological order. |
| 206 | +/// void visit(SILBasicBlock *) |
| 207 | +/// } |
| 208 | +template <typename Visitor> |
| 209 | +void visitSortedTopologicallyBackwards(SILFunction *function, |
| 210 | + ArrayRef<SILBasicBlock *> roots, |
| 211 | + Visitor &visitor) { |
| 212 | + BasicBlockSet visited(function); |
| 213 | + for (auto *root : roots) { |
| 214 | + struct Inner { |
| 215 | + Visitor &outer; |
| 216 | + BasicBlockSet &visited; |
| 217 | + int offset = 0; |
| 218 | + Inner(Visitor &outer, BasicBlockSet &visited) |
| 219 | + : outer(outer), visited(visited) {} |
| 220 | + bool isInRegion(SILBasicBlock *block) { |
| 221 | + return !visited.contains(block) && outer.isInRegion(block); |
| 222 | + } |
| 223 | + void visit(SILBasicBlock *block) { outer.visit(block); } |
| 224 | + }; |
| 225 | + Inner inner(visitor, visited); |
| 226 | + visitPostOrderBackwards(function, root, inner); |
| 227 | + } |
| 228 | +} |
158 | 229 | } // namespace swift
|
159 | 230 |
|
160 | 231 | #endif
|
0 commit comments