classInterval { /// HeaderNode - The header BasicBlock, which dominates all BasicBlocks in this /// interval. Also, any loops in this interval must go through the HeaderNode. /// BasicBlock *HeaderNode;
/// Nodes - The basic blocks in this interval. std::vector<BasicBlock*> Nodes;
构造函数和一些基本定义, Nodes 存了 Interval 里所有的 BasicBlock。
1 2 3 4
/// Successors - List of BasicBlocks that are reachable directly from nodes in /// this interval, but are not in the interval themselves. /// These nodes necessarily must be header nodes for other intervals. std::vector<BasicBlock*> Successors;
Successors 是所有从Interval 里的 Node 可以直接到达的 Nodes
1 2 3
/// Predecessors - List of BasicBlocks that have this Interval's header block /// as one of their successors. std::vector<BasicBlock*> Predecessors;
/// contains - Find out if a basic block is in this interval inlineboolcontains(BasicBlock *BB)const{ for (BasicBlock *Node : Nodes) if (Node == BB) returntrue; returnfalse; // I don't want the dependency on <algorithm> //return find(Nodes.begin(), Nodes.end(), BB) != Nodes.end(); }
/// isSuccessor - find out if a basic block is a successor of this Interval inlineboolisSuccessor(BasicBlock *BB)const{ for (BasicBlock *Successor : Successors) if (Successor == BB) returntrue; returnfalse; // I don't want the dependency on <algorithm> //return find(Successors.begin(), Successors.end(), BB) != Successors.end(); }
/// Equality operator. It is only valid to compare two intervals from the /// same partition, because of this, all we have to check is the header node /// for equality. inlinebooloperator==(const Interval &I) const { return HeaderNode == I.HeaderNode; }
// addIntervalToPartition - Add an interval to the internal list of intervals, // and then add mappings from all of the basic blocks in the interval to the // interval itself (in the IntervalMap). voidIntervalPartition::addIntervalToPartition(Interval *I){ Intervals.push_back(I);
// Add mappings for all of the basic blocks in I to the IntervalPartition for (Interval::node_iterator It = I->Nodes.begin(), End = I->Nodes.end(); It != End; ++It) IntervalMap.insert(std::make_pair(*It, I)); }
// updatePredecessors - Interval generation only sets the successor fields of // the interval data structures. After interval generation is complete, // run through all of the intervals and propagate successor info as // predecessor info. voidIntervalPartition::updatePredecessors(Interval *Int){ BasicBlock *Header = Int->getHeaderNode(); for (BasicBlock *Successor : Int->Successors) getBlockInterval(Successor)->Predecessors.push_back(Header); }
// IntervalPartition ctor - Build the first level interval partition for the // specified function... boolIntervalPartition::runOnFunction(Function &F){ // Pass false to intervals_begin because we take ownership of it's memory function_interval_iterator I = intervals_begin(&F, false); assert(I != intervals_end(&F) && "No intervals in function!?!?!");
addIntervalToPartition(RootInterval = *I);
++I; // After the first one...
// Add the rest of the intervals to the partition. for (function_interval_iterator E = intervals_end(&F); I != E; ++I) addIntervalToPartition(*I);
// Now that we know all of the successor information, propagate this to the // predecessors for each block. for (Interval *I : Intervals) updatePredecessors(I); returnfalse; }
template<classNodeTy, classOrigContainer_t, classGT = GraphTraits<NodeTy *>, class IGT = GraphTraits<Inverse<NodeTy *>>> class IntervalIterator { std::vector<std::pair<Interval *, typename Interval::succ_iterator>> IntStack; std::set<BasicBlock *> Visited; OrigContainer_t *OrigContainer; bool IOwnMem; // If True, delete intervals when done with them // See file header for conditions of use
// ProcessInterval - This method is used during the construction of the // interval graph. It walks through the source graph, recursively creating // an interval per invocation until the entire graph is covered. This uses // the ProcessNode method to add all of the nodes to the interval. // // This method is templated because it may operate on two different source // graphs: a basic block graph, or a preexisting interval graph. boolProcessInterval(NodeTy *Node){ BasicBlock *Header = getNodeHeader(Node); if (!Visited.insert(Header).second) returnfalse;
Interval *Int = newInterval(Header);
// Check all of our successors to see if they are in the interval... for (typename GT::ChildIteratorType I = GT::child_begin(Node), E = GT::child_end(Node); I != E; ++I) ProcessNode(Int, getSourceGraphNode(OrigContainer, *I));
// ProcessNode - This method is called by ProcessInterval to add nodes to the // interval being constructed, and it is also called recursively as it walks // the source graph. A node is added to the current interval only if all of // its predecessors are already in the graph. This also takes care of keeping // the successor set of an interval up to date. // // This method is templated because it may operate on two different source // graphs: a basic block graph, or a preexisting interval graph. voidProcessNode(Interval *Int, NodeTy *Node){ assert(Int && "Null interval == bad!"); assert(Node && "Null Node == bad!");
BasicBlock *NodeHeader = getNodeHeader(Node);
if (Visited.count(NodeHeader)) { // Node already been visited? if (Int->contains(NodeHeader)) { // Already in this interval... return; } else { // In other interval, add as successor if (!Int->isSuccessor(NodeHeader)) // Add only if not already in set Int->Successors.push_back(NodeHeader); } } else { // Otherwise, not in interval yet for (typename IGT::ChildIteratorType I = IGT::child_begin(Node), E = IGT::child_end(Node); I != E; ++I) { if (!Int->contains(*I)) { // If pred not in interval, we can't be if (!Int->isSuccessor(NodeHeader)) // Add only if not already in set Int->Successors.push_back(NodeHeader); return; // See you later } }
// If we get here, then all of the predecessors of BB are in the interval // already. In this case, we must add BB to the interval! addNodeToInterval(Int, Node); Visited.insert(NodeHeader); // The node has now been visited!
if (Int->isSuccessor(NodeHeader)) { // If we were in the successor list from before... remove from succ list llvm::erase_value(Int->Successors, NodeHeader); }
// Now that we have discovered that Node is in the interval, perhaps some // of its successors are as well? for (typename GT::ChildIteratorType It = GT::child_begin(Node), End = GT::child_end(Node); It != End; ++It) ProcessNode(Int, getSourceGraphNode(OrigContainer, *It)); } }