diff options
| author | Chris Lattner <sabre@nondot.org> | 2001-06-24 04:07:37 +0000 | 
|---|---|---|
| committer | Chris Lattner <sabre@nondot.org> | 2001-06-24 04:07:37 +0000 | 
| commit | db1d8bdf34275a4dab160e54539042a446c72631 (patch) | |
| tree | bc5d2fa768bc676614e281f79a1823750f8d940d | |
| parent | 72bd8ccbacd8519eb3f54c79dbe9e58438b67cca (diff) | |
| download | bcm5719-llvm-db1d8bdf34275a4dab160e54539042a446c72631.tar.gz bcm5719-llvm-db1d8bdf34275a4dab160e54539042a446c72631.zip  | |
New files due to the Intervals.h splitup
llvm-svn: 65
| -rw-r--r-- | llvm/include/llvm/Analysis/IntervalIterator.h | 223 | ||||
| -rw-r--r-- | llvm/include/llvm/Analysis/IntervalPartition.h | 123 | 
2 files changed, 346 insertions, 0 deletions
diff --git a/llvm/include/llvm/Analysis/IntervalIterator.h b/llvm/include/llvm/Analysis/IntervalIterator.h new file mode 100644 index 00000000000..ec70c8782df --- /dev/null +++ b/llvm/include/llvm/Analysis/IntervalIterator.h @@ -0,0 +1,223 @@ +//===- IntervalIterator.h - Interval Iterator Declaration --------*- C++ -*--=// +// +// This file defines an iterator that enumerates the intervals in a control flow +// graph of some sort.  This iterator is parametric, allowing iterator over the +// following types of graphs: +//  +//  TODO +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_INTERVAL_ITERATOR_H +#define LLVM_INTERVAL_ITERATOR_H + +#include "llvm/Analysis/IntervalPartition.h" +#include "llvm/Method.h" +#include "llvm/CFG.h" +#include <stack> +#include <set> +#include <algorithm> + +namespace cfg { + +// TODO: Provide an interval iterator that codifies the internals of  +// IntervalPartition.  Inside, it would have a stack of Interval*'s, and would +// walk the interval partition in depth first order.  IntervalPartition would +// then be a client of this iterator.  The iterator should work on Method*, +// const Method*, IntervalPartition*, and const IntervalPartition*. +// + + +// getNodeHeader - Given a source graph node and the source graph, return the  +// BasicBlock that is the header node.  This is the opposite of +// getSourceGraphNode. +// +inline BasicBlock *getNodeHeader(BasicBlock *BB) { return BB; } +inline BasicBlock *getNodeHeader(Interval *I) { return I->getHeaderNode(); } + +// getSourceGraphNode - Given a BasicBlock and the source graph, return the  +// source graph node that corresponds to the BasicBlock.  This is the opposite +// of getNodeHeader. +// +inline BasicBlock *getSourceGraphNode(Method *, BasicBlock *BB) { +  return BB;  +} +inline Interval *getSourceGraphNode(IntervalPartition *IP, BasicBlock *BB) {  +  return IP->getBlockInterval(BB); +} + +// addNodeToInterval - This method exists to assist the generic ProcessNode +// with the task of adding a node to the new interval, depending on the  +// type of the source node.  In the case of a CFG source graph (BasicBlock  +// case), the BasicBlock itself is added to the interval. +// +inline void addNodeToInterval(Interval *Int, BasicBlock *BB){ +  Int->Nodes.push_back(BB); +} + +// addNodeToInterval - This method exists to assist the generic ProcessNode +// with the task of adding a node to the new interval, depending on the  +// type of the source node.  In the case of a CFG source graph (BasicBlock  +// case), the BasicBlock itself is added to the interval.  In the case of +// an IntervalPartition source graph (Interval case), all of the member +// BasicBlocks are added to the interval. +// +inline void addNodeToInterval(Interval *Int, Interval *I) { +  // Add all of the nodes in I as new nodes in Int. +  copy(I->Nodes.begin(), I->Nodes.end(), back_inserter(Int->Nodes)); +} + + +template<class NodeTy, class OrigContainer_t> +class IntervalIterator { +  stack<pair<Interval, typename Interval::succ_iterator> > IntStack; +  set<BasicBlock*> Visited; +  OrigContainer_t *OrigContainer; +public: +  typedef BasicBlock* _BB; + +  typedef IntervalIterator<NodeTy, OrigContainer_t> _Self; +  typedef forward_iterator_tag iterator_category; +  +  IntervalIterator() {} // End iterator, empty stack +  IntervalIterator(Method *M) { +    OrigContainer = M; +    if (!ProcessInterval(M->getBasicBlocks().front())) { +      assert(0 && "ProcessInterval should never fail for first interval!"); +    } +  } + +  IntervalIterator(IntervalPartition &IP) { +    OrigContainer = &IP; +    if (!ProcessInterval(IP.getRootInterval())) { +      assert(0 && "ProcessInterval should never fail for first interval!"); +    } +  } + +  inline bool operator==(const _Self& x) const { return IntStack == x.IntStack; } +  inline bool operator!=(const _Self& x) const { return !operator==(x); } + +  inline Interval &operator*() const { return IntStack.top(); } +  inline Interval *operator->() const { return &(operator*()); } + +  inline _Self& operator++() {  // Preincrement +    do { +      // All of the intervals on the stack have been visited.  Try visiting their +      // successors now. +      Interval           &CurInt = IntStack.top().first; +      Interval::iterator &SuccIt = IntStack.top().second,End = succ_end(&CurInt); + +      for (; SuccIt != End; ++SuccIt)    // Loop over all interval successors +	if (ProcessInterval(*SuccIt))    // Found a new interval! +	  return *this;                  // Use it! + +      // We ran out of successors for this interval... pop off the stack +      IntStack.pop(); +    } while (!IntStack.empty()); + +    return *this;  +  } +  inline _Self operator++(int) { // Postincrement +    _Self tmp = *this; ++*this; return tmp;  +  } + +private: +  // ProcessInterval - This method is used during the construction of the  +  // interval graph.  It walks through the source graph, recursively creating +  // an interval per invokation 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. +  // +  bool ProcessInterval(NodeTy *Node) { +    BasicBlock *Header = getNodeHeader(Node); +    if (Visited.count(Header)) return false; + +    Interval Int(Header); +    Visited.insert(Header);   // The header has now been visited! + +    // Check all of our successors to see if they are in the interval... +    for (typename NodeTy::succ_iterator I = succ_begin(Node), E = succ_end(Node); +	 I != E; ++I) +      ProcessNode(&Int, getSourceGraphNode(OrigContainer, *I)); + +    IntStack.push(make_pair(Int, succ_begin(&Int))); +    return true; +  } +   +  // 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. +  // +  void ProcessNode(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 another 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 NodeTy::pred_iterator I = pred_begin(Node),  +	                                  E = pred_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 +	Int->Successors.erase(remove(Int->Successors.begin(), +				     Int->Successors.end(), NodeHeader),  +			      Int->Successors.end()); +      } +     +      // Now that we have discovered that Node is in the interval, perhaps some +      // of its successors are as well? +      for (typename NodeTy::succ_iterator It = succ_begin(Node),  +	     End = succ_end(Node); It != End; ++It) +	ProcessNode(Int, getSourceGraphNode(OrigContainer, *It)); +    } +  } +}; + +typedef IntervalIterator<BasicBlock, Method> method_interval_iterator; +typedef IntervalIterator<Interval, IntervalPartition> interval_part_interval_iterator; + + +inline method_interval_iterator intervals_begin(Method *M) { +  return method_interval_iterator(M); +} +inline method_interval_iterator intervals_end(Method *M) { +  return method_interval_iterator(); +} + +inline interval_part_interval_iterator intervals_begin(IntervalPartition &IP) { +  return interval_part_interval_iterator(IP); +} + +inline interval_part_interval_iterator intervals_end(IntervalPartition &IP) { +  return interval_part_interval_iterator(); +} + +}    // End namespace cfg + +#endif diff --git a/llvm/include/llvm/Analysis/IntervalPartition.h b/llvm/include/llvm/Analysis/IntervalPartition.h new file mode 100644 index 00000000000..fd24b2fb987 --- /dev/null +++ b/llvm/include/llvm/Analysis/IntervalPartition.h @@ -0,0 +1,123 @@ +//===- IntervalPartition.h - Interval partition Calculation ------*- C++ -*--=// +// +// This file contains the declaration of the cfg::IntervalPartition class, which +// calculates and represents the interval partition of a method, or a +// preexisting interval partition. +// +// In this way, the interval partition may be used to reduce a flow graph down +// to its degenerate single node interval partition (unless it is irreducible). +// +// TODO: The IntervalPartition class should take a bool parameter that tells +// whether it should add the "tails" of an interval to an interval itself or if +// they should be represented as distinct intervals. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_INTERVAL_PARTITION_H +#define LLVM_INTERVAL_PARTITION_H + +#include "llvm/Analysis/Interval.h" +#include <map> + +class Method; + +namespace cfg { + +//===----------------------------------------------------------------------===// +// +// IntervalPartition - This class builds and holds an "interval partition" for +// a method.  This partition divides the control flow graph into a set of +// maximal intervals, as defined with the properties above.  Intuitively, a +// BasicBlock is a (possibly nonexistent) loop with a "tail" of non looping +// nodes following it. +// +class IntervalPartition { +  typedef map<BasicBlock*, Interval*> IntervalMapTy; +  IntervalMapTy IntervalMap; + +  typedef vector<Interval*> IntervalListTy; +  IntervalListTy IntervalList; +  Interval *RootInterval; + +public: +  typedef IntervalListTy::iterator iterator; + +public: +  // IntervalPartition ctor - Build the partition for the specified method +  IntervalPartition(Method *M); + +  // IntervalPartition ctor - Build a reduced interval partition from an +  // existing interval graph.  This takes an additional boolean parameter to +  // distinguish it from a copy constructor.  Always pass in false for now. +  // +  IntervalPartition(IntervalPartition &I, bool); + +  // Destructor - Free memory +  ~IntervalPartition(); + +  // getRootInterval() - Return the root interval that contains the starting +  // block of the method. +  inline Interval *getRootInterval() { return RootInterval; } + +  // isDegeneratePartition() - Returns true if the interval partition contains +  // a single interval, and thus cannot be simplified anymore. +  bool isDegeneratePartition() { return size() == 1; } + +  // TODO: isIrreducible - look for triangle graph. + +  // getBlockInterval - Return the interval that a basic block exists in. +  inline Interval *getBlockInterval(BasicBlock *BB) { +    IntervalMapTy::iterator I = IntervalMap.find(BB); +    return I != IntervalMap.end() ? I->second : 0; +  } + +  // Iterators to iterate over all of the intervals in the method +  inline iterator begin() { return IntervalList.begin(); } +  inline iterator end()   { return IntervalList.end(); } +  inline unsigned size()  { return IntervalList.size(); } + +private: +  // ProcessInterval - This method is used during the construction of the  +  // interval graph.  It walks through the source graph, recursively creating +  // an interval per invokation 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. +  // +  template<class NodeTy, class OrigContainer> +  void ProcessInterval(NodeTy *Node, OrigContainer *OC); + +  // 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. +  // +  template<class NodeTy, class OrigContainer> +  void ProcessNode(Interval *Int, NodeTy *Node, OrigContainer *OC); + +  // addNodeToInterval - This method exists to assist the generic ProcessNode +  // with the task of adding a node to the new interval, depending on the  +  // type of the source node.  In the case of a CFG source graph (BasicBlock  +  // case), the BasicBlock itself is added to the interval.  In the case of +  // an IntervalPartition source graph (Interval case), all of the member +  // BasicBlocks are added to the interval. +  // +  inline void addNodeToInterval(Interval *Int, Interval *I); +  inline void addNodeToInterval(Interval *Int, BasicBlock *BB); + +  // 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 propogate successor info as +  // predecessor info. +  // +  void updatePredecessors(Interval *Int); +}; + +}    // End namespace cfg + +#endif  | 

