LLVM  4.0.0
IntervalIterator.h
Go to the documentation of this file.
1 //===- IntervalIterator.h - Interval Iterator Declaration -------*- C++ -*-===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file defines an iterator that enumerates the intervals in a control flow
11 // graph of some sort. This iterator is parametric, allowing iterator over the
12 // following types of graphs:
13 //
14 // 1. A Function* object, composed of BasicBlock nodes.
15 // 2. An IntervalPartition& object, composed of Interval nodes.
16 //
17 // This iterator is defined to walk the control flow graph, returning intervals
18 // in depth first order. These intervals are completely filled in except for
19 // the predecessor fields (the successor information is filled in however).
20 //
21 // By default, the intervals created by this iterator are deleted after they
22 // are no longer any use to the iterator. This behavior can be changed by
23 // passing a false value into the intervals_begin() function. This causes the
24 // IOwnMem member to be set, and the intervals to not be deleted.
25 //
26 // It is only safe to use this if all of the intervals are deleted by the caller
27 // and all of the intervals are processed. However, the user of the iterator is
28 // not allowed to modify or delete the intervals until after the iterator has
29 // been used completely. The IntervalPartition class uses this functionality.
30 //
31 //===----------------------------------------------------------------------===//
32 
33 #ifndef LLVM_ANALYSIS_INTERVALITERATOR_H
34 #define LLVM_ANALYSIS_INTERVALITERATOR_H
35 
37 #include "llvm/IR/CFG.h"
38 #include "llvm/IR/Function.h"
39 #include <algorithm>
40 #include <set>
41 #include <vector>
42 
43 namespace llvm {
44 
45 // getNodeHeader - Given a source graph node and the source graph, return the
46 // BasicBlock that is the header node. This is the opposite of
47 // getSourceGraphNode.
48 //
49 inline BasicBlock *getNodeHeader(BasicBlock *BB) { return BB; }
50 inline BasicBlock *getNodeHeader(Interval *I) { return I->getHeaderNode(); }
51 
52 // getSourceGraphNode - Given a BasicBlock and the source graph, return the
53 // source graph node that corresponds to the BasicBlock. This is the opposite
54 // of getNodeHeader.
55 //
57  return BB;
58 }
60  return IP->getBlockInterval(BB);
61 }
62 
63 // addNodeToInterval - This method exists to assist the generic ProcessNode
64 // with the task of adding a node to the new interval, depending on the
65 // type of the source node. In the case of a CFG source graph (BasicBlock
66 // case), the BasicBlock itself is added to the interval.
67 //
68 inline void addNodeToInterval(Interval *Int, BasicBlock *BB) {
69  Int->Nodes.push_back(BB);
70 }
71 
72 // addNodeToInterval - This method exists to assist the generic ProcessNode
73 // with the task of adding a node to the new interval, depending on the
74 // type of the source node. In the case of a CFG source graph (BasicBlock
75 // case), the BasicBlock itself is added to the interval. In the case of
76 // an IntervalPartition source graph (Interval case), all of the member
77 // BasicBlocks are added to the interval.
78 //
79 inline void addNodeToInterval(Interval *Int, Interval *I) {
80  // Add all of the nodes in I as new nodes in Int.
81  Int->Nodes.insert(Int->Nodes.end(), I->Nodes.begin(), I->Nodes.end());
82 }
83 
84 
85 
86 
87 
88 template<class NodeTy, class OrigContainer_t, class GT = GraphTraits<NodeTy*>,
89  class IGT = GraphTraits<Inverse<NodeTy*> > >
91  std::vector<std::pair<Interval*, typename Interval::succ_iterator> > IntStack;
92  std::set<BasicBlock*> Visited;
93  OrigContainer_t *OrigContainer;
94  bool IOwnMem; // If True, delete intervals when done with them
95  // See file header for conditions of use
96 public:
97  typedef std::forward_iterator_tag iterator_category;
98 
99  IntervalIterator() {} // End iterator, empty stack
100  IntervalIterator(Function *M, bool OwnMemory) : IOwnMem(OwnMemory) {
101  OrigContainer = M;
102  if (!ProcessInterval(&M->front())) {
103  llvm_unreachable("ProcessInterval should never fail for first interval!");
104  }
105  }
106 
108  : IntStack(std::move(x.IntStack)), Visited(std::move(x.Visited)),
109  OrigContainer(x.OrigContainer), IOwnMem(x.IOwnMem) {
110  x.IOwnMem = false;
111  }
112 
113  IntervalIterator(IntervalPartition &IP, bool OwnMemory) : IOwnMem(OwnMemory) {
114  OrigContainer = &IP;
115  if (!ProcessInterval(IP.getRootInterval())) {
116  llvm_unreachable("ProcessInterval should never fail for first interval!");
117  }
118  }
119 
121  if (IOwnMem)
122  while (!IntStack.empty()) {
123  delete operator*();
124  IntStack.pop_back();
125  }
126  }
127 
128  bool operator==(const IntervalIterator &x) const {
129  return IntStack == x.IntStack;
130  }
131  bool operator!=(const IntervalIterator &x) const { return !(*this == x); }
132 
133  const Interval *operator*() const { return IntStack.back().first; }
134  Interval *operator*() { return IntStack.back().first; }
135  const Interval *operator->() const { return operator*(); }
136  Interval *operator->() { return operator*(); }
137 
138  IntervalIterator &operator++() { // Preincrement
139  assert(!IntStack.empty() && "Attempting to use interval iterator at end!");
140  do {
141  // All of the intervals on the stack have been visited. Try visiting
142  // their successors now.
143  Interval::succ_iterator &SuccIt = IntStack.back().second,
144  EndIt = succ_end(IntStack.back().first);
145  while (SuccIt != EndIt) { // Loop over all interval succs
146  bool Done = ProcessInterval(getSourceGraphNode(OrigContainer, *SuccIt));
147  ++SuccIt; // Increment iterator
148  if (Done) return *this; // Found a new interval! Use it!
149  }
150 
151  // Free interval memory... if necessary
152  if (IOwnMem) delete IntStack.back().first;
153 
154  // We ran out of successors for this interval... pop off the stack
155  IntStack.pop_back();
156  } while (!IntStack.empty());
157 
158  return *this;
159  }
160  IntervalIterator operator++(int) { // Postincrement
161  IntervalIterator tmp = *this;
162  ++*this;
163  return tmp;
164  }
165 
166 private:
167  // ProcessInterval - This method is used during the construction of the
168  // interval graph. It walks through the source graph, recursively creating
169  // an interval per invocation until the entire graph is covered. This uses
170  // the ProcessNode method to add all of the nodes to the interval.
171  //
172  // This method is templated because it may operate on two different source
173  // graphs: a basic block graph, or a preexisting interval graph.
174  //
175  bool ProcessInterval(NodeTy *Node) {
176  BasicBlock *Header = getNodeHeader(Node);
177  if (!Visited.insert(Header).second)
178  return false;
179 
180  Interval *Int = new Interval(Header);
181 
182  // Check all of our successors to see if they are in the interval...
183  for (typename GT::ChildIteratorType I = GT::child_begin(Node),
184  E = GT::child_end(Node); I != E; ++I)
185  ProcessNode(Int, getSourceGraphNode(OrigContainer, *I));
186 
187  IntStack.push_back(std::make_pair(Int, succ_begin(Int)));
188  return true;
189  }
190 
191  // ProcessNode - This method is called by ProcessInterval to add nodes to the
192  // interval being constructed, and it is also called recursively as it walks
193  // the source graph. A node is added to the current interval only if all of
194  // its predecessors are already in the graph. This also takes care of keeping
195  // the successor set of an interval up to date.
196  //
197  // This method is templated because it may operate on two different source
198  // graphs: a basic block graph, or a preexisting interval graph.
199  //
200  void ProcessNode(Interval *Int, NodeTy *Node) {
201  assert(Int && "Null interval == bad!");
202  assert(Node && "Null Node == bad!");
203 
204  BasicBlock *NodeHeader = getNodeHeader(Node);
205 
206  if (Visited.count(NodeHeader)) { // Node already been visited?
207  if (Int->contains(NodeHeader)) { // Already in this interval...
208  return;
209  } else { // In other interval, add as successor
210  if (!Int->isSuccessor(NodeHeader)) // Add only if not already in set
211  Int->Successors.push_back(NodeHeader);
212  }
213  } else { // Otherwise, not in interval yet
214  for (typename IGT::ChildIteratorType I = IGT::child_begin(Node),
215  E = IGT::child_end(Node); I != E; ++I) {
216  if (!Int->contains(*I)) { // If pred not in interval, we can't be
217  if (!Int->isSuccessor(NodeHeader)) // Add only if not already in set
218  Int->Successors.push_back(NodeHeader);
219  return; // See you later
220  }
221  }
222 
223  // If we get here, then all of the predecessors of BB are in the interval
224  // already. In this case, we must add BB to the interval!
225  addNodeToInterval(Int, Node);
226  Visited.insert(NodeHeader); // The node has now been visited!
227 
228  if (Int->isSuccessor(NodeHeader)) {
229  // If we were in the successor list from before... remove from succ list
230  Int->Successors.erase(std::remove(Int->Successors.begin(),
231  Int->Successors.end(), NodeHeader),
232  Int->Successors.end());
233  }
234 
235  // Now that we have discovered that Node is in the interval, perhaps some
236  // of its successors are as well?
237  for (typename GT::ChildIteratorType It = GT::child_begin(Node),
238  End = GT::child_end(Node); It != End; ++It)
239  ProcessNode(Int, getSourceGraphNode(OrigContainer, *It));
240  }
241  }
242 };
243 
247 
248 
250  bool DeleteInts = true) {
251  return function_interval_iterator(F, DeleteInts);
252 }
255 }
256 
258  intervals_begin(IntervalPartition &IP, bool DeleteIntervals = true) {
259  return interval_part_interval_iterator(IP, DeleteIntervals);
260 }
261 
264 }
265 
266 } // End llvm namespace
267 
268 #endif
function_interval_iterator intervals_end(Function *)
const Interval * operator->() const
Various leaf nodes.
Definition: ISDOpcodes.h:60
Interval Class - An Interval is a set of nodes defined such that every node in the interval has all o...
Definition: Interval.h:37
std::error_code remove(const Twine &path, bool IgnoreNonExisting=true)
Remove path.
bool operator==(const IntervalIterator &x) const
BasicBlock * getNodeHeader(BasicBlock *BB)
IntervalIterator< Interval, IntervalPartition > interval_part_interval_iterator
Interval::succ_iterator succ_begin(Interval *I)
succ_begin/succ_end - define methods so that Intervals may be used just like BasicBlocks can with the...
Definition: Interval.h:106
#define F(x, y, z)
Definition: MD5.cpp:51
function_interval_iterator intervals_begin(Function *F, bool DeleteInts=true)
void addNodeToInterval(Interval *Int, BasicBlock *BB)
static GCRegistry::Add< CoreCLRGC > E("coreclr","CoreCLR-compatible GC")
Interval::succ_iterator succ_end(Interval *I)
Definition: Interval.h:109
LLVM Basic Block Representation.
Definition: BasicBlock.h:51
bool operator!=(const IntervalIterator &x) const
static const unsigned End
const Interval * operator*() const
std::vector< BasicBlock * > Nodes
Nodes - The basic blocks in this interval.
Definition: Interval.h:55
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
BasicBlock * getSourceGraphNode(Function *, BasicBlock *BB)
std::pair< uint32_t, uint32_t > Interval
IntervalIterator< BasicBlock, Function > function_interval_iterator
IntervalIterator(Function *M, bool OwnMemory)
BasicBlock * getHeaderNode() const
Definition: Interval.h:51
#define I(x, y, z)
Definition: MD5.cpp:54
IntervalIterator operator++(int)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
const BasicBlock & front() const
Definition: Function.h:542
IntervalIterator(IntervalIterator &&x)
IntervalIterator(IntervalPartition &IP, bool OwnMemory)
std::vector< BasicBlock * >::iterator succ_iterator
Definition: Interval.h:43
IntervalIterator & operator++()
std::forward_iterator_tag iterator_category
Interval * getBlockInterval(BasicBlock *BB)