1 //===- PgmDependenceGraph.h - Enumerate the PDG for a function --*- C++ -*-===//
3 // The Program Dependence Graph (PDG) for a single function represents all
4 // data and control dependences for the function. This file provides an
5 // iterator to enumerate all these dependences. In particular, it enumerates:
7 // -- Data dependences on memory locations, computed using the
8 // MemoryDepAnalysis pass;
9 // -- Data dependences on SSA registers, directly from Def-Use edges of Values;
10 // -- Control dependences, computed using postdominance frontiers
11 // (NOT YET IMPLEMENTED).
13 // Note that this file does not create an explicit dependence graph --
14 // it only provides an iterator to traverse the PDG conceptually.
15 // The MemoryDepAnalysis does build an explicit graph, which is used internally
16 // here. That graph could be augmented with the other dependences above if
17 // desired, but for most uses there will be little need to do that.
21 // enum PDGIteratorFlags -- Specify which dependences to enumerate.
23 // class PDGIterator -- The PDG iterator. This is essentially like a
24 // pointer to class Dependence, but doesn't explicitly
25 // construct a Dependence object for each dependence.
27 // class PgmDependenceGraph -- Interface to obtain PDGIterators for each
29 //===----------------------------------------------------------------------===//
31 #ifndef LLVM_ANALYSIS_PGMDEPENDENCEGRAPH_H
32 #define LLVM_ANALYSIS_PGMDEPENDENCEGRAPH_H
34 #include "llvm/Analysis/DependenceGraph.h"
35 #include "llvm/Analysis/MemoryDepAnalysis.h"
36 /* #include "llvm/Analysis/PostDominators.h" -- see below */
37 #include "llvm/Instruction.h"
38 #include "llvm/Value.h"
39 #include "llvm/Pass.h"
40 #include "Support/NonCopyable.h"
47 class DependenceGraph;
48 class PgmDependenceGraph;
51 ///---------------------------------------------------------------------------
52 /// enum PDGIteratorFlags
54 /// These bit flags specify which dependences incident on a statement are to be
55 /// enumerated: Memory deps, SSA deps, Control deps, or any combination thereof.
56 ///---------------------------------------------------------------------------
58 enum PDGIteratorFlags {
59 MemoryDeps = 0x1, // load/store/call deps
60 SSADeps = 0x2, // SSA deps (true)
61 ControlDeps = /* 0x4*/ 0x0, // control dependences
62 AllDataDeps = MemoryDeps | SSADeps, // shorthand for data deps
63 AllDeps = MemoryDeps | SSADeps | ControlDeps // shorthand for all three
67 ///---------------------------------------------------------------------------
68 /// struct DepIterState
70 /// This data type is primarily an internal implementation detail.
71 /// It are exposed here only to give inlinable access to field dep,
72 /// which is the representation for the current dependence pointed to by
73 /// a PgmDependenceGraph::iterator.
74 ///---------------------------------------------------------------------------
78 typedef char IterStateFlags;
79 static const IterStateFlags NoFlag, MemDone, SSADone, AllDone, FirstTimeFlag;
82 DepGraphNode* depNode; // the node being enumerated
83 DependenceGraph::iterator memDepIter; // pointer to current memory dep
84 Instruction::op_iterator ssaInEdgeIter; // pointer to current SSA in-dep
85 Value::use_iterator ssaOutEdgeIter; // pointer to current SSA out-dep
86 DependenceGraph* memDepGraph; // the core dependence graph
87 Dependence dep; // the "current" dependence
88 PDGIteratorFlags depFlags:8; // which deps are we enumerating?
89 IterStateFlags iterFlags:8; // marking where the iter stands
91 /*ctor*/ DepIterState (DependenceGraph* _memDepGraph,
94 PDGIteratorFlags whichDeps);
96 bool operator==(const DepIterState& S) {
97 assert(memDepGraph == S.memDepGraph &&
98 "Incompatible iterators! This is a probable sign of something BAD.");
99 return (iterFlags == S.iterFlags &&
100 dep == S.dep && depFlags == S.depFlags && depNode == S.depNode &&
101 memDepIter == S.memDepIter && ssaInEdgeIter == S.ssaInEdgeIter &&
102 ssaOutEdgeIter == S.ssaOutEdgeIter);
105 // Is the iteration completely done?
107 bool done () const { return iterFlags & AllDone; }
109 // Bump this iterator logically by 1 (to next dependence) and reset the
110 // dep field to represent the new dependence if there is one.
111 // Set done = true otherwise.
115 // Find the first memory dependence for the current Mem In/Out iterators.
116 // Sets dep to that dependence and returns true if one is found.
117 // Returns false and leaves dep unchanged otherwise.
119 bool SetFirstMemoryDep();
121 // Find the next valid data dependence for the current SSA In/Out iterators.
122 // A valid data dependence is one that is to/from an Instruction.
123 // E.g., an SSA edge from a formal parameter is not a valid dependence.
124 // Sets dep to that dependence and returns true if a valid one is found.
125 // Returns false and leaves dep unchanged otherwise.
127 bool SetFirstSSADep ();
131 ///---------------------------------------------------------------------------
132 /// The dependence iterator class. This class represents a pointer to
133 /// a single dependence in the program dependence graph. It is essentially
134 /// like a pointer to an object of class Dependence but it is much more
135 /// efficient to retrieve information about the dependence directly rather
136 /// than constructing the equivalent Dependence object (since that object
137 /// is normally not constructed for SSA def-use dependences).
138 ///---------------------------------------------------------------------------
140 class PDGIterator: public forward_iterator<Dependence, ptrdiff_t>
142 DepIterState* istate;
145 /*copy*/ PDGIterator (const PDGIterator& I); // do not implement!
146 PDGIterator& operator= (const PDGIterator& I); // do not implement!
148 /*copy*/ PDGIterator (PDGIterator& I) : istate(I.istate) {
149 I.istate = NULL; // ensure this is not deleted twice.
153 friend class PgmDependenceGraph;
156 typedef PDGIterator _Self;
158 /*ctor*/ PDGIterator (DepIterState* _istate) : istate(_istate) { }
159 /*dtor*/ ~PDGIterator () { delete istate; }
161 /*copy*/ PDGIterator (const PDGIterator& I)
162 : istate(new DepIterState(*I.istate)) { }
164 PDGIterator& operator= (const PDGIterator& I) {
165 if (istate) delete istate;
166 istate = new DepIterState(*I.istate);
170 // Check if the iteration is complete
172 bool fini() const { return !istate || istate->done(); }
174 // Retrieve the underlying Dependence. Returns NULL if fini().
176 Dependence* operator*() const { return fini() ? NULL : &istate->dep; }
177 Dependence* operator->() const { assert(!fini()); return &istate->dep; }
179 // Increment the iterator
181 _Self& operator++() { if (!fini()) istate->Next(); return *this;}
182 _Self& operator++(int); // do not implement!
184 // Equality comparison: a "null" state should compare equal to done
185 // This is efficient for comparing with "end" or with itself, but could
186 // be quite inefficient for other cases.
188 bool operator==(const PDGIterator& I) const {
189 if (I.istate == NULL) // most common case: iter == end()
190 return (istate == NULL || istate->done());
192 return (I.istate == NULL || I.istate->done());
193 return (*istate == *I.istate);
195 bool operator!=(const PDGIterator& I) const {
196 return ! (*this == I);
201 ///---------------------------------------------------------------------------
202 /// class PgmDependenceGraph:
204 /// This pass enumerates dependences incident on each instruction in a function.
205 /// It can be made a FunctionPass once a Pass (such as Parallelize) is
206 /// allowed to use a FunctionPass such as this one.
207 ///---------------------------------------------------------------------------
209 class PgmDependenceGraph: public Pass {
211 /// Information about the function being analyzed.
213 DependenceGraph* memDepGraph;
215 // print helper function.
216 void printOutgoingSSADeps(Instruction& I, std::ostream &O);
219 // The first version creates and initializes an iterator as specified.
220 // The second version creates a null iterator representing end-of-iteration.
222 PDGIterator MakeIterator (Instruction& I,
224 PDGIteratorFlags whichDeps);
226 PDGIterator MakeIterator () { return PDGIterator(NULL); }
228 friend class PDGIterator;
229 friend class DepIterState;
232 typedef PDGIterator iterator;
233 /* typedef PDGIterator<const Dependence> const iterator; */
236 PgmDependenceGraph() : memDepGraph(NULL) { }
237 ~PgmDependenceGraph() { }
239 /// Iterators to enumerate the program dependence graph for a function.
240 /// Note that this does not provide "end" iterators to check for completion.
241 /// Instead, just use iterator::fini() or iterator::operator*() == NULL
243 iterator inDepBegin(Instruction& I, PDGIteratorFlags whichDeps = AllDeps) {
244 return MakeIterator(I, /*inDeps*/ true, whichDeps);
246 iterator inDepEnd (Instruction& I, PDGIteratorFlags whichDeps = AllDeps) {
247 return MakeIterator();
249 iterator outDepBegin(Instruction& I, PDGIteratorFlags whichDeps = AllDeps) {
250 return MakeIterator(I, /*inDeps*/ false, whichDeps);
252 iterator outDepEnd (Instruction& I, PDGIteratorFlags whichDeps = AllDeps) {
253 return MakeIterator();
256 ///------------------------------------------------------------------------
257 /// TEMPORARY FUNCTIONS TO MAKE THIS A MODULE PASS ---
258 /// These functions will go away once this class becomes a FunctionPass.
260 /// Driver function to compute dependence graphs for every function.
262 bool run(Module& M) { return true; }
264 /// getGraph() -- Retrieve the pgm dependence graph for a function.
265 /// This is temporary and will go away once this is a FunctionPass.
266 /// At that point, this class itself will be the PgmDependenceGraph you want.
268 PgmDependenceGraph& getGraph(Function& F) {
274 void Visiting(Function& F) {
275 memDepGraph = &getAnalysis<MemoryDepAnalysis>().getGraph(F);
278 ///----END TEMPORARY FUNCTIONS---------------------------------------------
281 /// This initializes the program dependence graph iterator for a function.
283 bool runOnFunction(Function& func) {
288 /// getAnalysisUsage - This does not modify anything.
289 /// It uses the Memory Dependence Analysis pass.
290 /// It needs to use the PostDominanceFrontier pass, but cannot because
291 /// that is a FunctionPass. This means control dependence are not emumerated.
293 void getAnalysisUsage(AnalysisUsage &AU) const {
294 AU.setPreservesAll();
295 AU.addRequired<MemoryDepAnalysis>();
296 /* AU.addRequired<PostDominanceFrontier>(); */
299 /// Debugging support methods
301 void print(std::ostream &O) const;
306 //===----------------------------------------------------------------------===//