[llvm-commits] CVS: llvm/lib/Analysis/DataStructure/BottomUpClosure.cpp DataStructure.cpp DataStructureStats.cpp Local.cpp Printer.cpp Steensgaard.cpp TopDownClosure.cpp

Chris Lattner lattner at cs.uiuc.edu
Wed Feb 5 16:01:01 PST 2003


Changes in directory llvm/lib/Analysis/DataStructure:

BottomUpClosure.cpp updated: 1.51 -> 1.52
DataStructure.cpp updated: 1.86 -> 1.87
DataStructureStats.cpp updated: 1.2 -> 1.3
Local.cpp updated: 1.46 -> 1.47
Printer.cpp updated: 1.46 -> 1.47
Steensgaard.cpp updated: 1.19 -> 1.20
TopDownClosure.cpp updated: 1.35 -> 1.36

---
Log message:

Implement optimization for direct function call case.  This dramatically
reduces the number of function nodes created and speeds up analysis by
about 10% overall.


---
Diffs of the changes:

Index: llvm/lib/Analysis/DataStructure/BottomUpClosure.cpp
diff -u llvm/lib/Analysis/DataStructure/BottomUpClosure.cpp:1.51 llvm/lib/Analysis/DataStructure/BottomUpClosure.cpp:1.52
--- llvm/lib/Analysis/DataStructure/BottomUpClosure.cpp:1.51	Mon Feb  3 13:11:38 2003
+++ llvm/lib/Analysis/DataStructure/BottomUpClosure.cpp	Wed Feb  5 15:59:56 2003
@@ -22,6 +22,13 @@
 
 using namespace DS;
 
+static bool isVAHackFn(const Function *F) {
+  return F->getName() == "printf"  || F->getName() == "sscanf" ||
+         F->getName() == "fprintf" || F->getName() == "open" ||
+         F->getName() == "sprintf" || F->getName() == "fputs" ||
+         F->getName() == "fscanf";
+}
+
 // isCompleteNode - Return true if we know all of the targets of this node, and
 // if the call sites are not external.
 //
@@ -29,14 +36,9 @@
   if (N->NodeType & DSNode::Incomplete) return false;
   const std::vector<GlobalValue*> &Callees = N->getGlobals();
   for (unsigned i = 0, e = Callees.size(); i != e; ++i)
-    if (Callees[i]->isExternal()) {
-      GlobalValue &FI = cast<Function>(*Callees[i]);
-      if (FI.getName() != "printf"  && FI.getName() != "sscanf" &&
-          FI.getName() != "fprintf" && FI.getName() != "open" &&
-          FI.getName() != "sprintf" && FI.getName() != "fputs" &&
-          FI.getName() != "fscanf")
+    if (Callees[i]->isExternal())
+      if (!isVAHackFn(cast<Function>(Callees[i])))
         return false;  // External function found...
-    }
   return true;  // otherwise ok
 }
 
@@ -48,7 +50,7 @@
 
   CallSiteIterator(std::vector<DSCallSite> &CS) : FCs(&CS) {
     CallSite = 0; CallSiteEntry = 0;
-    advanceToNextValid();
+    advanceToValidCallee();
   }
 
   // End iterator ctor...
@@ -56,18 +58,24 @@
     CallSite = FCs->size(); CallSiteEntry = 0;
   }
 
-  void advanceToNextValid() {
+  void advanceToValidCallee() {
     while (CallSite < FCs->size()) {
-      if (DSNode *CalleeNode = (*FCs)[CallSite].getCallee().getNode()) {
+      if ((*FCs)[CallSite].isDirectCall()) {
+        if (CallSiteEntry == 0 &&        // direct call only has one target...
+            (!(*FCs)[CallSite].getCalleeFunc()->isExternal() ||
+             isVAHackFn((*FCs)[CallSite].getCalleeFunc()))) // If not external
+          return;
+      } else {
+        DSNode *CalleeNode = (*FCs)[CallSite].getCalleeNode();
         if (CallSiteEntry || isCompleteNode(CalleeNode)) {
           const std::vector<GlobalValue*> &Callees = CalleeNode->getGlobals();
           
           if (CallSiteEntry < Callees.size())
             return;
         }
-        CallSiteEntry = 0;
-        ++CallSite;
       }
+      CallSiteEntry = 0;
+      ++CallSite;
     }
   }
 public:
@@ -87,14 +95,18 @@
   unsigned getCallSiteIdx() const { return CallSite; }
   DSCallSite &getCallSite() const { return (*FCs)[CallSite]; }
 
-  Function* operator*() const {
-    DSNode *Node = (*FCs)[CallSite].getCallee().getNode();
-    return cast<Function>(Node->getGlobals()[CallSiteEntry]);
+  Function *operator*() const {
+    if ((*FCs)[CallSite].isDirectCall()) {
+      return (*FCs)[CallSite].getCalleeFunc();
+    } else {
+      DSNode *Node = (*FCs)[CallSite].getCalleeNode();
+      return cast<Function>(Node->getGlobals()[CallSiteEntry]);
+    }
   }
 
   CallSiteIterator& operator++() {                // Preincrement
     ++CallSiteEntry;
-    advanceToNextValid();
+    advanceToValidCallee();
     return *this;
   }
   CallSiteIterator operator++(int) { // Postincrement


Index: llvm/lib/Analysis/DataStructure/DataStructure.cpp
diff -u llvm/lib/Analysis/DataStructure/DataStructure.cpp:1.86 llvm/lib/Analysis/DataStructure/DataStructure.cpp:1.87
--- llvm/lib/Analysis/DataStructure/DataStructure.cpp:1.86	Mon Feb  3 18:03:04 2003
+++ llvm/lib/Analysis/DataStructure/DataStructure.cpp	Wed Feb  5 15:59:56 2003
@@ -799,7 +799,8 @@
   std::sort(Calls.begin(), Calls.end());  // Sort by callee as primary key!
 
   // Scan the call list cleaning it up as necessary...
-  DSNode *LastCalleeNode = 0;
+  DSNode   *LastCalleeNode = 0;
+  Function *LastCalleeFunc = 0;
   unsigned NumDuplicateCalls = 0;
   bool LastCalleeContainsExternalFunction = false;
   for (unsigned i = 0; i != Calls.size(); ++i) {
@@ -807,8 +808,9 @@
 
     // If the Callee is a useless edge, this must be an unreachable call site,
     // eliminate it.
-    killIfUselessEdge(CS.getCallee());
-    if (CS.getCallee().getNode() == 0) {
+    if (CS.isIndirectCall() && CS.getCalleeNode()->getReferrers().size() == 1 &&
+        CS.getCalleeNode()->NodeType == 0) {  // No useful info?
+      std::cerr << "WARNING: Useless call site found??\n";
       CS.swap(Calls.back());
       Calls.pop_back();
       --i;
@@ -826,11 +828,15 @@
       // never be resolved.  Merge the arguments of the call node because no
       // information will be lost.
       //
-      if (CS.getCallee().getNode() == LastCalleeNode) {
+      if ((CS.isDirectCall()   && CS.getCalleeFunc() == LastCalleeFunc) ||
+          (CS.isIndirectCall() && CS.getCalleeNode() == LastCalleeNode)) {
         ++NumDuplicateCalls;
         if (NumDuplicateCalls == 1) {
-          LastCalleeContainsExternalFunction =
-            nodeContainsExternalFunction(LastCalleeNode);
+          if (LastCalleeNode)
+            LastCalleeContainsExternalFunction =
+              nodeContainsExternalFunction(LastCalleeNode);
+          else
+            LastCalleeContainsExternalFunction = LastCalleeFunc->isExternal();
         }
         
         if (LastCalleeContainsExternalFunction ||
@@ -847,7 +853,13 @@
             OCS = CS;
         }
       } else {
-        LastCalleeNode = CS.getCallee().getNode();
+        if (CS.isDirectCall()) {
+          LastCalleeFunc = CS.getCalleeFunc();
+          LastCalleeNode = 0;
+        } else {
+          LastCalleeNode = CS.getCalleeNode();
+          LastCalleeFunc = 0;
+        }
         NumDuplicateCalls = 0;
       }
     }
@@ -877,7 +889,7 @@
   for (unsigned i = 0; i != Nodes.size(); ++i) {
     DSNode *Node = Nodes[i];
     if (!(Node->NodeType & ~(DSNode::Composition | DSNode::Array |
-                                 DSNode::DEAD))) {
+                             DSNode::DEAD))) {
       // This is a useless node if it has no mod/ref info (checked above),
       // outgoing edges (which it cannot, as it is not modified in this
       // context), and it has no incoming edges.  If it is a global node it may
@@ -918,7 +930,7 @@
 
 void DSCallSite::markReachableNodes(hash_set<DSNode*> &Nodes) {
   getRetVal().getNode()->markReachableNodes(Nodes);
-  getCallee().getNode()->markReachableNodes(Nodes);
+  if (isIndirectCall()) getCalleeNode()->markReachableNodes(Nodes);
   
   for (unsigned i = 0, e = getNumPtrArgs(); i != e; ++i)
     getPtrArg(i).getNode()->markReachableNodes(Nodes);
@@ -954,8 +966,10 @@
 //
 static bool CallSiteUsesAliveArgs(DSCallSite &CS, hash_set<DSNode*> &Alive,
                                   hash_set<DSNode*> &Visited) {
-  if (CanReachAliveNodes(CS.getRetVal().getNode(), Alive, Visited) ||
-      CanReachAliveNodes(CS.getCallee().getNode(), Alive, Visited))
+  if (CanReachAliveNodes(CS.getRetVal().getNode(), Alive, Visited))
+    return true;
+  if (CS.isIndirectCall() &&
+      CanReachAliveNodes(CS.getCalleeNode(), Alive, Visited))
     return true;
   for (unsigned i = 0, e = CS.getNumPtrArgs(); i != e; ++i)
     if (CanReachAliveNodes(CS.getPtrArg(i).getNode(), Alive, Visited))


Index: llvm/lib/Analysis/DataStructure/DataStructureStats.cpp
diff -u llvm/lib/Analysis/DataStructure/DataStructureStats.cpp:1.2 llvm/lib/Analysis/DataStructure/DataStructureStats.cpp:1.3
--- llvm/lib/Analysis/DataStructure/DataStructureStats.cpp:1.2	Sun Nov 17 16:17:12 2002
+++ llvm/lib/Analysis/DataStructure/DataStructureStats.cpp	Wed Feb  5 15:59:56 2003
@@ -48,9 +48,7 @@
 }
 
 
-void DSGraphStats::countCallees(const Function& F,
-                                const DSGraph& tdGraph)
-{
+void DSGraphStats::countCallees(const Function& F, const DSGraph& tdGraph) {
   unsigned numIndirectCalls = 0, totalNumCallees = 0;
 
   const std::vector<DSCallSite>& callSites = tdGraph.getFunctionCalls();
@@ -58,12 +56,11 @@
     if (isIndirectCallee(callSites[i].getCallInst().getCalledValue()))
       { // This is an indirect function call
         std::vector<GlobalValue*> Callees =
-          callSites[i].getCallee().getNode()->getGlobals();
-        if (Callees.size() > 0)
-          {
-            totalNumCallees  += Callees.size();
-            ++numIndirectCalls;
-          }
+          callSites[i].getCalleeNode()->getGlobals();
+        if (Callees.size() > 0) {
+          totalNumCallees  += Callees.size();
+          ++numIndirectCalls;
+        }
 #ifndef NDEBUG
         else
           std::cerr << "WARNING: No callee in Function " << F.getName()
@@ -81,8 +78,7 @@
 }
 
 
-bool DSGraphStats::runOnFunction(Function& F)
-{
+bool DSGraphStats::runOnFunction(Function& F) {
   const DSGraph& tdGraph = getAnalysis<TDDataStructures>().getDSGraph(F);
   countCallees(F, tdGraph);
   return true;


Index: llvm/lib/Analysis/DataStructure/Local.cpp
diff -u llvm/lib/Analysis/DataStructure/Local.cpp:1.46 llvm/lib/Analysis/DataStructure/Local.cpp:1.47
--- llvm/lib/Analysis/DataStructure/Local.cpp:1.46	Mon Feb  3 18:59:50 2003
+++ llvm/lib/Analysis/DataStructure/Local.cpp	Wed Feb  5 15:59:56 2003
@@ -19,6 +19,7 @@
 #include "llvm/Target/TargetData.h"
 #include "Support/Statistic.h"
 #include "Support/Timer.h"
+#include "Support/CommandLine.h"
 
 // FIXME: This should eventually be a FunctionPass that is automatically
 // aggregated into a Pass.
@@ -45,6 +46,11 @@
 
 
 namespace {
+  cl::opt<bool>
+  DisableDirectCallOpt("disable-direct-call-dsopt", cl::Hidden,
+                       cl::desc("Disable direct call optimization in "
+                                "DSGraph construction"));
+
   //===--------------------------------------------------------------------===//
   //  GraphBuilder Class
   //===--------------------------------------------------------------------===//
@@ -375,7 +381,9 @@
   if (isPointerType(CI.getType()))
     RetVal = getValueDest(CI);
 
-  DSNodeHandle Callee = getValueDest(*CI.getOperand(0));
+  DSNode *Callee = 0;
+  if (DisableDirectCallOpt || !isa<Function>(CI.getOperand(0)))
+    Callee = getValueDest(*CI.getOperand(0)).getNode();
 
   std::vector<DSNodeHandle> Args;
   Args.reserve(CI.getNumOperands()-1);
@@ -386,7 +394,11 @@
       Args.push_back(getValueDest(*CI.getOperand(i)));
 
   // Add a new function call entry...
-  FunctionCalls.push_back(DSCallSite(CI, RetVal, Callee, Args));
+  if (Callee)
+    FunctionCalls.push_back(DSCallSite(CI, RetVal, Callee, Args));
+  else
+    FunctionCalls.push_back(DSCallSite(CI, RetVal,
+                                       cast<Function>(CI.getOperand(0)), Args));
 }
 
 void GraphBuilder::visitFreeInst(FreeInst &FI) {


Index: llvm/lib/Analysis/DataStructure/Printer.cpp
diff -u llvm/lib/Analysis/DataStructure/Printer.cpp:1.46 llvm/lib/Analysis/DataStructure/Printer.cpp:1.47
--- llvm/lib/Analysis/DataStructure/Printer.cpp:1.46	Mon Feb  3 18:03:18 2003
+++ llvm/lib/Analysis/DataStructure/Printer.cpp	Wed Feb  5 15:59:56 2003
@@ -123,18 +123,27 @@
       : G->getFunctionCalls();
     for (unsigned i = 0, e = FCs.size(); i != e; ++i) {
       const DSCallSite &Call = FCs[i];
-      GW.emitSimpleNode(&Call, "shape=record", "call", Call.getNumPtrArgs()+2);
+      std::vector<std::string> EdgeSourceCaptions(Call.getNumPtrArgs()+2);
+      EdgeSourceCaptions[0] = "r";
+      if (Call.isDirectCall())
+        EdgeSourceCaptions[1] = Call.getCalleeFunc()->getName();
+
+      GW.emitSimpleNode(&Call, "shape=record", "call", Call.getNumPtrArgs()+2,
+                        &EdgeSourceCaptions);
 
       if (DSNode *N = Call.getRetVal().getNode()) {
         int EdgeDest = Call.getRetVal().getOffset() >> DS::PointerShift;
         if (EdgeDest == 0) EdgeDest = -1;
         GW.emitEdge(&Call, 0, N, EdgeDest, "color=gray63");
       }
-      if (DSNode *N = Call.getCallee().getNode()) {
-        int EdgeDest = Call.getCallee().getOffset() >> DS::PointerShift;
-        if (EdgeDest == 0) EdgeDest = -1;
-        GW.emitEdge(&Call, 1, N, EdgeDest, "color=gray63");
+
+      // Print out the callee...
+      if (Call.isIndirectCall()) {
+        DSNode *N = Call.getCalleeNode();
+        assert(N && "Null call site callee node!");
+        GW.emitEdge(&Call, 1, N, -1, "color=gray63");
       }
+
       for (unsigned j = 0, e = Call.getNumPtrArgs(); j != e; ++j)
         if (DSNode *N = Call.getPtrArg(j).getNode()) {
           int EdgeDest = Call.getPtrArg(j).getOffset() >> DS::PointerShift;


Index: llvm/lib/Analysis/DataStructure/Steensgaard.cpp
diff -u llvm/lib/Analysis/DataStructure/Steensgaard.cpp:1.19 llvm/lib/Analysis/DataStructure/Steensgaard.cpp:1.20
--- llvm/lib/Analysis/DataStructure/Steensgaard.cpp:1.19	Tue Feb  4 10:33:23 2003
+++ llvm/lib/Analysis/DataStructure/Steensgaard.cpp	Wed Feb  5 15:59:56 2003
@@ -163,8 +163,12 @@
     DSCallSite &CurCall = Calls[i];
     
     // Loop over the called functions, eliminating as many as possible...
-    std::vector<GlobalValue*> CallTargets =
-      CurCall.getCallee().getNode()->getGlobals();
+    std::vector<GlobalValue*> CallTargets;
+    if (CurCall.isDirectCall())
+      CallTargets.push_back(CurCall.getCalleeFunc());
+    else 
+      CallTargets = CurCall.getCalleeNode()->getGlobals();
+
     for (unsigned c = 0; c != CallTargets.size(); ) {
       // If we can eliminate this function call, do so!
       bool Eliminated = false;


Index: llvm/lib/Analysis/DataStructure/TopDownClosure.cpp
diff -u llvm/lib/Analysis/DataStructure/TopDownClosure.cpp:1.35 llvm/lib/Analysis/DataStructure/TopDownClosure.cpp:1.36
--- llvm/lib/Analysis/DataStructure/TopDownClosure.cpp:1.35	Mon Feb  3 18:59:32 2003
+++ llvm/lib/Analysis/DataStructure/TopDownClosure.cpp	Wed Feb  5 15:59:56 2003
@@ -116,17 +116,22 @@
   std::multimap<Function*, const DSCallSite*> CalleeSites;
   for (unsigned i = 0, e = CallSites.size(); i != e; ++i) {
     const DSCallSite &CS = CallSites[i];
-    const std::vector<GlobalValue*> Callees =
-      CS.getCallee().getNode()->getGlobals();
+    if (CS.isDirectCall()) {
+      if (!CS.getCalleeFunc()->isExternal())           // If it's not external
+        CalleeSites.insert(std::make_pair(CS.getCalleeFunc(), &CS)); // Keep it
+    } else {
+      const std::vector<GlobalValue*> &Callees =
+        CS.getCalleeNode()->getGlobals();
 
-    // Loop over all of the functions that this call may invoke...
-    for (unsigned c = 0, e = Callees.size(); c != e; ++c)
-      if (Function *F = dyn_cast<Function>(Callees[c]))  // If this is a fn...
-        if (!F->isExternal())                            // If it's not external
-          CalleeSites.insert(std::make_pair(F, &CS));    // Keep track of it!
+      // Loop over all of the functions that this call may invoke...
+      for (unsigned c = 0, e = Callees.size(); c != e; ++c)
+        if (Function *F = dyn_cast<Function>(Callees[c]))  // If this is a fn...
+          if (!F->isExternal())                            // If it's not extern
+            CalleeSites.insert(std::make_pair(F, &CS));    // Keep track of it!
+    }
   }
 
-  // Now that we have information about all of the callees, propogate the
+  // Now that we have information about all of the callees, propagate the
   // current graph into the callees.
   //
   DEBUG(std::cerr << "  [TD] Inlining '" << F.getName() << "' into "





More information about the llvm-commits mailing list