llvm.org GIT mirror llvm / 59d4f7d
[Dominators] Move helper functions into SemiNCAInfo Summary: Helper functions (DFSPass, ReverseDFSPass, Eval) need SemiNCAInfo anyway, so it's simpler to have them there as member functions. This also makes them simpler by removing template boilerplate. Reviewers: dberlin, sanjoy, chandlerc Reviewed By: dberlin Subscribers: llvm-commits Differential Revision: https://reviews.llvm.org/D34427 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@306579 91177308-0d34-0410-b5e6-96231b3b80d8 Jakub Kuderski 3 years ago
2 changed file(s) with 209 addition(s) and 216 deletion(s). Raw diff Collapse all Expand all
659659 friend void Calculate(DominatorTreeBaseByGraphTraits> &DT,
660660 FuncT &F);
661661
662 void addRoot(NodeT *BB) { this->Roots.push_back(BB); }
662 void addRoot(NodeT *BB) { this->Roots.push_back(BB); }
663663
664664 public:
665665 /// updateDFSNumbers - Assign In and Out numbers to the nodes while walking
7575 llvm::make_unique>(BB, IDomNode)))
7676 .get();
7777 }
78
79 // External storage for depth first iterator that reuses the info lookup map
80 // SemiNCAInfo already has. We don't have a set, but a map instead, so we are
81 // converting the one argument insert calls.
82 struct df_iterator_dom_storage {
83 public:
84 using BaseSet = decltype(NodeToInfo);
85 df_iterator_dom_storage(BaseSet &Storage) : Storage(Storage) {}
86
87 using iterator = typename BaseSet::iterator;
88 std::pair insert(NodePtr N) {
89 return Storage.insert({N, InfoRec()});
90 }
91 void completed(NodePtr) {}
92
93 private:
94 BaseSet &Storage;
95 };
96
97 df_iterator_dom_storage getStorage() { return {NodeToInfo}; }
98
99 unsigned runReverseDFS(NodePtr V, unsigned N) {
100 auto DFStorage = getStorage();
101
102 bool IsChildOfArtificialExit = (N != 0);
103 for (auto I = idf_ext_begin(V, DFStorage), E = idf_ext_end(V, DFStorage);
104 I != E; ++I) {
105 NodePtr BB = *I;
106 auto &BBInfo = NodeToInfo[BB];
107 BBInfo.DFSNum = BBInfo.Semi = ++N;
108 BBInfo.Label = BB;
109 // Set the parent to the top of the visited stack. The stack includes us,
110 // and is 1 based, so we subtract to account for both of these.
111 if (I.getPathLength() > 1)
112 BBInfo.Parent = NodeToInfo[I.getPath(I.getPathLength() - 2)].DFSNum;
113 NumToNode.push_back(BB); // NumToNode[n] = V;
114
115 if (IsChildOfArtificialExit)
116 BBInfo.Parent = 1;
117
118 IsChildOfArtificialExit = false;
119 }
120 return N;
121 }
122
123 unsigned runDFS(NodePtr V, unsigned N) {
124 auto DFStorage = getStorage();
125
126 for (auto I = df_ext_begin(V, DFStorage), E = df_ext_end(V, DFStorage);
127 I != E; ++I) {
128 NodePtr BB = *I;
129 auto &BBInfo = NodeToInfo[BB];
130 BBInfo.DFSNum = BBInfo.Semi = ++N;
131 BBInfo.Label = BB;
132 // Set the parent to the top of the visited stack. The stack includes us,
133 // and is 1 based, so we subtract to account for both of these.
134 if (I.getPathLength() > 1)
135 BBInfo.Parent = NodeToInfo[I.getPath(I.getPathLength() - 2)].DFSNum;
136 NumToNode.push_back(BB); // NumToNode[n] = V;
137 }
138 return N;
139 }
140
141 NodePtr eval(NodePtr VIn, unsigned LastLinked) {
142 auto &VInInfo = NodeToInfo[VIn];
143 if (VInInfo.DFSNum < LastLinked)
144 return VIn;
145
146 SmallVector Work;
147 SmallPtrSet Visited;
148
149 if (VInInfo.Parent >= LastLinked)
150 Work.push_back(VIn);
151
152 while (!Work.empty()) {
153 NodePtr V = Work.back();
154 auto &VInfo = NodeToInfo[V];
155 NodePtr VAncestor = NumToNode[VInfo.Parent];
156
157 // Process Ancestor first
158 if (Visited.insert(VAncestor).second && VInfo.Parent >= LastLinked) {
159 Work.push_back(VAncestor);
160 continue;
161 }
162 Work.pop_back();
163
164 // Update VInfo based on Ancestor info
165 if (VInfo.Parent < LastLinked)
166 continue;
167
168 auto &VAInfo = NodeToInfo[VAncestor];
169 NodePtr VAncestorLabel = VAInfo.Label;
170 NodePtr VLabel = VInfo.Label;
171 if (NodeToInfo[VAncestorLabel].Semi < NodeToInfo[VLabel].Semi)
172 VInfo.Label = VAncestorLabel;
173 VInfo.Parent = VAInfo.Parent;
174 }
175
176 return VInInfo.Label;
177 }
178
179 template
180 void runSemiNCA(unsigned NumBlocks) {
181 unsigned N = 0;
182 NumToNode.push_back(nullptr);
183
184 bool MultipleRoots = (DT.Roots.size() > 1);
185 if (MultipleRoots) {
186 auto &BBInfo = NodeToInfo[nullptr];
187 BBInfo.DFSNum = BBInfo.Semi = ++N;
188 BBInfo.Label = nullptr;
189
190 NumToNode.push_back(nullptr); // NumToNode[n] = V;
191 }
192
193 // Step #1: Number blocks in depth-first order and initialize variables used
194 // in later stages of the algorithm.
195 if (DT.isPostDominator()){
196 for (unsigned i = 0, e = static_cast(DT.Roots.size());
197 i != e; ++i)
198 N = runReverseDFS(DT.Roots[i], N);
199 } else {
200 N = runDFS(DT.Roots[0], N);
201 }
202
203 // It might be that some blocks did not get a DFS number (e.g., blocks of
204 // infinite loops). In these cases an artificial exit node is required.
205 MultipleRoots |= (DT.isPostDominator() && N != NumBlocks);
206
207 // Initialize IDoms to spanning tree parents.
208 for (unsigned i = 1; i <= N; ++i) {
209 const NodePtr V = NumToNode[i];
210 auto &VInfo = NodeToInfo[V];
211 VInfo.IDom = NumToNode[VInfo.Parent];
212 }
213
214 // Step #2: Calculate the semidominators of all vertices.
215 for (unsigned i = N; i >= 2; --i) {
216 NodePtr W = NumToNode[i];
217 auto &WInfo = NodeToInfo[W];
218
219 // Initialize the semi dominator to point to the parent node.
220 WInfo.Semi = WInfo.Parent;
221 for (const auto &N : inverse_children(W))
222 if (NodeToInfo.count(N)) { // Only if this predecessor is reachable!
223 unsigned SemiU = NodeToInfo[eval(N, i + 1)].Semi;
224 if (SemiU < WInfo.Semi)
225 WInfo.Semi = SemiU;
226 }
227 }
228
229 // Step #3: Explicitly define the immediate dominator of each vertex.
230 // IDom[i] = NCA(SDom[i], SpanningTreeParent(i)).
231 // Note that the parents were stored in IDoms and later got invalidated
232 // during path compression in Eval.
233 for (unsigned i = 2; i <= N; ++i) {
234 const NodePtr W = NumToNode[i];
235 auto &WInfo = NodeToInfo[W];
236 const unsigned SDomNum = NodeToInfo[NumToNode[WInfo.Semi]].DFSNum;
237 NodePtr WIDomCandidate = WInfo.IDom;
238 while (NodeToInfo[WIDomCandidate].DFSNum > SDomNum)
239 WIDomCandidate = NodeToInfo[WIDomCandidate].IDom;
240
241 WInfo.IDom = WIDomCandidate;
242 }
243
244 if (DT.Roots.empty()) return;
245
246 // Add a node for the root. This node might be the actual root, if there is
247 // one exit block, or it may be the virtual exit (denoted by
248 // (BasicBlock *)0) which postdominates all real exits if there are multiple
249 // exit blocks, or an infinite loop.
250 NodePtr Root = !MultipleRoots ? DT.Roots[0] : nullptr;
251
252 DT.RootNode =
253 (DT.DomTreeNodes[Root] =
254 llvm::make_unique>(Root, nullptr))
255 .get();
256
257 // Loop over all of the reachable blocks in the function...
258 for (unsigned i = 2; i <= N; ++i) {
259 NodePtr W = NumToNode[i];
260
261 // Don't replace this with 'count', the insertion side effect is important
262 if (DT.DomTreeNodes[W])
263 continue; // Haven't calculated this node yet?
264
265 NodePtr ImmDom = getIDom(W);
266
267 assert(ImmDom || DT.DomTreeNodes[nullptr]);
268
269 // Get or calculate the node for the immediate dominator
270 TreeNodePtr IDomNode = getNodeForBlock(ImmDom);
271
272 // Add a new tree node for this BasicBlock, and link it as a child of
273 // IDomNode
274 DT.DomTreeNodes[W] = IDomNode->addChild(
275 llvm::make_unique>(W, IDomNode));
276 }
277
278 DT.updateDFSNumbers();
279 }
78280 };
79281 } // namespace DomTreeBuilder
80
81 // External storage for depth first iterator that reuses the info lookup map
82 // domtree already has. We don't have a set, but a map instead, so we are
83 // converting the one argument insert calls.
84 template struct df_iterator_dom_storage {
85 public:
86 using BaseSet = DenseMap;
87 df_iterator_dom_storage(BaseSet &Storage) : Storage(Storage) {}
88
89 using iterator = typename BaseSet::iterator;
90 std::pair insert(NodeRef N) {
91 return Storage.insert({N, InfoType()});
92 }
93 void completed(NodeRef) {}
94
95 private:
96 BaseSet &Storage;
97 };
98
99 template
100 class NodeT = typename std::remove_pointer::type>
101 unsigned ReverseDFSPass(NodePtr V, DomTreeBuilder::SemiNCAInfo &SNCA,
102 unsigned N) {
103 using SNCAInfoTy = DomTreeBuilder::SemiNCAInfo;
104 df_iterator_dom_storage DFStorage(
105 SNCA.NodeToInfo);
106
107 bool IsChildOfArtificialExit = (N != 0);
108 for (auto I = idf_ext_begin(V, DFStorage), E = idf_ext_end(V, DFStorage);
109 I != E; ++I) {
110 NodePtr BB = *I;
111 auto &BBInfo = SNCA.NodeToInfo[BB];
112 BBInfo.DFSNum = BBInfo.Semi = ++N;
113 BBInfo.Label = BB;
114 // Set the parent to the top of the visited stack. The stack includes us,
115 // and is 1 based, so we subtract to account for both of these.
116 if (I.getPathLength() > 1)
117 BBInfo.Parent = SNCA.NodeToInfo[I.getPath(I.getPathLength() - 2)].DFSNum;
118 SNCA.NumToNode.push_back(BB); // NumToNode[n] = V;
119
120 if (IsChildOfArtificialExit)
121 BBInfo.Parent = 1;
122
123 IsChildOfArtificialExit = false;
124 }
125 return N;
126 }
127
128 template
129 class NodeT = typename std::remove_pointer::type>
130 unsigned DFSPass(NodePtr V, DomTreeBuilder::SemiNCAInfo &SNCA, unsigned N) {
131 using SNCAInfoTy = DomTreeBuilder::SemiNCAInfo;
132 df_iterator_dom_storage DFStorage(
133 SNCA.NodeToInfo);
134
135 for (auto I = df_ext_begin(V, DFStorage), E = df_ext_end(V, DFStorage);
136 I != E; ++I) {
137 NodePtr BB = *I;
138 auto &BBInfo = SNCA.NodeToInfo[BB];
139 BBInfo.DFSNum = BBInfo.Semi = ++N;
140 BBInfo.Label = BB;
141 // Set the parent to the top of the visited stack. The stack includes us,
142 // and is 1 based, so we subtract to account for both of these.
143 if (I.getPathLength() > 1)
144 BBInfo.Parent = SNCA.NodeToInfo[I.getPath(I.getPathLength() - 2)].DFSNum;
145 SNCA.NumToNode.push_back(BB); // NumToNode[n] = V;
146 }
147 return N;
148 }
149
150 template
151 class NodeT = typename std::remove_pointer::type>
152 NodePtr Eval(NodePtr VIn, DomTreeBuilder::SemiNCAInfo &SNCA,
153 unsigned LastLinked) {
154 auto &VInInfo = SNCA.NodeToInfo[VIn];
155 if (VInInfo.DFSNum < LastLinked)
156 return VIn;
157
158 SmallVector Work;
159 SmallPtrSet Visited;
160
161 if (VInInfo.Parent >= LastLinked)
162 Work.push_back(VIn);
163
164 while (!Work.empty()) {
165 NodePtr V = Work.back();
166 auto &VInfo = SNCA.NodeToInfo[V];
167 NodePtr VAncestor = SNCA.NumToNode[VInfo.Parent];
168
169 // Process Ancestor first
170 if (Visited.insert(VAncestor).second && VInfo.Parent >= LastLinked) {
171 Work.push_back(VAncestor);
172 continue;
173 }
174 Work.pop_back();
175
176 // Update VInfo based on Ancestor info
177 if (VInfo.Parent < LastLinked)
178 continue;
179
180 auto &VAInfo = SNCA.NodeToInfo[VAncestor];
181 NodePtr VAncestorLabel = VAInfo.Label;
182 NodePtr VLabel = VInfo.Label;
183 if (SNCA.NodeToInfo[VAncestorLabel].Semi < SNCA.NodeToInfo[VLabel].Semi)
184 VInfo.Label = VAncestorLabel;
185 VInfo.Parent = VAInfo.Parent;
186 }
187
188 return VInInfo.Label;
189 }
190282
191283 template
192284 void Calculate(DominatorTreeBaseByGraphTraits> &DT,
193285 FuncT &F) {
194 using GraphT = GraphTraits;
195 using NodePtr = typename GraphT::NodeRef;
286 using NodePtr = typename GraphTraits::NodeRef;
196287 static_assert(std::is_pointer::value,
197288 "NodePtr should be a pointer type");
198 using NodeType = typename std::remove_pointer::type;
199
200 unsigned N = 0;
201 DomTreeBuilder::SemiNCAInfo SNCA(DT);
202 SNCA.NumToNode.push_back(nullptr);
203
204 bool MultipleRoots = (DT.Roots.size() > 1);
205 if (MultipleRoots) {
206 auto &BBInfo = SNCA.NodeToInfo[nullptr];
207 BBInfo.DFSNum = BBInfo.Semi = ++N;
208 BBInfo.Label = nullptr;
209
210 SNCA.NumToNode.push_back(nullptr); // NumToNode[n] = V;
211 }
212
213 // Step #1: Number blocks in depth-first order and initialize variables used
214 // in later stages of the algorithm.
215 if (DT.isPostDominator()){
216 for (unsigned i = 0, e = static_cast(DT.Roots.size());
217 i != e; ++i)
218 N = ReverseDFSPass(DT.Roots[i], SNCA, N);
219 } else {
220 N = DFSPass(DT.Roots[0], SNCA, N);
221 }
222
223 // It might be that some blocks did not get a DFS number (e.g., blocks of
224 // infinite loops). In these cases an artificial exit node is required.
225 MultipleRoots |= (DT.isPostDominator() && N != GraphTraits::size(&F));
226
227 // Initialize IDoms to spanning tree parents.
228 for (unsigned i = 1; i <= N; ++i) {
229 const NodePtr V = SNCA.NumToNode[i];
230 auto &VInfo = SNCA.NodeToInfo[V];
231 VInfo.IDom = SNCA.NumToNode[VInfo.Parent];
232 }
233
234 // Step #2: Calculate the semidominators of all vertices.
235 for (unsigned i = N; i >= 2; --i) {
236 NodePtr W = SNCA.NumToNode[i];
237 auto &WInfo = SNCA.NodeToInfo[W];
238
239 // Initialize the semi dominator to point to the parent node.
240 WInfo.Semi = WInfo.Parent;
241 for (const auto &N : inverse_children(W))
242 if (SNCA.NodeToInfo.count(N)) { // Only if this predecessor is reachable!
243 unsigned SemiU = SNCA.NodeToInfo[Eval(N, SNCA, i + 1)].Semi;
244 if (SemiU < WInfo.Semi)
245 WInfo.Semi = SemiU;
246 }
247 }
248
249
250 // Step #3: Explicitly define the immediate dominator of each vertex.
251 // IDom[i] = NCA(SDom[i], SpanningTreeParent(i)).
252 // Note that the parents were stored in IDoms and later got invalidated during
253 // path compression in Eval.
254 for (unsigned i = 2; i <= N; ++i) {
255 const NodePtr W = SNCA.NumToNode[i];
256 auto &WInfo = SNCA.NodeToInfo[W];
257 const unsigned SDomNum = SNCA.NodeToInfo[SNCA.NumToNode[WInfo.Semi]].DFSNum;
258 NodePtr WIDomCandidate = WInfo.IDom;
259 while (SNCA.NodeToInfo[WIDomCandidate].DFSNum > SDomNum)
260 WIDomCandidate = SNCA.NodeToInfo[WIDomCandidate].IDom;
261
262 WInfo.IDom = WIDomCandidate;
263 }
264
265 if (DT.Roots.empty()) return;
266
267 // Add a node for the root. This node might be the actual root, if there is
268 // one exit block, or it may be the virtual exit (denoted by (BasicBlock *)0)
269 // which postdominates all real exits if there are multiple exit blocks, or
270 // an infinite loop.
271 NodePtr Root = !MultipleRoots ? DT.Roots[0] : nullptr;
272
273 DT.RootNode =
274 (DT.DomTreeNodes[Root] =
275 llvm::make_unique>(Root, nullptr))
276 .get();
277
278 // Loop over all of the reachable blocks in the function...
279 for (unsigned i = 2; i <= N; ++i) {
280 NodePtr W = SNCA.NumToNode[i];
281
282 // Don't replace this with 'count', the insertion side effect is important
283 if (DT.DomTreeNodes[W])
284 continue; // Haven't calculated this node yet?
285
286 NodePtr ImmDom = SNCA.getIDom(W);
287
288 assert(ImmDom || DT.DomTreeNodes[nullptr]);
289
290 // Get or calculate the node for the immediate dominator
291 DomTreeNodeBase *IDomNode = SNCA.getNodeForBlock(ImmDom);
292
293 // Add a new tree node for this BasicBlock, and link it as a child of
294 // IDomNode
295 DT.DomTreeNodes[W] = IDomNode->addChild(
296 llvm::make_unique>(W, IDomNode));
297 }
298
299 DT.updateDFSNumbers();
289
290 DomTreeBuilder::SemiNCAInfo::type>
291 SNCA(DT);
292 SNCA.template runSemiNCA(GraphTraits::size(&F));
300293 }
301 } // namespace DomTreeBuilder
294 } // namespace llvm
302295
303296 #endif