2b155584683e9dfc59c26847cd3d8bff4528068f
[oota-llvm.git] / include / llvm / Analysis / IntervalIterator.h
1 //===- IntervalIterator.h - Interval Iterator Declaration -------*- C++ -*-===//
2 //
3 // This file defines an iterator that enumerates the intervals in a control flow
4 // graph of some sort.  This iterator is parametric, allowing iterator over the
5 // following types of graphs:
6 // 
7 //  1. A Function* object, composed of BasicBlock nodes.
8 //  2. An IntervalPartition& object, composed of Interval nodes.
9 //
10 // This iterator is defined to walk the control flow graph, returning intervals
11 // in depth first order.  These intervals are completely filled in except for
12 // the predecessor fields (the successor information is filled in however).
13 //
14 // By default, the intervals created by this iterator are deleted after they 
15 // are no longer any use to the iterator.  This behavior can be changed by
16 // passing a false value into the intervals_begin() function. This causes the 
17 // IOwnMem member to be set, and the intervals to not be deleted.
18 //
19 // It is only safe to use this if all of the intervals are deleted by the caller
20 // and all of the intervals are processed.  However, the user of the iterator is
21 // not allowed to modify or delete the intervals until after the iterator has
22 // been used completely.  The IntervalPartition class uses this functionality.
23 //
24 //===----------------------------------------------------------------------===//
25
26 #ifndef LLVM_INTERVAL_ITERATOR_H
27 #define LLVM_INTERVAL_ITERATOR_H
28
29 #include "llvm/Analysis/IntervalPartition.h"
30 #include "llvm/Function.h"
31 #include "llvm/Support/CFG.h"
32 #include <stack>
33 #include <set>
34 #include <algorithm>
35
36 // getNodeHeader - Given a source graph node and the source graph, return the 
37 // BasicBlock that is the header node.  This is the opposite of
38 // getSourceGraphNode.
39 //
40 inline BasicBlock *getNodeHeader(BasicBlock *BB) { return BB; }
41 inline BasicBlock *getNodeHeader(Interval *I) { return I->getHeaderNode(); }
42
43 // getSourceGraphNode - Given a BasicBlock and the source graph, return the 
44 // source graph node that corresponds to the BasicBlock.  This is the opposite
45 // of getNodeHeader.
46 //
47 inline BasicBlock *getSourceGraphNode(Function *, BasicBlock *BB) {
48   return BB; 
49 }
50 inline Interval *getSourceGraphNode(IntervalPartition *IP, BasicBlock *BB) { 
51   return IP->getBlockInterval(BB);
52 }
53
54 // addNodeToInterval - This method exists to assist the generic ProcessNode
55 // with the task of adding a node to the new interval, depending on the 
56 // type of the source node.  In the case of a CFG source graph (BasicBlock 
57 // case), the BasicBlock itself is added to the interval.
58 //
59 inline void addNodeToInterval(Interval *Int, BasicBlock *BB) {
60   Int->Nodes.push_back(BB);
61 }
62
63 // addNodeToInterval - This method exists to assist the generic ProcessNode
64 // with the task of adding a node to the new interval, depending on the 
65 // type of the source node.  In the case of a CFG source graph (BasicBlock 
66 // case), the BasicBlock itself is added to the interval.  In the case of
67 // an IntervalPartition source graph (Interval case), all of the member
68 // BasicBlocks are added to the interval.
69 //
70 inline void addNodeToInterval(Interval *Int, Interval *I) {
71   // Add all of the nodes in I as new nodes in Int.
72   copy(I->Nodes.begin(), I->Nodes.end(), back_inserter(Int->Nodes));
73 }
74
75
76
77
78
79 template<class NodeTy, class OrigContainer_t, class GT = GraphTraits<NodeTy*>,
80          class IGT = GraphTraits<Inverse<NodeTy*> > >
81 class IntervalIterator {
82   std::stack<std::pair<Interval*, typename Interval::succ_iterator> > IntStack;
83   std::set<BasicBlock*> Visited;
84   OrigContainer_t *OrigContainer;
85   bool IOwnMem;     // If True, delete intervals when done with them
86                     // See file header for conditions of use
87 public:
88   typedef BasicBlock* _BB;
89
90   typedef IntervalIterator<NodeTy, OrigContainer_t> _Self;
91   typedef std::forward_iterator_tag iterator_category;
92  
93   IntervalIterator() {} // End iterator, empty stack
94   IntervalIterator(Function *M, bool OwnMemory) : IOwnMem(OwnMemory) {
95     OrigContainer = M;
96     if (!ProcessInterval(&M->front())) {
97       assert(0 && "ProcessInterval should never fail for first interval!");
98     }
99   }
100
101   IntervalIterator(IntervalPartition &IP, bool OwnMemory) : IOwnMem(OwnMemory) {
102     OrigContainer = &IP;
103     if (!ProcessInterval(IP.getRootInterval())) {
104       assert(0 && "ProcessInterval should never fail for first interval!");
105     }
106   }
107
108   inline ~IntervalIterator() {
109     if (IOwnMem)
110       while (!IntStack.empty()) {
111         delete operator*();
112         IntStack.pop();
113       }
114   }
115
116   inline bool operator==(const _Self& x) const { return IntStack == x.IntStack;}
117   inline bool operator!=(const _Self& x) const { return !operator==(x); }
118
119   inline const Interval *operator*() const { return IntStack.top().first; }
120   inline       Interval *operator*()       { return IntStack.top().first; }
121   inline const Interval *operator->() const { return operator*(); }
122   inline       Interval *operator->()       { return operator*(); }
123
124   _Self& operator++() {  // Preincrement
125     assert(!IntStack.empty() && "Attempting to use interval iterator at end!");
126     do {
127       // All of the intervals on the stack have been visited.  Try visiting
128       // their successors now.
129       Interval::succ_iterator &SuccIt = IntStack.top().second,
130                                 EndIt = succ_end(IntStack.top().first);
131       while (SuccIt != EndIt) {                 // Loop over all interval succs
132         bool Done = ProcessInterval(getSourceGraphNode(OrigContainer, *SuccIt));
133         ++SuccIt;                               // Increment iterator
134         if (Done) return *this;                 // Found a new interval! Use it!
135       }
136
137       // Free interval memory... if necessary
138       if (IOwnMem) delete IntStack.top().first;
139
140       // We ran out of successors for this interval... pop off the stack
141       IntStack.pop();
142     } while (!IntStack.empty());
143
144     return *this; 
145   }
146   inline _Self operator++(int) { // Postincrement
147     _Self tmp = *this; ++*this; return tmp; 
148   }
149
150 private:
151   // ProcessInterval - This method is used during the construction of the 
152   // interval graph.  It walks through the source graph, recursively creating
153   // an interval per invokation until the entire graph is covered.  This uses
154   // the ProcessNode method to add all of the nodes to the interval.
155   //
156   // This method is templated because it may operate on two different source
157   // graphs: a basic block graph, or a preexisting interval graph.
158   //
159   bool ProcessInterval(NodeTy *Node) {
160     BasicBlock *Header = getNodeHeader(Node);
161     if (Visited.count(Header)) return false;
162
163     Interval *Int = new Interval(Header);
164     Visited.insert(Header);   // The header has now been visited!
165
166     // Check all of our successors to see if they are in the interval...
167     for (typename GT::ChildIteratorType I = GT::child_begin(Node),
168            E = GT::child_end(Node); I != E; ++I)
169       ProcessNode(Int, getSourceGraphNode(OrigContainer, *I));
170
171     IntStack.push(make_pair(Int, succ_begin(Int)));
172     return true;
173   }
174   
175   // ProcessNode - This method is called by ProcessInterval to add nodes to the
176   // interval being constructed, and it is also called recursively as it walks
177   // the source graph.  A node is added to the current interval only if all of
178   // its predecessors are already in the graph.  This also takes care of keeping
179   // the successor set of an interval up to date.
180   //
181   // This method is templated because it may operate on two different source
182   // graphs: a basic block graph, or a preexisting interval graph.
183   //
184   void ProcessNode(Interval *Int, NodeTy *Node) {
185     assert(Int && "Null interval == bad!");
186     assert(Node && "Null Node == bad!");
187   
188     BasicBlock *NodeHeader = getNodeHeader(Node);
189
190     if (Visited.count(NodeHeader)) {     // Node already been visited?
191       if (Int->contains(NodeHeader)) {   // Already in this interval...
192         return;
193       } else {                           // In other interval, add as successor
194         if (!Int->isSuccessor(NodeHeader)) // Add only if not already in set
195           Int->Successors.push_back(NodeHeader);
196       }
197     } else {                             // Otherwise, not in interval yet
198       for (typename IGT::ChildIteratorType I = IGT::child_begin(Node), 
199              E = IGT::child_end(Node); I != E; ++I) {
200         if (!Int->contains(*I)) {        // If pred not in interval, we can't be
201           if (!Int->isSuccessor(NodeHeader)) // Add only if not already in set
202             Int->Successors.push_back(NodeHeader);
203           return;                        // See you later
204         }
205       }
206
207       // If we get here, then all of the predecessors of BB are in the interval
208       // already.  In this case, we must add BB to the interval!
209       addNodeToInterval(Int, Node);
210       Visited.insert(NodeHeader);     // The node has now been visited!
211     
212       if (Int->isSuccessor(NodeHeader)) {
213         // If we were in the successor list from before... remove from succ list
214         Int->Successors.erase(remove(Int->Successors.begin(),
215                                      Int->Successors.end(), NodeHeader), 
216                               Int->Successors.end());
217       }
218     
219       // Now that we have discovered that Node is in the interval, perhaps some
220       // of its successors are as well?
221       for (typename GT::ChildIteratorType It = GT::child_begin(Node),
222              End = GT::child_end(Node); It != End; ++It)
223         ProcessNode(Int, getSourceGraphNode(OrigContainer, *It));
224     }
225   }
226 };
227
228 typedef IntervalIterator<BasicBlock, Function> function_interval_iterator;
229 typedef IntervalIterator<Interval, IntervalPartition> interval_part_interval_iterator;
230
231
232 inline function_interval_iterator intervals_begin(Function *F, 
233                                                   bool DeleteInts = true) {
234   return function_interval_iterator(F, DeleteInts);
235 }
236 inline function_interval_iterator intervals_end(Function *) {
237   return function_interval_iterator();
238 }
239
240 inline interval_part_interval_iterator 
241    intervals_begin(IntervalPartition &IP, bool DeleteIntervals = true) {
242   return interval_part_interval_iterator(IP, DeleteIntervals);
243 }
244
245 inline interval_part_interval_iterator intervals_end(IntervalPartition &IP) {
246   return interval_part_interval_iterator();
247 }
248
249 #endif