Make error messages more useful than jsut an abort
[oota-llvm.git] / lib / Analysis / DataStructure / DataStructure.cpp
index 80586de2f141a8911c0fc34afa0cd5d5111c1a52..1aad8cf69ee544cda6c2154747e16c4f75aca9e6 100644 (file)
@@ -24,6 +24,27 @@ namespace DS {   // TODO: FIXME
 }
 using namespace DS;
 
+DSNode *DSNodeHandle::HandleForwarding() const {
+  assert(!N->ForwardNH.isNull() && "Can only be invoked if forwarding!");
+
+  // Handle node forwarding here!
+  DSNode *Next = N->ForwardNH.getNode();  // Cause recursive shrinkage
+  Offset += N->ForwardNH.getOffset();
+
+  if (--N->NumReferrers == 0) {
+    // Removing the last referrer to the node, sever the forwarding link
+    N->stopForwarding();
+  }
+
+  N = Next;
+  N->NumReferrers++;
+  if (N->Size <= Offset) {
+    assert(N->Size <= 1 && "Forwarded to shrunk but not collapsed node?");
+    Offset = 0;
+  }
+  return N;
+}
+
 //===----------------------------------------------------------------------===//
 // DSNode Implementation
 //===----------------------------------------------------------------------===//
@@ -131,7 +152,8 @@ bool DSNode::isNodeCompletelyFolded() const {
 ///
 /// This method returns true if the node is completely folded, otherwise false.
 ///
-bool DSNode::mergeTypeInfo(const Type *NewTy, unsigned Offset) {
+bool DSNode::mergeTypeInfo(const Type *NewTy, unsigned Offset,
+                           bool FoldIfIncompatible) {
   // Check to make sure the Size member is up-to-date.  Size can be one of the
   // following:
   //  Size = 0, Ty = Void: Nothing is known about this node.
@@ -192,14 +214,14 @@ bool DSNode::mergeTypeInfo(const Type *NewTy, unsigned Offset) {
     // It is illegal to grow this node if we have treated it as an array of
     // objects...
     if (isArray()) {
-      foldNodeCompletely();
+      if (FoldIfIncompatible) foldNodeCompletely();
       return true;
     }
 
     if (Offset) {  // We could handle this case, but we don't for now...
       DEBUG(std::cerr << "UNIMP: Trying to merge a growth type into "
                       << "offset != 0: Collapsing!\n");
-      foldNodeCompletely();
+      if (FoldIfIncompatible) foldNodeCompletely();
       return true;
     }
 
@@ -256,7 +278,7 @@ bool DSNode::mergeTypeInfo(const Type *NewTy, unsigned Offset) {
       break;
     }
     default:
-      foldNodeCompletely();
+      if (FoldIfIncompatible) foldNodeCompletely();
       return true;
     }
   }
@@ -335,7 +357,7 @@ bool DSNode::mergeTypeInfo(const Type *NewTy, unsigned Offset) {
                   << "\n due to:" << NewTy << " @ " << Offset << "!\n"
                   << "SubType: " << SubType << "\n\n");
 
-  foldNodeCompletely();
+  if (FoldIfIncompatible) foldNodeCompletely();
   return true;
 }
 
@@ -778,7 +800,7 @@ void DSGraph::markIncompleteNodes(unsigned Flags) {
   // Mark all global nodes as incomplete...
   if ((Flags & DSGraph::IgnoreGlobals) == 0)
     for (unsigned i = 0, e = Nodes.size(); i != e; ++i)
-      if (Nodes[i]->NodeType & DSNode::GlobalNode)
+      if (Nodes[i]->NodeType & DSNode::GlobalNode && Nodes[i]->getNumLinks())
         markIncompleteNode(Nodes[i]);
 }
 
@@ -1018,12 +1040,29 @@ void DSGraph::removeDeadNodes(unsigned Flags) {
 
   // Mark all nodes reachable by (non-global) scalar nodes as alive...
   for (hash_map<Value*, DSNodeHandle>::iterator I = ScalarMap.begin(),
-         E = ScalarMap.end(); I != E; ++I)
-    if (!isa<GlobalValue>(I->first))
-      I->second.getNode()->markReachableNodes(Alive);
-    else {                   // Keep track of global nodes
-      GlobalNodes.push_back(std::make_pair(I->first, I->second.getNode()));
+         E = ScalarMap.end(); I != E; )
+    if (isa<GlobalValue>(I->first)) {             // Keep track of global nodes
       assert(I->second.getNode() && "Null global node?");
+      GlobalNodes.push_back(std::make_pair(I->first, I->second.getNode()));
+      ++I;
+    } else {
+      // Check to see if this is a worthless node generated for non-pointer
+      // values, such as integers.  Consider an addition of long types: A+B.
+      // Assuming we can track all uses of the value in this context, and it is
+      // NOT used as a pointer, we can delete the node.  We will be able to
+      // detect this situation if the node pointed to ONLY has Unknown bit set
+      // in the node.  In this case, the node is not incomplete, does not point
+      // to any other nodes (no mod/ref bits set), and is therefore
+      // uninteresting for data structure analysis.  If we run across one of
+      // these, prune the scalar pointing to it.
+      //
+      DSNode *N = I->second.getNode();
+      if (N->NodeType == DSNode::UnknownNode && !isa<Argument>(I->first)) {
+        ScalarMap.erase(I++);
+      } else {
+        I->second.getNode()->markReachableNodes(Alive);
+        ++I;
+      }
     }
 
   // The return value is alive as well...