GenericDomTreeConstruction.h revision 314564
1//===- GenericDomTreeConstruction.h - Dominator Calculation ------*- C++ -*-==//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9/// \file
10///
11/// Generic dominator tree construction - This file provides routines to
12/// construct immediate dominator information for a flow-graph based on the
13/// algorithm described in this document:
14///
15///   A Fast Algorithm for Finding Dominators in a Flowgraph
16///   T. Lengauer & R. Tarjan, ACM TOPLAS July 1979, pgs 121-141.
17///
18/// This implements the O(n*log(n)) versions of EVAL and LINK, because it turns
19/// out that the theoretically slower O(n*log(n)) implementation is actually
20/// faster than the almost-linear O(n*alpha(n)) version, even for large CFGs.
21///
22//===----------------------------------------------------------------------===//
23
24#ifndef LLVM_SUPPORT_GENERICDOMTREECONSTRUCTION_H
25#define LLVM_SUPPORT_GENERICDOMTREECONSTRUCTION_H
26
27#include "llvm/ADT/SmallPtrSet.h"
28#include "llvm/Support/GenericDomTree.h"
29
30namespace llvm {
31
32template <class GraphT>
33unsigned DFSPass(DominatorTreeBaseByGraphTraits<GraphT> &DT,
34                 typename GraphT::NodeRef V, unsigned N) {
35  // This is more understandable as a recursive algorithm, but we can't use the
36  // recursive algorithm due to stack depth issues.  Keep it here for
37  // documentation purposes.
38#if 0
39  InfoRec &VInfo = DT.Info[DT.Roots[i]];
40  VInfo.DFSNum = VInfo.Semi = ++N;
41  VInfo.Label = V;
42
43  Vertex.push_back(V);        // Vertex[n] = V;
44
45  for (succ_iterator SI = succ_begin(V), E = succ_end(V); SI != E; ++SI) {
46    InfoRec &SuccVInfo = DT.Info[*SI];
47    if (SuccVInfo.Semi == 0) {
48      SuccVInfo.Parent = V;
49      N = DTDFSPass(DT, *SI, N);
50    }
51  }
52#else
53  bool IsChildOfArtificialExit = (N != 0);
54
55  SmallVector<
56      std::pair<typename GraphT::NodeRef, typename GraphT::ChildIteratorType>,
57      32>
58      Worklist;
59  Worklist.push_back(std::make_pair(V, GraphT::child_begin(V)));
60  while (!Worklist.empty()) {
61    typename GraphT::NodeRef BB = Worklist.back().first;
62    typename GraphT::ChildIteratorType NextSucc = Worklist.back().second;
63
64    auto &BBInfo = DT.Info[BB];
65
66    // First time we visited this BB?
67    if (NextSucc == GraphT::child_begin(BB)) {
68      BBInfo.DFSNum = BBInfo.Semi = ++N;
69      BBInfo.Label = BB;
70
71      DT.Vertex.push_back(BB);       // Vertex[n] = V;
72
73      if (IsChildOfArtificialExit)
74        BBInfo.Parent = 1;
75
76      IsChildOfArtificialExit = false;
77    }
78
79    // store the DFS number of the current BB - the reference to BBInfo might
80    // get invalidated when processing the successors.
81    unsigned BBDFSNum = BBInfo.DFSNum;
82
83    // If we are done with this block, remove it from the worklist.
84    if (NextSucc == GraphT::child_end(BB)) {
85      Worklist.pop_back();
86      continue;
87    }
88
89    // Increment the successor number for the next time we get to it.
90    ++Worklist.back().second;
91
92    // Visit the successor next, if it isn't already visited.
93    typename GraphT::NodeRef Succ = *NextSucc;
94
95    auto &SuccVInfo = DT.Info[Succ];
96    if (SuccVInfo.Semi == 0) {
97      SuccVInfo.Parent = BBDFSNum;
98      Worklist.push_back(std::make_pair(Succ, GraphT::child_begin(Succ)));
99    }
100  }
101#endif
102    return N;
103}
104
105template <class GraphT>
106typename GraphT::NodeRef Eval(DominatorTreeBaseByGraphTraits<GraphT> &DT,
107                              typename GraphT::NodeRef VIn,
108                              unsigned LastLinked) {
109  auto &VInInfo = DT.Info[VIn];
110  if (VInInfo.DFSNum < LastLinked)
111    return VIn;
112
113  SmallVector<typename GraphT::NodeRef, 32> Work;
114  SmallPtrSet<typename GraphT::NodeRef, 32> Visited;
115
116  if (VInInfo.Parent >= LastLinked)
117    Work.push_back(VIn);
118
119  while (!Work.empty()) {
120    typename GraphT::NodeRef V = Work.back();
121    auto &VInfo = DT.Info[V];
122    typename GraphT::NodeRef VAncestor = DT.Vertex[VInfo.Parent];
123
124    // Process Ancestor first
125    if (Visited.insert(VAncestor).second && VInfo.Parent >= LastLinked) {
126      Work.push_back(VAncestor);
127      continue;
128    }
129    Work.pop_back();
130
131    // Update VInfo based on Ancestor info
132    if (VInfo.Parent < LastLinked)
133      continue;
134
135    auto &VAInfo = DT.Info[VAncestor];
136    typename GraphT::NodeRef VAncestorLabel = VAInfo.Label;
137    typename GraphT::NodeRef VLabel = VInfo.Label;
138    if (DT.Info[VAncestorLabel].Semi < DT.Info[VLabel].Semi)
139      VInfo.Label = VAncestorLabel;
140    VInfo.Parent = VAInfo.Parent;
141  }
142
143  return VInInfo.Label;
144}
145
146template <class FuncT, class NodeT>
147void Calculate(DominatorTreeBaseByGraphTraits<GraphTraits<NodeT>> &DT,
148               FuncT &F) {
149  typedef GraphTraits<NodeT> GraphT;
150  static_assert(std::is_pointer<typename GraphT::NodeRef>::value,
151                "NodeRef should be pointer type");
152  typedef typename std::remove_pointer<typename GraphT::NodeRef>::type NodeType;
153
154  unsigned N = 0;
155  bool MultipleRoots = (DT.Roots.size() > 1);
156  if (MultipleRoots) {
157    auto &BBInfo = DT.Info[nullptr];
158    BBInfo.DFSNum = BBInfo.Semi = ++N;
159    BBInfo.Label = nullptr;
160
161    DT.Vertex.push_back(nullptr);       // Vertex[n] = V;
162  }
163
164  // Step #1: Number blocks in depth-first order and initialize variables used
165  // in later stages of the algorithm.
166  for (unsigned i = 0, e = static_cast<unsigned>(DT.Roots.size());
167       i != e; ++i)
168    N = DFSPass<GraphT>(DT, DT.Roots[i], N);
169
170  // it might be that some blocks did not get a DFS number (e.g., blocks of
171  // infinite loops). In these cases an artificial exit node is required.
172  MultipleRoots |= (DT.isPostDominator() && N != GraphTraits<FuncT*>::size(&F));
173
174  // When naively implemented, the Lengauer-Tarjan algorithm requires a separate
175  // bucket for each vertex. However, this is unnecessary, because each vertex
176  // is only placed into a single bucket (that of its semidominator), and each
177  // vertex's bucket is processed before it is added to any bucket itself.
178  //
179  // Instead of using a bucket per vertex, we use a single array Buckets that
180  // has two purposes. Before the vertex V with preorder number i is processed,
181  // Buckets[i] stores the index of the first element in V's bucket. After V's
182  // bucket is processed, Buckets[i] stores the index of the next element in the
183  // bucket containing V, if any.
184  SmallVector<unsigned, 32> Buckets;
185  Buckets.resize(N + 1);
186  for (unsigned i = 1; i <= N; ++i)
187    Buckets[i] = i;
188
189  for (unsigned i = N; i >= 2; --i) {
190    typename GraphT::NodeRef W = DT.Vertex[i];
191    auto &WInfo = DT.Info[W];
192
193    // Step #2: Implicitly define the immediate dominator of vertices
194    for (unsigned j = i; Buckets[j] != i; j = Buckets[j]) {
195      typename GraphT::NodeRef V = DT.Vertex[Buckets[j]];
196      typename GraphT::NodeRef U = Eval<GraphT>(DT, V, i + 1);
197      DT.IDoms[V] = DT.Info[U].Semi < i ? U : W;
198    }
199
200    // Step #3: Calculate the semidominators of all vertices
201
202    // initialize the semi dominator to point to the parent node
203    WInfo.Semi = WInfo.Parent;
204    typedef GraphTraits<Inverse<NodeT> > InvTraits;
205    for (typename InvTraits::ChildIteratorType CI =
206         InvTraits::child_begin(W),
207         E = InvTraits::child_end(W); CI != E; ++CI) {
208      typename InvTraits::NodeRef N = *CI;
209      if (DT.Info.count(N)) {  // Only if this predecessor is reachable!
210        unsigned SemiU = DT.Info[Eval<GraphT>(DT, N, i + 1)].Semi;
211        if (SemiU < WInfo.Semi)
212          WInfo.Semi = SemiU;
213      }
214    }
215
216    // If V is a non-root vertex and sdom(V) = parent(V), then idom(V) is
217    // necessarily parent(V). In this case, set idom(V) here and avoid placing
218    // V into a bucket.
219    if (WInfo.Semi == WInfo.Parent) {
220      DT.IDoms[W] = DT.Vertex[WInfo.Parent];
221    } else {
222      Buckets[i] = Buckets[WInfo.Semi];
223      Buckets[WInfo.Semi] = i;
224    }
225  }
226
227  if (N >= 1) {
228    typename GraphT::NodeRef Root = DT.Vertex[1];
229    for (unsigned j = 1; Buckets[j] != 1; j = Buckets[j]) {
230      typename GraphT::NodeRef V = DT.Vertex[Buckets[j]];
231      DT.IDoms[V] = Root;
232    }
233  }
234
235  // Step #4: Explicitly define the immediate dominator of each vertex
236  for (unsigned i = 2; i <= N; ++i) {
237    typename GraphT::NodeRef W = DT.Vertex[i];
238    typename GraphT::NodeRef &WIDom = DT.IDoms[W];
239    if (WIDom != DT.Vertex[DT.Info[W].Semi])
240      WIDom = DT.IDoms[WIDom];
241  }
242
243  if (DT.Roots.empty()) return;
244
245  // Add a node for the root.  This node might be the actual root, if there is
246  // one exit block, or it may be the virtual exit (denoted by (BasicBlock *)0)
247  // which postdominates all real exits if there are multiple exit blocks, or
248  // an infinite loop.
249  typename GraphT::NodeRef Root = !MultipleRoots ? DT.Roots[0] : nullptr;
250
251  DT.RootNode =
252      (DT.DomTreeNodes[Root] =
253           llvm::make_unique<DomTreeNodeBase<NodeType>>(Root, nullptr))
254          .get();
255
256  // Loop over all of the reachable blocks in the function...
257  for (unsigned i = 2; i <= N; ++i) {
258    typename GraphT::NodeRef W = DT.Vertex[i];
259
260    // Don't replace this with 'count', the insertion side effect is important
261    if (DT.DomTreeNodes[W])
262      continue; // Haven't calculated this node yet?
263
264    typename GraphT::NodeRef ImmDom = DT.getIDom(W);
265
266    assert(ImmDom || DT.DomTreeNodes[nullptr]);
267
268    // Get or calculate the node for the immediate dominator
269    DomTreeNodeBase<NodeType> *IDomNode = DT.getNodeForBlock(ImmDom);
270
271    // Add a new tree node for this BasicBlock, and link it as a child of
272    // IDomNode
273    DT.DomTreeNodes[W] = IDomNode->addChild(
274        llvm::make_unique<DomTreeNodeBase<NodeType>>(W, IDomNode));
275  }
276
277  // Free temporary memory used to construct idom's
278  DT.IDoms.clear();
279  DT.Info.clear();
280  DT.Vertex.clear();
281  DT.Vertex.shrink_to_fit();
282
283  DT.updateDFSNumbers();
284}
285}
286
287#endif
288