New file due to the Intervals.h splitup
[oota-llvm.git] / lib / Analysis / IntervalPartition.cpp
1 //===- IntervalPartition.cpp - Interval Partition module code ----*- C++ -*--=//
2 //
3 // This file contains the definition of the cfg::IntervalPartition class, which
4 // calculates and represent the interval partition of a method.
5 //
6 //===----------------------------------------------------------------------===//
7
8 #include "llvm/Analysis/IntervalIterator.h"
9
10 using namespace cfg;
11
12 //===----------------------------------------------------------------------===//
13 // IntervalPartition Implementation
14 //===----------------------------------------------------------------------===//
15
16 template <class T> static inline void deleter(T *Ptr) { delete Ptr; }
17
18 // Destructor - Free memory
19 IntervalPartition::~IntervalPartition() {
20   for_each(begin(), end(), deleter<cfg::Interval>);
21 }
22
23 // addNodeToInterval - This method exists to assist the generic ProcessNode
24 // with the task of adding a node to the new interval, depending on the 
25 // type of the source node.  In the case of a CFG source graph (BasicBlock 
26 // case), the BasicBlock itself is added to the interval.
27 //
28 inline void IntervalPartition::addNodeToInterval(Interval *Int, BasicBlock *BB){
29   Int->Nodes.push_back(BB);
30   IntervalMap.insert(make_pair(BB, Int));
31 }
32
33 // addNodeToInterval - This method exists to assist the generic ProcessNode
34 // with the task of adding a node to the new interval, depending on the 
35 // type of the source node.  In the case of a CFG source graph (BasicBlock 
36 // case), the BasicBlock itself is added to the interval.  In the case of
37 // an IntervalPartition source graph (Interval case), all of the member
38 // BasicBlocks are added to the interval.
39 //
40 inline void IntervalPartition::addNodeToInterval(Interval *Int, Interval *I) {
41   // Add all of the nodes in I as new nodes in Int.
42   copy(I->Nodes.begin(), I->Nodes.end(), back_inserter(Int->Nodes));
43
44   // Add mappings for all of the basic blocks in I to the IntervalPartition
45   for (Interval::node_iterator It = I->Nodes.begin(), End = I->Nodes.end();
46        It != End; ++It)
47     IntervalMap.insert(make_pair(*It, Int));
48 }
49
50
51 // ProcessNode - This method is called by ProcessInterval to add nodes to the
52 // interval being constructed, and it is also called recursively as it walks
53 // the source graph.  A node is added to the current interval only if all of
54 // its predecessors are already in the graph.  This also takes care of keeping
55 // the successor set of an interval up to date.
56 //
57 // This method is templated because it may operate on two different source
58 // graphs: a basic block graph, or a preexisting interval graph.
59 //
60 template<class NodeTy, class OrigContainer>
61 void IntervalPartition::ProcessNode(Interval *Int, 
62                                     NodeTy *Node, OrigContainer *OC) {
63   assert(Int && "Null interval == bad!");
64   assert(Node && "Null Node == bad!");
65   
66   BasicBlock *NodeHeader = getNodeHeader(Node);
67   Interval *CurInt = getBlockInterval(NodeHeader);
68   if (CurInt == Int) {                  // Already in this interval...
69     return;
70   } else if (CurInt != 0) {             // In another interval, add as successor
71     if (!Int->isSuccessor(NodeHeader))  // Add only if not already in set
72       Int->Successors.push_back(NodeHeader);
73   } else {                              // Otherwise, not in interval yet
74     for (typename NodeTy::pred_iterator I = pred_begin(Node), 
75                                         E = pred_end(Node); I != E; ++I) {
76       if (!Int->contains(*I)) {         // If pred not in interval, we can't be
77         if (!Int->isSuccessor(NodeHeader)) // Add only if not already in set
78           Int->Successors.push_back(NodeHeader);
79         return;                         // See you later
80       }
81     }
82     
83     // If we get here, then all of the predecessors of BB are in the interval
84     // already.  In this case, we must add BB to the interval!
85     addNodeToInterval(Int, Node);
86     
87     if (Int->isSuccessor(NodeHeader)) {
88       // If we were in the successor list from before... remove from succ list
89       Int->Successors.erase(remove(Int->Successors.begin(),
90                                    Int->Successors.end(), NodeHeader), 
91                             Int->Successors.end());
92     }
93     
94     // Now that we have discovered that Node is in the interval, perhaps some of
95     // its successors are as well?
96     for (typename NodeTy::succ_iterator It = succ_begin(Node), 
97                                        End = succ_end(Node); It != End; ++It)
98       ProcessNode(Int, getSourceGraphNode(OC, *It), OC);
99   }
100 }
101
102
103 // ProcessInterval - This method is used during the construction of the 
104 // interval graph.  It walks through the source graph, recursively creating
105 // an interval per invokation until the entire graph is covered.  This uses
106 // the ProcessNode method to add all of the nodes to the interval.
107 //
108 // This method is templated because it may operate on two different source
109 // graphs: a basic block graph, or a preexisting interval graph.
110 //
111 template<class NodeTy, class OrigContainer>
112 void IntervalPartition::ProcessInterval(NodeTy *Node, OrigContainer *OC) {
113   BasicBlock *Header = getNodeHeader(Node);
114   if (getBlockInterval(Header)) return;  // Interval already constructed?
115
116   // Create a new interval and add the interval to our current set
117   Interval *Int = new Interval(Header);
118   IntervalList.push_back(Int);
119   IntervalMap.insert(make_pair(Header, Int));
120
121   // Check all of our successors to see if they are in the interval...
122   for (typename NodeTy::succ_iterator I = succ_begin(Node), E = succ_end(Node); 
123        I != E; ++I)
124     ProcessNode(Int, getSourceGraphNode(OC, *I), OC);
125
126   // Build all of the successor intervals of this interval now...
127   for(Interval::succ_iterator I = Int->Successors.begin(), 
128                               E = Int->Successors.end(); I != E; ++I) {
129     ProcessInterval(getSourceGraphNode(OC, *I), OC);
130   }
131 }
132
133
134
135 // updatePredecessors - Interval generation only sets the successor fields of
136 // the interval data structures.  After interval generation is complete,
137 // run through all of the intervals and propogate successor info as
138 // predecessor info.
139 //
140 void IntervalPartition::updatePredecessors(cfg::Interval *Int) {
141   BasicBlock *Header = Int->getHeaderNode();
142   for (Interval::succ_iterator I = Int->Successors.begin(), 
143                                E = Int->Successors.end(); I != E; ++I)
144     getBlockInterval(*I)->Predecessors.push_back(Header);
145 }
146
147
148
149 // IntervalPartition ctor - Build the first level interval partition for the
150 // specified method...
151 //
152 IntervalPartition::IntervalPartition(Method *M) {
153   BasicBlock *MethodStart = M->getBasicBlocks().front();
154   assert(MethodStart && "Cannot operate on prototypes!");
155
156   ProcessInterval(MethodStart, M);
157   RootInterval = getBlockInterval(MethodStart);
158
159   // Now that we know all of the successor information, propogate this to the
160   // predecessors for each block...
161   for(iterator I = begin(), E = end(); I != E; ++I)
162     updatePredecessors(*I);
163 }
164
165
166 // IntervalPartition ctor - Build a reduced interval partition from an
167 // existing interval graph.  This takes an additional boolean parameter to
168 // distinguish it from a copy constructor.  Always pass in false for now.
169 //
170 IntervalPartition::IntervalPartition(IntervalPartition &I, bool) {
171   Interval *MethodStart = I.getRootInterval();
172   assert(MethodStart && "Cannot operate on empty IntervalPartitions!");
173
174   ProcessInterval(MethodStart, &I);
175   RootInterval = getBlockInterval(*MethodStart->Nodes.begin());
176
177   // Now that we know all of the successor information, propogate this to the
178   // predecessors for each block...
179   for(iterator I = begin(), E = end(); I != E; ++I)
180     updatePredecessors(*I);
181 }