Chris Lattner | 2d676c9 | 2001-06-24 04:07:44 +0000 | [diff] [blame^] | 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 | } |