[llvm-commits] [poolalloc] r116902 - in /poolalloc/trunk: include/dsa/DSGraph.h lib/DSA/BottomUpClosure.cpp lib/DSA/DSGraph.cpp lib/DSA/Local.cpp lib/DSA/StdLibPass.cpp lib/DSA/TopDownClosure.cpp

Will Dietz wdietz2 at illinois.edu
Tue Oct 19 18:34:01 PDT 2010


Author: wdietz2
Date: Tue Oct 19 20:34:01 2010
New Revision: 116902

URL: http://llvm.org/viewvc/llvm-project?rev=116902&view=rev
Log:
Mark things External instead of Incomplete,
also handles a number of additional sources of external.

Modified:
    poolalloc/trunk/include/dsa/DSGraph.h
    poolalloc/trunk/lib/DSA/BottomUpClosure.cpp
    poolalloc/trunk/lib/DSA/DSGraph.cpp
    poolalloc/trunk/lib/DSA/Local.cpp
    poolalloc/trunk/lib/DSA/StdLibPass.cpp
    poolalloc/trunk/lib/DSA/TopDownClosure.cpp

Modified: poolalloc/trunk/include/dsa/DSGraph.h
URL: http://llvm.org/viewvc/llvm-project/poolalloc/trunk/include/dsa/DSGraph.h?rev=116902&r1=116901&r2=116902&view=diff
==============================================================================
--- poolalloc/trunk/include/dsa/DSGraph.h (original)
+++ poolalloc/trunk/include/dsa/DSGraph.h Tue Oct 19 20:34:01 2010
@@ -507,13 +507,14 @@
   };
   void markIncompleteNodes(unsigned Flags);
 
-  // recalculateExternalNodes - Clear the external flag on all nodes,
-  // then traverse the graph, identifying nodes that may be
-  // exposed to external code.  The sources of this happening are:
-  // --Arguments and return values for external functions
-  // --Arguments and return values for externally visible functions
-  // --Externally visible globals
-  void recalculateExternalNodes(void);
+  // Mark all reachable from external as external. 
+  enum ComputeExternalFlags {
+    MarkFormalsExternal = 1, DontMarkFormalsExternal = 0,
+    ProcessCallSites = 2, IgnoreCallSites = 0,
+    ResetExternal = 4, DontResetExternal = 0,
+    MarkGlobalsReachableFromFormals = 8, IgnoreGlobalsReachableFromFormals = 0
+  };
+  void computeExternalFlags(unsigned Flags);
 
   // removeDeadNodes - Use a reachability analysis to eliminate subgraphs that
   // are unreachable.  This often occurs because the data structure doesn't

Modified: poolalloc/trunk/lib/DSA/BottomUpClosure.cpp
URL: http://llvm.org/viewvc/llvm-project/poolalloc/trunk/lib/DSA/BottomUpClosure.cpp?rev=116902&r1=116901&r2=116902&view=diff
==============================================================================
--- poolalloc/trunk/lib/DSA/BottomUpClosure.cpp (original)
+++ poolalloc/trunk/lib/DSA/BottomUpClosure.cpp Tue Oct 19 20:34:01 2010
@@ -133,6 +133,7 @@
 
   // Mark external globals incomplete.
   GlobalsGraph->markIncompleteNodes(DSGraph::IgnoreGlobals);
+  GlobalsGraph->computeExternalFlags(DSGraph::DontMarkFormalsExternal);
 
   //
   // Create equivalence classes for aliasing globals so that we only need to
@@ -151,7 +152,7 @@
       Graph->maskIncompleteMarkers();
       Graph->markIncompleteNodes(DSGraph::MarkFormalArgs |
                                    DSGraph::IgnoreGlobals);
-      
+      Graph->computeExternalFlags(DSGraph::DontMarkFormalsExternal);
     }
   }
 
@@ -163,7 +164,7 @@
   //
   callgraph.buildSCCs();
   callgraph.buildRoots();
-  
+
   return false;
 }
 
@@ -746,7 +747,7 @@
         std::sort(NodeCallees.begin(), NodeCallees.end());
         eraseCS = std::includes(CalledFuncs.begin(), CalledFuncs.end(),
                                 NodeCallees.begin(), NodeCallees.end());
-      } 
+      }
 
       //
       // Update the statistics on resolved indirect function calls.
@@ -794,7 +795,7 @@
   // Recompute the Incomplete markers
   Graph->maskIncompleteMarkers();
   Graph->markIncompleteNodes(DSGraph::MarkFormalArgs);
-
+  Graph->computeExternalFlags(DSGraph::DontMarkFormalsExternal);
   
   //
   // Update the callgraph with the new information that we have gleaned.

Modified: poolalloc/trunk/lib/DSA/DSGraph.cpp
URL: http://llvm.org/viewvc/llvm-project/poolalloc/trunk/lib/DSA/DSGraph.cpp?rev=116902&r1=116901&r2=116902&view=diff
==============================================================================
--- poolalloc/trunk/lib/DSA/DSGraph.cpp (original)
+++ poolalloc/trunk/lib/DSA/DSGraph.cpp Tue Oct 19 20:34:01 2010
@@ -648,18 +648,6 @@
            E = AuxFunctionCalls.end(); I != E; ++I)
       markIncomplete(*I);
 
-  // Mark stuff passed into external functions as being incomplete.
-  // External functions may not appear in Aux during td, so process
-  // them specially
-#if 0
-  for (std::list<DSCallSite>::iterator I = FunctionCalls.begin(),
-         E = FunctionCalls.end(); I != E; ++I)
-    if(I->isDirectCall() && I->getCalleeFunc()->isDeclaration())
-      markIncomplete(*I);
-#endif
-  // Handle all sources of external
-  recalculateExternalNodes();
-
   // Mark all global nodes as incomplete.
   for (DSScalarMap::global_iterator I = ScalarMap.global_begin(),
          E = ScalarMap.global_end(); I != E; ++I)
@@ -676,104 +664,182 @@
   }
 }
 
-static void markExternalNode(DSNode *N) {
-  // Stop recursion if no node, or if node already marked...
-  if (N == 0 || N->isExternalNode()) return;
+// markExternalNode -- Marks the specified node, and all that's reachable from it,
+// as external.  Uses 'processedNodes' to track recursion.
+static void markExternalNode(DSNode *N, svset<DSNode *> & processedNodes) {
+  // Stop recursion if no node, or if node already processed
+  if (N == 0 || processedNodes.count(N) ) return;
+
+  processedNodes.insert(N);
 
   // Actually mark the node
   N->setExternalMarker();
-
-  // External also means incomplete
-  N->setIncompleteMarker();
   
   // FIXME: Should we 'collapse' the node as well?
 
   // Recursively process children...
   for (DSNode::edge_iterator ii = N->edge_begin(), ee = N->edge_end();
        ii != ee; ++ii)
-    markExternalNode(ii->second.getNode());
+    markExternalNode(ii->second.getNode(), processedNodes);
 }
 
-static void markExternal(DSCallSite &Call) {
-  markExternalNode(Call.getRetVal().getNode());
+// markExternal --marks the specified callsite external, using 'processedNodes' to track recursion.
+// Additionally, we set the externFuncMarker as appropriate.
+static void markExternal(const DSCallSite &Call, svset<DSNode *> & processedNodes) {
+  markExternalNode(Call.getRetVal().getNode(), processedNodes);
 
-  markExternalNode(Call.getVAVal().getNode());
+  markExternalNode(Call.getVAVal().getNode(), processedNodes);
 
-  // All objects pointed to by function arguments are incomplete!
+  // Mark all pointer arguments...
   for (unsigned i = 0, e = Call.getNumPtrArgs(); i != e; ++i)
-    markExternalNode(Call.getPtrArg(i).getNode());
+    markExternalNode(Call.getPtrArg(i).getNode(), processedNodes);
+
+  // Set the flag indicating this fptr contains external functions.
+  // FIXME: As far as I can tell, we don't actually set this anywhere else,
+  // and I haven't given much thought to where it's appropriate to do so.
+  // For now, setting it because it's not wrong and clearly a step forward
+  // but want to make it clear that I don't claim that this is now set
+  // properly everywhere the way it should.
+  if (Call.isIndirectCall()) {
+    Call.getCalleeNode()->setExternFuncMarker();
+  }
 }
 
-// recalculateExternalNodes - Clear the external flag on all nodes,
-// then traverse the graph, identifying nodes that may be
-// exposed to external code.  The sources of this happening are:
-// --Arguments and return values for external functions
-// --Arguments and return values for externally visible functions
-// --Externally visible globals
-void DSGraph::recalculateExternalNodes() {
-
-  // Clear the external flag (we use it as marker for recursion)
-  maskNodeTypes(~DSNode::ExternalNode);
-
-  // Process all CallSites that call functions influenced by external code
-  for (std::list<DSCallSite>::iterator I = FunctionCalls.begin(),
-         E = FunctionCalls.end(); I != E; ++I) {
-    bool shouldBeMarkedExternal = false;
-
-    // Figure out what this callsite calls...
-    std::vector<const Function *> Functions;
-    if (I->isDirectCall())
-      Functions.push_back(I->getCalleeFunc());
-    else
-      I->getCalleeNode()->addFullFunctionList(Functions);
+// propagateExternal -- Walk the given DSGraph making sure that within this graph
+// everything reachable from an already-external node is also marked External.
+static void propagateExternal(DSGraph * G, svset<DSNode *> & processedNodes) {
+  DSGraph::node_iterator I = G->node_begin(),
+                         E = G->node_end();
+  for ( ; I != E; ++I ) {
+    if (I->isExternalNode())
+      markExternalNode(&*I, processedNodes);
+  }
+}
 
-    // ...And examine each callee:
-    for (std::vector<const Function *>::iterator II = Functions.begin(),
-                                            EE = Functions.end();
-          (II != EE) && !shouldBeMarkedExternal; ++II) {
+// computeExternalFlags -- mark all reachable from external as external
+void DSGraph::computeExternalFlags(unsigned Flags) {
 
-      // Calls to external functions should be marked external
-      shouldBeMarkedExternal |= (*II)->isDeclaration();
-      // Calls to code that is externally visible should be marked
-      // external.  This might be overkill due to unification and the
-      // various passes propagating this information,
-      // but for now we /ensure/ the flags are set correctly.
-      shouldBeMarkedExternal |= !(*II)->hasInternalLinkage();
-    }
-
-    if (shouldBeMarkedExternal) {
-      markExternal(*I);
+  svset<DSNode *> processedNodes;
+
+  // Reset if indicated
+  if (Flags & ResetExternal) {
+    maskNodeTypes(~DSNode::ExternalNode);
+  }
+
+  if (Flags & MarkGlobalsReachableFromFormals) {
+    DenseSet<const DSNode*> ReachableFromFormals;
+    for (ReturnNodesTy::iterator FI = ReturnNodes.begin(), E = ReturnNodes.end();
+        FI != E; ++FI) {
+      const Function &F = *FI->first;
+      // Find all reachable from arguments...
+      for (Function::const_arg_iterator I = F.arg_begin(), E = F.arg_end();
+          I != E; ++I)
+        if (isa<PointerType>(I->getType())) {
+          DSNode * N = getNodeForValue(I).getNode();
+          if (N) N->markReachableNodes(ReachableFromFormals);
+        }
+      // ...and the return value...
+      if (!FI->second.isNull())
+        FI->second.getNode()->markReachableNodes(ReachableFromFormals);
+      if (!getVANodeFor(F).isNull())
+        getVANodeFor(F).getNode()->markReachableNodes(ReachableFromFormals);
+    }
+
+    DenseSet<const DSNode*> ReachableFromGlobals;
+
+    for (DSScalarMap::global_iterator I = ScalarMap.global_begin(),
+        E = ScalarMap.global_end(); I != E; ++I) {
+      DSNode * N = getNodeForValue(*I).getNode();
+      if (N) N->markReachableNodes(ReachableFromGlobals);
+    }
+
+    // Find intersection of the two...
+    // FIXME: This works fine for local, but what about in other places where we might newly
+    // discover that something reachable from an externally visible function's argument is
+    // also reachable from a global and as such should be marked external in all graphs
+    // that use it?
+    for (DenseSet<const DSNode*>::iterator I = ReachableFromFormals.begin(),
+         E = ReachableFromFormals.end(); I != E; ++I) {
+      DSNode * N = (DSNode *)*I;
+      if (ReachableFromGlobals.count(N)) {
+        // Reachable from both a global and the formals, mark external!
+        markExternalNode(N, processedNodes);
+      }
     }
   }
 
-  // Additionally, look at each *function* that is external-related
-  // and set the External flag for its arguments and return value.
-  for (ReturnNodesTy::iterator FI = ReturnNodes.begin(), E =ReturnNodes.end();
-      FI != E; ++FI) {
-    const Function &F = *FI->first;
-    // If this function is potentially influenced by external code...
-    if (!F.hasInternalLinkage() || F.isDeclaration()) {
+  // Make sure that everything reachable from something already external is also external
+  propagateExternal(this, processedNodes);
+
+  // If requested, we mark all functions (their formals) in this
+  // graph (read: SCC) as external.
+  if (Flags & MarkFormalsExternal) {
+    for (ReturnNodesTy::iterator FI = ReturnNodes.begin(), E =ReturnNodes.end();
+        FI != E; ++FI) {
+      const Function &F = *FI->first;
       // Mark its arguments, return value (and vanode) as external.
       for (Function::const_arg_iterator I = F.arg_begin(), E = F.arg_end();
           I != E; ++I)
         if (isa<PointerType>(I->getType()))
-          markExternalNode(getNodeForValue(I).getNode());
-      markExternalNode(FI->second.getNode());
-      markExternalNode(getVANodeFor(F).getNode());
+          markExternalNode(getNodeForValue(I).getNode(), processedNodes);
+      markExternalNode(FI->second.getNode(), processedNodes);
+      markExternalNode(getVANodeFor(F).getNode(), processedNodes);
+    }
+  }
+
+  // If requested, look for callsites to external functions and make
+  // sure that they're marked external as appropriate.
+  if (Flags & ProcessCallSites) {
+    // Get List of all callsites, resolved or not...
+    std::list<DSCallSite> AllCalls;
+    AllCalls.insert(AllCalls.begin(), fc_begin(), fc_end());
+    AllCalls.insert(AllCalls.begin(), afc_begin(), afc_end());
+
+    // ...and use that list to find all CallSites that call external functions
+    // and mark them accordingly.
+    for (std::list<DSCallSite>::iterator I = AllCalls.begin(),
+        E = AllCalls.end(); I != E; ++I) {
+      bool shouldBeMarkedExternal = false;
+
+      // Figure out what this callsite calls...
+      std::vector<const Function *> Functions;
+      if (I->isDirectCall())
+        Functions.push_back(I->getCalleeFunc());
+      else
+        I->getCalleeNode()->addFullFunctionList(Functions);
+
+      // ...And examine each callee:
+      for (std::vector<const Function *>::iterator II = Functions.begin(),
+          EE = Functions.end();
+          (II != EE) && !shouldBeMarkedExternal; ++II) {
+
+        // Calls to external functions should be marked external
+        shouldBeMarkedExternal |= (*II)->isDeclaration();
+      }
+
+      // If this callsite can call external code, it better be the case that the pointer arguments
+      // and the return values are all marked external (and what's reachable from them)
+      if (shouldBeMarkedExternal) {
+        markExternal(*I, processedNodes);
+      }
     }
   }
 
-  // Now handle all external globals...
+  // Finally handle all external globals...
   for (DSScalarMap::global_iterator I = ScalarMap.global_begin(),
-         E = ScalarMap.global_end(); I != E; ++I)
+      E = ScalarMap.global_end(); I != E; ++I)
     if (const GlobalVariable *GV = dyn_cast<GlobalVariable>(*I)) {
       // If the global is external... mark it as such!
       // FIXME: It's unclear to me that a global we initialize
-      // can't be externally visible.  For now preserving original
-      // behavior (and additionally marking external as well as incomplete).
-      if (!GV->hasInitializer())
-        markExternalNode(ScalarMap[GV].getNode());
+      // can't be externally visible.  For now following original
+      // behavior and marking external.
+      DSNode * N = ScalarMap[GV].getNode();
+      if (!GV->hasInitializer() || N->isExternalNode())
+        markExternalNode(N, processedNodes);
     }
+
+  // FIXME: Sync with globals graph?
+  // For now, trust the caller to do this as appropriate.
 }
 
 static inline void killIfUselessEdge(DSNodeHandle &Edge) {

Modified: poolalloc/trunk/lib/DSA/Local.cpp
URL: http://llvm.org/viewvc/llvm-project/poolalloc/trunk/lib/DSA/Local.cpp?rev=116902&r1=116901&r2=116902&view=diff
==============================================================================
--- poolalloc/trunk/lib/DSA/Local.cpp (original)
+++ poolalloc/trunk/lib/DSA/Local.cpp Tue Oct 19 20:34:01 2010
@@ -159,10 +159,18 @@
       for (Function::arg_iterator I = f.arg_begin(), E = f.arg_end();
            I != E; ++I) {
         if (isa<PointerType>(I->getType())) {
+          // WD: Why do we set the external marker so early in the analysis?
+          // Functions we have definitions for, but are externally reachable have no external contexts
+          // that we'd want to BU external information into (since those contexts are by definition
+          // ones we don't have code for).  Shouldn't this just be set in TD?
+#if 0
           DSNode * Node = getValueDest(I).getNode();
 
           if (!f.hasInternalLinkage())
             Node->setExternalMarker();
+#else
+          getValueDest(I).getNode();
+#endif
 
         }
       }
@@ -194,7 +202,19 @@
       }
 
       g.markIncompleteNodes(DSGraph::MarkFormalArgs);
-      
+
+      // Compute sources of external
+      unsigned EFlags = 0
+        | DSGraph::DontMarkFormalsExternal
+        | DSGraph::ProcessCallSites;
+      // Mark globals reachable from formals as external if we don't have
+      // internal linkage.
+      if (!f.hasInternalLinkage()) {
+        EFlags |= DSGraph::MarkGlobalsReachableFromFormals;
+      }
+
+      g.computeExternalFlags(EFlags);
+
       // Remove any nodes made dead due to merging...
       g.removeDeadNodes(DSGraph::KeepUnreachableGlobals);
     }
@@ -1236,6 +1256,7 @@
 
   GlobalsGraph->removeTriviallyDeadNodes();
   GlobalsGraph->markIncompleteNodes(DSGraph::MarkFormalArgs);
+  GlobalsGraph->computeExternalFlags(DSGraph::ProcessCallSites);
 
   // Now that we've computed all of the graphs, and merged all of the info into
   // the globals graph, see if we have further constrained the globals in the

Modified: poolalloc/trunk/lib/DSA/StdLibPass.cpp
URL: http://llvm.org/viewvc/llvm-project/poolalloc/trunk/lib/DSA/StdLibPass.cpp?rev=116902&r1=116901&r2=116902&view=diff
==============================================================================
--- poolalloc/trunk/lib/DSA/StdLibPass.cpp (original)
+++ poolalloc/trunk/lib/DSA/StdLibPass.cpp Tue Oct 19 20:34:01 2010
@@ -388,7 +388,7 @@
         //
         eraseCallsTo(F);
       }
-  
+
   //
   // Merge return values and checked pointer values for SAFECode run-time
   // checks.
@@ -397,5 +397,22 @@
   processRuntimeCheck (M, "sc.boundscheckui");
   processRuntimeCheck (M, "sc.exactcheck2");
 
+  // In Local we marked nodes passed to/returned from 'StdLib' functions as External, because at
+  // that point they were.  However they no longer are necessarily so, and we need to update accordingly.
+  GlobalsGraph->computeExternalFlags(DSGraph::ResetExternal);
+  for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I)
+    if (!I->isDeclaration()) {
+      DSGraph * G = getDSGraph(*I);
+      unsigned EFlags = 0
+        | DSGraph::ResetExternal
+        | DSGraph::DontMarkFormalsExternal
+        | DSGraph::ProcessCallSites;
+      if (!I->hasInternalLinkage()) {
+        EFlags |= DSGraph::MarkGlobalsReachableFromFormals;
+      }
+      G->computeExternalFlags(EFlags);
+    }
+  GlobalsGraph->computeExternalFlags(DSGraph::ProcessCallSites);
+
   return false;
 }

Modified: poolalloc/trunk/lib/DSA/TopDownClosure.cpp
URL: http://llvm.org/viewvc/llvm-project/poolalloc/trunk/lib/DSA/TopDownClosure.cpp?rev=116902&r1=116901&r2=116902&view=diff
==============================================================================
--- poolalloc/trunk/lib/DSA/TopDownClosure.cpp (original)
+++ poolalloc/trunk/lib/DSA/TopDownClosure.cpp Tue Oct 19 20:34:01 2010
@@ -89,7 +89,8 @@
   for (DSScalarMap::global_iterator I=GGSM.global_begin(), E=GGSM.global_end();
        I != E; ++I) {
     DSNode *N = GGSM.find(*I)->second.getNode();
-    if (N->isIncompleteNode())
+    if (N->isIncompleteNode()) assert(N->isExternalNode());
+    if (N->isIncompleteNode() || N->isExternalNode())
       markReachableFunctionsExternallyAccessible(N, Visited);
   }
 
@@ -150,6 +151,7 @@
 
   ArgsRemainIncomplete.clear();
   GlobalsGraph->removeTriviallyDeadNodes();
+  GlobalsGraph->computeExternalFlags(DSGraph::DontMarkFormalsExternal);
 
   // CBU contains the correct call graph.
   // Restore it, so that subsequent passes and clients can get it.
@@ -274,10 +276,16 @@
     }
 
   // Recompute the Incomplete markers.  Depends on whether args are complete
-  unsigned Flags
-    = HasIncompleteArgs ? DSGraph::MarkFormalArgs : DSGraph::IgnoreFormalArgs;
-  Flags |= DSGraph::IgnoreGlobals | DSGraph::MarkVAStart;
-  DSG->markIncompleteNodes(Flags);
+  unsigned IncFlags = DSGraph::IgnoreFormalArgs;
+  IncFlags |= DSGraph::IgnoreGlobals | DSGraph::MarkVAStart;
+  DSG->markIncompleteNodes(IncFlags);
+
+  // If this graph contains functions that are externally callable, now is the time to mark
+  // their arguments and return values as external.  At this point TD is inlining all caller information,
+  // and that means External callers too.
+  unsigned ExtFlags
+    = HasIncompleteArgs ? DSGraph::MarkFormalsExternal : DSGraph::DontMarkFormalsExternal;
+  DSG->computeExternalFlags(ExtFlags);
 
   //
   // Delete dead nodes.  Treat globals that are unreachable as dead also.





More information about the llvm-commits mailing list