|
19 | 19 | #define SWIFT_SIL_DOMINANCE_H
|
20 | 20 |
|
21 | 21 | #include "llvm/Support/GenericDomTree.h"
|
| 22 | +#include "swift/Basic/ScopedTracking.h" |
22 | 23 | #include "swift/SIL/CFG.h"
|
23 | 24 |
|
24 | 25 | extern template class llvm::DominatorTreeBase<swift::SILBasicBlock, false>;
|
@@ -184,6 +185,62 @@ class PostDominanceInfo : public PostDominatorTreeBase {
|
184 | 185 | using super::properlyDominates;
|
185 | 186 | };
|
186 | 187 |
|
| 188 | +/// Invoke the given callback for all the reachable blocks |
| 189 | +/// in a function. It will be called in a depth-first, |
| 190 | +/// dominance-consistent order. |
| 191 | +/// |
| 192 | +/// Furthermore, prior to running each block, a tracking scope will |
| 193 | +/// be entered for each of the trackers passed in, as if by: |
| 194 | +/// |
| 195 | +/// typename ScopedTrackingTraits<Tracker>::scope_type scope(tracker); |
| 196 | +/// |
| 197 | +/// This allows state to be saved and restored for each of the trackers, |
| 198 | +/// such that each tracker will only represent state that was computed |
| 199 | +/// in a dominating block. |
| 200 | +template <class... Trackers, class Fn> |
| 201 | +void runInDominanceOrderWithScopes(DominanceInfo *dominance, Fn &&fn, |
| 202 | + Trackers &...trackers) { |
| 203 | + using TrackingStackNode = TrackingScopes<Trackers...>; |
| 204 | + llvm::SmallVector<std::unique_ptr<TrackingStackNode>, 8> trackingStack; |
| 205 | + |
| 206 | + // The stack of work to do. A null item means to pop the top |
| 207 | + // entry off the tracking stack. |
| 208 | + llvm::SmallVector<DominanceInfoNode *, 16> workStack; |
| 209 | + workStack.push_back(dominance->getRootNode()); |
| 210 | + |
| 211 | + while (!workStack.empty()) { |
| 212 | + auto node = workStack.pop_back_val(); |
| 213 | + |
| 214 | + // If the node is null, pop the top entry off the tracking stack. |
| 215 | + if (node == nullptr) { |
| 216 | + (void) trackingStack.pop_back_val(); |
| 217 | + continue; |
| 218 | + } |
| 219 | + |
| 220 | + auto bb = node->getBlock(); |
| 221 | + |
| 222 | + // If the node has no children, build the stack node in local |
| 223 | + // storage to avoid having to heap-allocate it. |
| 224 | + if (node->isLeaf()) { |
| 225 | + TrackingStackNode stackNode(trackers...); |
| 226 | + |
| 227 | + fn(bb); |
| 228 | + |
| 229 | + // Otherwise, we have to use the more general approach. |
| 230 | + } else { |
| 231 | + // Push a tracking stack node. |
| 232 | + trackingStack.emplace_back(new TrackingStackNode(trackers...)); |
| 233 | + // Push a work command to pop the tracking stack node. |
| 234 | + workStack.push_back(nullptr); |
| 235 | + // Push all the child nodes as work items. |
| 236 | + workStack.append(node->begin(), node->end()); |
| 237 | + |
| 238 | + fn(bb); |
| 239 | + } |
| 240 | + } |
| 241 | + |
| 242 | + assert(trackingStack.empty()); |
| 243 | +} |
187 | 244 |
|
188 | 245 | } // end namespace swift
|
189 | 246 |
|
|
0 commit comments