blob: 8906682eff95a8f29865be08bbe04a15110f7b42 [file] [log] [blame]
Chris Lattner71ef8f72004-06-28 00:20:04 +00001//===- PgmDependenceGraph.h - Enumerate the PDG for a function --*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file was developed by the LLVM research group and is distributed under
6// the University of Illinois Open Source License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// The Program Dependence Graph (PDG) for a single function represents all
11// data and control dependences for the function. This file provides an
12// iterator to enumerate all these dependences. In particular, it enumerates:
13//
14// -- Data dependences on memory locations, computed using the
15// MemoryDepAnalysis pass;
16// -- Data dependences on SSA registers, directly from Def-Use edges of Values;
17// -- Control dependences, computed using postdominance frontiers
18// (NOT YET IMPLEMENTED).
19//
20// Note that this file does not create an explicit dependence graph --
21// it only provides an iterator to traverse the PDG conceptually.
22// The MemoryDepAnalysis does build an explicit graph, which is used internally
23// here. That graph could be augmented with the other dependences above if
24// desired, but for most uses there will be little need to do that.
25//
26// Key Classes:
27//
28// enum PDGIteratorFlags -- Specify which dependences to enumerate.
29//
30// class PDGIterator -- The PDG iterator. This is essentially like a
31// pointer to class Dependence, but doesn't explicitly
32// construct a Dependence object for each dependence.
33//
34// class PgmDependenceGraph -- Interface to obtain PDGIterators for each
35// instruction.
36//
37//===----------------------------------------------------------------------===//
38
39#ifndef LLVM_ANALYSIS_PGMDEPENDENCEGRAPH_H
40#define LLVM_ANALYSIS_PGMDEPENDENCEGRAPH_H
41
42#include "llvm/Analysis/DependenceGraph.h"
Chris Lattner0ecdcbe2004-06-28 00:27:16 +000043#include "MemoryDepAnalysis.h"
Chris Lattner71ef8f72004-06-28 00:20:04 +000044/* #include "llvm/Analysis/PostDominators.h" -- see below */
45#include "llvm/Instruction.h"
46#include "llvm/Pass.h"
47#include "Support/iterator"
48
49namespace llvm {
50
51class DSGraph;
52class DependenceGraph;
53class PgmDependenceGraph;
54
55//---------------------------------------------------------------------------
56/// enum PDGIteratorFlags - specify which dependences incident on a statement
57/// are to be enumerated: Memory deps, SSA deps, Control deps, or any
58/// combination thereof.
59///
60enum PDGIteratorFlags {
61 MemoryDeps = 0x1, // load/store/call deps
62 SSADeps = 0x2, // SSA deps (true)
63 ControlDeps = /* 0x4*/ 0x0, // control dependences
64 AllDataDeps = MemoryDeps | SSADeps, // shorthand for data deps
65 AllDeps = MemoryDeps | SSADeps | ControlDeps // shorthand for all three
66};
67
68//---------------------------------------------------------------------------
69/// struct DepIterState - an internal implementation detail.
70/// It are exposed here only to give inlinable access to field dep,
71/// which is the representation for the current dependence pointed to by
72/// a PgmDependenceGraph::iterator.
73///
74class DepIterState {
75private:
76 typedef char IterStateFlags;
77 static const IterStateFlags NoFlag, MemDone, SSADone, AllDone, FirstTimeFlag;
78
79public:
80 DepGraphNode* depNode; // the node being enumerated
81 DependenceGraph::iterator memDepIter; // pointer to current memory dep
82 Instruction::op_iterator ssaInEdgeIter; // pointer to current SSA in-dep
83 Value::use_iterator ssaOutEdgeIter; // pointer to current SSA out-dep
84 DependenceGraph* memDepGraph; // the core dependence graph
85 Dependence dep; // the "current" dependence
86 PDGIteratorFlags depFlags:8; // which deps are we enumerating?
87 IterStateFlags iterFlags:8; // marking where the iter stands
88
89 DepIterState(DependenceGraph* _memDepGraph,
90 Instruction& I,
91 bool incomingDeps,
92 PDGIteratorFlags whichDeps);
93
94 bool operator==(const DepIterState& S) {
95 assert(memDepGraph == S.memDepGraph &&
96 "Incompatible iterators! This is a probable sign of something BAD.");
97 return (iterFlags == S.iterFlags &&
98 dep == S.dep && depFlags == S.depFlags && depNode == S.depNode &&
99 memDepIter == S.memDepIter && ssaInEdgeIter == S.ssaInEdgeIter &&
100 ssaOutEdgeIter == S.ssaOutEdgeIter);
101 }
102
103 // Is the iteration completely done?
104 //
105 bool done() const { return iterFlags & AllDone; }
106
107 /// Next - Bump this iterator logically by 1 (to next dependence) and reset
108 /// the dep field to represent the new dependence if there is one.
109 /// Set done = true otherwise.
110 ///
111 void Next();
112
113 /// SetFirstMemoryDep - Find the first memory dependence for the current Mem
114 /// In/Out iterators. Sets dep to that dependence and returns true if one is
115 /// found. Returns false and leaves dep unchanged otherwise.
116 ///
117 bool SetFirstMemoryDep();
118
119 /// SetFirstSSADep - Find the next valid data dependence for the current SSA
120 /// In/Out iterators. A valid data dependence is one that is to/from an
121 /// Instruction. E.g., an SSA edge from a formal parameter is not a valid
122 /// dependence. Sets dep to that dependence and returns true if a valid one is
123 /// found. Returns false and leaves dep unchanged otherwise.
124 ///
125 bool SetFirstSSADep();
126};
127
128
129//---------------------------------------------------------------------------
130/// PDGIterator Class - represents a pointer to a single dependence in the
131/// program dependence graph. It is essentially like a pointer to an object of
132/// class Dependence but it is much more efficient to retrieve information about
133/// the dependence directly rather than constructing the equivalent Dependence
134/// object (since that object is normally not constructed for SSA def-use
135/// dependences).
136///
137class PDGIterator: public forward_iterator<Dependence, ptrdiff_t> {
138 DepIterState* istate;
139
140#if 0
141 /*copy*/ PDGIterator (const PDGIterator& I); // do not implement!
142 PDGIterator& operator= (const PDGIterator& I); // do not implement!
143
144 /*copy*/ PDGIterator (PDGIterator& I) : istate(I.istate) {
145 I.istate = NULL; // ensure this is not deleted twice.
146 }
147#endif
148
149 friend class PgmDependenceGraph;
150
151public:
152 typedef PDGIterator _Self;
153
154 PDGIterator(DepIterState* _istate) : istate(_istate) {}
155 ~PDGIterator() { delete istate; }
156
157 PDGIterator(const PDGIterator& I) :istate(new DepIterState(*I.istate)) {}
158
159 PDGIterator& operator=(const PDGIterator& I) {
160 if (istate) delete istate;
161 istate = new DepIterState(*I.istate);
162 return *this;
163 }
164
165 /// fini - check if the iteration is complete
166 ///
167 bool fini() const { return !istate || istate->done(); }
168
169 // Retrieve the underlying Dependence. Returns NULL if fini().
170 //
171 Dependence* operator*() const { return fini() ? NULL : &istate->dep; }
172 Dependence* operator->() const { assert(!fini()); return &istate->dep; }
173
174 // Increment the iterator
175 //
176 _Self& operator++() { if (!fini()) istate->Next(); return *this;}
177 _Self& operator++(int); // do not implement!
178
179 // Equality comparison: a "null" state should compare equal to done
180 // This is efficient for comparing with "end" or with itself, but could
181 // be quite inefficient for other cases.
182 //
183 bool operator==(const PDGIterator& I) const {
184 if (I.istate == NULL) // most common case: iter == end()
185 return (istate == NULL || istate->done());
186 if (istate == NULL)
187 return (I.istate == NULL || I.istate->done());
188 return (*istate == *I.istate);
189 }
190 bool operator!=(const PDGIterator& I) const {
191 return ! (*this == I);
192 }
193};
194
195
196///---------------------------------------------------------------------------
197/// class PgmDependenceGraph:
198///
199/// This pass enumerates dependences incident on each instruction in a function.
200/// It can be made a FunctionPass once a Pass (such as Parallelize) is
201/// allowed to use a FunctionPass such as this one.
202///---------------------------------------------------------------------------
203
204class PgmDependenceGraph: public Pass {
205
206 /// Information about the function being analyzed.
207 ///
208 DependenceGraph* memDepGraph;
209
210 // print helper function.
211 void printOutgoingSSADeps(Instruction& I, std::ostream &O);
212
213 /// MakeIterator - creates and initializes an iterator as specified.
214 ///
215 PDGIterator MakeIterator(Instruction& I,
216 bool incomingDeps,
217 PDGIteratorFlags whichDeps);
218
219 /// MakeIterator - creates a null iterator representing end-of-iteration.
220 ///
221 PDGIterator MakeIterator() { return PDGIterator(NULL); }
222
223 friend class PDGIterator;
224 friend class DepIterState;
225
226public:
227 typedef PDGIterator iterator;
228 /* typedef PDGIterator<const Dependence> const iterator; */
229
230public:
231 PgmDependenceGraph() : memDepGraph(NULL) {}
232 ~PgmDependenceGraph() {}
233
234 /// Iterators to enumerate the program dependence graph for a function.
235 /// Note that this does not provide "end" iterators to check for completion.
236 /// Instead, just use iterator::fini() or iterator::operator*() == NULL
237 ///
238 iterator inDepBegin(Instruction& I, PDGIteratorFlags whichDeps = AllDeps) {
239 return MakeIterator(I, /*inDeps*/ true, whichDeps);
240 }
241 iterator inDepEnd (Instruction& I, PDGIteratorFlags whichDeps = AllDeps) {
242 return MakeIterator();
243 }
244 iterator outDepBegin(Instruction& I, PDGIteratorFlags whichDeps = AllDeps) {
245 return MakeIterator(I, /*inDeps*/ false, whichDeps);
246 }
247 iterator outDepEnd (Instruction& I, PDGIteratorFlags whichDeps = AllDeps) {
248 return MakeIterator();
249 }
250
251 //------------------------------------------------------------------------
252 /// TEMPORARY FUNCTIONS TO MAKE THIS A MODULE PASS ---
253 /// These functions will go away once this class becomes a FunctionPass.
254
255 /// Driver function to compute dependence graphs for every function.
256 ///
257 bool run(Module& M) { return true; }
258
259 /// getGraph() -- Retrieve the pgm dependence graph for a function.
260 /// This is temporary and will go away once this is a FunctionPass.
261 /// At that point, this class itself will be the PgmDependenceGraph you want.
262 ///
263 PgmDependenceGraph& getGraph(Function& F) {
264 Visiting(F);
265 return *this;
266 }
267
268 private:
269 void Visiting(Function& F) {
270 memDepGraph = &getAnalysis<MemoryDepAnalysis>().getGraph(F);
271 }
272 public:
273 ///----END TEMPORARY FUNCTIONS---------------------------------------------
274
275
276 /// This initializes the program dependence graph iterator for a function.
277 ///
278 bool runOnFunction(Function& func) {
279 Visiting(func);
280 return true;
281 }
282
283 /// getAnalysisUsage - This does not modify anything.
284 /// It uses the Memory Dependence Analysis pass.
285 /// It needs to use the PostDominanceFrontier pass, but cannot because
286 /// that is a FunctionPass. This means control dependence are not emumerated.
287 ///
288 void getAnalysisUsage(AnalysisUsage &AU) const {
289 AU.setPreservesAll();
290 AU.addRequired<MemoryDepAnalysis>();
291 /* AU.addRequired<PostDominanceFrontier>(); */
292 }
293
294 /// Debugging support methods
295 ///
296 void print(std::ostream &O) const;
297 void dump() const;
298};
299
300} // End llvm namespace
301
302#endif