llvm.org GIT mirror llvm / ed465bc
Add capability to build a derived interval graph git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@41 91177308-0d34-0410-b5e6-96231b3b80d8 Chris Lattner 19 years ago
2 changed file(s) with 227 addition(s) and 50 deletion(s). Raw diff Collapse all Expand all
0 //===- llvm/Analysis/Intervals.h - Interval partition Calculation-*- C++ -*--=//
11 //
22 // This file contains the declaration of the cfg::IntervalPartition class, which
3 // calculates and represent the interval partition of a method.
3 // calculates and represents the interval partition of a method, or a
4 // preexisting interval partition.
5 //
6 // In this way, the interval partition may be used to reduce a flow graph down
7 // to its degenerate single node interval partition (unless it is irreducible).
48 //
59 //===----------------------------------------------------------------------===//
610
6367 };
6468
6569
70 // succ_begin/succ_end - define global functions so that Intervals may be used
71 // just like BasicBlocks can with the succ_* functions, and *::succ_iterator.
72 //
73 inline Interval::succ_iterator succ_begin(Interval *I) {
74 return I->Successors.begin();
75 }
76 inline Interval::succ_iterator succ_end(Interval *I) {
77 return I->Successors.end();
78 }
79
80 // pred_begin/pred_end - define global functions so that Intervals may be used
81 // just like BasicBlocks can with the pred_* functions, and *::pred_iterator.
82 //
83 inline Interval::pred_iterator pred_begin(Interval *I) {
84 return I->Predecessors.begin();
85 }
86 inline Interval::pred_iterator pred_end(Interval *I) {
87 return I->Predecessors.end();
88 }
89
90
91
6692 // IntervalPartition - This class builds and holds an "interval partition" for
6793 // a method. This partition divides the control flow graph into a set of
6894 // maximal intervals, as defined with the properties above. Intuitively, a
84110 // IntervalPartition ctor - Build the partition for the specified method
85111 IntervalPartition(Method *M);
86112
113 // IntervalPartition ctor - Build a reduced interval partition from an
114 // existing interval graph. This takes an additional boolean parameter to
115 // distinguish it from a copy constructor. Always pass in false for now.
116 //
117 IntervalPartition(IntervalPartition &I, bool);
118
87119 // getRootInterval() - Return the root interval that contains the starting
88120 // block of the method
89121 inline Interval *getRootInterval() { return RootInterval; }
101133 inline iterator end() { return IntervalList.end(); }
102134
103135 private:
104 void ProcessInterval(BasicBlock *Header);
105 void ProcessBasicBlock(Interval *I, BasicBlock *BB);
106 void UpdateSuccessors(Interval *Int);
136 // ProcessInterval - This method is used during the construction of the
137 // interval graph. It walks through the source graph, recursively creating
138 // an interval per invokation until the entire graph is covered. This uses
139 // the ProcessNode method to add all of the nodes to the interval.
140 //
141 // This method is templated because it may operate on two different source
142 // graphs: a basic block graph, or a preexisting interval graph.
143 //
144 template
145 void ProcessInterval(NodeTy *Node, OrigContainer *OC);
146
147 // ProcessNode - This method is called by ProcessInterval to add nodes to the
148 // interval being constructed, and it is also called recursively as it walks
149 // the source graph. A node is added to the current interval only if all of
150 // its predecessors are already in the graph. This also takes care of keeping
151 // the successor set of an interval up to date.
152 //
153 // This method is templated because it may operate on two different source
154 // graphs: a basic block graph, or a preexisting interval graph.
155 //
156 template
157 void ProcessNode(Interval *Int, NodeTy *Node, OrigContainer *OC);
158
159 // addNodeToInterval - This method exists to assist the generic ProcessNode
160 // with the task of adding a node to the new interval, depending on the
161 // type of the source node. In the case of a CFG source graph (BasicBlock
162 // case), the BasicBlock itself is added to the interval. In the case of
163 // an IntervalPartition source graph (Interval case), all of the member
164 // BasicBlocks are added to the interval.
165 //
166 inline void addNodeToInterval(Interval *Int, Interval *I);
167 inline void addNodeToInterval(Interval *Int, BasicBlock *BB);
168
169 // updatePredecessors - Interval generation only sets the successor fields of
170 // the interval data structures. After interval generation is complete,
171 // run through all of the intervals and propogate successor info as
172 // predecessor info.
173 //
174 void updatePredecessors(Interval *Int);
107175 };
108176
109177 } // End namespace cfg
99 #include "llvm/BasicBlock.h"
1010 #include "llvm/CFG.h"
1111
12 void cfg::IntervalPartition::UpdateSuccessors(cfg::Interval *Int) {
13 BasicBlock *Header = Int->HeaderNode;
14 for (cfg::Interval::succ_iterator I = Int->Successors.begin(),
15 E = Int->Successors.end(); I != E; ++I)
16 getBlockInterval(*I)->Predecessors.push_back(Header);
12 using namespace cfg;
13
14 // getNodeHeader - Given a source graph node and the source graph, return the
15 // BasicBlock that is the header node. This is the opposite of
16 // getSourceGraphNode.
17 //
18 inline static BasicBlock *getNodeHeader(BasicBlock *BB) { return BB; }
19 inline static BasicBlock *getNodeHeader(Interval *I) { return I->HeaderNode; }
20
21
22 // getSourceGraphNode - Given a BasicBlock and the source graph, return the
23 // source graph node that corresponds to the BasicBlock. This is the opposite
24 // of getNodeHeader.
25 //
26 inline static BasicBlock *getSourceGraphNode(Method *, BasicBlock *BB) {
27 return BB;
28 }
29 inline static Interval *getSourceGraphNode(IntervalPartition *IP,
30 BasicBlock *BB) {
31 return IP->getBlockInterval(BB);
1732 }
1833
19 // IntervalPartition ctor - Build the partition for the specified method
20 cfg::IntervalPartition::IntervalPartition(Method *M) {
21 BasicBlock *MethodStart = M->getBasicBlocks().front();
22 assert(MethodStart && "Cannot operate on prototypes!");
2334
24 ProcessInterval(MethodStart);
25 RootInterval = getBlockInterval(MethodStart);
26
27 // Now that we know all of the successor information, propogate this to the
28 // predecessors for each block...
29 for(iterator I = begin(), E = end(); I != E; ++I)
30 UpdateSuccessors(*I);
35 // addNodeToInterval - This method exists to assist the generic ProcessNode
36 // with the task of adding a node to the new interval, depending on the
37 // type of the source node. In the case of a CFG source graph (BasicBlock
38 // case), the BasicBlock itself is added to the interval.
39 //
40 inline void IntervalPartition::addNodeToInterval(Interval *Int, BasicBlock *BB){
41 Int->Nodes.push_back(BB);
42 IntervalMap.insert(make_pair(BB, Int));
3143 }
3244
33 void cfg::IntervalPartition::ProcessInterval(BasicBlock *Header) {
34 if (getBlockInterval(Header)) return; // Interval already constructed
45 // addNodeToInterval - This method exists to assist the generic ProcessNode
46 // with the task of adding a node to the new interval, depending on the
47 // type of the source node. In the case of a CFG source graph (BasicBlock
48 // case), the BasicBlock itself is added to the interval. In the case of
49 // an IntervalPartition source graph (Interval case), all of the member
50 // BasicBlocks are added to the interval.
51 //
52 inline void IntervalPartition::addNodeToInterval(Interval *Int, Interval *I) {
53 // Add all of the nodes in I as new nodes in Int.
54 copy(I->Nodes.begin(), I->Nodes.end(), back_inserter(Int->Nodes));
3555
36 Interval *Int = new Interval(Header);
37 IntervalList.push_back(Int); // Add the interval to our current set
38 IntervalMap.insert(make_pair(Header, Int));
39
40 // Check all of our successors to see if they are in the interval...
41 for (succ_iterator I = succ_begin(Header), E = succ_end(Header); I != E; ++I)
42 ProcessBasicBlock(Int, *I);
43
44 // Build all of the successor intervals of this interval now...
45 for(Interval::succ_iterator I = Int->Successors.begin(),
46 E = Int->Successors.end(); I != E; ++I)
47 ProcessInterval(*I);
56 // Add mappings for all of the basic blocks in I to the IntervalPartition
57 for (Interval::node_iterator It = I->Nodes.begin(), End = I->Nodes.end();
58 It != End; ++It)
59 IntervalMap.insert(make_pair(*It, Int));
4860 }
4961
50 void cfg::IntervalPartition::ProcessBasicBlock(Interval *Int, BasicBlock *BB) {
62
63 // ProcessNode - This method is called by ProcessInterval to add nodes to the
64 // interval being constructed, and it is also called recursively as it walks
65 // the source graph. A node is added to the current interval only if all of
66 // its predecessors are already in the graph. This also takes care of keeping
67 // the successor set of an interval up to date.
68 //
69 // This method is templated because it may operate on two different source
70 // graphs: a basic block graph, or a preexisting interval graph.
71 //
72 template
73 void IntervalPartition::ProcessNode(Interval *Int,
74 NodeTy *Node, OrigContainer *OC) {
5175 assert(Int && "Null interval == bad!");
52 assert(BB && "Null interval == bad!");
53
54 Interval *CurInt = getBlockInterval(BB);
76 assert(Node && "Null Node == bad!");
77
78 BasicBlock *NodeHeader = getNodeHeader(Node);
79 Interval *CurInt = getBlockInterval(NodeHeader);
5580 if (CurInt == Int) { // Already in this interval...
5681 return;
5782 } else if (CurInt != 0) { // In another interval, add as successor
58 if (!Int->isSuccessor(BB)) // Add only if not already in set
59 Int->Successors.push_back(BB);
83 if (!Int->isSuccessor(NodeHeader)) // Add only if not already in set
84 Int->Successors.push_back(NodeHeader);
6085 } else { // Otherwise, not in interval yet
61 for (pred_iterator I = pred_begin(BB), E = pred_end(BB); I != E; ++I) {
86 for (typename NodeTy::pred_iterator I = pred_begin(Node),
87 E = pred_end(Node); I != E; ++I) {
6288 if (!Int->contains(*I)) { // If pred not in interval, we can't be
63 if (!Int->isSuccessor(BB)) // Add only if not already in set
64 Int->Successors.push_back(BB);
89 if (!Int->isSuccessor(NodeHeader)) // Add only if not already in set
90 Int->Successors.push_back(NodeHeader);
6591 return; // See you later
6692 }
6793 }
6894
6995 // If we get here, then all of the predecessors of BB are in the interval
7096 // already. In this case, we must add BB to the interval!
71 Int->Nodes.push_back(BB);
72 IntervalMap.insert(make_pair(BB, Int));
97 addNodeToInterval(Int, Node);
7398
74 if (Int->isSuccessor(BB)) {
99 if (Int->isSuccessor(NodeHeader)) {
75100 // If we were in the successor list from before... remove from succ list
76 remove(Int->Successors.begin(), Int->Successors.end(), BB);
101 Int->Successors.erase(remove(Int->Successors.begin(),
102 Int->Successors.end(), NodeHeader),
103 Int->Successors.end());
77104 }
78105
79 // Now that we have discovered that BB is in the interval, perhaps some of
106 // Now that we have discovered that Node is in the interval, perhaps some of
80107 // its successors are as well?
81 for (succ_iterator I = succ_begin(BB), E = succ_end(BB); I != E; ++I)
82 ProcessBasicBlock(Int, *I);
108 for (typename NodeTy::succ_iterator It = succ_begin(Node),
109 End = succ_end(Node); It != End; ++It)
110 ProcessNode(Int, getSourceGraphNode(OC, *It), OC);
83111 }
84112 }
113
114
115 // ProcessInterval - This method is used during the construction of the
116 // interval graph. It walks through the source graph, recursively creating
117 // an interval per invokation until the entire graph is covered. This uses
118 // the ProcessNode method to add all of the nodes to the interval.
119 //
120 // This method is templated because it may operate on two different source
121 // graphs: a basic block graph, or a preexisting interval graph.
122 //
123 template
124 void IntervalPartition::ProcessInterval(NodeTy *Node, OrigContainer *OC) {
125 BasicBlock *Header = getNodeHeader(Node);
126 if (getBlockInterval(Header)) return; // Interval already constructed?
127
128 // Create a new interval and add the interval to our current set
129 Interval *Int = new Interval(Header);
130 IntervalList.push_back(Int);
131 IntervalMap.insert(make_pair(Header, Int));
132
133 // Check all of our successors to see if they are in the interval...
134 for (typename NodeTy::succ_iterator I = succ_begin(Node), E = succ_end(Node);
135 I != E; ++I)
136 ProcessNode(Int, getSourceGraphNode(OC, *I), OC);
137
138 // Build all of the successor intervals of this interval now...
139 for(Interval::succ_iterator I = Int->Successors.begin(),
140 E = Int->Successors.end(); I != E; ++I) {
141 ProcessInterval(getSourceGraphNode(OC, *I), OC);
142 }
143 }
144
145
146
147 // updatePredecessors - Interval generation only sets the successor fields of
148 // the interval data structures. After interval generation is complete,
149 // run through all of the intervals and propogate successor info as
150 // predecessor info.
151 //
152 void IntervalPartition::updatePredecessors(cfg::Interval *Int) {
153 BasicBlock *Header = Int->HeaderNode;
154 for (Interval::succ_iterator I = Int->Successors.begin(),
155 E = Int->Successors.end(); I != E; ++I)
156 getBlockInterval(*I)->Predecessors.push_back(Header);
157 }
158
159
160
161 // IntervalPartition ctor - Build the first level interval partition for the
162 // specified method...
163 //
164 IntervalPartition::IntervalPartition(Method *M) {
165 BasicBlock *MethodStart = M->getBasicBlocks().front();
166 assert(MethodStart && "Cannot operate on prototypes!");
167
168 ProcessInterval(MethodStart, M);
169 RootInterval = getBlockInterval(MethodStart);
170
171 // Now that we know all of the successor information, propogate this to the
172 // predecessors for each block...
173 for(iterator I = begin(), E = end(); I != E; ++I)
174 updatePredecessors(*I);
175 }
176
177
178 // IntervalPartition ctor - Build a reduced interval partition from an
179 // existing interval graph. This takes an additional boolean parameter to
180 // distinguish it from a copy constructor. Always pass in false for now.
181 //
182 IntervalPartition::IntervalPartition(IntervalPartition &I, bool) {
183 Interval *MethodStart = I.getRootInterval();
184 assert(MethodStart && "Cannot operate on empty IntervalPartitions!");
185
186 ProcessInterval(MethodStart, &I);
187 RootInterval = getBlockInterval(*MethodStart->Nodes.begin());
188
189 // Now that we know all of the successor information, propogate this to the
190 // predecessors for each block...
191 for(iterator I = begin(), E = end(); I != E; ++I)
192 updatePredecessors(*I);
193 }