llvm.org GIT mirror llvm / 6d12ee8
Revert "[Dominators] Teach IDF to use level information" This reverts commit r306894. Revert "[Dominators] Add NearestCommonDominator verification" This reverts commit r306893. Revert "[Dominators] Keep tree level in DomTreeNode and use it to find NCD and answer dominance queries" This reverts commit r306892. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@306907 91177308-0d34-0410-b5e6-96231b3b80d8 Jakub Kuderski 2 years ago
5 changed file(s) with 77 addition(s) and 154 deletion(s). Raw diff Collapse all Expand all
8585 private:
8686 DominatorTreeBase &DT;
8787 bool useLiveIn;
88 DenseMap DomLevels;
8889 const SmallPtrSetImpl *LiveInBlocks;
8990 const SmallPtrSetImpl *DefBlocks;
9091 };
6464
6565 NodeT *TheBB;
6666 DomTreeNodeBase *IDom;
67 unsigned Level;
6867 std::vector Children;
6968 mutable unsigned DFSNumIn = ~0;
7069 mutable unsigned DFSNumOut = ~0;
7170
7271 public:
73 DomTreeNodeBase(NodeT *BB, DomTreeNodeBase *iDom)
74 : TheBB(BB), IDom(iDom), Level(IDom ? IDom->Level + 1 : 0) {}
72 DomTreeNodeBase(NodeT *BB, DomTreeNodeBase *iDom) : TheBB(BB), IDom(iDom) {}
7573
7674 using iterator = typename std::vector::iterator;
7775 using const_iterator =
8482
8583 NodeT *getBlock() const { return TheBB; }
8684 DomTreeNodeBase *getIDom() const { return IDom; }
87 unsigned getLevel() const { return Level; }
8885
8986 const std::vector &getChildren() const { return Children; }
9087
10299 if (getNumChildren() != Other->getNumChildren())
103100 return true;
104101
105 if (Level != Other->Level) return true;
106
107102 SmallPtrSet OtherChildren;
108103 for (const DomTreeNodeBase *I : *Other) {
109104 const NodeT *Nd = I->getBlock();
120115
121116 void setIDom(DomTreeNodeBase *NewIDom) {
122117 assert(IDom && "No immediate dominator?");
123 if (IDom == NewIDom) return;
124
125 auto I = find(IDom->Children, this);
126 assert(I != IDom->Children.end() &&
127 "Not in immediate dominator children set!");
128 // I am no longer your child...
129 IDom->Children.erase(I);
130
131 // Switch to new dominator
132 IDom = NewIDom;
133 IDom->Children.push_back(this);
134
135 UpdateLevel();
118 if (IDom != NewIDom) {
119 typename std::vector::iterator I =
120 find(IDom->Children, this);
121 assert(I != IDom->Children.end() &&
122 "Not in immediate dominator children set!");
123 // I am no longer your child...
124 IDom->Children.erase(I);
125
126 // Switch to new dominator
127 IDom = NewIDom;
128 IDom->Children.push_back(this);
129 }
136130 }
137131
138132 /// getDFSNumIn/getDFSNumOut - These return the DFS visitation order for nodes
148142 return this->DFSNumIn >= other->DFSNumIn &&
149143 this->DFSNumOut <= other->DFSNumOut;
150144 }
151
152 void UpdateLevel() {
153 assert(IDom);
154 if (Level == IDom->Level + 1) return;
155
156 SmallVector WorkStack = {this};
157
158 while (!WorkStack.empty()) {
159 DomTreeNodeBase *Current = WorkStack.pop_back_val();
160 Current->Level = Current->IDom->Level + 1;
161
162 for (DomTreeNodeBase *C : *Current) {
163 assert(C->IDom);
164 if (C->Level != C->IDom->Level + 1) WorkStack.push_back(C);
165 }
166 }
167 }
168145 };
169146
170147 template
174151 else
175152 O << " <>";
176153
177 O << " {" << Node->getDFSNumIn() << "," << Node->getDFSNumOut() << "} ["
178 << Node->getLevel() << "]\n";
179
180 return O;
154 O << " {" << Node->getDFSNumIn() << "," << Node->getDFSNumOut() << "}";
155
156 return O << "\n";
181157 }
182158
183159 template
368344 if (!isReachableFromEntry(A))
369345 return false;
370346
371 if (B->getIDom() == A) return true;
372
373 if (A->getIDom() == B) return false;
374
375 // A can only dominate B if it is higher in the tree.
376 if (A->getLevel() >= B->getLevel()) return false;
377
378347 // Compare the result of the tree walk and the dfs numbers, if expensive
379348 // checks are enabled.
380349 #ifdef EXPENSIVE_CHECKS
406375
407376 /// findNearestCommonDominator - Find nearest common dominator basic block
408377 /// for basic block A and B. If there is no such block then return NULL.
409 NodeT *findNearestCommonDominator(NodeT *A, NodeT *B) const {
378 NodeT *findNearestCommonDominator(NodeT *A, NodeT *B) {
410379 assert(A->getParent() == B->getParent() &&
411380 "Two blocks are not in same function");
412381
418387 return &Entry;
419388 }
420389
390 // If B dominates A then B is nearest common dominator.
391 if (dominates(B, A))
392 return B;
393
394 // If A dominates B then A is nearest common dominator.
395 if (dominates(A, B))
396 return A;
397
421398 DomTreeNodeBase *NodeA = getNode(A);
422399 DomTreeNodeBase *NodeB = getNode(B);
423400
424 // Use level information to go up the tree until the levels match. Then
425 // continue going up til we arrive at the same node.
426 while (NodeA && NodeA != NodeB) {
427 if (NodeA->getLevel() < NodeB->getLevel()) std::swap(NodeA, NodeB);
428
429 NodeA = NodeA->IDom;
430 }
431
432 return NodeA ? NodeA->getBlock() : nullptr;
433 }
434
435 const NodeT *findNearestCommonDominator(const NodeT *A,
436 const NodeT *B) const {
401 // If we have DFS info, then we can avoid all allocations by just querying
402 // it from each IDom. Note that because we call 'dominates' twice above, we
403 // expect to call through this code at most 16 times in a row without
404 // building valid DFS information. This is important as below is a *very*
405 // slow tree walk.
406 if (DFSInfoValid) {
407 DomTreeNodeBase *IDomA = NodeA->getIDom();
408 while (IDomA) {
409 if (NodeB->DominatedBy(IDomA))
410 return IDomA->getBlock();
411 IDomA = IDomA->getIDom();
412 }
413 return nullptr;
414 }
415
416 // Collect NodeA dominators set.
417 SmallPtrSet *, 16> NodeADoms;
418 NodeADoms.insert(NodeA);
419 DomTreeNodeBase *IDomA = NodeA->getIDom();
420 while (IDomA) {
421 NodeADoms.insert(IDomA);
422 IDomA = IDomA->getIDom();
423 }
424
425 // Walk NodeB immediate dominators chain and find common dominator node.
426 DomTreeNodeBase *IDomB = NodeB->getIDom();
427 while (IDomB) {
428 if (NodeADoms.count(IDomB) != 0)
429 return IDomB->getBlock();
430
431 IDomB = IDomB->getIDom();
432 }
433
434 return nullptr;
435 }
436
437 const NodeT *findNearestCommonDominator(const NodeT *A, const NodeT *B) {
437438 // Cast away the const qualifiers here. This is ok since
438439 // const is re-introduced on the return type.
439440 return findNearestCommonDominator(const_cast(A),
479480 } else {
480481 assert(Roots.size() == 1);
481482 NodeT *OldRoot = Roots.front();
482 auto &OldNode = DomTreeNodes[OldRoot];
483 OldNode = NewNode->addChild(std::move(DomTreeNodes[OldRoot]));
484 OldNode->IDom = NewNode;
485 OldNode->UpdateLevel();
483 DomTreeNodes[OldRoot] =
484 NewNode->addChild(std::move(DomTreeNodes[OldRoot]));
486485 Roots[0] = BB;
487486 }
488487 return RootNode = NewNode;
279279 }
280280
281281 void doFullDFSWalk(const DomTreeT &DT) {
282 NumToNode.push_back(nullptr);
283282 unsigned Num = 0;
284283 for (auto *Root : DT.Roots)
285284 if (!DT.isPostDominator())
309308 errs() << "DomTree node ";
310309 PrintBlockOrNullptr(errs(), BB);
311310 errs() << " not found by DFS walk!\n";
312 errs().flush();
313
314 return false;
315 }
316 }
317
318 return true;
319 }
320
321 // Check if for every parent with a level L in the tree all of its children
322 // have level L + 1.
323 static bool VerifyLevels(const DomTreeT &DT) {
324 for (auto &NodeToTN : DT.DomTreeNodes) {
325 const TreeNodePtr TN = NodeToTN.second.get();
326 const NodePtr BB = TN->getBlock();
327 if (!BB) continue;
328
329 const TreeNodePtr IDom = TN->getIDom();
330 if (!IDom && TN->getLevel() != 0) {
331 errs() << "Node without an IDom ";
332 PrintBlockOrNullptr(errs(), BB);
333 errs() << " has a nonzero level " << TN->getLevel() << "!\n";
334 errs().flush();
335
336 return false;
337 }
338
339 if (IDom && TN->getLevel() != IDom->getLevel() + 1) {
340 errs() << "Node ";
341 PrintBlockOrNullptr(errs(), BB);
342 errs() << " has level " << TN->getLevel() << " while it's IDom ";
343 PrintBlockOrNullptr(errs(), IDom->getBlock());
344 errs() << " has level " << IDom->getLevel() << "!\n";
345 errs().flush();
346
347 return false;
348 }
349 }
350
351 return true;
352 }
353
354 // Checks if for every edge From -> To in the graph
355 // NCD(From, To) == IDom(To) or To.
356 bool verifyNCD(const DomTreeT &DT) {
357 clear();
358 doFullDFSWalk(DT);
359
360 for (auto &BlockToInfo : NodeToInfo) {
361 auto &Info = BlockToInfo.second;
362
363 const NodePtr From = NumToNode[Info.Parent];
364 if (!From) continue;
365
366 const NodePtr To = BlockToInfo.first;
367 const TreeNodePtr ToTN = DT.getNode(To);
368 assert(ToTN);
369
370 const NodePtr NCD = DT.findNearestCommonDominator(From, To);
371 const TreeNodePtr NCDTN = NCD ? DT.getNode(NCD) : nullptr;
372 const TreeNodePtr ToIDom = ToTN->getIDom();
373 if (NCDTN != ToTN && NCDTN != ToIDom) {
374 errs() << "NearestCommonDominator verification failed:\n\tNCD(From:";
375 PrintBlockOrNullptr(errs(), From);
376 errs() << ", To:";
377 PrintBlockOrNullptr(errs(), To);
378 errs() << ") = ";
379 PrintBlockOrNullptr(errs(), NCD);
380 errs() << ",\t (should be To or IDom[To]: ";
381 PrintBlockOrNullptr(errs(), ToIDom ? ToIDom->getBlock() : nullptr);
382 errs() << ")\n";
383311 errs().flush();
384312
385313 return false;
476404 "NodePtr should be a pointer type");
477405 SemiNCAInfo::type> SNCA;
478406
479 return SNCA.verifyReachability(DT) && SNCA.VerifyLevels(DT) &&
480 SNCA.verifyNCD(DT) && SNCA.verifyParentProperty(DT) &&
407 return SNCA.verifyReachability(DT) && SNCA.verifyParentProperty(DT) &&
481408 SNCA.verifySiblingProperty(DT);
409
482410 }
483411
484412 } // namespace DomTreeBuilder
1919 template
2020 void IDFCalculator::calculate(
2121 SmallVectorImpl &PHIBlocks) {
22 // If we haven't computed dominator tree levels, do so now.
23 if (DomLevels.empty()) {
24 for (auto DFI = df_begin(DT.getRootNode()), DFE = df_end(DT.getRootNode());
25 DFI != DFE; ++DFI) {
26 DomLevels[*DFI] = DFI.getPathLength() - 1;
27 }
28 }
29
2230 // Use a priority queue keyed on dominator tree level so that inserted nodes
2331 // are handled from the bottom of the dominator tree upwards.
2432 typedef std::pair DomTreeNodePair;
2836
2937 for (BasicBlock *BB : *DefBlocks) {
3038 if (DomTreeNode *Node = DT.getNode(BB))
31 PQ.push({Node, Node->getLevel()});
39 PQ.push(std::make_pair(Node, DomLevels.lookup(Node)));
3240 }
3341
3442 SmallVector Worklist;
6371 if (SuccNode->getIDom() == Node)
6472 continue;
6573
66 const unsigned SuccLevel = SuccNode->getLevel();
74 unsigned SuccLevel = DomLevels.lookup(SuccNode);
6775 if (SuccLevel > RootLevel)
6876 continue;
6977
229229 EXPECT_EQ(DT->getNode(BB4)->getDFSNumIn(), 3UL);
230230 EXPECT_EQ(DT->getNode(BB4)->getDFSNumOut(), 4UL);
231231
232 // Check levels before
233 EXPECT_EQ(DT->getNode(BB0)->getLevel(), 0U);
234 EXPECT_EQ(DT->getNode(BB1)->getLevel(), 1U);
235 EXPECT_EQ(DT->getNode(BB2)->getLevel(), 1U);
236 EXPECT_EQ(DT->getNode(BB4)->getLevel(), 1U);
237
238232 // Reattach block 3 to block 1 and recalculate
239233 BB1->getTerminator()->eraseFromParent();
240234 BranchInst::Create(BB4, BB3, ConstantInt::getTrue(F.getContext()), BB1);
252246 EXPECT_EQ(DT->getNode(BB3)->getDFSNumOut(), 3UL);
253247 EXPECT_EQ(DT->getNode(BB4)->getDFSNumIn(), 5UL);
254248 EXPECT_EQ(DT->getNode(BB4)->getDFSNumOut(), 6UL);
255
256 // Check levels after
257 EXPECT_EQ(DT->getNode(BB0)->getLevel(), 0U);
258 EXPECT_EQ(DT->getNode(BB1)->getLevel(), 1U);
259 EXPECT_EQ(DT->getNode(BB2)->getLevel(), 1U);
260 EXPECT_EQ(DT->getNode(BB3)->getLevel(), 2U);
261 EXPECT_EQ(DT->getNode(BB4)->getLevel(), 1U);
262249
263250 // Change root node
264251 DT->verifyDomTree();