Implement optimization for direct function call case. This dramatically
[oota-llvm.git] / include / llvm / Analysis / DSGraph.h
1 //===- DSGraph.h - Represent a collection of data structures ----*- C++ -*-===//
2 //
3 // This header defines the data structure graph.
4 //
5 //===----------------------------------------------------------------------===//
6
7 #ifndef LLVM_ANALYSIS_DSGRAPH_H
8 #define LLVM_ANALYSIS_DSGRAPH_H
9
10 #include "llvm/Analysis/DSNode.h"
11
12 //===----------------------------------------------------------------------===//
13 /// DSGraph - The graph that represents a function.
14 ///
15 class DSGraph {
16   Function *Func;          // Func - The LLVM function this graph corresponds to
17   DSGraph *GlobalsGraph;   // Pointer to the common graph of global objects
18   bool PrintAuxCalls;      // Should this graph print the Aux calls vector?
19
20   DSNodeHandle RetNode;    // The node that gets returned...
21   std::vector<DSNode*> Nodes;
22   hash_map<Value*, DSNodeHandle> ScalarMap;
23
24   // FunctionCalls - This vector maintains a single entry for each call
25   // instruction in the current graph.  The first entry in the vector is the
26   // scalar that holds the return value for the call, the second is the function
27   // scalar being invoked, and the rest are pointer arguments to the function.
28   // This vector is built by the Local graph and is never modified after that.
29   //
30   std::vector<DSCallSite> FunctionCalls;
31
32   // AuxFunctionCalls - This vector contains call sites that have been processed
33   // by some mechanism.  In pratice, the BU Analysis uses this vector to hold
34   // the _unresolved_ call sites, because it cannot modify FunctionCalls.
35   //
36   std::vector<DSCallSite> AuxFunctionCalls;
37
38   void operator=(const DSGraph &); // DO NOT IMPLEMENT
39 public:
40   DSGraph() : Func(0), GlobalsGraph(0) {}      // Create a new, empty, DSGraph.
41   DSGraph(Function &F, DSGraph *GlobalsGraph); // Compute the local DSGraph
42
43   // Copy ctor - If you want to capture the node mapping between the source and
44   // destination graph, you may optionally do this by specifying a map to record
45   // this into.
46   //
47   // Note that a copied graph does not retain the GlobalsGraph pointer of the
48   // source.  You need to set a new GlobalsGraph with the setGlobalsGraph
49   // method.
50   //
51   DSGraph(const DSGraph &DSG);
52   DSGraph(const DSGraph &DSG, hash_map<const DSNode*, DSNodeHandle> &NodeMap);
53   ~DSGraph();
54
55   bool hasFunction() const { return Func != 0; }
56   Function &getFunction() const {
57     assert(hasFunction() && "Cannot call getFunction on graph without a fn!");
58     return *Func;
59   }
60
61   DSGraph *getGlobalsGraph() const { return GlobalsGraph; }
62   void setGlobalsGraph(DSGraph *G) { GlobalsGraph = G; }
63
64   // setPrintAuxCalls - If you call this method, the auxillary call vector will
65   // be printed instead of the standard call vector to the dot file.
66   //
67   void setPrintAuxCalls() { PrintAuxCalls = true; }
68   bool shouldPrintAuxCalls() const { return PrintAuxCalls; }
69
70   /// getNodes - Get a vector of all the nodes in the graph
71   /// 
72   const std::vector<DSNode*> &getNodes() const { return Nodes; }
73         std::vector<DSNode*> &getNodes()       { return Nodes; }
74
75   /// addNode - Add a new node to the graph.
76   ///
77   void addNode(DSNode *N) { Nodes.push_back(N); }
78
79   /// getScalarMap - Get a map that describes what the nodes the scalars in this
80   /// function point to...
81   ///
82   hash_map<Value*, DSNodeHandle> &getScalarMap() { return ScalarMap; }
83   const hash_map<Value*, DSNodeHandle> &getScalarMap() const {return ScalarMap;}
84
85   /// getFunctionCalls - Return the list of call sites in the original local
86   /// graph...
87   ///
88   const std::vector<DSCallSite> &getFunctionCalls() const {
89     return FunctionCalls;
90   }
91
92   /// getAuxFunctionCalls - Get the call sites as modified by whatever passes
93   /// have been run.
94   ///
95   std::vector<DSCallSite> &getAuxFunctionCalls() {
96     return AuxFunctionCalls;
97   }
98   const std::vector<DSCallSite> &getAuxFunctionCalls() const {
99     return AuxFunctionCalls;
100   }
101
102   /// getNodeForValue - Given a value that is used or defined in the body of the
103   /// current function, return the DSNode that it points to.
104   ///
105   DSNodeHandle &getNodeForValue(Value *V) { return ScalarMap[V]; }
106
107   const DSNodeHandle &getNodeForValue(Value *V) const {
108     hash_map<Value*, DSNodeHandle>::const_iterator I = ScalarMap.find(V);
109     assert(I != ScalarMap.end() &&
110            "Use non-const lookup function if node may not be in the map");
111     return I->second;
112   }
113
114   const DSNodeHandle &getRetNode() const { return RetNode; }
115         DSNodeHandle &getRetNode()       { return RetNode; }
116
117   unsigned getGraphSize() const {
118     return Nodes.size();
119   }
120
121   void print(std::ostream &O) const;
122   void dump() const;
123   void writeGraphToFile(std::ostream &O, const std::string &GraphName) const;
124
125   /// maskNodeTypes - Apply a mask to all of the node types in the graph.  This
126   /// is useful for clearing out markers like Incomplete.
127   ///
128   void maskNodeTypes(unsigned char Mask) {
129     for (unsigned i = 0, e = Nodes.size(); i != e; ++i)
130       Nodes[i]->NodeType &= Mask;
131   }
132   void maskIncompleteMarkers() { maskNodeTypes(~DSNode::Incomplete); }
133
134   // markIncompleteNodes - Traverse the graph, identifying nodes that may be
135   // modified by other functions that have not been resolved yet.  This marks
136   // nodes that are reachable through three sources of "unknownness":
137   //   Global Variables, Function Calls, and Incoming Arguments
138   //
139   // For any node that may have unknown components (because something outside
140   // the scope of current analysis may have modified it), the 'Incomplete' flag
141   // is added to the NodeType.
142   //
143   enum MarkIncompleteFlags {
144     MarkFormalArgs = 1, IgnoreFormalArgs = 0,
145   };
146   void markIncompleteNodes(unsigned Flags);
147
148   // removeDeadNodes - Use a reachability analysis to eliminate subgraphs that
149   // are unreachable.  This often occurs because the data structure doesn't
150   // "escape" into it's caller, and thus should be eliminated from the caller's
151   // graph entirely.  This is only appropriate to use when inlining graphs.
152   //
153   enum RemoveDeadNodesFlags {
154     RemoveUnreachableGlobals = 1, KeepUnreachableGlobals = 0,
155   };
156   void removeDeadNodes(unsigned Flags);
157
158   // CloneFlags enum - Bits that may be passed into the cloneInto method to
159   // specify how to clone the function graph.
160   enum CloneFlags {
161     StripAllocaBit        = 1 << 0, KeepAllocaBit     = 0 << 0,
162     DontCloneCallNodes    = 1 << 1, CloneCallNodes    = 0 << 0,
163     DontCloneAuxCallNodes = 1 << 2, CloneAuxCallNodes = 0 << 0,
164     StripModRefBits       = 1 << 3, KeepModRefBits    = 0 << 0,
165   };
166
167   // cloneInto - Clone the specified DSGraph into the current graph, returning
168   // the Return node of the graph.  The translated ScalarMap for the old
169   // function is filled into the OldValMap member.  If StripAllocas is set to
170   // 'StripAllocaBit', Alloca markers are removed from the graph as the graph is
171   // being cloned.
172   //
173   DSNodeHandle cloneInto(const DSGraph &G,
174                          hash_map<Value*, DSNodeHandle> &OldValMap,
175                          hash_map<const DSNode*, DSNodeHandle> &OldNodeMap,
176                          unsigned CloneFlags = 0);
177
178   /// mergeInGraph - The method is used for merging graphs together.  If the
179   /// argument graph is not *this, it makes a clone of the specified graph, then
180   /// merges the nodes specified in the call site with the formal arguments in
181   /// the graph.  If the StripAlloca's argument is 'StripAllocaBit' then Alloca
182   /// markers are removed from nodes.
183   ///
184   void mergeInGraph(DSCallSite &CS, const DSGraph &Graph, unsigned CloneFlags);
185
186   // Methods for checking to make sure graphs are well formed...
187   void AssertNodeInGraph(const DSNode *N) const {
188     assert((!N || find(Nodes.begin(), Nodes.end(), N) != Nodes.end()) &&
189            "AssertNodeInGraph: Node is not in graph!");
190   }
191   void AssertNodeContainsGlobal(const DSNode *N, GlobalValue *GV) const {
192     assert(std::find(N->getGlobals().begin(), N->getGlobals().end(), GV) !=
193            N->getGlobals().end() && "Global value not in node!");
194   }
195
196   void AssertCallSiteInGraph(const DSCallSite &CS) const {
197     if (CS.isIndirectCall())
198       AssertNodeInGraph(CS.getCalleeNode());
199     AssertNodeInGraph(CS.getRetVal().getNode());
200     for (unsigned j = 0, e = CS.getNumPtrArgs(); j != e; ++j)
201       AssertNodeInGraph(CS.getPtrArg(j).getNode());
202   }
203
204   void AssertCallNodesInGraph() const {
205     for (unsigned i = 0, e = FunctionCalls.size(); i != e; ++i)
206       AssertCallSiteInGraph(FunctionCalls[i]);
207   }
208   void AssertAuxCallNodesInGraph() const {
209     for (unsigned i = 0, e = AuxFunctionCalls.size(); i != e; ++i)
210       AssertCallSiteInGraph(AuxFunctionCalls[i]);
211   }
212
213   void AssertGraphOK() const;
214
215 public:
216   // removeTriviallyDeadNodes - After the graph has been constructed, this
217   // method removes all unreachable nodes that are created because they got
218   // merged with other nodes in the graph.  This is used as the first step of
219   // removeDeadNodes.
220   //
221   void removeTriviallyDeadNodes();
222 };
223
224 #endif