PostOrderIterator.h revision 256281
190075Sobrien//===- llvm/ADT/PostOrderIterator.h - PostOrder iterator --------*- C++ -*-===//
2169689Skan//
3132718Skan//                     The LLVM Compiler Infrastructure
490075Sobrien//
590075Sobrien// This file is distributed under the University of Illinois Open Source
690075Sobrien// License. See LICENSE.TXT for details.
790075Sobrien//
890075Sobrien//===----------------------------------------------------------------------===//
990075Sobrien//
1090075Sobrien// This file builds on the ADT/GraphTraits.h file to build a generic graph
1190075Sobrien// post order iterator.  This should work over any graph type that has a
1290075Sobrien// GraphTraits specialization.
1390075Sobrien//
1490075Sobrien//===----------------------------------------------------------------------===//
1590075Sobrien
1690075Sobrien#ifndef LLVM_ADT_POSTORDERITERATOR_H
1790075Sobrien#define LLVM_ADT_POSTORDERITERATOR_H
1890075Sobrien
19169689Skan#include "llvm/ADT/GraphTraits.h"
20169689Skan#include "llvm/ADT/SmallPtrSet.h"
2190075Sobrien#include <set>
2290075Sobrien#include <vector>
23169689Skan
24169689Skannamespace llvm {
2590075Sobrien
26169689Skan// The po_iterator_storage template provides access to the set of already
27169689Skan// visited nodes during the po_iterator's depth-first traversal.
28169689Skan//
2990075Sobrien// The default implementation simply contains a set of visited nodes, while
30169689Skan// the Extended=true version uses a reference to an external set.
3190075Sobrien//
3290075Sobrien// It is possible to prune the depth-first traversal in several ways:
3390075Sobrien//
3490075Sobrien// - When providing an external set that already contains some graph nodes,
3590075Sobrien//   those nodes won't be visited again. This is useful for restarting a
3690075Sobrien//   post-order traversal on a graph with nodes that aren't dominated by a
3790075Sobrien//   single node.
3890075Sobrien//
3990075Sobrien// - By providing a custom SetType class, unwanted graph nodes can be excluded
4090075Sobrien//   by having the insert() function return false. This could for example
4190075Sobrien//   confine a CFG traversal to blocks in a specific loop.
4290075Sobrien//
4390075Sobrien// - Finally, by specializing the po_iterator_storage template itself, graph
4490075Sobrien//   edges can be pruned by returning false in the insertEdge() function. This
45169689Skan//   could be used to remove loop back-edges from the CFG seen by po_iterator.
4690075Sobrien//
47132718Skan// A specialized po_iterator_storage class can observe both the pre-order and
4890075Sobrien// the post-order. The insertEdge() function is called in a pre-order, while
49132718Skan// the finishPostorder() function is called just before the po_iterator moves
5090075Sobrien// on to the next node.
5190075Sobrien
52132718Skan/// Default po_iterator_storage implementation with an internal set object.
5390075Sobrientemplate<class SetType, bool External>
5490075Sobrienclass po_iterator_storage {
5590075Sobrien  SetType Visited;
5690075Sobrienpublic:
5790075Sobrien  // Return true if edge destination should be visited.
5890075Sobrien  template<typename NodeType>
5990075Sobrien  bool insertEdge(NodeType *From, NodeType *To) {
60132718Skan    return Visited.insert(To);
6190075Sobrien  }
62132718Skan
6390075Sobrien  // Called after all children of BB have been visited.
64132718Skan  template<typename NodeType>
6590075Sobrien  void finishPostorder(NodeType *BB) {}
6690075Sobrien};
67132718Skan
6890075Sobrien/// Specialization of po_iterator_storage that references an external set.
6990075Sobrientemplate<class SetType>
7090075Sobrienclass po_iterator_storage<SetType, true> {
7190075Sobrien  SetType &Visited;
7290075Sobrienpublic:
7390075Sobrien  po_iterator_storage(SetType &VSet) : Visited(VSet) {}
7490075Sobrien  po_iterator_storage(const po_iterator_storage &S) : Visited(S.Visited) {}
7590075Sobrien
7690075Sobrien  // Return true if edge destination should be visited, called with From = 0 for
77132718Skan  // the root node.
7890075Sobrien  // Graph edges can be pruned by specializing this function.
79132718Skan  template<class NodeType>
8090075Sobrien  bool insertEdge(NodeType *From, NodeType *To) { return Visited.insert(To); }
81132718Skan
8290075Sobrien  // Called after all children of BB have been visited.
8390075Sobrien  template<class NodeType>
84132718Skan  void finishPostorder(NodeType *BB) {}
8590075Sobrien};
8690075Sobrien
8790075Sobrientemplate<class GraphT,
8890075Sobrien  class SetType = llvm::SmallPtrSet<typename GraphTraits<GraphT>::NodeType*, 8>,
8990075Sobrien  bool ExtStorage = false,
9090075Sobrien  class GT = GraphTraits<GraphT> >
9190075Sobrienclass po_iterator : public std::iterator<std::forward_iterator_tag,
92132718Skan                                         typename GT::NodeType, ptrdiff_t>,
9390075Sobrien                    public po_iterator_storage<SetType, ExtStorage> {
94132718Skan  typedef std::iterator<std::forward_iterator_tag,
9590075Sobrien                        typename GT::NodeType, ptrdiff_t> super;
96132718Skan  typedef typename GT::NodeType          NodeType;
9790075Sobrien  typedef typename GT::ChildIteratorType ChildItTy;
9890075Sobrien
99132718Skan  // VisitStack - Used to maintain the ordering.  Top = current block
10090075Sobrien  // First element is basic block pointer, second is the 'next child' to visit
10190075Sobrien  std::vector<std::pair<NodeType *, ChildItTy> > VisitStack;
10290075Sobrien
10390075Sobrien  void traverseChild() {
10490075Sobrien    while (VisitStack.back().second != GT::child_end(VisitStack.back().first)) {
10590075Sobrien      NodeType *BB = *VisitStack.back().second++;
10690075Sobrien      if (this->insertEdge(VisitStack.back().first, BB)) {
10790075Sobrien        // If the block is not visited...
10890075Sobrien        VisitStack.push_back(std::make_pair(BB, GT::child_begin(BB)));
10990075Sobrien      }
11090075Sobrien    }
111132718Skan  }
11290075Sobrien
11390075Sobrien  inline po_iterator(NodeType *BB) {
11490075Sobrien    this->insertEdge((NodeType*)0, BB);
11590075Sobrien    VisitStack.push_back(std::make_pair(BB, GT::child_begin(BB)));
11690075Sobrien    traverseChild();
11790075Sobrien  }
11890075Sobrien  inline po_iterator() {} // End is when stack is empty.
11990075Sobrien
12090075Sobrien  inline po_iterator(NodeType *BB, SetType &S) :
121132718Skan    po_iterator_storage<SetType, ExtStorage>(S) {
12290075Sobrien    if (this->insertEdge((NodeType*)0, BB)) {
12390075Sobrien      VisitStack.push_back(std::make_pair(BB, GT::child_begin(BB)));
12490075Sobrien      traverseChild();
12590075Sobrien    }
12690075Sobrien  }
12790075Sobrien
12890075Sobrien  inline po_iterator(SetType &S) :
12990075Sobrien      po_iterator_storage<SetType, ExtStorage>(S) {
13090075Sobrien  } // End is when stack is empty.
131132718Skanpublic:
13290075Sobrien  typedef typename super::pointer pointer;
133169689Skan  typedef po_iterator<GraphT, SetType, ExtStorage, GT> _Self;
13490075Sobrien
135  // Provide static "constructors"...
136  static inline _Self begin(GraphT G) { return _Self(GT::getEntryNode(G)); }
137  static inline _Self end  (GraphT G) { return _Self(); }
138
139  static inline _Self begin(GraphT G, SetType &S) {
140    return _Self(GT::getEntryNode(G), S);
141  }
142  static inline _Self end  (GraphT G, SetType &S) { return _Self(S); }
143
144  inline bool operator==(const _Self& x) const {
145    return VisitStack == x.VisitStack;
146  }
147  inline bool operator!=(const _Self& x) const { return !operator==(x); }
148
149  inline pointer operator*() const {
150    return VisitStack.back().first;
151  }
152
153  // This is a nonstandard operator-> that dereferences the pointer an extra
154  // time... so that you can actually call methods ON the BasicBlock, because
155  // the contained type is a pointer.  This allows BBIt->getTerminator() f.e.
156  //
157  inline NodeType *operator->() const { return operator*(); }
158
159  inline _Self& operator++() {   // Preincrement
160    this->finishPostorder(VisitStack.back().first);
161    VisitStack.pop_back();
162    if (!VisitStack.empty())
163      traverseChild();
164    return *this;
165  }
166
167  inline _Self operator++(int) { // Postincrement
168    _Self tmp = *this; ++*this; return tmp;
169  }
170};
171
172// Provide global constructors that automatically figure out correct types...
173//
174template <class T>
175po_iterator<T> po_begin(T G) { return po_iterator<T>::begin(G); }
176template <class T>
177po_iterator<T> po_end  (T G) { return po_iterator<T>::end(G); }
178
179// Provide global definitions of external postorder iterators...
180template<class T, class SetType=std::set<typename GraphTraits<T>::NodeType*> >
181struct po_ext_iterator : public po_iterator<T, SetType, true> {
182  po_ext_iterator(const po_iterator<T, SetType, true> &V) :
183  po_iterator<T, SetType, true>(V) {}
184};
185
186template<class T, class SetType>
187po_ext_iterator<T, SetType> po_ext_begin(T G, SetType &S) {
188  return po_ext_iterator<T, SetType>::begin(G, S);
189}
190
191template<class T, class SetType>
192po_ext_iterator<T, SetType> po_ext_end(T G, SetType &S) {
193  return po_ext_iterator<T, SetType>::end(G, S);
194}
195
196// Provide global definitions of inverse post order iterators...
197template <class T,
198          class SetType = std::set<typename GraphTraits<T>::NodeType*>,
199          bool External = false>
200struct ipo_iterator : public po_iterator<Inverse<T>, SetType, External > {
201  ipo_iterator(const po_iterator<Inverse<T>, SetType, External> &V) :
202     po_iterator<Inverse<T>, SetType, External> (V) {}
203};
204
205template <class T>
206ipo_iterator<T> ipo_begin(T G, bool Reverse = false) {
207  return ipo_iterator<T>::begin(G, Reverse);
208}
209
210template <class T>
211ipo_iterator<T> ipo_end(T G){
212  return ipo_iterator<T>::end(G);
213}
214
215// Provide global definitions of external inverse postorder iterators...
216template <class T,
217          class SetType = std::set<typename GraphTraits<T>::NodeType*> >
218struct ipo_ext_iterator : public ipo_iterator<T, SetType, true> {
219  ipo_ext_iterator(const ipo_iterator<T, SetType, true> &V) :
220    ipo_iterator<T, SetType, true>(V) {}
221  ipo_ext_iterator(const po_iterator<Inverse<T>, SetType, true> &V) :
222    ipo_iterator<T, SetType, true>(V) {}
223};
224
225template <class T, class SetType>
226ipo_ext_iterator<T, SetType> ipo_ext_begin(T G, SetType &S) {
227  return ipo_ext_iterator<T, SetType>::begin(G, S);
228}
229
230template <class T, class SetType>
231ipo_ext_iterator<T, SetType> ipo_ext_end(T G, SetType &S) {
232  return ipo_ext_iterator<T, SetType>::end(G, S);
233}
234
235//===--------------------------------------------------------------------===//
236// Reverse Post Order CFG iterator code
237//===--------------------------------------------------------------------===//
238//
239// This is used to visit basic blocks in a method in reverse post order.  This
240// class is awkward to use because I don't know a good incremental algorithm to
241// computer RPO from a graph.  Because of this, the construction of the
242// ReversePostOrderTraversal object is expensive (it must walk the entire graph
243// with a postorder iterator to build the data structures).  The moral of this
244// story is: Don't create more ReversePostOrderTraversal classes than necessary.
245//
246// This class should be used like this:
247// {
248//   ReversePostOrderTraversal<Function*> RPOT(FuncPtr); // Expensive to create
249//   for (rpo_iterator I = RPOT.begin(); I != RPOT.end(); ++I) {
250//      ...
251//   }
252//   for (rpo_iterator I = RPOT.begin(); I != RPOT.end(); ++I) {
253//      ...
254//   }
255// }
256//
257
258template<class GraphT, class GT = GraphTraits<GraphT> >
259class ReversePostOrderTraversal {
260  typedef typename GT::NodeType NodeType;
261  std::vector<NodeType*> Blocks;       // Block list in normal PO order
262  inline void Initialize(NodeType *BB) {
263    std::copy(po_begin(BB), po_end(BB), std::back_inserter(Blocks));
264  }
265public:
266  typedef typename std::vector<NodeType*>::reverse_iterator rpo_iterator;
267
268  inline ReversePostOrderTraversal(GraphT G) {
269    Initialize(GT::getEntryNode(G));
270  }
271
272  // Because we want a reverse post order, use reverse iterators from the vector
273  inline rpo_iterator begin() { return Blocks.rbegin(); }
274  inline rpo_iterator end()   { return Blocks.rend(); }
275};
276
277} // End llvm namespace
278
279#endif
280