summaryrefslogtreecommitdiff
path: root/lib/Analysis/PostDominators.cpp
blob: 4f9d1d160696f336866748311c1cdbf7642ad835 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
//===- PostDominators.cpp - Post-Dominator Calculation --------------------===//
// 
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
// 
//===----------------------------------------------------------------------===//
//
// This file implements the post-dominator construction algorithms.
//
//===----------------------------------------------------------------------===//

#include "llvm/Analysis/PostDominators.h"
#include "llvm/Instructions.h"
#include "llvm/Support/CFG.h"
#include "llvm/ADT/DepthFirstIterator.h"
#include "llvm/ADT/SetOperations.h"
using namespace llvm;

//===----------------------------------------------------------------------===//
//  PostDominatorSet Implementation
//===----------------------------------------------------------------------===//

static RegisterAnalysis<PostDominatorSet>
B("postdomset", "Post-Dominator Set Construction", true);

// Postdominator set construction.  This converts the specified function to only
// have a single exit node (return stmt), then calculates the post dominance
// sets for the function.
//
bool PostDominatorSet::runOnFunction(Function &F) {
  Doms.clear();   // Reset from the last time we were run...

  // Scan the function looking for the root nodes of the post-dominance
  // relationships.  These blocks end with return and unwind instructions.
  // While we are iterating over the function, we also initialize all of the
  // domsets to empty.
  Roots.clear();
  for (Function::iterator I = F.begin(), E = F.end(); I != E; ++I) {
    Doms[I];  // Initialize to empty

    if (succ_begin(I) == succ_end(I))
      Roots.push_back(I);
  }

  // If there are no exit nodes for the function, postdomsets are all empty.
  // This can happen if the function just contains an infinite loop, for
  // example.
  if (Roots.empty()) return false;

  // If we have more than one root, we insert an artificial "null" exit, which
  // has "virtual edges" to each of the real exit nodes.
  if (Roots.size() > 1)
    Doms[0].insert(0);

  bool Changed;
  do {
    Changed = false;

    std::set<BasicBlock*> Visited;
    DomSetType WorkingSet;

    for (unsigned i = 0, e = Roots.size(); i != e; ++i)
      for (idf_ext_iterator<BasicBlock*> It = idf_ext_begin(Roots[i], Visited),
             E = idf_ext_end(Roots[i], Visited); It != E; ++It) {
        BasicBlock *BB = *It;
        succ_iterator SI = succ_begin(BB), SE = succ_end(BB);
        if (SI != SE) {                // Is there SOME successor?
          // Loop until we get to a successor that has had it's dom set filled
          // in at least once.  We are guaranteed to have this because we are
          // traversing the graph in DFO and have handled start nodes specially.
          //
          while (Doms[*SI].size() == 0) ++SI;
          WorkingSet = Doms[*SI];
          
          for (++SI; SI != SE; ++SI) { // Intersect all of the successor sets
            DomSetType &SuccSet = Doms[*SI];
            if (SuccSet.size())
              set_intersect(WorkingSet, SuccSet);
          }
        } else {
          // If this node has no successors, it must be one of the root nodes.
          // We will already take care of the notion that the node
          // post-dominates itself.  The only thing we have to add is that if
          // there are multiple root nodes, we want to insert a special "null"
          // exit node which dominates the roots as well.
          if (Roots.size() > 1)
            WorkingSet.insert(0);
        }
	
        WorkingSet.insert(BB);           // A block always dominates itself
        DomSetType &BBSet = Doms[BB];
        if (BBSet != WorkingSet) {
          BBSet.swap(WorkingSet);        // Constant time operation!
          Changed = true;                // The sets changed.
        }
        WorkingSet.clear();              // Clear out the set for next iteration
      }
  } while (Changed);
  return false;
}

//===----------------------------------------------------------------------===//
//  ImmediatePostDominators Implementation
//===----------------------------------------------------------------------===//

static RegisterAnalysis<ImmediatePostDominators>
D("postidom", "Immediate Post-Dominators Construction", true);


// calcIDoms - Calculate the immediate dominator mapping, given a set of
// dominators for every basic block.
void ImmediatePostDominators::calcIDoms(const DominatorSetBase &DS) {
  // Loop over all of the nodes that have dominators... figuring out the IDOM
  // for each node...
  //
  for (DominatorSet::const_iterator DI = DS.begin(), DEnd = DS.end(); 
       DI != DEnd; ++DI) {
    BasicBlock *BB = DI->first;
    const DominatorSet::DomSetType &Dominators = DI->second;
    unsigned DomSetSize = Dominators.size();
    if (DomSetSize == 1) continue;  // Root node... IDom = null

    // Loop over all dominators of this node.  This corresponds to looping over
    // nodes in the dominator chain, looking for a node whose dominator set is
    // equal to the current nodes, except that the current node does not exist
    // in it.  This means that it is one level higher in the dom chain than the
    // current node, and it is our idom!
    //
    DominatorSet::DomSetType::const_iterator I = Dominators.begin();
    DominatorSet::DomSetType::const_iterator End = Dominators.end();
    for (; I != End; ++I) {   // Iterate over dominators...
      // All of our dominators should form a chain, where the number of elements
      // in the dominator set indicates what level the node is at in the chain.
      // We want the node immediately above us, so it will have an identical 
      // dominator set, except that BB will not dominate it... therefore it's
      // dominator set size will be one less than BB's...
      //
      if (DS.getDominators(*I).size() == DomSetSize - 1) {
	IDoms[BB] = *I;
	break;
      }
    }
  }
}

//===----------------------------------------------------------------------===//
//  PostDominatorTree Implementation
//===----------------------------------------------------------------------===//

static RegisterAnalysis<PostDominatorTree>
F("postdomtree", "Post-Dominator Tree Construction", true);

void PostDominatorTree::calculate(const PostDominatorSet &DS) {
  if (Roots.empty()) return;
  BasicBlock *Root = Roots.size() == 1 ? Roots[0] : 0;

  Nodes[Root] = RootNode = new Node(Root, 0);   // Add a node for the root...

  // Iterate over all nodes in depth first order...
  for (unsigned i = 0, e = Roots.size(); i != e; ++i)
    for (idf_iterator<BasicBlock*> I = idf_begin(Roots[i]),
           E = idf_end(Roots[i]); I != E; ++I) {
      BasicBlock *BB = *I;
      const DominatorSet::DomSetType &Dominators = DS.getDominators(BB);
      unsigned DomSetSize = Dominators.size();
      if (DomSetSize == 1) continue;  // Root node... IDom = null

      // If we have already computed the immediate dominator for this node,
      // don't revisit.  This can happen due to nodes reachable from multiple
      // roots, but which the idf_iterator doesn't know about.
      if (Nodes.find(BB) != Nodes.end()) continue;

      // Loop over all dominators of this node.  This corresponds to looping
      // over nodes in the dominator chain, looking for a node whose dominator
      // set is equal to the current nodes, except that the current node does
      // not exist in it.  This means that it is one level higher in the dom
      // chain than the current node, and it is our idom!  We know that we have
      // already added a DominatorTree node for our idom, because the idom must
      // be a predecessor in the depth first order that we are iterating through
      // the function.
      //
      for (DominatorSet::DomSetType::const_iterator I = Dominators.begin(),
           E = Dominators.end(); I != E; ++I) {  // Iterate over dominators.
        // All of our dominators should form a chain, where the number
        // of elements in the dominator set indicates what level the
        // node is at in the chain.  We want the node immediately
        // above us, so it will have an identical dominator set,
        // except that BB will not dominate it... therefore it's
        // dominator set size will be one less than BB's...
        //
        if (DS.getDominators(*I).size() == DomSetSize - 1) {
          // We know that the immediate dominator should already have a node, 
          // because we are traversing the CFG in depth first order!
          //
          Node *IDomNode = Nodes[*I];
          assert(IDomNode && "No node for IDOM?");
	  
          // Add a new tree node for this BasicBlock, and link it as a child of
          // IDomNode
          Nodes[BB] = IDomNode->addChild(new Node(BB, IDomNode));
          break;
        }
      }
    }
}

//===----------------------------------------------------------------------===//
//  PostDominanceFrontier Implementation
//===----------------------------------------------------------------------===//

static RegisterAnalysis<PostDominanceFrontier>
H("postdomfrontier", "Post-Dominance Frontier Construction", true);

const DominanceFrontier::DomSetType &
PostDominanceFrontier::calculate(const PostDominatorTree &DT, 
                                 const DominatorTree::Node *Node) {
  // Loop over CFG successors to calculate DFlocal[Node]
  BasicBlock *BB = Node->getBlock();
  DomSetType &S = Frontiers[BB];       // The new set to fill in...
  if (getRoots().empty()) return S;

  if (BB)
    for (pred_iterator SI = pred_begin(BB), SE = pred_end(BB);
         SI != SE; ++SI)
      // Does Node immediately dominate this predecessor?
      if (DT[*SI]->getIDom() != Node)
        S.insert(*SI);

  // At this point, S is DFlocal.  Now we union in DFup's of our children...
  // Loop through and visit the nodes that Node immediately dominates (Node's
  // children in the IDomTree)
  //
  for (PostDominatorTree::Node::const_iterator
         NI = Node->begin(), NE = Node->end(); NI != NE; ++NI) {
    DominatorTree::Node *IDominee = *NI;
    const DomSetType &ChildDF = calculate(DT, IDominee);

    DomSetType::const_iterator CDFI = ChildDF.begin(), CDFE = ChildDF.end();
    for (; CDFI != CDFE; ++CDFI) {
      if (!Node->dominates(DT[*CDFI]))
	S.insert(*CDFI);
    }
  }

  return S;
}

// stub - a dummy function to make linking work ok.
void PostDominanceFrontier::stub() {
}