blob: 62b72287f97454eec7d63a8d35c2c30d2b4e3bad [file] [log] [blame]
Ted Kremenek58f6f1e2011-10-25 00:25:24 +00001//==- 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