Dramatically simplify internal DSNode representation, get implementation

*FULLY OPERATIONAL* and safe.  We are now capable of completely analyzing
at LEAST the Olden benchmarks + 181.mcf


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@4562 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Chris Lattner
2002-11-06 06:20:27 +00:00
parent 4268c93b00
commit 08db719c4b
9 changed files with 441 additions and 593 deletions

View File

@ -23,7 +23,9 @@ class DSNodeIterator : public forward_iterator<const DSNode, ptrdiff_t> {
DSNodeIterator(const DSNode *N) : Node(N), Offset(0) {} // begin iterator
DSNodeIterator(const DSNode *N, bool) // Create end iterator
: Node(N), Offset(N->getSize()) {
: Node(N) {
Offset = (N->getSize()+((1 << DS::PointerShift)-1)) &
~((1 << DS::PointerShift)-1);
}
public:
DSNodeIterator(const DSNodeHandle &NH)
@ -41,13 +43,12 @@ public:
}
pointer operator*() const {
const DSNodeHandle *NH = Node->getLink(Offset);
return NH ? NH->getNode() : 0;
return Node->getLink(Offset).getNode();
}
pointer operator->() const { return operator*(); }
_Self& operator++() { // Preincrement
++Offset;
Offset += (1 << DS::PointerShift);
return *this;
}
_Self operator++(int) { // Postincrement

View File

@ -17,47 +17,34 @@
/// different types represented in this object.
///
class DSNode {
/// Links - Contains one entry for every _distinct_ pointer field in the
/// memory block. These are demand allocated and indexed by the MergeMap
/// vector.
///
std::vector<DSNodeHandle> Links;
/// MergeMap - Maps from every byte in the object to a signed byte number.
/// This map is neccesary due to the merging that is possible as part of the
/// unification algorithm. To merge two distinct bytes of the object together
/// into a single logical byte, the indexes for the two bytes are set to the
/// same value. This fully general merging is capable of representing all
/// manners of array merging if neccesary.
///
/// This map is also used to map outgoing pointers to various byte offsets in
/// this data structure node. If this value is >= 0, then it indicates that
/// the numbered entry in the Links vector contains the outgoing edge for this
/// byte offset. In this way, the Links vector can be demand allocated and
/// byte elements of the node may be merged without needing a Link allocated
/// for it.
///
/// Initially, each each element of the MergeMap is assigned a unique negative
/// number, which are then merged as the unification occurs.
///
std::vector<signed char> MergeMap;
/// Referrers - Keep track of all of the node handles that point to this
/// DSNode. These pointers may need to be updated to point to a different
/// node if this node gets merged with it.
///
std::vector<DSNodeHandle*> Referrers;
/// TypeEntries - As part of the merging process of this algorithm, nodes of
/// different types can be represented by this single DSNode. This vector is
/// kept sorted.
/// Links - Contains one entry for every sizeof(void*) bytes in this memory
/// object. Note that if the node is not a multiple of size(void*) bytes
/// large, that there is an extra entry for the "remainder" of the node as
/// well. For this reason, nodes of 1 byte in size do have one link.
///
std::vector<DSTypeRec> TypeEntries;
std::vector<DSNodeHandle> Links;
/// Globals - The list of global values that are merged into this node.
///
std::vector<GlobalValue*> Globals;
/// Type - Keep track of the current outer most type of this object, in
/// addition to whether or not it has been indexed like an array or not. If
/// the isArray bit is set, the node cannot grow.
///
DSTypeRec Ty;
/// Size - The current size of the node. This should be equal to the size of
/// the current type record.
///
unsigned Size;
void operator=(const DSNode &); // DO NOT IMPLEMENT
public:
enum NodeTy {
@ -99,10 +86,10 @@ public:
/// getSize - Return the maximum number of bytes occupied by this object...
///
unsigned getSize() const { return MergeMap.size(); }
unsigned getSize() const { return Size; }
// getTypeEntries - Return the possible types and their offsets in this object
const std::vector<DSTypeRec> &getTypeEntries() const { return TypeEntries; }
// getType - Return the node type of this object...
const DSTypeRec &getType() const { return Ty; }
/// getReferrers - Return a list of the pointers to this node...
///
@ -117,51 +104,46 @@ public:
bool isRead() const { return (NodeType & Read) != 0; }
/// hasLink - Return true if this memory object has a link at the specified
/// location.
/// hasLink - Return true if this memory object has a link in slot #LinkNo
///
bool hasLink(unsigned i) const {
assert(i < getSize() && "Field Link index is out of range!");
return MergeMap[i] >= 0;
bool hasLink(unsigned Offset) const {
assert((Offset & ((1 << DS::PointerShift)-1)) == 0 &&
"Pointer offset not aligned correctly!");
unsigned Index = Offset >> DS::PointerShift;
assert(Index < Links.size() && "Link index is out of range!");
return Links[Index].getNode();
}
DSNodeHandle &getLink(unsigned Offset) {
assert((Offset & ((1 << DS::PointerShift)-1)) == 0 &&
"Pointer offset not aligned correctly!");
unsigned Index = Offset >> DS::PointerShift;
assert(Index < Links.size() && "Link index is out of range!");
return Links[Index];
}
const DSNodeHandle &getLink(unsigned Offset) const {
assert((Offset & ((1 << DS::PointerShift)-1)) == 0 &&
"Pointer offset not aligned correctly!");
unsigned Index = Offset >> DS::PointerShift;
assert(Index < Links.size() && "Link index is out of range!");
return Links[Index];
}
DSNodeHandle *getLink(unsigned i) {
if (hasLink(i)) {
assert((unsigned)MergeMap[i] < Links.size() &&
"MergeMap references Link that doesn't exist!");
return &Links[MergeMap[i]];
}
return 0;
}
const DSNodeHandle *getLink(unsigned i) const {
if (hasLink(i)) {
assert((unsigned)MergeMap[i] < Links.size() &&
"MergeMap references Link that doesn't exist!");
return &Links[MergeMap[i]];
}
return 0;
}
/// getMergeMapLabel - Return the merge map entry specified, to allow printing
/// out of DSNodes nicely for DOT graphs.
/// mergeTypeInfo - This method merges the specified type into the current
/// node at the specified offset. This may update the current node's type
/// record if this gives more information to the node, it may do nothing to
/// the node if this information is already known, or it may merge the node
/// completely (and return true) if the information is incompatible with what
/// is already known.
///
int getMergeMapLabel(unsigned i) const {
assert(i < MergeMap.size() && "MergeMap index out of range!");
return MergeMap[i];
}
/// getTypeRec - This method returns the specified type record if it exists.
/// If it does not yet exist, the method checks to see whether or not the
/// request would result in an untrackable state. If adding it would cause
/// untrackable state, we foldNodeCompletely the node and return the void
/// record, otherwise we add an new TypeEntry and return it.
/// This method returns true if the node is completely folded, otherwise
/// false.
///
DSTypeRec &getTypeRec(const Type *Ty, unsigned Offset);
bool mergeTypeInfo(const Type *Ty, unsigned Offset);
/// foldNodeCompletely - If we determine that this node has some funny
/// behavior happening to it that we cannot represent, we fold it down to a
/// single, completely pessimistic, node. This node is represented as a
/// single byte with a single TypeEntry of "void".
/// single byte with a single TypeEntry of "void" with isArray = true.
///
void foldNodeCompletely();
@ -175,7 +157,13 @@ public:
/// NodeHandle, replacing what was there. It is uncommon to use this method,
/// instead one of the higher level methods should be used, below.
///
void setLink(unsigned i, const DSNodeHandle &NH);
void setLink(unsigned Offset, const DSNodeHandle &NH) {
assert((Offset & ((1 << DS::PointerShift)-1)) == 0 &&
"Pointer offset not aligned correctly!");
unsigned Index = Offset >> DS::PointerShift;
assert(Index < Links.size() && "Link index is out of range!");
Links[Index] = NH;
}
/// addEdgeTo - Add an edge from the current node to the specified node. This
/// can cause merging of nodes in the graph.
@ -191,18 +179,6 @@ public:
///
void mergeWith(const DSNodeHandle &NH, unsigned Offset);
/// mergeIndexes - If we discover that two indexes are equivalent and must be
/// merged, this function is used to do the dirty work.
///
void mergeIndexes(unsigned idx1, unsigned idx2) {
assert(idx1 < getSize() && idx2 < getSize() && "Indexes out of range!");
signed char MV1 = MergeMap[idx1];
signed char MV2 = MergeMap[idx2];
if (MV1 != MV2)
mergeMappedValues(MV1, MV2);
}
/// addGlobal - Add an entry for a global value to the Globals list. This
/// also marks the node with the 'G' flag if it does not already have it.
///
@ -226,34 +202,6 @@ private:
// addReferrer - Keep the referrer set up to date...
void addReferrer(DSNodeHandle *H) { Referrers.push_back(H); }
void removeReferrer(DSNodeHandle *H);
/// rewriteMergeMap - Loop over the mergemap, replacing any references to the
/// index From to be references to the index To.
///
void rewriteMergeMap(signed char From, signed char To) {
assert(From != To && "Cannot change something into itself!");
assert(To < (int)Links.size() &&
"Changing MergeMap entry to an illegal entry!");
for (unsigned i = 0, e = MergeMap.size(); i != e; ++i)
if (MergeMap[i] == From)
MergeMap[i] = To;
}
/// mergeMappedValues - This is the higher level form of rewriteMergeMap. It
/// is fully capable of merging links together if neccesary as well as simply
/// rewriting the map entries.
///
void mergeMappedValues(signed char V1, signed char V2);
/// growNode - Attempt to grow the node to the specified size. This may do
/// one of three things:
/// 1. Grow the node, return false
/// 2. Refuse to grow the node, but maintain a trackable situation, return
/// false.
/// 3. Be unable to track if node was that size, so collapse the node and
/// return true.
///
bool growNode(unsigned RequestedSize);
};
@ -276,26 +224,26 @@ inline bool DSNodeHandle::hasLink(unsigned Num) const {
/// getLink - Treat this current node pointer as a pointer to a structure of
/// some sort. This method will return the pointer a mem[this+Num]
///
inline const DSNodeHandle *DSNodeHandle::getLink(unsigned Num) const {
inline const DSNodeHandle &DSNodeHandle::getLink(unsigned Off) const {
assert(N && "DSNodeHandle does not point to a node yet!");
return N->getLink(Num+Offset);
return N->getLink(Offset+Off);
}
inline DSNodeHandle *DSNodeHandle::getLink(unsigned Num) {
inline DSNodeHandle &DSNodeHandle::getLink(unsigned Off) {
assert(N && "DSNodeHandle does not point to a node yet!");
return N->getLink(Num+Offset);
return N->getLink(Off+Offset);
}
inline void DSNodeHandle::setLink(unsigned Num, const DSNodeHandle &NH) {
inline void DSNodeHandle::setLink(unsigned Off, const DSNodeHandle &NH) {
assert(N && "DSNodeHandle does not point to a node yet!");
N->setLink(Num+Offset, NH);
N->setLink(Off+Offset, NH);
}
/// 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 LinkNo, const DSNodeHandle &Node) {
inline void DSNodeHandle::addEdgeTo(unsigned Off, const DSNodeHandle &Node) {
assert(N && "DSNodeHandle does not point to a node yet!");
N->addEdgeTo(LinkNo+Offset, Node);
N->addEdgeTo(Off+Offset, Node);
}
/// mergeWith - Merge the logical node pointed to by 'this' with the node
@ -304,9 +252,8 @@ inline void DSNodeHandle::addEdgeTo(unsigned LinkNo, const DSNodeHandle &Node) {
inline void DSNodeHandle::mergeWith(const DSNodeHandle &Node) {
if (N != 0)
N->mergeWith(Node, Offset);
else { // No node to merge with, so just point to Node
else // No node to merge with, so just point to Node
*this = Node;
}
}
#endif

View File

@ -22,6 +22,10 @@ class DSNode; // Each node in the graph
class DSGraph; // A graph for a function
class DSNodeIterator; // Data structure graph traversal iterator
namespace DS {
extern const unsigned PointerShift; // 64bit ptrs = 3, 32 bit ptrs = 2
};
//===----------------------------------------------------------------------===//
/// DSNodeHandle - Implement a "handle" to a data structure node that takes care
/// of all of the add/un'refing of the node to prevent the backpointers in the
@ -32,6 +36,7 @@ class DSNodeIterator; // Data structure graph traversal iterator
/// defined in DSNode.h because they need knowledge of DSNode operation. Putting
/// them in a CPP file wouldn't help making them inlined and keeping DSNode and
/// DSNodeHandle (and friends) in one file complicates things.
///
class DSNodeHandle {
DSNode *N;
unsigned Offset;
@ -77,8 +82,8 @@ public:
/// getLink - Treat this current node pointer as a pointer to a structure of
/// some sort. This method will return the pointer a mem[this+Num]
///
inline const DSNodeHandle *getLink(unsigned Num) const;
inline DSNodeHandle *getLink(unsigned Num);
inline const DSNodeHandle &getLink(unsigned Num) const;
inline DSNodeHandle &getLink(unsigned Num);
inline void setLink(unsigned Num, const DSNodeHandle &NH);
};
@ -90,26 +95,14 @@ public:
///
struct DSTypeRec {
const Type *Ty; // The type itself...
unsigned Offset; // The offset in the node
bool isArray; // Have we accessed an array of elements?
DSTypeRec() : Ty(0), Offset(0), isArray(false) {}
DSTypeRec(const Type *T, unsigned O) : Ty(T), Offset(O), isArray(false) {}
bool operator<(const DSTypeRec &TR) const {
// Sort first by offset!
return Offset < TR.Offset || (Offset == TR.Offset && Ty < TR.Ty);
}
bool operator==(const DSTypeRec &TR) const {
return Ty == TR.Ty && Offset == TR.Offset;
}
bool operator!=(const DSTypeRec &TR) const { return !operator==(TR); }
DSTypeRec(const Type *T = 0, bool A = false)
: Ty(T), isArray(A) {}
};
//===----------------------------------------------------------------------===//
/// DSCallSite - Representation of a call site via its call instruction,
/// the DSNode handle for the callee function (or function pointer), and