Doxygenified and cleand up comments.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@12294 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Misha Brukman 2004-03-11 23:08:20 +00:00
parent 3497ae9f05
commit dd298c8c6e
16 changed files with 472 additions and 440 deletions

View File

@ -61,6 +61,7 @@ public:
/// getTargetData - Every alias analysis implementation depends on the size of
/// data items in the current Target. This provides a uniform way to handle
/// it.
///
const TargetData &getTargetData() const { return *TD; }
//===--------------------------------------------------------------------===//

View File

@ -56,6 +56,7 @@ public:
/// 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!");
@ -189,6 +190,7 @@ public:
/// 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.
@ -240,6 +242,7 @@ public:
/// getReturnNodes - Return the mapping of functions to their return nodes for
/// this graph.
///
const ReturnNodesTy &getReturnNodes() const { return ReturnNodes; }
ReturnNodesTy &getReturnNodes() { return ReturnNodes; }
@ -273,6 +276,7 @@ public:
/// 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;
@ -354,7 +358,6 @@ public:
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.
///
@ -389,54 +392,57 @@ public:
};
/// 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;
/// 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;
/// 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);
// 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 clonedAnyNodes() 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);
}
/// 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

View File

@ -40,10 +40,12 @@ class DSNode {
/// that this node really is. When nodes get folded together, the node to be
/// eliminated has these fields filled in, otherwise ForwardNH.getNode() is
/// null.
///
DSNodeHandle ForwardNH;
/// Next, Prev - These instance variables are used to keep the node on a
/// doubly-linked ilist in the DSGraph.
///
DSNode *Next, *Prev;
friend class ilist_traits<DSNode>;
@ -105,12 +107,14 @@ public:
/// DSNode ctor - Create a node of the specified type, inserting it into the
/// specified graph.
///
DSNode(const Type *T, DSGraph *G);
/// DSNode "copy ctor" - Copy the specified node, inserting it into the
/// specified graph. If NullLinks is true, then null out all of the links,
/// but keep the same number of them. This can be used for efficiency if the
/// links are just going to be clobbered anyway.
///
DSNode(const DSNode &, DSGraph *G, bool NullLinks = false);
~DSNode() {
@ -133,8 +137,10 @@ public:
///
unsigned getSize() const { return Size; }
// getType - Return the node type of this object...
/// getType - Return the node type of this object...
///
const Type *getType() const { return Ty; }
bool isArray() const { return NodeType & Array; }
/// hasNoReferrers - Return true if nothing is pointing to this node at all.
@ -156,6 +162,7 @@ public:
/// getForwardNode - This method returns the node that this node is forwarded
/// to, if any.
///
DSNode *getForwardNode() const { return ForwardNH.getNode(); }
/// isForwarding - Return true if this node is forwarding to another.
@ -164,9 +171,10 @@ public:
/// stopForwarding - When the last reference to this forwarding node has been
/// dropped, delete the node.
///
void stopForwarding() {
assert(isForwarding() &&
"Node isn't forwarding, cannot stopForwarding!");
"Node isn't forwarding, cannot stopForwarding()!");
ForwardNH.setNode(0);
assert(ParentGraph == 0 &&
"Forwarding nodes must have been removed from graph!");
@ -184,6 +192,7 @@ public:
}
/// getLink - Return the link at the specified offset.
///
DSNodeHandle &getLink(unsigned Offset) {
assert((Offset & ((1 << DS::PointerShift)-1)) == 0 &&
"Pointer offset not aligned correctly!");
@ -283,6 +292,7 @@ public:
/// getNodeFlags - Return all of the flags set on the node. If the DEAD flag
/// is set, hide it from the caller.
///
unsigned getNodeFlags() const { return NodeType & ~DEAD; }
bool isAllocaNode() const { return NodeType & AllocaNode; }
@ -331,6 +341,7 @@ public:
/// remapLinks - Change all of the Links in the current node according to the
/// specified mapping.
///
void remapLinks(hash_map<const DSNode*, DSNodeHandle> &OldNodeMap);
/// markReachableNodes - This method recursively traverses the specified
@ -423,7 +434,7 @@ inline void DSNodeHandle::setLink(unsigned Off, const DSNodeHandle &NH) {
getNode()->setLink(Off+Offset, NH);
}
/// addEdgeTo - Add an edge from the current node to the specified node. This
/// addEdgeTo - Add an edge from the current node to the specified node. This
/// can cause merging of nodes in the graph.
///
inline void DSNodeHandle::addEdgeTo(unsigned Off, const DSNodeHandle &Node) {

View File

@ -35,9 +35,9 @@ namespace DS { // FIXME: After the paper, this should get cleaned up
PointerSize = 1 << PointerShift
};
// isPointerType - Return true if this first class type is big enough to hold
// a pointer.
//
/// isPointerType - Return true if this first class type is big enough to hold
/// a pointer.
///
bool isPointerType(const Type *Ty);
};
@ -89,6 +89,7 @@ public:
/// isNull - Check to see if getNode() == 0, without going through the trouble
/// of checking to see if we are forwarding...
///
bool isNull() const { return N == 0; }
// Allow explicit conversion to DSNode...
@ -112,7 +113,8 @@ public:
///
void mergeWith(const DSNodeHandle &N) const;
// hasLink - Return true if there is a link at the specified offset...
/// hasLink - Return true if there is a link at the specified offset...
///
inline bool hasLink(unsigned Num) const;
/// getLink - Treat this current node pointer as a pointer to a structure of
@ -262,8 +264,9 @@ public:
}
}
// mergeWith - Merge the return value and parameters of the these two call
// sites.
/// mergeWith - Merge the return value and parameters of the these two call
/// sites.
///
void mergeWith(DSCallSite &CS) {
getRetVal().mergeWith(CS.getRetVal());
unsigned MinArgs = getNumPtrArgs();

View File

@ -27,9 +27,9 @@ class DSNode;
// FIXME: move this stuff to a private header
namespace DataStructureAnalysis {
// isPointerType - Return true if this first class type is big enough to hold
// a pointer.
//
/// isPointerType - Return true if this first class type is big enough to hold
/// a pointer.
///
bool isPointerType(const Type *Ty);
}
@ -53,7 +53,8 @@ public:
return DSInfo.find(const_cast<Function*>(&F)) != DSInfo.end();
}
// getDSGraph - Return the data structure graph for the specified function.
/// getDSGraph - Return the data structure graph for the specified function.
///
DSGraph &getDSGraph(const Function &F) const {
hash_map<Function*, DSGraph*>::const_iterator I =
DSInfo.find(const_cast<Function*>(&F));
@ -63,13 +64,17 @@ public:
DSGraph &getGlobalsGraph() const { return *GlobalsGraph; }
// print - Print out the analysis results...
/// print - Print out the analysis results...
///
void print(std::ostream &O, const Module *M) const;
// If the pass pipeline is done with this pass, we can release our memory...
/// releaseMemory - if the pass pipeline is done with this pass, we can
/// release our memory...
///
virtual void releaseMemory();
// getAnalysisUsage - This obviously provides a data structure graph.
/// getAnalysisUsage - This obviously provides a data structure graph.
///
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
AU.setPreservesAll();
AU.addRequired<TargetData>();
@ -77,10 +82,10 @@ public:
};
// BUDataStructures - The analysis that computes the interprocedurally closed
// data structure graphs for all of the functions in the program. This pass
// only performs a "Bottom Up" propagation (hence the name).
//
/// BUDataStructures - The analysis that computes the interprocedurally closed
/// data structure graphs for all of the functions in the program. This pass
/// only performs a "Bottom Up" propagation (hence the name).
///
class BUDataStructures : public Pass {
protected:
// DSInfo, one graph for each function
@ -96,7 +101,8 @@ public:
return DSInfo.find(const_cast<Function*>(&F)) != DSInfo.end();
}
// getDSGraph - Return the data structure graph for the specified function.
/// getDSGraph - Return the data structure graph for the specified function.
///
DSGraph &getDSGraph(const Function &F) const {
hash_map<Function*, DSGraph*>::const_iterator I =
DSInfo.find(const_cast<Function*>(&F));
@ -106,10 +112,13 @@ public:
DSGraph &getGlobalsGraph() const { return *GlobalsGraph; }
// print - Print out the analysis results...
/// print - Print out the analysis results...
///
void print(std::ostream &O, const Module *M) const;
// If the pass pipeline is done with this pass, we can release our memory...
/// releaseMemory - if the pass pipeline is done with this pass, we can
/// release our memory...
///
virtual void releaseMemory();
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
@ -136,10 +145,10 @@ private:
};
// TDDataStructures - Analysis that computes new data structure graphs
// for each function using the closed graphs for the callers computed
// by the bottom-up pass.
//
/// TDDataStructures - Analysis that computes new data structure graphs
/// for each function using the closed graphs for the callers computed
/// by the bottom-up pass.
///
class TDDataStructures : public Pass {
// DSInfo, one graph for each function
hash_map<Function*, DSGraph*> DSInfo;
@ -154,7 +163,8 @@ public:
return DSInfo.find(const_cast<Function*>(&F)) != DSInfo.end();
}
// getDSGraph - Return the data structure graph for the specified function.
/// getDSGraph - Return the data structure graph for the specified function.
///
DSGraph &getDSGraph(const Function &F) const {
hash_map<Function*, DSGraph*>::const_iterator I =
DSInfo.find(const_cast<Function*>(&F));
@ -164,13 +174,16 @@ public:
DSGraph &getGlobalsGraph() const { return *GlobalsGraph; }
// print - Print out the analysis results...
/// print - Print out the analysis results...
///
void print(std::ostream &O, const Module *M) const;
// If the pass pipeline is done with this pass, we can release our memory...
/// If the pass pipeline is done with this pass, we can release our memory...
///
virtual void releaseMyMemory();
// getAnalysisUsage - This obviously provides a data structure graph.
/// getAnalysisUsage - This obviously provides a data structure graph.
///
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
AU.setPreservesAll();
AU.addRequired<BUDataStructures>();
@ -188,11 +201,11 @@ private:
};
// CompleteBUDataStructures - This is the exact same as the bottom-up graphs,
// but we use take a completed call graph and inline all indirect callees into
// their callers graphs, making the result more useful for things like pool
// allocation.
//
/// CompleteBUDataStructures - This is the exact same as the bottom-up graphs,
/// but we use take a completed call graph and inline all indirect callees into
/// their callers graphs, making the result more useful for things like pool
/// allocation.
///
struct CompleteBUDataStructures : public BUDataStructures {
virtual bool run(Module &M);
@ -200,7 +213,8 @@ struct CompleteBUDataStructures : public BUDataStructures {
return DSInfo.find(const_cast<Function*>(&F)) != DSInfo.end();
}
// getDSGraph - Return the data structure graph for the specified function.
/// getDSGraph - Return the data structure graph for the specified function.
///
DSGraph &getDSGraph(const Function &F) const {
hash_map<Function*, DSGraph*>::const_iterator I =
DSInfo.find(const_cast<Function*>(&F));
@ -217,7 +231,8 @@ struct CompleteBUDataStructures : public BUDataStructures {
AU.addRequired<TDDataStructures>();
}
// print - Print out the analysis results...
/// print - Print out the analysis results...
///
void print(std::ostream &O, const Module *M) const;
private:
@ -228,8 +243,6 @@ private:
void processGraph(DSGraph &G);
};
} // End llvm namespace
#endif

View File

@ -56,6 +56,7 @@ public:
/// 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!");
@ -189,6 +190,7 @@ public:
/// 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.
@ -240,6 +242,7 @@ public:
/// getReturnNodes - Return the mapping of functions to their return nodes for
/// this graph.
///
const ReturnNodesTy &getReturnNodes() const { return ReturnNodes; }
ReturnNodesTy &getReturnNodes() { return ReturnNodes; }
@ -273,6 +276,7 @@ public:
/// 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;
@ -354,7 +358,6 @@ public:
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.
///
@ -389,54 +392,57 @@ public:
};
/// 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;
/// 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;
/// 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);
// 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 clonedAnyNodes() 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);
}
/// 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

View File

@ -40,10 +40,12 @@ class DSNode {
/// that this node really is. When nodes get folded together, the node to be
/// eliminated has these fields filled in, otherwise ForwardNH.getNode() is
/// null.
///
DSNodeHandle ForwardNH;
/// Next, Prev - These instance variables are used to keep the node on a
/// doubly-linked ilist in the DSGraph.
///
DSNode *Next, *Prev;
friend class ilist_traits<DSNode>;
@ -105,12 +107,14 @@ public:
/// DSNode ctor - Create a node of the specified type, inserting it into the
/// specified graph.
///
DSNode(const Type *T, DSGraph *G);
/// DSNode "copy ctor" - Copy the specified node, inserting it into the
/// specified graph. If NullLinks is true, then null out all of the links,
/// but keep the same number of them. This can be used for efficiency if the
/// links are just going to be clobbered anyway.
///
DSNode(const DSNode &, DSGraph *G, bool NullLinks = false);
~DSNode() {
@ -133,8 +137,10 @@ public:
///
unsigned getSize() const { return Size; }
// getType - Return the node type of this object...
/// getType - Return the node type of this object...
///
const Type *getType() const { return Ty; }
bool isArray() const { return NodeType & Array; }
/// hasNoReferrers - Return true if nothing is pointing to this node at all.
@ -156,6 +162,7 @@ public:
/// getForwardNode - This method returns the node that this node is forwarded
/// to, if any.
///
DSNode *getForwardNode() const { return ForwardNH.getNode(); }
/// isForwarding - Return true if this node is forwarding to another.
@ -164,9 +171,10 @@ public:
/// stopForwarding - When the last reference to this forwarding node has been
/// dropped, delete the node.
///
void stopForwarding() {
assert(isForwarding() &&
"Node isn't forwarding, cannot stopForwarding!");
"Node isn't forwarding, cannot stopForwarding()!");
ForwardNH.setNode(0);
assert(ParentGraph == 0 &&
"Forwarding nodes must have been removed from graph!");
@ -184,6 +192,7 @@ public:
}
/// getLink - Return the link at the specified offset.
///
DSNodeHandle &getLink(unsigned Offset) {
assert((Offset & ((1 << DS::PointerShift)-1)) == 0 &&
"Pointer offset not aligned correctly!");
@ -283,6 +292,7 @@ public:
/// getNodeFlags - Return all of the flags set on the node. If the DEAD flag
/// is set, hide it from the caller.
///
unsigned getNodeFlags() const { return NodeType & ~DEAD; }
bool isAllocaNode() const { return NodeType & AllocaNode; }
@ -331,6 +341,7 @@ public:
/// remapLinks - Change all of the Links in the current node according to the
/// specified mapping.
///
void remapLinks(hash_map<const DSNode*, DSNodeHandle> &OldNodeMap);
/// markReachableNodes - This method recursively traverses the specified
@ -423,7 +434,7 @@ inline void DSNodeHandle::setLink(unsigned Off, const DSNodeHandle &NH) {
getNode()->setLink(Off+Offset, NH);
}
/// addEdgeTo - Add an edge from the current node to the specified node. This
/// addEdgeTo - Add an edge from the current node to the specified node. This
/// can cause merging of nodes in the graph.
///
inline void DSNodeHandle::addEdgeTo(unsigned Off, const DSNodeHandle &Node) {

View File

@ -35,9 +35,9 @@ namespace DS { // FIXME: After the paper, this should get cleaned up
PointerSize = 1 << PointerShift
};
// isPointerType - Return true if this first class type is big enough to hold
// a pointer.
//
/// isPointerType - Return true if this first class type is big enough to hold
/// a pointer.
///
bool isPointerType(const Type *Ty);
};
@ -89,6 +89,7 @@ public:
/// isNull - Check to see if getNode() == 0, without going through the trouble
/// of checking to see if we are forwarding...
///
bool isNull() const { return N == 0; }
// Allow explicit conversion to DSNode...
@ -112,7 +113,8 @@ public:
///
void mergeWith(const DSNodeHandle &N) const;
// hasLink - Return true if there is a link at the specified offset...
/// hasLink - Return true if there is a link at the specified offset...
///
inline bool hasLink(unsigned Num) const;
/// getLink - Treat this current node pointer as a pointer to a structure of
@ -262,8 +264,9 @@ public:
}
}
// mergeWith - Merge the return value and parameters of the these two call
// sites.
/// mergeWith - Merge the return value and parameters of the these two call
/// sites.
///
void mergeWith(DSCallSite &CS) {
getRetVal().mergeWith(CS.getRetVal());
unsigned MinArgs = getNumPtrArgs();

View File

@ -27,9 +27,9 @@ class DSNode;
// FIXME: move this stuff to a private header
namespace DataStructureAnalysis {
// isPointerType - Return true if this first class type is big enough to hold
// a pointer.
//
/// isPointerType - Return true if this first class type is big enough to hold
/// a pointer.
///
bool isPointerType(const Type *Ty);
}
@ -53,7 +53,8 @@ public:
return DSInfo.find(const_cast<Function*>(&F)) != DSInfo.end();
}
// getDSGraph - Return the data structure graph for the specified function.
/// getDSGraph - Return the data structure graph for the specified function.
///
DSGraph &getDSGraph(const Function &F) const {
hash_map<Function*, DSGraph*>::const_iterator I =
DSInfo.find(const_cast<Function*>(&F));
@ -63,13 +64,17 @@ public:
DSGraph &getGlobalsGraph() const { return *GlobalsGraph; }
// print - Print out the analysis results...
/// print - Print out the analysis results...
///
void print(std::ostream &O, const Module *M) const;
// If the pass pipeline is done with this pass, we can release our memory...
/// releaseMemory - if the pass pipeline is done with this pass, we can
/// release our memory...
///
virtual void releaseMemory();
// getAnalysisUsage - This obviously provides a data structure graph.
/// getAnalysisUsage - This obviously provides a data structure graph.
///
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
AU.setPreservesAll();
AU.addRequired<TargetData>();
@ -77,10 +82,10 @@ public:
};
// BUDataStructures - The analysis that computes the interprocedurally closed
// data structure graphs for all of the functions in the program. This pass
// only performs a "Bottom Up" propagation (hence the name).
//
/// BUDataStructures - The analysis that computes the interprocedurally closed
/// data structure graphs for all of the functions in the program. This pass
/// only performs a "Bottom Up" propagation (hence the name).
///
class BUDataStructures : public Pass {
protected:
// DSInfo, one graph for each function
@ -96,7 +101,8 @@ public:
return DSInfo.find(const_cast<Function*>(&F)) != DSInfo.end();
}
// getDSGraph - Return the data structure graph for the specified function.
/// getDSGraph - Return the data structure graph for the specified function.
///
DSGraph &getDSGraph(const Function &F) const {
hash_map<Function*, DSGraph*>::const_iterator I =
DSInfo.find(const_cast<Function*>(&F));
@ -106,10 +112,13 @@ public:
DSGraph &getGlobalsGraph() const { return *GlobalsGraph; }
// print - Print out the analysis results...
/// print - Print out the analysis results...
///
void print(std::ostream &O, const Module *M) const;
// If the pass pipeline is done with this pass, we can release our memory...
/// releaseMemory - if the pass pipeline is done with this pass, we can
/// release our memory...
///
virtual void releaseMemory();
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
@ -136,10 +145,10 @@ private:
};
// TDDataStructures - Analysis that computes new data structure graphs
// for each function using the closed graphs for the callers computed
// by the bottom-up pass.
//
/// TDDataStructures - Analysis that computes new data structure graphs
/// for each function using the closed graphs for the callers computed
/// by the bottom-up pass.
///
class TDDataStructures : public Pass {
// DSInfo, one graph for each function
hash_map<Function*, DSGraph*> DSInfo;
@ -154,7 +163,8 @@ public:
return DSInfo.find(const_cast<Function*>(&F)) != DSInfo.end();
}
// getDSGraph - Return the data structure graph for the specified function.
/// getDSGraph - Return the data structure graph for the specified function.
///
DSGraph &getDSGraph(const Function &F) const {
hash_map<Function*, DSGraph*>::const_iterator I =
DSInfo.find(const_cast<Function*>(&F));
@ -164,13 +174,16 @@ public:
DSGraph &getGlobalsGraph() const { return *GlobalsGraph; }
// print - Print out the analysis results...
/// print - Print out the analysis results...
///
void print(std::ostream &O, const Module *M) const;
// If the pass pipeline is done with this pass, we can release our memory...
/// If the pass pipeline is done with this pass, we can release our memory...
///
virtual void releaseMyMemory();
// getAnalysisUsage - This obviously provides a data structure graph.
/// getAnalysisUsage - This obviously provides a data structure graph.
///
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
AU.setPreservesAll();
AU.addRequired<BUDataStructures>();
@ -188,11 +201,11 @@ private:
};
// CompleteBUDataStructures - This is the exact same as the bottom-up graphs,
// but we use take a completed call graph and inline all indirect callees into
// their callers graphs, making the result more useful for things like pool
// allocation.
//
/// CompleteBUDataStructures - This is the exact same as the bottom-up graphs,
/// but we use take a completed call graph and inline all indirect callees into
/// their callers graphs, making the result more useful for things like pool
/// allocation.
///
struct CompleteBUDataStructures : public BUDataStructures {
virtual bool run(Module &M);
@ -200,7 +213,8 @@ struct CompleteBUDataStructures : public BUDataStructures {
return DSInfo.find(const_cast<Function*>(&F)) != DSInfo.end();
}
// getDSGraph - Return the data structure graph for the specified function.
/// getDSGraph - Return the data structure graph for the specified function.
///
DSGraph &getDSGraph(const Function &F) const {
hash_map<Function*, DSGraph*>::const_iterator I =
DSInfo.find(const_cast<Function*>(&F));
@ -217,7 +231,8 @@ struct CompleteBUDataStructures : public BUDataStructures {
AU.addRequired<TDDataStructures>();
}
// print - Print out the analysis results...
/// print - Print out the analysis results...
///
void print(std::ostream &O, const Module *M) const;
private:
@ -228,8 +243,6 @@ private:
void processGraph(DSGraph &G);
};
} // End llvm namespace
#endif

View File

@ -25,10 +25,10 @@
#define LLVM_ANALYSIS_DEPENDENCEGRAPH_H
#include "Support/hash_map"
#include <iosfwd>
#include <vector>
#include <utility>
#include <cassert>
#include <iosfwd>
#include <utility>
#include <vector>
namespace llvm {
@ -38,11 +38,9 @@ class Dependence;
class DepGraphNode;
class DependenceGraph;
//----------------------------------------------------------------------------
// enum DependenceType: The standard data dependence types.
//----------------------------------------------------------------------------
/// enum DependenceType - The standard data dependence types
///
enum DependenceType {
NoDependence = 0x0,
TrueDependence = 0x1,
@ -52,13 +50,10 @@ enum DependenceType {
IncomingFlag = 0x10 // is this an incoming or outgoing dep?
};
//----------------------------------------------------------------------------
// class Dependence:
//
// A representation of a simple (non-loop-related) dependence.
//----------------------------------------------------------------------------
/// Dependence Class - A representation of a simple (non-loop-related)
/// dependence.
///
class Dependence {
DepGraphNode* toOrFromNode;
unsigned char depType;
@ -68,8 +63,7 @@ public:
: toOrFromNode(toOrFromN),
depType(type | (isIncoming? IncomingFlag : 0x0)) { }
/* copy ctor*/ Dependence (const Dependence& D)
: toOrFromNode(D.toOrFromNode),
Dependence(const Dependence& D) : toOrFromNode(D.toOrFromNode),
depType(D.depType) { }
bool operator==(const Dependence& D) const {
@ -84,17 +78,17 @@ public:
/// Get source or sink depending on what type of node this is!
///
DepGraphNode* getSrc() {
DepGraphNode* getSrc() {
assert(depType & IncomingFlag); return toOrFromNode;
}
const DepGraphNode* getSrc() const {
const DepGraphNode* getSrc() const {
assert(depType & IncomingFlag); return toOrFromNode;
}
DepGraphNode* getSink() {
DepGraphNode* getSink() {
assert(! (depType & IncomingFlag)); return toOrFromNode;
}
const DepGraphNode* getSink() const {
const DepGraphNode* getSink() const {
assert(! (depType & IncomingFlag)); return toOrFromNode;
}
@ -104,10 +98,9 @@ public:
// Default constructor: Do not use directly except for graph builder code
//
/*ctor*/ Dependence() : toOrFromNode(NULL), depType(NoDependence) { }
Dependence() : toOrFromNode(NULL), depType(NoDependence) { }
};
#ifdef SUPPORTING_LOOP_DEPENDENCES
struct LoopDependence: public Dependence {
DependenceDirection dir;
@ -119,12 +112,9 @@ struct LoopDependence: public Dependence {
//----------------------------------------------------------------------------
// class DepGraphNode:
//
// A representation of a single node in a dependence graph, corresponding
// to a single instruction.
//----------------------------------------------------------------------------
/// DepGraphNode Class - A representation of a single node in a dependence
/// graph, corresponding to a single instruction.
///
class DepGraphNode {
Instruction* instr;
std::vector<Dependence> inDeps;
@ -134,22 +124,21 @@ class DepGraphNode {
typedef std::vector<Dependence>:: iterator iterator;
typedef std::vector<Dependence>::const_iterator const_iterator;
iterator inDepBegin() { return inDeps.begin(); }
const_iterator inDepBegin() const { return inDeps.begin(); }
iterator inDepEnd() { return inDeps.end(); }
const_iterator inDepEnd() const { return inDeps.end(); }
iterator inDepBegin() { return inDeps.begin(); }
const_iterator inDepBegin() const { return inDeps.begin(); }
iterator inDepEnd() { return inDeps.end(); }
const_iterator inDepEnd() const { return inDeps.end(); }
iterator outDepBegin() { return outDeps.begin(); }
const_iterator outDepBegin() const { return outDeps.begin(); }
iterator outDepEnd() { return outDeps.end(); }
const_iterator outDepEnd() const { return outDeps.end(); }
iterator outDepBegin() { return outDeps.begin(); }
const_iterator outDepBegin() const { return outDeps.begin(); }
iterator outDepEnd() { return outDeps.end(); }
const_iterator outDepEnd() const { return outDeps.end(); }
public:
DepGraphNode(Instruction& I) : instr(&I) { }
Instruction& getInstr() { return *instr; }
const Instruction& getInstr() const { return *instr; }
Instruction& getInstr() { return *instr; }
const Instruction& getInstr() const { return *instr; }
/// Debugging support methods
///
@ -158,14 +147,11 @@ public:
//----------------------------------------------------------------------------
// class DependenceGraph:
//
// A representation of a dependence graph for a procedure.
// The primary query operation here is to look up a DepGraphNode for
// a particular instruction, and then use the in/out dependence iterators
// for the node.
//----------------------------------------------------------------------------
/// DependenceGraph Class - A representation of a dependence graph for a
/// procedure. The primary query operation here is to look up a DepGraphNode for
/// a particular instruction, and then use the in/out dependence iterators
/// for the node.
///
class DependenceGraph {
DependenceGraph(const DependenceGraph&); // DO NOT IMPLEMENT
void operator=(const DependenceGraph&); // DO NOT IMPLEMENT
@ -177,7 +163,7 @@ class DependenceGraph {
DepNodeMapType depNodeMap;
inline DepGraphNode* getNodeInternal(Instruction& inst,
bool createIfMissing = false) {
bool createIfMissing = false) {
map_iterator I = depNodeMap.find(&inst);
if (I == depNodeMap.end())
return (!createIfMissing)? NULL :
@ -240,10 +226,10 @@ public:
void print(const Function& func, std::ostream &O) const;
public:
/// Functions for adding and modifying the dependence graph.
/// AddSimpleDependence - adding and modifying the dependence graph.
/// These should to be used only by dependence analysis implementations.
void AddSimpleDependence(Instruction& fromI,
Instruction& toI,
///
void AddSimpleDependence(Instruction& fromI, Instruction& toI,
DependenceType depType) {
DepGraphNode* fromNode = getNodeInternal(fromI, /*create*/ true);
DepGraphNode* toNode = getNodeInternal(toI, /*create*/ true);
@ -252,8 +238,8 @@ public:
}
#ifdef SUPPORTING_LOOP_DEPENDENCES
/// This interface is a placeholder to show what information is needed.
/// It will probably change when it starts being used.
// This interface is a placeholder to show what information is needed.
// It will probably change when it starts being used.
void AddLoopDependence(Instruction& fromI,
Instruction& toI,
DependenceType depType,
@ -264,8 +250,6 @@ public:
#endif // SUPPORTING_LOOP_DEPENDENCES
};
//===----------------------------------------------------------------------===//
} // End llvm namespace
#endif

View File

@ -35,10 +35,9 @@ class Instruction;
template <typename GraphType> struct GraphTraits;
//===----------------------------------------------------------------------===//
//
// DominatorBase - Base class that other, more interesting dominator analyses
// inherit from.
//
/// DominatorBase - Base class that other, more interesting dominator analyses
/// inherit from.
///
class DominatorBase : public FunctionPass {
protected:
std::vector<BasicBlock*> Roots;
@ -46,21 +45,22 @@ protected:
inline DominatorBase(bool isPostDom) : Roots(), IsPostDominators(isPostDom) {}
public:
// Return the root blocks of the current CFG. This may include multiple
// blocks if we are computing post dominators. For forward dominators, this
// will always be a single block (the entry node).
/// getRoots - Return the root blocks of the current CFG. This may include
/// multiple blocks if we are computing post dominators. For forward
/// dominators, this will always be a single block (the entry node).
///
inline const std::vector<BasicBlock*> &getRoots() const { return Roots; }
// Returns true if analysis based of postdoms
/// isPostDominator - Returns true if analysis based of postdoms
///
bool isPostDominator() const { return IsPostDominators; }
};
//===----------------------------------------------------------------------===//
//
// ImmediateDominators - Calculate the immediate dominator for each node in a
// function.
//
/// ImmediateDominators - Calculate the immediate dominator for each node in a
/// function.
///
class ImmediateDominatorsBase : public DominatorBase {
protected:
std::map<BasicBlock*, BasicBlock*> IDoms;
@ -76,14 +76,15 @@ public:
inline const_iterator end() const { return IDoms.end(); }
inline const_iterator find(BasicBlock* B) const { return IDoms.find(B);}
// operator[] - Return the idom for the specified basic block. The start
// node returns null, because it does not have an immediate dominator.
//
/// operator[] - Return the idom for the specified basic block. The start
/// node returns null, because it does not have an immediate dominator.
///
inline BasicBlock *operator[](BasicBlock *BB) const {
return get(BB);
}
// get() - Synonym for operator[].
/// get() - Synonym for operator[].
///
inline BasicBlock *get(BasicBlock *BB) const {
std::map<BasicBlock*, BasicBlock*>::const_iterator I = IDoms.find(BB);
return I != IDoms.end() ? I->second : 0;
@ -105,19 +106,21 @@ public:
/// change the current immediate dominator for the specified block to another
/// block. This method requires that BB already have an IDom, otherwise just
/// use addNewBlock.
///
void setImmediateDominator(BasicBlock *BB, BasicBlock *NewIDom) {
assert(IDoms.find(BB) != IDoms.end() && "BB doesn't have idom yet!");
IDoms[BB] = NewIDom;
}
// print - Convert to human readable form
/// print - Convert to human readable form
///
virtual void print(std::ostream &OS) const;
};
//===-------------------------------------
// ImmediateDominators Class - Concrete subclass of ImmediateDominatorsBase that
// is used to compute a normal immediate dominator set.
//
/// ImmediateDominators Class - Concrete subclass of ImmediateDominatorsBase
/// that is used to compute a normal immediate dominator set.
///
struct ImmediateDominators : public ImmediateDominatorsBase {
ImmediateDominators() : ImmediateDominatorsBase(false) {}
@ -158,12 +161,11 @@ private:
//===----------------------------------------------------------------------===//
//
// DominatorSet - Maintain a set<BasicBlock*> for every basic block in a
// function, that represents the blocks that dominate the block. If the block
// is unreachable in this function, the set will be empty. This cannot happen
// for reachable code, because every block dominates at least itself.
//
/// DominatorSet - Maintain a set<BasicBlock*> for every basic block in a
/// function, that represents the blocks that dominate the block. If the block
/// is unreachable in this function, the set will be empty. This cannot happen
/// for reachable code, because every block dominates at least itself.
///
struct DominatorSetBase : public DominatorBase {
typedef std::set<BasicBlock*> DomSetType; // Dom set for a bb
// Map of dom sets
@ -197,6 +199,7 @@ public:
/// isReachable - Return true if the specified basicblock is reachable. If
/// the block is reachable, we have dominator set information for it.
///
bool isReachable(BasicBlock *BB) const {
return !getDominators(BB).empty();
}
@ -214,6 +217,7 @@ public:
}
/// print - Convert to human readable form
///
virtual void print(std::ostream &OS) const;
/// dominates - Return true if A dominates B. This performs the special
@ -227,14 +231,15 @@ public:
/// addBasicBlock - Call to update the dominator set with information about a
/// new block that was inserted into the function.
///
void addBasicBlock(BasicBlock *BB, const DomSetType &Dominators) {
assert(find(BB) == end() && "Block already in DominatorSet!");
Doms.insert(std::make_pair(BB, Dominators));
}
// addDominator - If a new block is inserted into the CFG, then method may be
// called to notify the blocks it dominates that it is in their set.
//
/// addDominator - If a new block is inserted into the CFG, then method may be
/// called to notify the blocks it dominates that it is in their set.
///
void addDominator(BasicBlock *BB, BasicBlock *NewDominator) {
iterator I = find(BB);
assert(I != end() && "BB is not in DominatorSet!");
@ -244,9 +249,9 @@ public:
//===-------------------------------------
// DominatorSet Class - Concrete subclass of DominatorSetBase that is used to
// compute a normal dominator set.
//
/// DominatorSet Class - Concrete subclass of DominatorSetBase that is used to
/// compute a normal dominator set.
///
struct DominatorSet : public DominatorSetBase {
DominatorSet() : DominatorSetBase(false) {}
@ -257,7 +262,8 @@ struct DominatorSet : public DominatorSetBase {
return Roots[0];
}
// getAnalysisUsage - This simply provides a dominator set
/// getAnalysisUsage - This simply provides a dominator set
///
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
AU.addRequired<ImmediateDominators>();
AU.setPreservesAll();
@ -266,9 +272,8 @@ struct DominatorSet : public DominatorSetBase {
//===----------------------------------------------------------------------===//
//
// DominatorTree - Calculate the immediate dominator tree for a function.
//
/// DominatorTree - Calculate the immediate dominator tree for a function.
///
struct DominatorTreeBase : public DominatorBase {
class Node;
protected:
@ -298,18 +303,18 @@ public:
inline Node *getIDom() const { return IDom; }
inline const std::vector<Node*> &getChildren() const { return Children; }
// dominates - Returns true iff this dominates N. Note that this is not a
// constant time operation!
/// dominates - Returns true iff this dominates N. Note that this is not a
/// constant time operation!
///
inline bool dominates(const Node *N) const {
const Node *IDom;
while ((IDom = N->getIDom()) != 0 && IDom != this)
N = IDom; // Walk up the tree
N = IDom; // Walk up the tree
return IDom != 0;
}
private:
inline Node(BasicBlock *BB, Node *iDom)
: TheBB(BB), IDom(iDom) {}
inline Node(BasicBlock *BB, Node *iDom) : TheBB(BB), IDom(iDom) {}
inline Node *addChild(Node *C) { Children.push_back(C); return C; }
void setIDom(Node *NewIDom);
@ -333,13 +338,13 @@ public:
return getNode(BB);
}
// getRootNode - This returns the entry node for the CFG of the function. If
// this tree represents the post-dominance relations for a function, however,
// this root may be a node with the block == NULL. This is the case when
// there are multiple exit nodes from a particular function. Consumers of
// post-dominance information must be capable of dealing with this
// possibility.
//
/// getRootNode - This returns the entry node for the CFG of the function. If
/// this tree represents the post-dominance relations for a function, however,
/// this root may be a node with the block == NULL. This is the case when
/// there are multiple exit nodes from a particular function. Consumers of
/// post-dominance information must be capable of dealing with this
/// possibility.
///
Node *getRootNode() { return RootNode; }
const Node *getRootNode() const { return RootNode; }
@ -366,14 +371,15 @@ public:
}
/// print - Convert to human readable form
///
virtual void print(std::ostream &OS) const;
};
//===-------------------------------------
// DominatorTree Class - Concrete subclass of DominatorTreeBase that is used to
// compute a normal dominator tree.
//
/// DominatorTree Class - Concrete subclass of DominatorTreeBase that is used to
/// compute a normal dominator tree.
///
struct DominatorTree : public DominatorTreeBase {
DominatorTree() : DominatorTreeBase(false) {}
@ -400,9 +406,9 @@ private:
};
//===-------------------------------------
// DominatorTree GraphTraits specialization so the DominatorTree can be
// iterable by generic graph iterators.
/// DominatorTree GraphTraits specialization so the DominatorTree can be
/// iterable by generic graph iterators.
///
template <> struct GraphTraits<DominatorTree::Node*> {
typedef DominatorTree::Node NodeType;
typedef NodeType::iterator ChildIteratorType;
@ -426,9 +432,8 @@ template <> struct GraphTraits<DominatorTree*>
};
//===----------------------------------------------------------------------===//
//
// DominanceFrontier - Calculate the dominance frontiers for a function.
//
/// DominanceFrontier - Calculate the dominance frontiers for a function.
///
struct DominanceFrontierBase : public DominatorBase {
typedef std::set<BasicBlock*> DomSetType; // Dom set for a bb
typedef std::map<BasicBlock*, DomSetType> DomSetMapType; // Dom set map
@ -465,15 +470,16 @@ public:
I->second.erase(Node);
}
// print - Convert to human readable form
/// print - Convert to human readable form
///
virtual void print(std::ostream &OS) const;
};
//===-------------------------------------
// DominatorTree Class - Concrete subclass of DominatorTreeBase that is used to
// compute a normal dominator tree.
//
/// DominatorTree Class - Concrete subclass of DominatorTreeBase that is used to
/// compute a normal dominator tree.
///
struct DominanceFrontier : public DominanceFrontierBase {
DominanceFrontier() : DominanceFrontierBase(false) {}

View File

@ -25,15 +25,15 @@ class ConstantInt;
struct ExprType;
/// ClassifyExpr: Analyze an expression to determine the complexity of the
/// ClassifyExpr - Analyze an expression to determine the complexity of the
/// expression, and which other values it depends on.
///
ExprType ClassifyExpr(Value *Expr);
// ExprType - Represent an expression of the form CONST*VAR+CONST
// or simpler. The expression form that yields the least information about the
// expression is just the Linear form with no offset.
//
/// ExprType Class - Represent an expression of the form CONST*VAR+CONST
/// or simpler. The expression form that yields the least information about the
/// expression is just the Linear form with no offset.
///
struct ExprType {
enum ExpressionType {
Constant, // Expr is a simple constant, Offset is value
@ -52,9 +52,9 @@ struct ExprType {
ExprType(Value *Val); // Create a linear or constant expression
ExprType(const ConstantInt *scale, Value *var, const ConstantInt *offset);
// If this expression has an intrinsic type, return it. If it is zero, return
// the specified type.
//
/// If this expression has an intrinsic type, return it. If it is zero,
/// return the specified type.
///
const Type *getExprType(const Type *Default) const;
};

View File

@ -40,18 +40,18 @@ public:
return UnsafeTypes;
}
// run - Inspect the operations that the specified module does on
// values of various types. If they are deemed to be 'unsafe' note that the
// type is not safe to transform.
//
/// run - Inspect the operations that the specified module does on
/// values of various types. If they are deemed to be 'unsafe' note that the
/// type is not safe to transform.
///
virtual bool run(Module &M);
// print - Loop over the results of the analysis, printing out unsafe types.
//
/// print - Loop over the results of the analysis, printing out unsafe types.
///
void print(std::ostream &o, const Module *Mod) const;
// getAnalysisUsage - Of course, we provide ourself...
//
/// getAnalysisUsage - Of course, we provide ourself...
///
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
AU.setPreservesAll();
}

View File

@ -65,23 +65,18 @@ class ModRefInfo; // Result of IP Mod/Ref for one entity
class FunctionModRefInfo; // ModRefInfo for a func and all calls in it
class IPModRef; // Pass that computes IP Mod/Ref info
//---------------------------------------------------------------------------
// class ModRefInfo
//
// Purpose:
// Representation of Mod/Ref information for a single function or callsite.
// This is represented as a pair of bit vectors, one each for Mod and Ref.
// Each bit vector is indexed by the node id of the DS graph node index.
//---------------------------------------------------------------------------
//----------------------------------------------------------------------------
/// ModRefInfo Class - Representation of Mod/Ref information for a single
/// function or callsite. This is represented as a pair of bit vectors, one each
/// for Mod and Ref. Each bit vector is indexed by the node id of the DS graph
/// node index.
///
class ModRefInfo {
BitSetVector modNodeSet; // set of modified nodes
BitSetVector refNodeSet; // set of referenced nodes
public:
//
// Methods to construct ModRefInfo objects.
//
ModRefInfo(unsigned int numNodes)
: modNodeSet(numNodes),
refNodeSet(numNodes) { }
@ -95,9 +90,7 @@ public:
void setNodeIsMod (unsigned nodeId) { modNodeSet[nodeId] = true; }
void setNodeIsRef (unsigned nodeId) { refNodeSet[nodeId] = true; }
//
// Methods to query the mod/ref info
//
bool nodeIsMod (unsigned nodeId) const { return modNodeSet.test(nodeId); }
bool nodeIsRef (unsigned nodeId) const { return refNodeSet.test(nodeId); }
bool nodeIsKill(unsigned nodeId) const { return false; }
@ -115,15 +108,12 @@ public:
//----------------------------------------------------------------------------
// class FunctionModRefInfo
//
// Representation of the results of IP Mod/Ref analysis for a function
// and for each of the call sites within the function.
// Each of these are represented as bit vectors of size = the number of
// nodes in the top-dwon DS graph of the function. Nodes are identified by
// their nodeId, in the range [0 .. funcTDGraph.size()-1].
//----------------------------------------------------------------------------
/// FunctionModRefInfo Class - Representation of the results of IP Mod/Ref
/// analysis for a function and for each of the call sites within the function.
/// Each of these are represented as bit vectors of size = the number of nodes
/// in the top-dwon DS graph of the function. Nodes are identified by their
/// nodeId, in the range [0 .. funcTDGraph.size()-1].
///
class FunctionModRefInfo {
const Function& F; // The function
IPModRef& IPModRefObj; // The IPModRef Object owning this
@ -135,33 +125,33 @@ class FunctionModRefInfo {
friend class IPModRef;
void computeModRef (const Function &func);
void computeModRef (CallSite call);
DSGraph *ResolveCallSiteModRefInfo(CallSite CS,
hash_map<const DSNode*, DSNodeHandle> &NodeMap);
void computeModRef(const Function &func);
void computeModRef(CallSite call);
DSGraph*
ResolveCallSiteModRefInfo(CallSite CS,
hash_map<const DSNode*, DSNodeHandle> &NodeMap);
public:
/* ctor */ FunctionModRefInfo (const Function& func,
IPModRef& IPModRefObj,
DSGraph* tdgClone);
/* dtor */ ~FunctionModRefInfo ();
FunctionModRefInfo(const Function& func, IPModRef &IPModRefObj,
DSGraph* tdgClone);
~FunctionModRefInfo();
// Identify the function and its relevant DS graph
//
const Function& getFunction() const { return F; }
const DSGraph& getFuncGraph() const { return *funcTDGraph; }
const Function& getFunction() const { return F; }
const DSGraph& getFuncGraph() const { return *funcTDGraph; }
// Retrieve Mod/Ref results for a single call site and for the function body
//
const ModRefInfo* getModRefInfo (const Function& func) const {
const ModRefInfo* getModRefInfo(const Function& func) const {
return &funcModRefInfo;
}
const ModRefInfo* getModRefInfo (const CallInst& callInst) const {
const ModRefInfo* getModRefInfo(const CallInst& callInst) const {
std::map<const Instruction*, ModRefInfo*>::const_iterator I =
callSiteModRefInfo.find((Instruction*)&callInst);
return (I == callSiteModRefInfo.end()) ? NULL : I->second;
}
const ModRefInfo* getModRefInfo (const InvokeInst& II) const {
const ModRefInfo* getModRefInfo(const InvokeInst& II) const {
std::map<const Instruction*, ModRefInfo*>::const_iterator I =
callSiteModRefInfo.find((Instruction*)&II);
return (I == callSiteModRefInfo.end()) ? NULL : I->second;
@ -169,13 +159,13 @@ public:
// Get the nodeIds used to index all Mod/Ref information for current function
//
unsigned getNodeId (const DSNode* node) const {
unsigned getNodeId(const DSNode* node) const {
std::map<const DSNode*, unsigned>::const_iterator iter = NodeIds.find(node);
assert(iter != NodeIds.end() && iter->second < funcModRefInfo.getSize());
return iter->second;
}
unsigned getNodeId (const Value* value) const;
unsigned getNodeId(const Value* value) const;
// Debugging support methods
void print(std::ostream &O) const;
@ -184,19 +174,15 @@ public:
//----------------------------------------------------------------------------
// class IPModRef
//
// Purpose:
// An interprocedural pass that computes IP Mod/Ref info for functions and
// for individual call sites.
//
// Given the DSGraph of a function, this class can be queried for
// a ModRefInfo object describing all the nodes in the DSGraph that are
// (a) modified, and (b) referenced during an execution of the function
// from an arbitrary callsite, or during an execution of a single call-site
// within the function.
//----------------------------------------------------------------------------
/// IPModRef Class - An interprocedural pass that computes IP Mod/Ref info for
/// functions and for individual call sites.
///
/// Given the DSGraph of a function, this class can be queried for
/// a ModRefInfo object describing all the nodes in the DSGraph that are
/// (a) modified, and (b) referenced during an execution of the function
/// from an arbitrary callsite, or during an execution of a single call-site
/// within the function.
///
class IPModRef : public Pass {
std::map<const Function*, FunctionModRefInfo*> funcToModRefInfoMap;
Module* M;
@ -204,17 +190,18 @@ class IPModRef : public Pass {
FunctionModRefInfo& getFuncInfo(const Function& func,
bool computeIfMissing = false);
public:
IPModRef() : M(NULL) { }
~IPModRef() { }
IPModRef() : M(NULL) {}
~IPModRef() {}
// Driver function to run IP Mod/Ref on a Module.
// This initializes the module reference, and then computes IPModRef
// results immediately if demand-driven analysis was *not* specified.
//
/// run - Driver function to run IP Mod/Ref on a Module.
/// This initializes the module reference, and then computes IPModRef
/// results immediately if demand-driven analysis was *not* specified.
///
virtual bool run(Module &M);
// Retrieve the Mod/Ref information for a single function
//
/// getFunctionModRefInfo - Retrieve the Mod/Ref information for a single
/// function
///
const FunctionModRefInfo& getFunctionModRefInfo(const Function& func) {
return getFuncInfo(func);
}
@ -229,18 +216,17 @@ public:
void print(std::ostream &O) const;
void dump() const;
// Release memory held by this pass when the pass pipeline is done
//
/// releaseMemory - Release memory held by this pass when the pass pipeline is
/// done
///
virtual void releaseMemory();
// getAnalysisUsage - This pass requires top-down data structure graphs.
// It modifies nothing.
//
/// getAnalysisUsage - This pass requires top-down data structure graphs.
/// It modifies nothing.
///
virtual void getAnalysisUsage(AnalysisUsage &AU) const;
};
//===----------------------------------------------------------------------===//
} // End llvm namespace
#endif

View File

@ -42,7 +42,7 @@ class FunctionModRefInfo;
class MemoryDepAnalysis : public Pass {
/// The following map and depGraph pointer are temporary until this class
/// becomes a FunctionPass instead of a module Pass. */
/// becomes a FunctionPass instead of a module Pass.
hash_map<Function*, DependenceGraph*> funcMap;
DependenceGraph* funcDepGraph;
@ -51,6 +51,7 @@ class MemoryDepAnalysis : public Pass {
const FunctionModRefInfo* funcModRef;
/// Internal routine that processes each SCC of the CFG.
///
void ProcessSCC(std::vector<BasicBlock*> &SCC, ModRefTable& ModRefAfter,
bool HasLoop);
@ -61,9 +62,10 @@ public:
~MemoryDepAnalysis();
/// Driver function to compute dependence graphs for every function.
///
bool run(Module &M);
/// getGraph() -- Retrieve the dependence graph for a function.
/// getGraph - Retrieve the dependence graph for a function.
/// This is temporary and will go away once this is a FunctionPass.
/// At that point, this class should directly inherit from DependenceGraph.
///
@ -73,8 +75,7 @@ public:
return *I->second;
}
const DependenceGraph& getGraph(Function& F) const {
hash_map<Function*, DependenceGraph*>::const_iterator
I = funcMap.find(&F);
hash_map<Function*, DependenceGraph*>::const_iterator I = funcMap.find(&F);
assert(I != funcMap.end());
return *I->second;
}
@ -83,7 +84,6 @@ public:
///
virtual void releaseMemory();
/// Driver functions to compute the Load/Store Dep. Graph per function.
///
bool runOnFunction(Function &F);

View File

@ -52,14 +52,11 @@ class DSGraph;
class DependenceGraph;
class PgmDependenceGraph;
///---------------------------------------------------------------------------
/// enum PDGIteratorFlags
///
/// These bit flags specify which dependences incident on a statement are to be
/// enumerated: Memory deps, SSA deps, Control deps, or any combination thereof.
///---------------------------------------------------------------------------
//---------------------------------------------------------------------------
/// enum PDGIteratorFlags - specify which dependences incident on a statement
/// are to be enumerated: Memory deps, SSA deps, Control deps, or any
/// combination thereof.
///
enum PDGIteratorFlags {
MemoryDeps = 0x1, // load/store/call deps
SSADeps = 0x2, // SSA deps (true)
@ -68,16 +65,12 @@ enum PDGIteratorFlags {
AllDeps = MemoryDeps | SSADeps | ControlDeps // shorthand for all three
};
///---------------------------------------------------------------------------
/// struct DepIterState
///
/// This data type is primarily an internal implementation detail.
//---------------------------------------------------------------------------
/// struct DepIterState - an internal implementation detail.
/// It are exposed here only to give inlinable access to field dep,
/// which is the representation for the current dependence pointed to by
/// a PgmDependenceGraph::iterator.
///---------------------------------------------------------------------------
///
class DepIterState {
private:
typedef char IterStateFlags;
@ -93,12 +86,12 @@ public:
PDGIteratorFlags depFlags:8; // which deps are we enumerating?
IterStateFlags iterFlags:8; // marking where the iter stands
/*ctor*/ DepIterState (DependenceGraph* _memDepGraph,
Instruction& I,
bool incomingDeps,
PDGIteratorFlags whichDeps);
DepIterState(DependenceGraph* _memDepGraph,
Instruction& I,
bool incomingDeps,
PDGIteratorFlags whichDeps);
bool operator==(const DepIterState& S) {
bool operator==(const DepIterState& S) {
assert(memDepGraph == S.memDepGraph &&
"Incompatible iterators! This is a probable sign of something BAD.");
return (iterFlags == S.iterFlags &&
@ -109,39 +102,38 @@ public:
// Is the iteration completely done?
//
bool done () const { return iterFlags & AllDone; }
bool done() const { return iterFlags & AllDone; }
// Bump this iterator logically by 1 (to next dependence) and reset the
// dep field to represent the new dependence if there is one.
// Set done = true otherwise.
//
void Next ();
/// Next - Bump this iterator logically by 1 (to next dependence) and reset
/// the dep field to represent the new dependence if there is one.
/// Set done = true otherwise.
///
void Next();
// Find the first memory dependence for the current Mem In/Out iterators.
// Sets dep to that dependence and returns true if one is found.
// Returns false and leaves dep unchanged otherwise.
//
bool SetFirstMemoryDep();
/// SetFirstMemoryDep - Find the first memory dependence for the current Mem
/// In/Out iterators. Sets dep to that dependence and returns true if one is
/// found. Returns false and leaves dep unchanged otherwise.
///
bool SetFirstMemoryDep();
// Find the next valid data dependence for the current SSA In/Out iterators.
// A valid data dependence is one that is to/from an Instruction.
// E.g., an SSA edge from a formal parameter is not a valid dependence.
// Sets dep to that dependence and returns true if a valid one is found.
// Returns false and leaves dep unchanged otherwise.
//
bool SetFirstSSADep ();
/// SetFirstSSADep - Find the next valid data dependence for the current SSA
/// In/Out iterators. A valid data dependence is one that is to/from an
/// Instruction. E.g., an SSA edge from a formal parameter is not a valid
/// dependence. Sets dep to that dependence and returns true if a valid one is
/// found. Returns false and leaves dep unchanged otherwise.
///
bool SetFirstSSADep();
};
///---------------------------------------------------------------------------
/// The dependence iterator class. This class represents a pointer to
/// a single dependence in the program dependence graph. It is essentially
/// like a pointer to an object of class Dependence but it is much more
/// efficient to retrieve information about the dependence directly rather
/// than constructing the equivalent Dependence object (since that object
/// is normally not constructed for SSA def-use dependences).
///---------------------------------------------------------------------------
//---------------------------------------------------------------------------
/// PDGIterator Class - represents a pointer to a single dependence in the
/// program dependence graph. It is essentially like a pointer to an object of
/// class Dependence but it is much more efficient to retrieve information about
/// the dependence directly rather than constructing the equivalent Dependence
/// object (since that object is normally not constructed for SSA def-use
/// dependences).
///
class PDGIterator: public forward_iterator<Dependence, ptrdiff_t> {
DepIterState* istate;
@ -159,44 +151,43 @@ class PDGIterator: public forward_iterator<Dependence, ptrdiff_t> {
public:
typedef PDGIterator _Self;
/*ctor*/ PDGIterator (DepIterState* _istate) : istate(_istate) { }
/*dtor*/ ~PDGIterator () { delete istate; }
PDGIterator(DepIterState* _istate) : istate(_istate) {}
~PDGIterator() { delete istate; }
/*copy*/ PDGIterator (const PDGIterator& I)
: istate(new DepIterState(*I.istate)) { }
PDGIterator(const PDGIterator& I) :istate(new DepIterState(*I.istate)) {}
PDGIterator& operator= (const PDGIterator& I) {
PDGIterator& operator=(const PDGIterator& I) {
if (istate) delete istate;
istate = new DepIterState(*I.istate);
return *this;
}
// Check if the iteration is complete
//
bool fini() const { return !istate || istate->done(); }
/// fini - check if the iteration is complete
///
bool fini() const { return !istate || istate->done(); }
// Retrieve the underlying Dependence. Returns NULL if fini().
//
Dependence* operator*() const { return fini() ? NULL : &istate->dep; }
Dependence* operator->() const { assert(!fini()); return &istate->dep; }
Dependence* operator*() const { return fini() ? NULL : &istate->dep; }
Dependence* operator->() const { assert(!fini()); return &istate->dep; }
// Increment the iterator
//
_Self& operator++() { if (!fini()) istate->Next(); return *this;}
_Self& operator++(int); // do not implement!
_Self& operator++() { if (!fini()) istate->Next(); return *this;}
_Self& operator++(int); // do not implement!
// Equality comparison: a "null" state should compare equal to done
// This is efficient for comparing with "end" or with itself, but could
// be quite inefficient for other cases.
//
bool operator==(const PDGIterator& I) const {
bool operator==(const PDGIterator& I) const {
if (I.istate == NULL) // most common case: iter == end()
return (istate == NULL || istate->done());
if (istate == NULL)
return (I.istate == NULL || I.istate->done());
return (*istate == *I.istate);
}
bool operator!=(const PDGIterator& I) const {
bool operator!=(const PDGIterator& I) const {
return ! (*this == I);
}
};
@ -219,15 +210,15 @@ class PgmDependenceGraph: public Pass {
// print helper function.
void printOutgoingSSADeps(Instruction& I, std::ostream &O);
// MakeIterator --
// The first version creates and initializes an iterator as specified.
// The second version creates a null iterator representing end-of-iteration.
//
PDGIterator MakeIterator (Instruction& I,
bool incomingDeps,
PDGIteratorFlags whichDeps);
/// MakeIterator - creates and initializes an iterator as specified.
///
PDGIterator MakeIterator(Instruction& I,
bool incomingDeps,
PDGIteratorFlags whichDeps);
PDGIterator MakeIterator () { return PDGIterator(NULL); }
/// MakeIterator - creates a null iterator representing end-of-iteration.
///
PDGIterator MakeIterator() { return PDGIterator(NULL); }
friend class PDGIterator;
friend class DepIterState;
@ -237,13 +228,13 @@ public:
/* typedef PDGIterator<const Dependence> const iterator; */
public:
PgmDependenceGraph() : memDepGraph(NULL) { }
~PgmDependenceGraph() { }
PgmDependenceGraph() : memDepGraph(NULL) {}
~PgmDependenceGraph() {}
/// Iterators to enumerate the program dependence graph for a function.
/// Note that this does not provide "end" iterators to check for completion.
/// Instead, just use iterator::fini() or iterator::operator*() == NULL
//
///
iterator inDepBegin(Instruction& I, PDGIteratorFlags whichDeps = AllDeps) {
return MakeIterator(I, /*inDeps*/ true, whichDeps);
}
@ -257,7 +248,7 @@ public:
return MakeIterator();
}
///------------------------------------------------------------------------
//------------------------------------------------------------------------
/// TEMPORARY FUNCTIONS TO MAKE THIS A MODULE PASS ---
/// These functions will go away once this class becomes a FunctionPass.
@ -306,8 +297,6 @@ public:
void dump() const;
};
//===----------------------------------------------------------------------===//
} // End llvm namespace
#endif