Dominators.cpp revision 7c4629c8bba02762119c873b657329d28abaa4ca
1//==- Dominators.cpp - Construct the Dominance Tree Given CFG ----*- 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// 10// This file implements a simple, fast dominance algorithm for source-level CFGs. 11// 12//===----------------------------------------------------------------------===// 13 14#include "clang/Analysis/Analyses/Dominators.h" 15#include "clang/Analysis/CFG.h" 16#include "clang/Analysis/AnalysisContext.h" 17#include "clang/Analysis/Analyses/PostOrderCFGView.h" 18 19using namespace clang; 20 21DominatorTree::~DominatorTree() { 22 IDoms.clear(); 23 RootNode = 0; 24} 25 26CFGBlock * DominatorTree::getNode(const CFGBlock *B) const { 27 CFGBlockMapTy::const_iterator I = IDoms.find(B); 28 return I != IDoms.end() ? I->second : 0; 29} 30 31bool DominatorTree::properlyDominates(const CFGBlock *A, 32 const CFGBlock *B) const { 33 if (0 == A || 0 == B || A == B) 34 return false; 35 36 // The EntryBlock dominates every other block. 37 if (A == RootNode) 38 return true; 39 40 // Note: The dominator of the EntryBlock is itself. 41 CFGBlock *IDom = getNode(B); 42 while (IDom != A && IDom != RootNode) 43 IDom = getNode(IDom); 44 45 return IDom != RootNode; 46} 47 48bool DominatorTree::dominates(const CFGBlock *A, 49 const CFGBlock *B) const { 50 if (A == B) 51 return true; 52 53 return properlyDominates(A, B); 54} 55 56const CFGBlock * DominatorTree::findNearestCommonDominator 57 (const CFGBlock *A, const CFGBlock *B) const { 58 //If A dominates B, then A is the nearest common dominator 59 if (dominates(A, B)) 60 return A; 61 62 //If B dominates A, then B is the nearest common dominator 63 if (dominates(B, A)) 64 return B; 65 66 //Collect all A's dominators 67 llvm::SmallPtrSet<CFGBlock *, 16> ADoms; 68 ADoms.insert(RootNode); 69 CFGBlock *ADom = getNode(A); 70 while (ADom != RootNode) { 71 ADoms.insert(ADom); 72 ADom = getNode(ADom); 73 } 74 75 //Check all B's dominators against ADoms 76 CFGBlock *BDom = getNode(B); 77 while (BDom != RootNode){ 78 if (ADoms.count(BDom) != 0) 79 return BDom; 80 81 BDom = getNode(BDom); 82 } 83 84 //The RootNode dominates every other node 85 return RootNode; 86} 87 88/// Constructs immediate dominator tree for a given CFG based on the algorithm 89/// described in this paper: 90/// 91/// A Simple, Fast Dominance Algorithm 92/// Keith D. Cooper, Timothy J. Harvey and Ken Kennedy 93/// Software-Practice and Expreience, 2001;4:1-10. 94/// 95/// This implementation is simple and runs faster in practice than the classis 96/// Lengauer-Tarjan algorithm. For detailed discussions, refer to the paper. 97void DominatorTree::BuildDominatorTree() { 98 CFG *cfg = AC.getCFG(); 99 CFGBlock *EntryBlk = &cfg->getEntry(); 100 101 //Sort all CFGBlocks in reverse order 102 PostOrderCFGView *rpocfg = AC.getAnalysis<PostOrderCFGView>(); 103 104 //Set the root of the dominance tree 105 RootNode = EntryBlk; 106 107 //Compute the immediate dominator for each CFGBlock 108 IDoms[EntryBlk] = EntryBlk; 109 bool changed = true; 110 while (changed){ 111 changed = false; 112 113 for (PostOrderCFGView::iterator I = rpocfg->begin(), 114 E = rpocfg->end(); I != E; ++I){ 115 if (EntryBlk == *I) 116 continue; 117 if (const CFGBlock *B = *I) { 118 //Compute immediate dominance information for CFGBlock B 119 CFGBlock *IDom = 0; 120 for (CFGBlock::const_pred_iterator J = B->pred_begin(), 121 K = B->pred_end(); J != K; ++J) 122 if( CFGBlock *P = *J) { 123 if (IDoms.find(P) == IDoms.end()) 124 continue; 125 if (!IDom) 126 IDom = P; 127 else { 128 //intersect IDom and P 129 CFGBlock *B1 = IDom, *B2 = P; 130 while (B1 != B2) { 131 while ((rpocfg->getComparator())(B2,B1)) 132 B1 = IDoms[B1]; 133 while ((rpocfg->getComparator())(B1,B2)) 134 B2 = IDoms[B2]; 135 } 136 IDom = B1; 137 } 138 } 139 if (IDoms[B] != IDom) { 140 IDoms[B] = IDom; 141 changed = true; 142 } 143 } 144 } 145 }//while 146} 147 148void DominatorTree::dump() { 149 CFG *cfg = AC.getCFG(); 150 151 llvm::errs() << "Immediate dominance tree (Node#,IDom#):\n"; 152 for (CFG::const_iterator I = cfg->begin(), 153 E = cfg->end(); I != E; ++I) { 154 assert(IDoms[(*I)] && 155 "Failed to find the immediate dominator for all CFG blocks."); 156 llvm::errs() << "(" << (*I)->getBlockID() 157 << "," << IDoms[(*I)]->getBlockID() << ")\n"; 158 } 159} 160 161