void erase(Value *V) { erase(find(V)); }
+ /// replaceScalar - When an instruction needs to be modified, this method can
+ /// be used to update the scalar map to remove the old and insert the new.
+ ///
+ void replaceScalar(Value *Old, Value *New) {
+ iterator I = find(Old);
+ assert(I != end() && "Old value is not in the map!");
+ ValueMap.insert(std::make_pair(New, I->second));
+ erase(I);
+ }
+
DSNodeHandle &operator[](Value *V) {
std::pair<iterator,bool> IP =
ValueMap.insert(std::make_pair(V, DSNodeHandle()));
typedef DSScalarMap ScalarMapTy;
typedef hash_map<Function*, DSNodeHandle> ReturnNodesTy;
typedef hash_set<GlobalValue*> GlobalSetTy;
- typedef std::vector<DSNode*> NodeListTy;
+ typedef ilist<DSNode> NodeListTy;
/// NodeMapTy - This data type is used when cloning one graph into another to
/// keep track of the correspondence between the nodes in the old and new
void setPrintAuxCalls() { PrintAuxCalls = true; }
bool shouldPrintAuxCalls() const { return PrintAuxCalls; }
- /// getNodes - Get a vector of all the nodes in the graph
- ///
- typedef NodeListTy::const_iterator node_iterator;
- node_iterator node_begin() const { return Nodes.begin(); }
- node_iterator node_end() const { return Nodes.end(); }
+ /// node_iterator/begin/end - Iterate over all of the nodes in the graph. Be
+ /// extremely careful with these methods because any merging of nodes could
+ /// cause the node to be removed from this list. This means that if you are
+ /// iterating over nodes and doing something that could cause _any_ node to
+ /// merge, your node_iterators into this graph can be invalidated.
+ typedef NodeListTy::compat_iterator node_iterator;
+ node_iterator node_begin() const { return Nodes.compat_begin(); }
+ node_iterator node_end() const { return Nodes.compat_end(); }
/// getFunctionNames - Return a space separated list of the name of the
/// functions in this graph (if any)
+ ///
std::string getFunctionNames() const;
/// addNode - Add a new node to the graph.
///
void addNode(DSNode *N) { Nodes.push_back(N); }
+ void unlinkNode(DSNode *N) { Nodes.remove(N); }
/// getScalarMap - Get a map that describes what the nodes the scalars in this
/// function point to...
/// getReturnNodes - Return the mapping of functions to their return nodes for
/// this graph.
+ ///
const ReturnNodesTy &getReturnNodes() const { return ReturnNodes; }
ReturnNodesTy &getReturnNodes() { return ReturnNodes; }
/// viewGraph - Emit a dot graph, run 'dot', run gv on the postscript file,
/// then cleanup. For use from the debugger.
+ ///
void viewGraph() const;
void writeGraphToFile(std::ostream &O, const std::string &GraphName) const;
void mergeInGraph(const DSCallSite &CS, Function &F, const DSGraph &Graph,
unsigned CloneFlags);
-
/// getCallSiteForArguments - Get the arguments and return value bindings for
/// the specified function in the current graph.
///
DSCallSite getCallSiteForArguments(Function &F) const;
+ /// getDSCallSiteForCallSite - Given an LLVM CallSite object that is live in
+ /// the context of this graph, return the DSCallSite for it.
+ DSCallSite getDSCallSiteForCallSite(CallSite CS) const;
+
// Methods for checking to make sure graphs are well formed...
void AssertNodeInGraph(const DSNode *N) const {
assert((!N || N->getParentGraph() == this) &&
N->getGlobals().end() && "Global value not in node!");
}
- void AssertCallSiteInGraph(const DSCallSite &CS) const {
- if (CS.isIndirectCall())
- AssertNodeInGraph(CS.getCalleeNode());
- AssertNodeInGraph(CS.getRetVal().getNode());
- for (unsigned j = 0, e = CS.getNumPtrArgs(); j != e; ++j)
- AssertNodeInGraph(CS.getPtrArg(j).getNode());
- }
-
- void AssertCallNodesInGraph() const {
- for (unsigned i = 0, e = FunctionCalls.size(); i != e; ++i)
- AssertCallSiteInGraph(FunctionCalls[i]);
- }
- void AssertAuxCallNodesInGraph() const {
- for (unsigned i = 0, e = AuxFunctionCalls.size(); i != e; ++i)
- AssertCallSiteInGraph(AuxFunctionCalls[i]);
- }
+ void AssertCallSiteInGraph(const DSCallSite &CS) const;
+ void AssertCallNodesInGraph() const;
+ void AssertAuxCallNodesInGraph() const;
void AssertGraphOK() const;
};
- /// ReachabilityCloner - This class is used to incrementally clone and merge
- /// nodes from a non-changing source graph into a potentially mutating
- /// destination graph. Nodes are only cloned over on demand, either in
- /// responds to a merge() or getClonedNH() call. When a node is cloned over,
- /// all of the nodes reachable from it are automatically brought over as well.
- class ReachabilityCloner {
- DSGraph &Dest;
- const DSGraph &Src;
-
- /// BitsToKeep - These bits are retained from the source node when the
- /// source nodes are merged into the destination graph.
- unsigned BitsToKeep;
- unsigned CloneFlags;
-
- // NodeMap - A mapping from nodes in the source graph to the nodes that
- // represent them in the destination graph.
- DSGraph::NodeMapTy NodeMap;
- public:
- ReachabilityCloner(DSGraph &dest, const DSGraph &src, unsigned cloneFlags)
- : Dest(dest), Src(src), CloneFlags(cloneFlags) {
- assert(&Dest != &Src && "Cannot clone from graph to same graph!");
- BitsToKeep = ~DSNode::DEAD;
- if (CloneFlags & DSGraph::StripAllocaBit)
- BitsToKeep &= ~DSNode::AllocaNode;
- if (CloneFlags & DSGraph::StripModRefBits)
- BitsToKeep &= ~(DSNode::Modified | DSNode::Read);
- if (CloneFlags & DSGraph::StripIncompleteBit)
- BitsToKeep &= ~DSNode::Incomplete;
- }
-
- DSNodeHandle getClonedNH(const DSNodeHandle &SrcNH);
+/// ReachabilityCloner - This class is used to incrementally clone and merge
+/// nodes from a non-changing source graph into a potentially mutating
+/// destination graph. Nodes are only cloned over on demand, either in
+/// responds to a merge() or getClonedNH() call. When a node is cloned over,
+/// all of the nodes reachable from it are automatically brought over as well.
+///
+class ReachabilityCloner {
+ DSGraph &Dest;
+ const DSGraph &Src;
+
+ /// BitsToKeep - These bits are retained from the source node when the
+ /// source nodes are merged into the destination graph.
+ unsigned BitsToKeep;
+ unsigned CloneFlags;
+
+ // NodeMap - A mapping from nodes in the source graph to the nodes that
+ // represent them in the destination graph.
+ DSGraph::NodeMapTy NodeMap;
+public:
+ ReachabilityCloner(DSGraph &dest, const DSGraph &src, unsigned cloneFlags)
+ : Dest(dest), Src(src), CloneFlags(cloneFlags) {
+ assert(&Dest != &Src && "Cannot clone from graph to same graph!");
+ BitsToKeep = ~DSNode::DEAD;
+ if (CloneFlags & DSGraph::StripAllocaBit)
+ BitsToKeep &= ~DSNode::AllocaNode;
+ if (CloneFlags & DSGraph::StripModRefBits)
+ BitsToKeep &= ~(DSNode::Modified | DSNode::Read);
+ if (CloneFlags & DSGraph::StripIncompleteBit)
+ BitsToKeep &= ~DSNode::Incomplete;
+ }
+
+ DSNodeHandle getClonedNH(const DSNodeHandle &SrcNH);
- void merge(const DSNodeHandle &NH, const DSNodeHandle &SrcNH);
+ void merge(const DSNodeHandle &NH, const DSNodeHandle &SrcNH);
- /// mergeCallSite - Merge the nodes reachable from the specified src call
- /// site into the nodes reachable from DestCS.
- void mergeCallSite(const DSCallSite &DestCS, const DSCallSite &SrcCS);
+ /// mergeCallSite - Merge the nodes reachable from the specified src call
+ /// site into the nodes reachable from DestCS.
+ ///
+ void mergeCallSite(const DSCallSite &DestCS, const DSCallSite &SrcCS);
- bool clonedNode() const { return !NodeMap.empty(); }
+ bool clonedAnyNodes() const { return !NodeMap.empty(); }
+
+ /// hasClonedNode - Return true if the specified node has been cloned from
+ /// the source graph into the destination graph.
+ bool hasClonedNode(const DSNode *N) {
+ return NodeMap.count(N);
+ }
+
+ void destroy() { NodeMap.clear(); }
+};
- void destroy() { NodeMap.clear(); }
- };
} // End llvm namespace
#endif