Stop representing scalars as explicit nodes in the graph. Now the only
authorChris Lattner <sabre@nondot.org>
Sat, 2 Nov 2002 00:13:20 +0000 (00:13 +0000)
committerChris Lattner <sabre@nondot.org>
Sat, 2 Nov 2002 00:13:20 +0000 (00:13 +0000)
nodes in the graph are memory objects, which is very nice.  This also greatly
reduces the size and memory footprint for DSGraphs.  For example, the local
DSGraph for llu went from 65 to 13 nodes with this change.  As a side bonus,
dot seems to lay out the graphs slightly better too.  :)

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@4488 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Analysis/DataStructure/BottomUpClosure.cpp
lib/Analysis/DataStructure/DataStructure.cpp
lib/Analysis/DataStructure/Local.cpp
lib/Analysis/DataStructure/Printer.cpp

index defd80e308f0afb360a9e81009c1c9fb9bc252fc..08c86c5e124fa13d5228dfd3709a16b666ced44b 100644 (file)
@@ -16,8 +16,7 @@ using std::map;
 static RegisterAnalysis<BUDataStructures>
 X("budatastructure", "Bottom-up Data Structure Analysis Closure");
 
-// TODO: FIXME
-namespace DataStructureAnalysis {
+namespace DataStructureAnalysis { // TODO: FIXME: Eliminate
   // isPointerType - Return true if this first class type is big enough to hold
   // a pointer.
   //
@@ -60,14 +59,12 @@ static void ResolveArguments(DSCallSite &Call, Function &F,
                              map<Value*, DSNodeHandle> &ValueMap) {
   // Resolve all of the function arguments...
   Function::aiterator AI = F.abegin();
-  for (unsigned i = 0, e = Call.getNumPtrArgs(); i != e; ++i) {
+  for (unsigned i = 0, e = Call.getNumPtrArgs(); i != e; ++i, ++AI) {
     // Advance the argument iterator to the first pointer argument...
     while (!isPointerType(AI->getType())) ++AI;
     
     // Add the link from the argument scalar to the provided value
-    DSNodeHandle &NN = ValueMap[AI];
-    NN.addEdgeTo(Call.getPtrArg(i));
-    ++AI;
+    ValueMap[AI].mergeWith(Call.getPtrArg(i));
   }
 }
 
@@ -118,8 +115,7 @@ DSGraph &BUDataStructures::calculateGraph(Function &F) {
             DEBUG(std::cerr << "\t[BU] Self Inlining: " << F.getName() << "\n");
 
             // Handle the return value if present...
-            if (Call.getRetVal().getNode())
-              Graph->getRetNode().mergeWith(Call.getRetVal());
+            Graph->getRetNode().mergeWith(Call.getRetVal());
 
             // Resolve the arguments in the call to the actual values...
             ResolveArguments(Call, F, Graph->getValueMap());
@@ -143,11 +139,12 @@ DSGraph &BUDataStructures::calculateGraph(Function &F) {
             // Record that the original DSCallSite was a call site of FI.
             // This may or may not have been known when the DSCallSite was
             // originally created.
+#if 1  /// FIXME: Reenable
             std::vector<DSCallSite> &CallSitesForFunc = CallSites[&FI];
             CallSitesForFunc.push_back(Call);
             CallSitesForFunc.back().setResolvingCaller(&F);
             CallSitesForFunc.back().setCallee(0);
-
+#endif
             // Clone the callee's graph into the current graph, keeping
             // track of where scalars in the old graph _used_ to point,
             // and of the new nodes matching nodes of the old graph.
@@ -163,8 +160,8 @@ DSGraph &BUDataStructures::calculateGraph(Function &F) {
             // Resolve the arguments in the call to the actual values...
             ResolveArguments(Call, FI, OldValMap);
 
-            if (Call.getRetVal().getNode())// Handle the return value if present
-              RetVal.mergeWith(Call.getRetVal());
+            // Handle the return value if present...
+            RetVal.mergeWith(Call.getRetVal());
 
             // Erase the entry in the Callees vector
             Callees.erase(Callees.begin()+c--);
@@ -172,9 +169,10 @@ DSGraph &BUDataStructures::calculateGraph(Function &F) {
           } else if (FI.getName() == "printf" || FI.getName() == "sscanf" ||
                      FI.getName() == "fprintf" || FI.getName() == "open" ||
                      FI.getName() == "sprintf") {
-            // FIXME: These special cases should go away when we can define
-            // functions that take a variable number of arguments.
+            // FIXME: These special cases (eg printf) should go away when we can
+            // define functions that take a variable number of arguments.
 
+            // FIXME: at the very least, this should update mod/ref info
             // Erase the entry in the globals vector
             Callees.erase(Callees.begin()+c--);
           }
index 44ecd01ab7e6bae6c078bd8a67d89cfcbd61d181..2aadc000f6c8bfb2e68c5a6bd1cc142cbc26cfe5 100644 (file)
@@ -16,8 +16,7 @@
 
 using std::vector;
 
-// TODO: FIXME
-namespace DataStructureAnalysis {
+namespace DataStructureAnalysis {   // TODO: FIXME
   // isPointerType - Return true if this first class type is big enough to hold
   // a pointer.
   //
@@ -538,14 +537,15 @@ void DSNode::remapLinks(std::map<const DSNode*, DSNode*> &OldNodeMap) {
 
 // cloneInto - Clone the specified DSGraph into the current graph, returning the
 // Return node of the graph.  The translated ValueMap for the old function is
-// filled into the OldValMap member.  If StripLocals is set to true, Scalar and
-// Alloca markers are removed from the graph, as the graph is being cloned into
-// calling function's graph.
+// filled into the OldValMap member.  If StripAllocas is set to true, Alloca
+// markers are removed from the graph, as the graph is being cloned into a
+// calling function's graph.
 //
 DSNodeHandle DSGraph::cloneInto(const DSGraph &G, 
                                 std::map<Value*, DSNodeHandle> &OldValMap,
                                 std::map<const DSNode*, DSNode*> &OldNodeMap,
-                                bool StripScalars, bool StripAllocas) {
+                                bool StripScalars,  // FIXME: Kill StripScalars
+                                bool StripAllocas) {
   assert(OldNodeMap.empty() && "Returned OldNodeMap should be empty!");
 
   unsigned FN = Nodes.size();           // First new node...
@@ -564,8 +564,7 @@ DSNodeHandle DSGraph::cloneInto(const DSGraph &G,
     Nodes[i]->remapLinks(OldNodeMap);
 
   // Remove local markers as specified
-  unsigned char StripBits = (StripScalars ? DSNode::ScalarNode : 0) |
-                            (StripAllocas ? DSNode::AllocaNode : 0);
+  unsigned char StripBits = StripAllocas ? DSNode::AllocaNode : 0;
   if (StripBits)
     for (unsigned i = FN, e = Nodes.size(); i != e; ++i)
       Nodes[i]->NodeType &= ~StripBits;
@@ -574,7 +573,8 @@ DSNodeHandle DSGraph::cloneInto(const DSGraph &G,
   for (std::map<Value*, DSNodeHandle>::const_iterator I = G.ValueMap.begin(),
          E = G.ValueMap.end(); I != E; ++I) {
     DSNodeHandle &H = OldValMap[I->first];
-    H = DSNodeHandle(OldNodeMap[I->second.getNode()], I->second.getOffset());
+    H.setNode(OldNodeMap[I->second.getNode()]);
+    H.setOffset(I->second.getOffset());
 
     if (isa<GlobalValue>(I->first)) {  // Is this a global?
       std::map<Value*, DSNodeHandle>::iterator GVI = ValueMap.find(I->first);
@@ -655,11 +655,8 @@ void DSGraph::markIncompleteNodes(bool markFormalArgs) {
   // Mark any incoming arguments as incomplete...
   if (markFormalArgs && Func)
     for (Function::aiterator I = Func->abegin(), E = Func->aend(); I != E; ++I)
-      if (isPointerType(I->getType()) && ValueMap.find(I) != ValueMap.end()) {
-        DSNodeHandle &INH = ValueMap[I];
-        if (INH.getNode() && INH.hasLink(0))
-          markIncompleteNode(ValueMap[I].getLink(0)->getNode());
-      }
+      if (isPointerType(I->getType()) && ValueMap.find(I) != ValueMap.end())
+        markIncompleteNode(ValueMap[I].getNode());
 
   // Mark stuff passed into functions calls as being incomplete...
   for (unsigned i = 0, e = FunctionCalls.size(); i != e; ++i) {
@@ -667,17 +664,16 @@ void DSGraph::markIncompleteNodes(bool markFormalArgs) {
     // Then the return value is certainly incomplete!
     markIncompleteNode(Call.getRetVal().getNode());
 
-    // The call does not make the function argument incomplete...
-    // All arguments to the function call are incomplete though!
+    // All objects pointed to by function arguments are incomplete though!
     for (unsigned i = 0, e = Call.getNumPtrArgs(); i != e; ++i)
       markIncompleteNode(Call.getPtrArg(i).getNode());
   }
 
-  // Mark all of the nodes pointed to by global or cast nodes as incomplete...
+  // Mark all of the nodes pointed to by global nodes as incomplete...
   for (unsigned i = 0, e = Nodes.size(); i != e; ++i)
     if (Nodes[i]->NodeType & DSNode::GlobalNode) {
       DSNode *N = Nodes[i];
+      // FIXME: Make more efficient by looking over Links directly
       for (unsigned i = 0, e = N->getSize(); i != e; ++i)
         if (DSNodeHandle *DSNH = N->getLink(i))
           markIncompleteNode(DSNH->getNode());
@@ -706,9 +702,7 @@ bool DSGraph::isNodeDead(DSNode *N) {
     return true;
 
   // Is it a function node or some other trivially unused global?
-  if (N->NodeType != 0 &&
-      (N->NodeType & ~DSNode::GlobalNode) == 0 && 
-      N->getSize() == 0 &&
+  if ((N->NodeType & ~DSNode::GlobalNode) == 0 && N->getSize() == 0 &&
       N->getReferrers().size() == N->getGlobals().size()) {
 
     // Remove the globals from the ValueMap, so that the referrer count will go
@@ -758,6 +752,7 @@ static void markAlive(DSNode *N, std::set<DSNode*> &Alive) {
   if (N == 0) return;
 
   Alive.insert(N);
+  // FIXME: Make more efficient by looking over Links directly
   for (unsigned i = 0, e = N->getSize(); i != e; ++i)
     if (DSNodeHandle *DSNH = N->getLink(i))
       if (!Alive.count(DSNH->getNode()))
@@ -887,7 +882,7 @@ static void markGlobalsAlive(DSGraph &G, std::set<DSNode*> &Alive,
   markGlobalsIteration(GlobalNodes, Calls, Alive, FilterCalls);
 
   // Free up references to dead globals from the ValueMap
-  std::set<DSNode*>::iterator I=GlobalNodes.begin(), E=GlobalNodes.end();
+  std::set<DSNode*>::iterator I = GlobalNodes.begin(), E = GlobalNodes.end();
   for( ; I != E; ++I)
     if (Alive.count(*I) == 0)
       removeRefsToGlobal(*I, G.getValueMap());
@@ -931,20 +926,21 @@ void DSGraph::removeDeadNodes(bool KeepAllGlobals, bool KeepCalls) {
       markAlive(FunctionCalls[i].getCallee().getNode(), Alive);
     }
 
+  // Mark all nodes reachable by scalar nodes as alive...
+  for (std::map<Value*, DSNodeHandle>::iterator I = ValueMap.begin(),
+         E = ValueMap.end(); I != E; ++I)
+    markAlive(I->second.getNode(), Alive);
+
 #if 0
-  for (unsigned i = 0, e = OrigFunctionCalls.size(); i != e; ++i)
-    for (unsigned j = 0, e = OrigFunctionCalls[i].size(); j != e; ++j)
-      markAlive(OrigFunctionCalls[i][j].getNode(), Alive);
+  // Marge all nodes reachable by global nodes, as alive.  Isn't this covered by
+  // the ValueMap?
+  //
+  if (KeepAllGlobals)
+    for (unsigned i = 0, e = Nodes.size(); i != e; ++i)
+      if (Nodes[i]->NodeType & DSNode::GlobalNode)
+        markAlive(Nodes[i], Alive);
 #endif
 
-  // Mark all nodes reachable by scalar nodes (and global nodes, if
-  // keeping them was specified) as alive...
-  unsigned char keepBits = DSNode::ScalarNode |
-                           (KeepAllGlobals ? DSNode::GlobalNode : 0);
-  for (unsigned i = 0, e = Nodes.size(); i != e; ++i)
-    if (Nodes[i]->NodeType & keepBits)
-      markAlive(Nodes[i], Alive);
-
   // The return value is alive as well...
   markAlive(RetNode.getNode(), Alive);
 
@@ -952,7 +948,7 @@ void DSGraph::removeDeadNodes(bool KeepAllGlobals, bool KeepCalls) {
   // This also marks all nodes reachable from such nodes as alive.
   // Of course, if KeepAllGlobals is specified, they would be live already.
   if (!KeepAllGlobals)
-    markGlobalsAlive(*this, Alive, ! KeepCalls);
+    markGlobalsAlive(*this, Alive, !KeepCalls);
 
   // Loop over all unreachable nodes, dropping their references...
   vector<DSNode*> DeadNodes;
index dddd54ad4925ef9226e3a05d993b861a2f9da0d1..456eb2f3335e4ee620480efcec584f86aecced0c 100644 (file)
@@ -61,7 +61,6 @@ namespace {
     vector<DSNode*> &Nodes;
     DSNodeHandle &RetNode;               // Node that gets returned...
     map<Value*, DSNodeHandle> &ValueMap;
-    map<GlobalValue*, DSNodeHandle> GlobalScalarValueMap;
     vector<DSCallSite> &FunctionCalls;
 
   public:
@@ -107,23 +106,21 @@ namespace {
     /// createNode - Create a new DSNode, ensuring that it is properly added to
     /// the graph.
     ///
-    DSNode *createNode(DSNode::NodeTy NodeType, const Type *Ty);
-
-    /// getValueNode - Return a DSNode that corresponds the the specified LLVM
-    /// value.  This either returns the already existing node, or creates a new
-    /// one and adds it to the graph, if none exists.
-    ///
-    DSNodeHandle &getValueNode(Value &V);
+    DSNode *createNode(DSNode::NodeTy NodeType, const Type *Ty = 0) {
+      DSNode *N = new DSNode(NodeType, Ty);   // Create the node
+      Nodes.push_back(N);                     // Add node to nodes list
+      return N;
+    }
 
-    /// getValueDest - Return the DSNode that the actual value points to.  This
-    /// is the same thing as: getLink(getValueNode(V))
+    /// setDestTo - Set the ValueMap entry for the specified value to point to
+    /// the specified destination.  If the Value already points to a node, make
+    /// sure to merge the two destinations together.
     ///
-    DSNodeHandle &getValueDest(Value &V);
+    void setDestTo(Value &V, const DSNodeHandle &NH);
 
-    /// getGlobalNode - Just like getValueNode, except the global node itself is
-    /// returned, not a scalar node pointing to a global.
+    /// getValueDest - Return the DSNode that the actual value points to. 
     ///
-    DSNodeHandle &getGlobalNode(GlobalValue &V);
+    DSNodeHandle getValueDest(Value &V);
 
     /// getLink - This method is used to return the specified link in the
     /// specified node if one exists.  If a link does not already exist (it's
@@ -148,78 +145,34 @@ DSGraph::DSGraph(Function &F) : Func(&F) {
 //
 
 
-// createNode - Create a new DSNode, ensuring that it is properly added to the
-// graph.
-//
-DSNode *GraphBuilder::createNode(DSNode::NodeTy NodeType, const Type *Ty) {
-  DSNode *N = new DSNode(NodeType, Ty);
-  Nodes.push_back(N);
-  return N;
-}
+/// getValueDest - Return the DSNode that the actual value points to.
+///
+DSNodeHandle GraphBuilder::getValueDest(Value &V) {
+  if (Constant *C = dyn_cast<Constant>(&V)) {
+    // FIXME: Return null NH for constants like 10 or null
+    // FIXME: Handle constant exprs here.
 
+    return 0;   // Constant doesn't point to anything.
+  }
 
-// getGlobalNode - Just like getValueNode, except the global node itself is
-// returned, not a scalar node pointing to a global.
-//
-DSNodeHandle &GraphBuilder::getGlobalNode(GlobalValue &V) {
   DSNodeHandle &NH = ValueMap[&V];
-  if (NH.getNode()) return NH;       // Already have a node?  Just return it...
-
-  // Create a new global node for this global variable...
-  DSNode *G = createNode(DSNode::GlobalNode, V.getType()->getElementType());
-  G->addGlobal(&V);
-
-  // If this node has outgoing edges, make sure to recycle the same node for
-  // each use.  For functions and other global variables, this is unneccesary,
-  // so avoid excessive merging by cloning these nodes on demand.
-  //
-  NH.setNode(G);
-  return NH;
-}
-
-
-// getValueNode - Return a DSNode that corresponds the the specified LLVM value.
-// This either returns the already existing node, or creates a new one and adds
-// it to the graph, if none exists.
-//
-DSNodeHandle &GraphBuilder::getValueNode(Value &V) {
-  assert(isPointerType(V.getType()) && "Should only use pointer scalars!");
+  if (NH.getNode())
+    return NH;     // Already have a node?  Just return it...
 
+  // Otherwise we need to create a new node to point to...
+  DSNode *N;
   if (GlobalValue *GV = dyn_cast<GlobalValue>(&V)) {
-    // The GlobalScalarValueMap keeps track of the scalar nodes that point to
-    // global values...  The ValueMap contains pointers to the global memory
-    // object itself, not the scalar constant that points to the memory.
-    //
-    DSNodeHandle &NH = GlobalScalarValueMap[GV];
-    if (NH.getNode()) return NH;
-
-    // If this is a global value, create the global pointed to.
-    DSNode *N = createNode(DSNode::ScalarNode, V.getType());
-    NH.setOffset(0);
-    NH.setNode(N);
-
-    N->addEdgeTo(0, getGlobalNode(*GV));
-    return NH;
-    
+    // Create a new global node for this global variable...
+    N = createNode(DSNode::GlobalNode, GV->getType()->getElementType());
+    N->addGlobal(GV);
   } else {
-    DSNodeHandle &NH = ValueMap[&V];
-    if (NH.getNode())
-      return NH;     // Already have a node?  Just return it...
-  
-    // Otherwise we need to create a new scalar node...
-    DSNode *N = createNode(DSNode::ScalarNode, V.getType());
-
-    NH.setOffset(0);
-    NH.setNode(N);
-    return NH;
+    // Otherwise just create a shadow node
+    N = createNode(DSNode::ShadowNode);
   }
-}
 
-/// getValueDest - Return the DSNode that the actual value points to.  This is
-/// the same thing as: getLink(getValueNode(V), 0)
-///
-DSNodeHandle &GraphBuilder::getValueDest(Value &V) {
-  return getLink(getValueNode(V));
+  NH.setNode(N);      // Remember that we are pointing to it...
+  NH.setOffset(0);
+  return NH;
 }
 
 
@@ -235,12 +188,25 @@ DSNodeHandle &GraphBuilder::getLink(const DSNodeHandle &node, unsigned LinkNo) {
   if (Link) return *Link;
 
   // If the link hasn't been created yet, make and return a new shadow node
-  DSNode *N = createNode(DSNode::ShadowNode, 0);
+  DSNode *N = createNode(DSNode::ShadowNode);
   Node.setLink(LinkNo, N);
   return *Node.getLink(LinkNo);
 }
 
 
+/// setDestTo - Set the ValueMap entry for the specified value to point to the
+/// specified destination.  If the Value already points to a node, make sure to
+/// merge the two destinations together.
+///
+void GraphBuilder::setDestTo(Value &V, const DSNodeHandle &NH) {
+  DSNodeHandle &AINH = ValueMap[&V];
+  if (AINH.getNode() == 0)   // Not pointing to anything yet?
+    AINH = NH;               // Just point directly to NH
+  else
+    AINH.mergeWith(NH);
+}
+
+
 //===----------------------------------------------------------------------===//
 // Specific instruction type handler implementations...
 //
@@ -249,10 +215,7 @@ DSNodeHandle &GraphBuilder::getLink(const DSNodeHandle &node, unsigned LinkNo) {
 /// object, pointing the scalar to it.
 ///
 void GraphBuilder::handleAlloc(AllocationInst &AI, DSNode::NodeTy NodeType) {
-  DSNode *New = createNode(NodeType, 0);
-
-  // Make the scalar point to the new node...
-  getValueNode(AI).addEdgeTo(New);
+  setDestTo(AI, createNode(NodeType));
 }
 
 // PHINode - Make the scalar for the PHI node point to all of the things the
@@ -261,14 +224,14 @@ void GraphBuilder::handleAlloc(AllocationInst &AI, DSNode::NodeTy NodeType) {
 void GraphBuilder::visitPHINode(PHINode &PN) {
   if (!isPointerType(PN.getType())) return; // Only pointer PHIs
 
-  DSNodeHandle &ScalarDest = getValueDest(PN);
+  DSNodeHandle &PNDest = ValueMap[&PN];
   for (unsigned i = 0, e = PN.getNumIncomingValues(); i != e; ++i)
-    if (!isa<ConstantPointerNull>(PN.getIncomingValue(i)))
-      ScalarDest.mergeWith(getValueDest(*PN.getIncomingValue(i)));
+    PNDest.mergeWith(getValueDest(*PN.getIncomingValue(i)));
 }
 
 void GraphBuilder::visitGetElementPtrInst(GetElementPtrInst &GEP) {
   DSNodeHandle Value = getValueDest(*GEP.getOperand(0));
+  if (Value.getNode() == 0) return;
 
   unsigned Offset = 0;
   const PointerType *PTy = cast<PointerType>(GEP.getOperand(0)->getType());
@@ -278,7 +241,7 @@ void GraphBuilder::visitGetElementPtrInst(GetElementPtrInst &GEP) {
 
   // If the node had to be folded... exit quickly
   if (TopTypeRec.Ty == Type::VoidTy) {
-    getValueNode(GEP).addEdgeTo(Value);  // GEP result points to folded node
+    setDestTo(GEP, Value);  // GEP result points to folded node
     return;
   }
 
@@ -297,7 +260,7 @@ void GraphBuilder::visitGetElementPtrInst(GetElementPtrInst &GEP) {
       if (Value.getOffset()) {
         // Value is now the pointer we want to GEP to be...
         Value.getNode()->foldNodeCompletely();
-        getValueNode(GEP).addEdgeTo(Value);  // GEP result points to folded node
+        setDestTo(GEP, Value);  // GEP result points to folded node
         return;
       } else {
         // This is a pointer to the first byte of the node.  Make sure that we
@@ -346,56 +309,51 @@ void GraphBuilder::visitGetElementPtrInst(GetElementPtrInst &GEP) {
   Value.setOffset(Value.getOffset()+Offset);
 
   // Value is now the pointer we want to GEP to be...
-  getValueNode(GEP).addEdgeTo(Value);
+  setDestTo(GEP, Value);
 }
 
 void GraphBuilder::visitLoadInst(LoadInst &LI) {
-  DSNodeHandle &Ptr = getValueDest(*LI.getOperand(0));
+  DSNodeHandle Ptr = getValueDest(*LI.getOperand(0));
+  if (Ptr.getNode() == 0) return;
+
+  // Make that the node is read from...
   Ptr.getNode()->NodeType |= DSNode::Read;
 
   // Ensure a typerecord exists...
   Ptr.getNode()->getTypeRec(LI.getType(), Ptr.getOffset());
-  
+
   if (isPointerType(LI.getType()))
-    getValueNode(LI).addEdgeTo(getLink(Ptr));
+    setDestTo(LI, getLink(Ptr));
 }
 
 void GraphBuilder::visitStoreInst(StoreInst &SI) {
-  DSNodeHandle &Dest = getValueDest(*SI.getOperand(1));
-  Dest.getNode()->NodeType |= DSNode::Modified;
   const Type *StoredTy = SI.getOperand(0)->getType();
+  DSNodeHandle Dest = getValueDest(*SI.getOperand(1));
+  if (Dest.getNode() == 0) return;
+
+  // Make that the node is written to...
+  Dest.getNode()->NodeType |= DSNode::Modified;
 
   // Ensure a typerecord exists...
   Dest.getNode()->getTypeRec(StoredTy, Dest.getOffset());
 
   // Avoid adding edges from null, or processing non-"pointer" stores
-  if (isPointerType(StoredTy) &&
-      !isa<ConstantPointerNull>(SI.getOperand(0))) {
+  if (isPointerType(StoredTy))
     Dest.addEdgeTo(getValueDest(*SI.getOperand(0)));
-  }
 }
 
 void GraphBuilder::visitReturnInst(ReturnInst &RI) {
-  if (RI.getNumOperands() && isPointerType(RI.getOperand(0)->getType()) &&
-      !isa<ConstantPointerNull>(RI.getOperand(0))) {
-    DSNodeHandle &Value = getValueDest(*RI.getOperand(0));
-    Value.mergeWith(RetNode);
-    RetNode = Value;
-  }
+  if (RI.getNumOperands() && isPointerType(RI.getOperand(0)->getType()))
+    RetNode.mergeWith(getValueDest(*RI.getOperand(0)));
 }
 
 void GraphBuilder::visitCallInst(CallInst &CI) {
   // Set up the return value...
   DSNodeHandle RetVal;
   if (isPointerType(CI.getType()))
-    RetVal = getLink(getValueNode(CI));
+    RetVal = getValueDest(CI);
 
-  DSNodeHandle Callee;
-  // Special case for a direct call, avoid creating spurious scalar node...
-  if (GlobalValue *GV = dyn_cast<GlobalValue>(CI.getOperand(0)))
-    Callee = getGlobalNode(*GV);
-  else
-    Callee = getLink(getValueNode(*CI.getOperand(0)));
+  DSNodeHandle Callee = getValueDest(*CI.getOperand(0));
 
   std::vector<DSNodeHandle> Args;
   Args.reserve(CI.getNumOperands()-1);
@@ -403,7 +361,7 @@ void GraphBuilder::visitCallInst(CallInst &CI) {
   // Calculate the arguments vector...
   for (unsigned i = 1, e = CI.getNumOperands(); i != e; ++i)
     if (isPointerType(CI.getOperand(i)->getType()))
-      Args.push_back(getLink(getValueNode(*CI.getOperand(i))));
+      Args.push_back(getValueDest(*CI.getOperand(i)));
 
   // Add a new function call entry...
   FunctionCalls.push_back(DSCallSite(CI, RetVal, Callee, Args));
@@ -411,8 +369,12 @@ void GraphBuilder::visitCallInst(CallInst &CI) {
 
 /// Handle casts...
 void GraphBuilder::visitCastInst(CastInst &CI) {
-  if (isPointerType(CI.getType()) && isPointerType(CI.getOperand(0)->getType()))
-    getValueNode(CI).addEdgeTo(getLink(getValueNode(*CI.getOperand(0))));
+  if (isPointerType(CI.getType())) {
+    if (isPointerType(CI.getOperand(0)->getType()))
+      setDestTo(CI, getValueDest(*CI.getOperand(0)));
+    else
+      ; // FIXME: "Other" node
+  }
 }
 
 
index 35f491dd5cfefa118b12f9db71d41744405a2946..fd6006c2a5dbd5c474c81de285222955fb9fc886 100644 (file)
@@ -36,7 +36,6 @@ static string getCaption(const DSNode *N, const DSGraph *G) {
     OS << "\n";
   }
 
-  if (N->NodeType & DSNode::ScalarNode) OS << "S";
   if (N->NodeType & DSNode::AllocaNode) OS << "A";
   if (N->NodeType & DSNode::NewNode   ) OS << "N";
   if (N->NodeType & DSNode::GlobalNode) OS << "G";
@@ -49,15 +48,6 @@ static string getCaption(const DSNode *N, const DSGraph *G) {
     OS << "\n";
   }
 
-  if ((N->NodeType & DSNode::ScalarNode) && G) {
-    const std::map<Value*, DSNodeHandle> &VM = G->getValueMap();
-    for (std::map<Value*, DSNodeHandle>::const_iterator I = VM.begin(),
-           E = VM.end(); I != E; ++I)
-      if (I->second.getNode() == N) {
-        WriteAsOperand(OS, I->first, false, true, M);
-        OS << "\n";
-      }
-  }
   return OS.str();
 }
 
@@ -94,6 +84,23 @@ struct DOTGraphTraits<const DSGraph*> : public DefaultDOTGraphTraits {
   ///
   static void addCustomGraphFeatures(const DSGraph *G,
                                      GraphWriter<const DSGraph*> &GW) {
+    // Add scalar nodes to the graph...
+    const std::map<Value*, DSNodeHandle> &VM = G->getValueMap();
+    for (std::map<Value*, DSNodeHandle>::const_iterator I = VM.begin();
+         I != VM.end(); ++I)
+      if (!isa<GlobalValue>(I->first)) {
+        std::stringstream OS;
+        WriteAsOperand(OS, I->first, false, true, G->getFunction().getParent());
+        GW.emitSimpleNode(I->first, "plaintext=circle", OS.str());
+        
+        // Add edge from return node to real destination
+        int EdgeDest = I->second.getOffset();
+        if (EdgeDest == 0) EdgeDest = -1;
+        GW.emitEdge(I->first, -1, I->second.getNode(),
+                    EdgeDest, "arrowtail=tee,color=gray63");
+      }
+
+
     // Output the returned value pointer...
     if (G->getRetNode().getNode() != 0) {
       // Output the return node...