aboutsummaryrefslogtreecommitdiff
path: root/lib/Analysis/DataStructure/DataStructure.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Analysis/DataStructure/DataStructure.cpp')
-rw-r--r--lib/Analysis/DataStructure/DataStructure.cpp216
1 files changed, 164 insertions, 52 deletions
diff --git a/lib/Analysis/DataStructure/DataStructure.cpp b/lib/Analysis/DataStructure/DataStructure.cpp
index 91c9a7cbd2..cd2c898319 100644
--- a/lib/Analysis/DataStructure/DataStructure.cpp
+++ b/lib/Analysis/DataStructure/DataStructure.cpp
@@ -31,38 +31,8 @@ using namespace DataStructureAnalysis;
//===----------------------------------------------------------------------===//
DSNode::DSNode(enum NodeTy NT, const Type *T) : NodeType(NT) {
- // If this node is big enough to have pointer fields, add space for them now.
- if (T != Type::VoidTy && !isa<FunctionType>(T)) { // Avoid TargetData assert's
- MergeMap.resize(TD.getTypeSize(T));
-
- // Assign unique values to all of the elements of MergeMap
- if (MergeMap.size() < 128) {
- // Handle the common case of reasonable size structures...
- for (unsigned i = 0, e = MergeMap.size(); i != e; ++i)
- MergeMap[i] = -1-i; // Assign -1, -2, -3, ...
- } else {
- // It's possible that we have something really big here. In this case,
- // divide the object into chunks until it will fit into 128 elements.
- unsigned Multiple = MergeMap.size()/128;
-
- // It's probably an array, and probably some power of two in size.
- // Because of this, find the biggest power of two that is bigger than
- // multiple to use as our real Multiple.
- unsigned RealMultiple = 2;
- while (RealMultiple <= Multiple) RealMultiple <<= 1;
-
- unsigned RealBound = MergeMap.size()/RealMultiple;
- assert(RealBound <= 128 && "Math didn't work out right");
-
- // Now go through and assign indexes that are between -1 and -128
- // inclusive
- //
- for (unsigned i = 0, e = MergeMap.size(); i != e; ++i)
- MergeMap[i] = -1-(i % RealBound); // Assign -1, -2, -3...
- }
- }
-
- TypeEntries.push_back(TypeRec(T, 0));
+ // Add the type entry if it is specified...
+ if (T) getTypeRec(T, 0);
}
// DSNode copy constructor... do not copy over the referrers list!
@@ -95,6 +65,44 @@ void DSNode::addGlobal(GlobalValue *GV) {
}
}
+/// 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".
+///
+void DSNode::foldNodeCompletely() {
+ // We are no longer typed at all...
+ TypeEntries.clear();
+ TypeEntries.push_back(DSTypeRec(Type::VoidTy, 0));
+
+ // Loop over all of our referrers, making them point to our one byte of space.
+ for (vector<DSNodeHandle*>::iterator I = Referrers.begin(), E=Referrers.end();
+ I != E; ++I)
+ (*I)->setOffset(0);
+
+ // Fold the MergeMap down to a single byte of space...
+ MergeMap.resize(1);
+ MergeMap[0] = -1;
+
+ // If we have links, merge all of our outgoing links together...
+ if (!Links.empty()) {
+ MergeMap[0] = 0; // We now contain an outgoing edge...
+ for (unsigned i = 1, e = Links.size(); i != e; ++i)
+ Links[0].mergeWith(Links[i]);
+ Links.resize(1);
+ }
+}
+
+/// isNodeCompletelyFolded - Return true if this node has been completely
+/// folded down to something that can never be expanded, effectively losing
+/// all of the field sensitivity that may be present in the node.
+///
+bool DSNode::isNodeCompletelyFolded() const {
+ return getSize() == 1 && TypeEntries.size() == 1 &&
+ TypeEntries[0].Ty == Type::VoidTy;
+}
+
+
/// setLink - Set the link at the specified offset to the specified
/// NodeHandle, replacing what was there. It is uncommon to use this method,
@@ -144,6 +152,108 @@ void DSNode::addEdgeTo(unsigned Offset, const DSNodeHandle &NH) {
}
}
+/// 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.
+///
+DSTypeRec &DSNode::getTypeRec(const Type *Ty, unsigned Offset) {
+ // If the node is already collapsed, we can't do anything... bail out early
+ if (isNodeCompletelyFolded()) {
+ assert(TypeEntries.size() == 1 && "Node folded and Entries.size() != 1?");
+ return TypeEntries[0];
+ }
+
+ // First search to see if we already have a record for this...
+ DSTypeRec SearchFor(Ty, Offset);
+
+ std::vector<DSTypeRec>::iterator I;
+ if (TypeEntries.size() < 5) { // Linear search if we have few entries.
+ I = TypeEntries.begin();
+ while (I != TypeEntries.end() && *I < SearchFor)
+ ++I;
+ } else {
+ I = std::lower_bound(TypeEntries.begin(), TypeEntries.end(), SearchFor);
+ }
+
+ // At this point, I either points to the right entry or it points to the entry
+ // we are to insert the new entry in front of...
+ //
+ if (I != TypeEntries.end() && *I == SearchFor)
+ return *I;
+
+ // ASSUME that it's okay to add this type entry.
+ // FIXME: This should check to make sure it's ok.
+
+ // If the data size is different then our current size, try to resize the node
+ unsigned ReqSize = Ty->isSized() ? TD.getTypeSize(Ty) : 0;
+ if (getSize() < ReqSize) {
+ // If we are trying to make it bigger, and we can grow the node, do so.
+ if (growNode(ReqSize)) {
+ assert(isNodeCompletelyFolded() && "Node isn't folded?");
+ return TypeEntries[0];
+ }
+
+ } else if (getSize() > ReqSize) {
+ // If we are trying to make the node smaller, we don't have to do anything.
+
+ }
+
+ return *TypeEntries.insert(I, SearchFor);
+}
+
+/// 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 DSNode::growNode(unsigned ReqSize) {
+ unsigned OldSize = getSize();
+
+ if (0) {
+ // FIXME: DSNode::growNode() doesn't perform correct safety checks yet!
+
+ foldNodeCompletely();
+ return true;
+ }
+
+ assert(ReqSize > OldSize && "Not growing node!");
+
+ // Resize the merge map to have enough space...
+ MergeMap.resize(ReqSize);
+
+ // Assign unique values to all of the elements of MergeMap
+ if (ReqSize < 128) {
+ // Handle the common case of reasonable size structures...
+ for (unsigned i = OldSize; i != ReqSize; ++i)
+ MergeMap[i] = -1-i; // Assign -1, -2, -3, ...
+ } else {
+ // It's possible that we have something really big here. In this case,
+ // divide the object into chunks until it will fit into 128 elements.
+ unsigned Multiple = ReqSize/128;
+
+ // It's probably an array, and probably some power of two in size.
+ // Because of this, find the biggest power of two that is bigger than
+ // multiple to use as our real Multiple.
+ unsigned RealMultiple = 2;
+ while (RealMultiple <= Multiple) RealMultiple <<= 1;
+
+ unsigned RealBound = ReqSize/RealMultiple;
+ assert(RealBound <= 128 && "Math didn't work out right");
+
+ // Now go through and assign indexes that are between -1 and -128
+ // inclusive
+ //
+ for (unsigned i = OldSize; i != ReqSize; ++i)
+ MergeMap[i] = -1-(i % RealBound); // Assign -1, -2, -3...
+ }
+ return false;
+}
+
/// 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.
@@ -236,11 +346,21 @@ void MergeSortedVectors(vector<T> &Dest, const vector<T> &Src) {
void DSNode::mergeWith(const DSNodeHandle &NH, unsigned Offset) {
DSNode *N = NH.getNode();
if (N == 0 || (N == this && NH.getOffset() == Offset))
- return; // Noop
+ return; // Noop
assert(NH.getNode() != this &&
"Cannot merge two portions of the same node yet!");
+ // If we are merging a node with a completely folded node, then both nodes are
+ // now completely folded.
+ //
+ if (isNodeCompletelyFolded()) {
+ NH.getNode()->foldNodeCompletely();
+ } else if (NH.getNode()->isNodeCompletelyFolded()) {
+ foldNodeCompletely();
+ Offset = 0;
+ }
+
// If both nodes are not at offset 0, make sure that we are merging the node
// at an later offset into the node with the zero offset.
//
@@ -322,27 +442,18 @@ void DSNode::mergeWith(const DSNodeHandle &NH, unsigned Offset) {
NodeType |= N->NodeType;
N->NodeType = 0; // N is now a dead node.
- // If this merging into node has more than just void nodes in it, merge!
- assert(!N->TypeEntries.empty() && "TypeEntries is empty for a node?");
- if (N->TypeEntries.size() != 1 || N->TypeEntries[0].Ty != Type::VoidTy) {
- // If the current node just has a Void entry in it, remove it.
- if (TypeEntries.size() == 1 && TypeEntries[0].Ty == Type::VoidTy)
- TypeEntries.clear();
-
- // Adjust all of the type entries we are merging in by the offset... and add
- // them to the TypeEntries list.
- //
- if (NOffset != 0) { // This case is common enough to optimize for
- // Offset all of the TypeEntries in N with their new offset
- for (unsigned i = 0, e = N->TypeEntries.size(); i != e; ++i)
- N->TypeEntries[i].Offset += NOffset;
- }
-
- MergeSortedVectors(TypeEntries, N->TypeEntries);
-
- N->TypeEntries.clear();
+ // Adjust all of the type entries we are merging in by the offset...
+ //
+ if (NOffset != 0) { // This case is common enough to optimize for
+ // Offset all of the TypeEntries in N with their new offset
+ for (unsigned i = 0, e = N->TypeEntries.size(); i != e; ++i)
+ N->TypeEntries[i].Offset += NOffset;
}
+ // ... now add them to the TypeEntries list.
+ MergeSortedVectors(TypeEntries, N->TypeEntries);
+ N->TypeEntries.clear(); // N is dead, no type-entries need exist
+
// Merge the globals list...
if (!N->Globals.empty()) {
MergeSortedVectors(Globals, N->Globals);
@@ -408,6 +519,7 @@ static void CopyFunctionCallsList(const vector<DSCallSite>& fromCalls,
/// remapLinks - Change all of the Links in the current node according to the
/// specified mapping.
+///
void DSNode::remapLinks(std::map<const DSNode*, DSNode*> &OldNodeMap) {
for (unsigned i = 0, e = Links.size(); i != e; ++i)
Links[i].setNode(OldNodeMap[Links[i].getNode()]);