llvm.org GIT mirror llvm / b49a900
[Dominators] Split SemiNCA into smaller functions Summary: This patch splits the SemiNCA algorithm into smaller functions. It also adds a new debug macro. In order to perform incremental updates, we need to be able to refire SemiNCA on a subset of CFG nodes (determined by a DFS walk results). We also need to skip nodes that are not deep enough in a DomTree. Reviewers: dberlin, davide, sanjoy, grosser Reviewed By: dberlin, davide Subscribers: llvm-commits Differential Revision: https://reviews.llvm.org/D35282 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@307950 91177308-0d34-0410-b5e6-96231b3b80d8 Jakub Kuderski 3 years ago
1 changed file(s) with 81 addition(s) and 62 deletion(s). Raw diff Collapse all Expand all
2626
2727 #include "llvm/ADT/DepthFirstIterator.h"
2828 #include "llvm/ADT/SmallPtrSet.h"
29 #include "llvm/Support/Debug.h"
2930 #include "llvm/Support/GenericDomTree.h"
31
32 #define DEBUG_TYPE "dom-tree-builder"
3033
3134 namespace llvm {
3235 namespace DomTreeBuilder {
6164 SmallVector ReverseChildren;
6265 };
6366
64 std::vector NumToNode;
67 // Number to node mapping is 1-based. Initialize the mapping to start with
68 // a dummy element.
69 std::vector NumToNode = {nullptr};
6570 DenseMap NodeToInfo;
6671
6772 void clear() {
68 NumToNode.clear();
73 NumToNode = {nullptr}; // Restore to initial state with a dummy start node.
6974 NodeToInfo.clear();
7075 }
7176
176181 return VInInfo.Label;
177182 }
178183
179 template
180 void runSemiNCA(DomTreeT &DT, unsigned NumBlocks) {
181 // Step #1: Number blocks in depth-first order and initialize variables used
182 // in later stages of the algorithm.
183 const unsigned N = doFullDFSWalk(DT, AlwaysDescend);
184
185 // It might be that some blocks did not get a DFS number (e.g., blocks of
186 // infinite loops). In these cases an artificial exit node is required.
187 const bool MultipleRoots =
188 DT.Roots.size() > 1 || (DT.isPostDominator() && N != NumBlocks);
189
184 void runSemiNCA(DomTreeT &DT, const unsigned MinLevel = 0) {
185 const unsigned NextDFSNum(NumToNode.size());
190186 // Initialize IDoms to spanning tree parents.
191 for (unsigned i = 1; i <= N; ++i) {
187 for (unsigned i = 1; i < NextDFSNum; ++i) {
192188 const NodePtr V = NumToNode[i];
193189 auto &VInfo = NodeToInfo[V];
194190 VInfo.IDom = NumToNode[VInfo.Parent];
195191 }
196192
197 // Step #2: Calculate the semidominators of all vertices.
198 for (unsigned i = N; i >= 2; --i) {
193 // Step #1: Calculate the semidominators of all vertices.
194 for (unsigned i = NextDFSNum - 1; i >= 2; --i) {
199195 NodePtr W = NumToNode[i];
200196 auto &WInfo = NodeToInfo[W];
201197
202198 // Initialize the semi dominator to point to the parent node.
203199 WInfo.Semi = WInfo.Parent;
204 for (const auto &N : WInfo.ReverseChildren)
205 if (NodeToInfo.count(N)) { // Only if this predecessor is reachable!
206 unsigned SemiU = NodeToInfo[eval(N, i + 1)].Semi;
207 if (SemiU < WInfo.Semi)
208 WInfo.Semi = SemiU;
209 }
210 }
211
212 // Step #3: Explicitly define the immediate dominator of each vertex.
200 for (const auto &N : WInfo.ReverseChildren) {
201 if (NodeToInfo.count(N) == 0) // Skip unreachable predecessors.
202 continue;
203
204 const TreeNodePtr TN = DT.getNode(N);
205 // Skip predecessors whose level is above the subtree we are processing.
206 if (TN && TN->getLevel() < MinLevel)
207 continue;
208
209 unsigned SemiU = NodeToInfo[eval(N, i + 1)].Semi;
210 if (SemiU < WInfo.Semi) WInfo.Semi = SemiU;
211 }
212 }
213
214 // Step #2: Explicitly define the immediate dominator of each vertex.
213215 // IDom[i] = NCA(SDom[i], SpanningTreeParent(i)).
214216 // Note that the parents were stored in IDoms and later got invalidated
215217 // during path compression in Eval.
216 for (unsigned i = 2; i <= N; ++i) {
218 for (unsigned i = 2; i < NextDFSNum; ++i) {
217219 const NodePtr W = NumToNode[i];
218220 auto &WInfo = NodeToInfo[W];
219221 const unsigned SDomNum = NodeToInfo[NumToNode[WInfo.Semi]].DFSNum;
223225
224226 WInfo.IDom = WIDomCandidate;
225227 }
226
227 if (DT.Roots.empty()) return;
228
229 // Add a node for the root. This node might be the actual root, if there is
230 // one exit block, or it may be the virtual exit (denoted by
231 // (BasicBlock *)0) which postdominates all real exits if there are multiple
232 // exit blocks, or an infinite loop.
233 NodePtr Root = !MultipleRoots ? DT.Roots[0] : nullptr;
234
235 DT.RootNode =
236 (DT.DomTreeNodes[Root] =
237 llvm::make_unique>(Root, nullptr))
238 .get();
239
240 // Loop over all of the reachable blocks in the function...
241 for (unsigned i = 2; i <= N; ++i) {
242 NodePtr W = NumToNode[i];
243
244 // Don't replace this with 'count', the insertion side effect is important
245 if (DT.DomTreeNodes[W])
246 continue; // Haven't calculated this node yet?
247
248 NodePtr ImmDom = getIDom(W);
249
250 assert(ImmDom || DT.DomTreeNodes[nullptr]);
251
252 // Get or calculate the node for the immediate dominator
253 TreeNodePtr IDomNode = getNodeForBlock(ImmDom, DT);
254
255 // Add a new tree node for this BasicBlock, and link it as a child of
256 // IDomNode
257 DT.DomTreeNodes[W] = IDomNode->addChild(
258 llvm::make_unique>(W, IDomNode));
259 }
260228 }
261229
262230 template
263231 unsigned doFullDFSWalk(const DomTreeT &DT, DescendCondition DC) {
264232 unsigned Num = 0;
265 NumToNode.push_back(nullptr);
266233
267234 if (DT.Roots.size() > 1) {
268235 auto &BBInfo = NodeToInfo[nullptr];
280247 }
281248
282249 return Num;
250 }
251
252 void calculateFromScratch(DomTreeT &DT, const unsigned NumBlocks) {
253 // Step #0: Number blocks in depth-first order and initialize variables used
254 // in later stages of the algorithm.
255 const unsigned LastDFSNum = doFullDFSWalk(DT, AlwaysDescend);
256
257 runSemiNCA(DT);
258
259 if (DT.Roots.empty()) return;
260
261 // Add a node for the root. This node might be the actual root, if there is
262 // one exit block, or it may be the virtual exit (denoted by
263 // (BasicBlock *)0) which postdominates all real exits if there are multiple
264 // exit blocks, or an infinite loop.
265 // It might be that some blocks did not get a DFS number (e.g., blocks of
266 // infinite loops). In these cases an artificial exit node is required.
267 const bool MultipleRoots = DT.Roots.size() > 1 || (DT.isPostDominator() &&
268 LastDFSNum != NumBlocks);
269 NodePtr Root = !MultipleRoots ? DT.Roots[0] : nullptr;
270
271 DT.RootNode = (DT.DomTreeNodes[Root] =
272 llvm::make_unique>(Root, nullptr))
273 .get();
274 attachNewSubtree(DT, DT.RootNode);
275 }
276
277 void attachNewSubtree(DomTreeT& DT, const TreeNodePtr AttachTo) {
278 // Attach the first unreachable block to AttachTo.
279 NodeToInfo[NumToNode[1]].IDom = AttachTo->getBlock();
280 // Loop over all of the discovered blocks in the function...
281 for (size_t i = 1, e = NumToNode.size(); i != e; ++i) {
282 NodePtr W = NumToNode[i];
283 DEBUG(dbgs() << "\tdiscovereed a new reachable node ");
284 DEBUG(PrintBlockOrNullptr(dbgs(), W));
285 DEBUG(dbgs() << "\n");
286
287 // Don't replace this with 'count', the insertion side effect is important
288 if (DT.DomTreeNodes[W]) continue; // Haven't calculated this node yet?
289
290 NodePtr ImmDom = getIDom(W);
291
292 // Get or calculate the node for the immediate dominator
293 TreeNodePtr IDomNode = getNodeForBlock(ImmDom, DT);
294
295 // Add a new tree node for this BasicBlock, and link it as a child of
296 // IDomNode
297 DT.DomTreeNodes[W] = IDomNode->addChild(
298 llvm::make_unique>(W, IDomNode));
299 }
283300 }
284301
285302 static void PrintBlockOrNullptr(raw_ostream &O, NodePtr Obj) {
513530 static_assert(std::is_pointer::value,
514531 "NodePtr should be a pointer type");
515532 SemiNCAInfo::type> SNCA;
516 SNCA.template runSemiNCA(DT, GraphTraits::size(&F));
533 SNCA.calculateFromScratch(DT, GraphTraits::size(&F));
517534 }
518535
519536 template
531548 } // namespace DomTreeBuilder
532549 } // namespace llvm
533550
551 #undef DEBUG_TYPE
552
534553 #endif