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/DepthFirstIterator.h" 28#include "llvm/ADT/SmallPtrSet.h" 29#include "llvm/Support/GenericDomTree.h" 30 31namespace llvm { 32 33// External storage for depth first iterator that reuses the info lookup map 34// domtree already has. We don't have a set, but a map instead, so we are 35// converting the one argument insert calls. 36template <class NodeRef, class InfoType> struct df_iterator_dom_storage { 37public: 38 typedef DenseMap<NodeRef, InfoType> BaseSet; 39 df_iterator_dom_storage(BaseSet &Storage) : Storage(Storage) {} 40 41 typedef typename BaseSet::iterator iterator; 42 std::pair<iterator, bool> insert(NodeRef N) { 43 return Storage.insert({N, InfoType()}); 44 } 45 void completed(NodeRef) {} 46 47private: 48 BaseSet &Storage; 49}; 50 51template <class GraphT> 52unsigned ReverseDFSPass(DominatorTreeBaseByGraphTraits<GraphT> &DT, 53 typename GraphT::NodeRef V, unsigned N) { 54 df_iterator_dom_storage< 55 typename GraphT::NodeRef, 56 typename DominatorTreeBaseByGraphTraits<GraphT>::InfoRec> 57 DFStorage(DT.Info); 58 bool IsChildOfArtificialExit = (N != 0); 59 for (auto I = idf_ext_begin(V, DFStorage), E = idf_ext_end(V, DFStorage); 60 I != E; ++I) { 61 typename GraphT::NodeRef BB = *I; 62 auto &BBInfo = DT.Info[BB]; 63 BBInfo.DFSNum = BBInfo.Semi = ++N; 64 BBInfo.Label = BB; 65 // Set the parent to the top of the visited stack. The stack includes us, 66 // and is 1 based, so we subtract to account for both of these. 67 if (I.getPathLength() > 1) 68 BBInfo.Parent = DT.Info[I.getPath(I.getPathLength() - 2)].DFSNum; 69 DT.Vertex.push_back(BB); // Vertex[n] = V; 70 71 if (IsChildOfArtificialExit) 72 BBInfo.Parent = 1; 73 74 IsChildOfArtificialExit = false; 75 } 76 return N; 77} 78template <class GraphT> 79unsigned DFSPass(DominatorTreeBaseByGraphTraits<GraphT> &DT, 80 typename GraphT::NodeRef V, unsigned N) { 81 df_iterator_dom_storage< 82 typename GraphT::NodeRef, 83 typename DominatorTreeBaseByGraphTraits<GraphT>::InfoRec> 84 DFStorage(DT.Info); 85 for (auto I = df_ext_begin(V, DFStorage), E = df_ext_end(V, DFStorage); 86 I != E; ++I) { 87 typename GraphT::NodeRef BB = *I; 88 auto &BBInfo = DT.Info[BB]; 89 BBInfo.DFSNum = BBInfo.Semi = ++N; 90 BBInfo.Label = BB; 91 // Set the parent to the top of the visited stack. The stack includes us, 92 // and is 1 based, so we subtract to account for both of these. 93 if (I.getPathLength() > 1) 94 BBInfo.Parent = DT.Info[I.getPath(I.getPathLength() - 2)].DFSNum; 95 DT.Vertex.push_back(BB); // Vertex[n] = V; 96 } 97 return N; 98} 99 100template <class GraphT> 101typename GraphT::NodeRef Eval(DominatorTreeBaseByGraphTraits<GraphT> &DT, 102 typename GraphT::NodeRef VIn, 103 unsigned LastLinked) { 104 auto &VInInfo = DT.Info[VIn]; 105 if (VInInfo.DFSNum < LastLinked) 106 return VIn; 107 108 SmallVector<typename GraphT::NodeRef, 32> Work; 109 SmallPtrSet<typename GraphT::NodeRef, 32> Visited; 110 111 if (VInInfo.Parent >= LastLinked) 112 Work.push_back(VIn); 113 114 while (!Work.empty()) { 115 typename GraphT::NodeRef V = Work.back(); 116 auto &VInfo = DT.Info[V]; 117 typename GraphT::NodeRef VAncestor = DT.Vertex[VInfo.Parent]; 118 119 // Process Ancestor first 120 if (Visited.insert(VAncestor).second && VInfo.Parent >= LastLinked) { 121 Work.push_back(VAncestor); 122 continue; 123 } 124 Work.pop_back(); 125 126 // Update VInfo based on Ancestor info 127 if (VInfo.Parent < LastLinked) 128 continue; 129 130 auto &VAInfo = DT.Info[VAncestor]; 131 typename GraphT::NodeRef VAncestorLabel = VAInfo.Label; 132 typename GraphT::NodeRef VLabel = VInfo.Label; 133 if (DT.Info[VAncestorLabel].Semi < DT.Info[VLabel].Semi) 134 VInfo.Label = VAncestorLabel; 135 VInfo.Parent = VAInfo.Parent; 136 } 137 138 return VInInfo.Label; 139} 140 141template <class FuncT, class NodeT> 142void Calculate(DominatorTreeBaseByGraphTraits<GraphTraits<NodeT>> &DT, 143 FuncT &F) { 144 typedef GraphTraits<NodeT> GraphT; 145 static_assert(std::is_pointer<typename GraphT::NodeRef>::value, 146 "NodeRef should be pointer type"); 147 typedef typename std::remove_pointer<typename GraphT::NodeRef>::type NodeType; 148 149 unsigned N = 0; 150 bool MultipleRoots = (DT.Roots.size() > 1); 151 if (MultipleRoots) { 152 auto &BBInfo = DT.Info[nullptr]; 153 BBInfo.DFSNum = BBInfo.Semi = ++N; 154 BBInfo.Label = nullptr; 155 156 DT.Vertex.push_back(nullptr); // Vertex[n] = V; 157 } 158 159 // Step #1: Number blocks in depth-first order and initialize variables used 160 // in later stages of the algorithm. 161 if (DT.isPostDominator()){ 162 for (unsigned i = 0, e = static_cast<unsigned>(DT.Roots.size()); 163 i != e; ++i) 164 N = ReverseDFSPass<GraphT>(DT, DT.Roots[i], N); 165 } else { 166 N = DFSPass<GraphT>(DT, DT.Roots[0], N); 167 } 168 169 // it might be that some blocks did not get a DFS number (e.g., blocks of 170 // infinite loops). In these cases an artificial exit node is required. 171 MultipleRoots |= (DT.isPostDominator() && N != GraphTraits<FuncT*>::size(&F)); 172 173 // When naively implemented, the Lengauer-Tarjan algorithm requires a separate 174 // bucket for each vertex. However, this is unnecessary, because each vertex 175 // is only placed into a single bucket (that of its semidominator), and each 176 // vertex's bucket is processed before it is added to any bucket itself. 177 // 178 // Instead of using a bucket per vertex, we use a single array Buckets that 179 // has two purposes. Before the vertex V with preorder number i is processed, 180 // Buckets[i] stores the index of the first element in V's bucket. After V's 181 // bucket is processed, Buckets[i] stores the index of the next element in the 182 // bucket containing V, if any. 183 SmallVector<unsigned, 32> Buckets; 184 Buckets.resize(N + 1); 185 for (unsigned i = 1; i <= N; ++i) 186 Buckets[i] = i; 187 188 for (unsigned i = N; i >= 2; --i) { 189 typename GraphT::NodeRef W = DT.Vertex[i]; 190 auto &WInfo = DT.Info[W]; 191 192 // Step #2: Implicitly define the immediate dominator of vertices 193 for (unsigned j = i; Buckets[j] != i; j = Buckets[j]) { 194 typename GraphT::NodeRef V = DT.Vertex[Buckets[j]]; 195 typename GraphT::NodeRef U = Eval<GraphT>(DT, V, i + 1); 196 DT.IDoms[V] = DT.Info[U].Semi < i ? U : W; 197 } 198 199 // Step #3: Calculate the semidominators of all vertices 200 201 // initialize the semi dominator to point to the parent node 202 WInfo.Semi = WInfo.Parent; 203 for (const auto &N : inverse_children<NodeT>(W)) 204 if (DT.Info.count(N)) { // Only if this predecessor is reachable! 205 unsigned SemiU = DT.Info[Eval<GraphT>(DT, N, i + 1)].Semi; 206 if (SemiU < WInfo.Semi) 207 WInfo.Semi = SemiU; 208 } 209 210 // If V is a non-root vertex and sdom(V) = parent(V), then idom(V) is 211 // necessarily parent(V). In this case, set idom(V) here and avoid placing 212 // V into a bucket. 213 if (WInfo.Semi == WInfo.Parent) { 214 DT.IDoms[W] = DT.Vertex[WInfo.Parent]; 215 } else { 216 Buckets[i] = Buckets[WInfo.Semi]; 217 Buckets[WInfo.Semi] = i; 218 } 219 } 220 221 if (N >= 1) { 222 typename GraphT::NodeRef Root = DT.Vertex[1]; 223 for (unsigned j = 1; Buckets[j] != 1; j = Buckets[j]) { 224 typename GraphT::NodeRef V = DT.Vertex[Buckets[j]]; 225 DT.IDoms[V] = Root; 226 } 227 } 228 229 // Step #4: Explicitly define the immediate dominator of each vertex 230 for (unsigned i = 2; i <= N; ++i) { 231 typename GraphT::NodeRef W = DT.Vertex[i]; 232 typename GraphT::NodeRef &WIDom = DT.IDoms[W]; 233 if (WIDom != DT.Vertex[DT.Info[W].Semi]) 234 WIDom = DT.IDoms[WIDom]; 235 } 236 237 if (DT.Roots.empty()) return; 238 239 // Add a node for the root. This node might be the actual root, if there is 240 // one exit block, or it may be the virtual exit (denoted by (BasicBlock *)0) 241 // which postdominates all real exits if there are multiple exit blocks, or 242 // an infinite loop. 243 typename GraphT::NodeRef Root = !MultipleRoots ? DT.Roots[0] : nullptr; 244 245 DT.RootNode = 246 (DT.DomTreeNodes[Root] = 247 llvm::make_unique<DomTreeNodeBase<NodeType>>(Root, nullptr)) 248 .get(); 249 250 // Loop over all of the reachable blocks in the function... 251 for (unsigned i = 2; i <= N; ++i) { 252 typename GraphT::NodeRef W = DT.Vertex[i]; 253 254 // Don't replace this with 'count', the insertion side effect is important 255 if (DT.DomTreeNodes[W]) 256 continue; // Haven't calculated this node yet? 257 258 typename GraphT::NodeRef ImmDom = DT.getIDom(W); 259 260 assert(ImmDom || DT.DomTreeNodes[nullptr]); 261 262 // Get or calculate the node for the immediate dominator 263 DomTreeNodeBase<NodeType> *IDomNode = DT.getNodeForBlock(ImmDom); 264 265 // Add a new tree node for this BasicBlock, and link it as a child of 266 // IDomNode 267 DT.DomTreeNodes[W] = IDomNode->addChild( 268 llvm::make_unique<DomTreeNodeBase<NodeType>>(W, IDomNode)); 269 } 270 271 // Free temporary memory used to construct idom's 272 DT.IDoms.clear(); 273 DT.Info.clear(); 274 DT.Vertex.clear(); 275 DT.Vertex.shrink_to_fit(); 276 277 DT.updateDFSNumbers(); 278} 279} 280 281#endif 282