[llvm-commits] CVS: llvm/lib/Analysis/DataStructure/BottomUpClosure.cpp

Chris Lattner lattner at cs.uiuc.edu
Fri Feb 4 12:00:02 PST 2005



Changes in directory llvm/lib/Analysis/DataStructure:

BottomUpClosure.cpp updated: 1.91 -> 1.92
---
Log message:

If we have an indirect call site that calls N functions, inline the N functions
into a temporary graph, remember it for later, then inline the tmp graph into
the call site.

In the case where there are other call sites to the same set of functions, this
permits us to just inline the temporary graph instead of all of the callees.

This turns N*M inlining situations into an N+M inlining situation.


---
Diffs of the changes:  (+98 -57)

 BottomUpClosure.cpp |  155 ++++++++++++++++++++++++++++++++--------------------
 1 files changed, 98 insertions(+), 57 deletions(-)


Index: llvm/lib/Analysis/DataStructure/BottomUpClosure.cpp
diff -u llvm/lib/Analysis/DataStructure/BottomUpClosure.cpp:1.91 llvm/lib/Analysis/DataStructure/BottomUpClosure.cpp:1.92
--- llvm/lib/Analysis/DataStructure/BottomUpClosure.cpp:1.91	Tue Feb  1 15:55:40 2005
+++ llvm/lib/Analysis/DataStructure/BottomUpClosure.cpp	Fri Feb  4 13:59:49 2005
@@ -61,6 +61,15 @@
 
   NumCallEdges += ActualCallees.size();
 
+  // If we computed any temporary indcallgraphs, free them now.
+  for (std::map<std::vector<Function*>,
+         std::pair<DSGraph*, std::vector<DSNodeHandle> > >::iterator I =
+         IndCallGraphMap.begin(), E = IndCallGraphMap.end(); I != E; ++I) {
+    I->second.second.clear();  // Drop arg refs into the graph.
+    delete I->second.first;
+  }
+  IndCallGraphMap.clear();
+
   // At the end of the bottom-up pass, the globals graph becomes complete.
   // FIXME: This is not the right way to do this, but it is sorta better than
   // nothing!  In particular, externally visible globals and unresolvable call
@@ -265,10 +274,11 @@
   DSGraph::ReturnNodesTy &ReturnNodes = Graph.getReturnNodes();
 
   bool Printed = false;
+  std::vector<Function*> CalledFuncs;
   while (!TempFCs.empty()) {
     DSCallSite &CS = *TempFCs.begin();
 
-    std::set<Function*> CalledFuncs;
+    CalledFuncs.clear();
 
     if (CS.isDirectCall()) {
       Function *F = CS.getCalleeFunc();
@@ -277,7 +287,7 @@
           TempFCs.erase(TempFCs.begin());
           continue;
         } else {
-          CalledFuncs.insert(F);
+          CalledFuncs.push_back(F);
         }
     } else {
       DSNode *Node = CS.getCalleeNode();
@@ -286,76 +296,107 @@
         for (unsigned i = 0, e = Node->getGlobals().size(); i != e; ++i)
           if (Function *CF = dyn_cast<Function>(Node->getGlobals()[i]))
             if (isResolvableFunc(CF) && !CF->isExternal())
-              CalledFuncs.insert(CF);
+              CalledFuncs.push_back(CF);
     }
 
     if (CalledFuncs.empty()) {
       // Remember that we could not resolve this yet!
       AuxCallsList.splice(AuxCallsList.end(), TempFCs, TempFCs.begin());
       continue;
-    } else if (CalledFuncs.size() == 1) {
-      Function *Callee = *CalledFuncs.begin();
-
-      ActualCallees.insert(std::make_pair(CS.getCallSite().getInstruction(),
-                                          Callee));
-
-      // Get the data structure graph for the called function.
-      //
-      DSGraph &GI = getDSGraph(*Callee);  // Graph to inline
-      
-      DEBUG(std::cerr << "    Inlining graph for " << Callee->getName()
-            << "[" << GI.getGraphSize() << "+"
-            << GI.getAuxFunctionCalls().size() << "] into '"
-            << Graph.getFunctionNames() << "' [" << Graph.getGraphSize() <<"+"
-            << Graph.getAuxFunctionCalls().size() << "]\n");
-      Graph.mergeInGraph(CS, *Callee, GI,
-                         DSGraph::KeepModRefBits | 
-                         DSGraph::StripAllocaBit|DSGraph::DontCloneCallNodes);
-      ++NumBUInlines;
-      
-#if 0
-      Graph.writeGraphToFile(std::cerr, "bu_" + F.getName() + "_after_" +
-                             Callee->getName());
-#endif
     } else {
-      if (!Printed)
-        std::cerr << "In Fns: " << Graph.getFunctionNames() << "\n";
-      std::cerr << "  calls " << CalledFuncs.size()
-                << " fns from site: " << CS.getCallSite().getInstruction() 
-                << "  " << *CS.getCallSite().getInstruction();
-      unsigned NumToPrint = CalledFuncs.size();
-      if (NumToPrint > 8) NumToPrint = 8;
-      std::cerr << "   Fns =";
-      for (std::set<Function*>::iterator I = CalledFuncs.begin(),
-             E = CalledFuncs.end(); I != E && NumToPrint; ++I, --NumToPrint)
-        std::cerr << " " << (*I)->getName();
-      std::cerr << "\n";
-
-      // Inline all of the called functions.
-      for (std::set<Function*>::iterator I = CalledFuncs.begin(),
-             E = CalledFuncs.end(); I != E; ++I) {
-        Function *Callee = *I;
+      DSGraph *GI;
+
+      if (CalledFuncs.size() == 1) {
+        Function *Callee = CalledFuncs[0];
         ActualCallees.insert(std::make_pair(CS.getCallSite().getInstruction(),
                                             Callee));
-          
+
         // Get the data structure graph for the called function.
-        //
-        DSGraph &GI = getDSGraph(*Callee);  // Graph to inline
-        
-        DEBUG(std::cerr << "    Inlining graph for " << Callee->getName()
-              << "[" << GI.getGraphSize() << "+"
-              << GI.getAuxFunctionCalls().size() << "] into '"
+        GI = &getDSGraph(*Callee);  // Graph to inline
+        DEBUG(std::cerr << "    Inlining graph for " << Callee->getName());
+
+        DEBUG(std::cerr << "[" << GI->getGraphSize() << "+"
+              << GI->getAuxFunctionCalls().size() << "] into '"
               << Graph.getFunctionNames() << "' [" << Graph.getGraphSize() <<"+"
               << Graph.getAuxFunctionCalls().size() << "]\n");
-        Graph.mergeInGraph(CS, *Callee, GI,
+        Graph.mergeInGraph(CS, *Callee, *GI,
                            DSGraph::KeepModRefBits | 
                            DSGraph::StripAllocaBit|DSGraph::DontCloneCallNodes);
         ++NumBUInlines;
-        
-#if 0
-        Graph.writeGraphToFile(std::cerr, "bu_" + F.getName() + "_after_" +
-                               Callee->getName());
-#endif
+      } else {
+        if (!Printed)
+          std::cerr << "In Fns: " << Graph.getFunctionNames() << "\n";
+        std::cerr << "  calls " << CalledFuncs.size()
+                  << " fns from site: " << CS.getCallSite().getInstruction() 
+                  << "  " << *CS.getCallSite().getInstruction();
+        unsigned NumToPrint = CalledFuncs.size();
+        if (NumToPrint > 8) NumToPrint = 8;
+        std::cerr << "   Fns =";
+        for (std::vector<Function*>::iterator I = CalledFuncs.begin(),
+               E = CalledFuncs.end(); I != E && NumToPrint; ++I, --NumToPrint)
+          std::cerr << " " << (*I)->getName();
+        std::cerr << "\n";
+
+        // See if we already computed a graph for this set of callees.
+        std::sort(CalledFuncs.begin(), CalledFuncs.end());
+        std::pair<DSGraph*, std::vector<DSNodeHandle> > &IndCallGraph =
+          IndCallGraphMap[CalledFuncs];
+
+        if (IndCallGraph.first == 0) {
+          std::vector<Function*>::iterator I = CalledFuncs.begin(),
+            E = CalledFuncs.end();
+          
+          // Start with a copy of the first graph.
+          GI = IndCallGraph.first = new DSGraph(getDSGraph(**I));
+          GI->setGlobalsGraph(Graph.getGlobalsGraph());
+          std::vector<DSNodeHandle> &Args = IndCallGraph.second;
+
+          // Get the argument nodes for the first callee.  The return value is
+          // the 0th index in the vector.
+          GI->getFunctionArgumentsForCall(*I, Args);
+
+          // Merge all of the other callees into this graph.
+          for (++I; I != E; ++I) {
+            // If the graph already contains the nodes for the function, don't
+            // bother merging it in again.
+            if (!GI->containsFunction(*I)) {
+              DSGraph::NodeMapTy NodeMap;
+              GI->cloneInto(getDSGraph(**I), GI->getScalarMap(),
+                            GI->getReturnNodes(), NodeMap);
+              ++NumBUInlines;
+            }
+
+            std::vector<DSNodeHandle> NextArgs;
+            GI->getFunctionArgumentsForCall(*I, NextArgs);
+            unsigned i = 0, e = Args.size();
+            for (; i != e; ++i) {
+              if (i == NextArgs.size()) break;
+              Args[i].mergeWith(NextArgs[i]);
+            }
+            for (e = NextArgs.size(); i != e; ++i)
+              Args.push_back(NextArgs[i]);
+          }
+          
+          // Clean up the final graph!
+          GI->removeDeadNodes(DSGraph::KeepUnreachableGlobals);
+        } else {
+          std::cerr << "***\n*** RECYCLED GRAPH ***\n***\n";
+        }
+
+        GI = IndCallGraph.first;
+
+        // Merge the unified graph into this graph now.
+        DEBUG(std::cerr << "    Inlining multi callee graph "
+              << "[" << GI->getGraphSize() << "+"
+              << GI->getAuxFunctionCalls().size() << "] into '"
+              << Graph.getFunctionNames() << "' [" << Graph.getGraphSize() <<"+"
+              << Graph.getAuxFunctionCalls().size() << "]\n");
+
+        Graph.mergeInGraph(CS, IndCallGraph.second, *GI,
+                           DSGraph::KeepModRefBits | 
+                           DSGraph::StripAllocaBit |
+                           DSGraph::DontCloneCallNodes);
+        ++NumBUInlines;
       }
     }
     TempFCs.erase(TempFCs.begin());






More information about the llvm-commits mailing list