Eliminate the cfg namespace, moving LoopInfo, Dominators, Interval* classes
[oota-llvm.git] / lib / Analysis / DataStructure / ComputeClosure.cpp
index 5ea706800ba4d5cc859d095d277b25883e1f3d40..f4345fae8018565489016e1c3a55e3f51d657afd 100644 (file)
@@ -8,6 +8,7 @@
 //#define DEBUG_IP_CLOSURE 1
 
 #include "llvm/Analysis/DataStructure.h"
+#include "llvm/Function.h"
 #include "llvm/iOther.h"
 #include "Support/STLExtras.h"
 #include <algorithm>
@@ -30,8 +31,17 @@ static void copyEdgesFromTo(PointerVal Val, DSNode *N) {
   }
 }
 
-static void ResolveNodesTo(const PointerVal &FromPtr,
+static void ResolveNodesTo(const PointerValSet &FromVals,
                            const PointerValSet &ToVals) {
+  // Only resolve the first pointer, although there many be many pointers here.
+  // The problem is that the inlined function might return one of the arguments
+  // to the function, and if so, extra values can be added to the arg or call
+  // node that point to what the other one got resolved to.  Since these will
+  // be added to the end of the PVS pointed in, we just ignore them.
+  //
+  assert(!FromVals.empty() && "From should have at least a shadow node!");
+  const PointerVal &FromPtr = FromVals[0];
+
   assert(FromPtr.Index == 0 &&
          "Resolved node return pointer should be index 0!");
   DSNode *N = FromPtr.Node;
@@ -57,28 +67,27 @@ static void ResolveNodeTo(DSNode *Node, const PointerValSet &ToVals) {
   assert(Node->getNumLinks() == 1 && "Resolved node can only be a scalar!!");
 
   const PointerValSet &PVS = Node->getLink(0);
-
-  // Only resolve the first pointer, although there many be many pointers here.
-  // The problem is that the inlined function might return one of the arguments
-  // to the function, and if so, extra values can be added to the arg or call
-  // node that point to what the other one got resolved to.  Since these will
-  // be added to the end of the PVS pointed in, we just ignore them.
-  //
-  ResolveNodesTo(PVS[0], ToVals);
+  ResolveNodesTo(PVS, ToVals);
 }
 
 // isResolvableCallNode - Return true if node is a call node and it is a call
 // node that we can inline...
 //
 static bool isResolvableCallNode(CallDSNode *CN) {
-  // Only operate on call nodes with direct method calls
-  Function *F = CN->getCall()->getCalledFunction();
-  if (F == 0) return false;
-
-  // Only work on call nodes with direct calls to methods with bodies.
-  return !F->isExternal();
+  // Only operate on call nodes with direct function calls
+  if (CN->getArgValues(0).size() == 1 &&
+      isa<GlobalDSNode>(CN->getArgValues(0)[0].Node)) {
+    GlobalDSNode *GDN = cast<GlobalDSNode>(CN->getArgValues(0)[0].Node);
+    Function *F = cast<Function>(GDN->getGlobal());
+
+    // Only work on call nodes with direct calls to methods with bodies.
+    return !F->isExternal();
+  }
+  return false;
 }
 
+#include "Support/CommandLine.h"
+static cl::Int InlineLimit("dsinlinelimit", "Max number of graphs to inline when computing ds closure", cl::Hidden, 100);
 
 // computeClosure - Replace all of the resolvable call nodes with the contents
 // of their corresponding method data structure graph...
@@ -97,10 +106,14 @@ void FunctionDSGraph::computeClosure(const DataStructure &DS) {
   NI = std::find_if(CallNodes.begin(), CallNodes.end(), isResolvableCallNode);
   while (NI != CallNodes.end()) {
     CallDSNode *CN = *NI;
-    Function *F = CN->getCall()->getCalledFunction();
+    GlobalDSNode *FGDN = cast<GlobalDSNode>(CN->getArgValues(0)[0].Node);
+    Function *F = cast<Function>(FGDN->getGlobal());
 
-    if (NumInlines++ == 100) {      // CUTE hack huh?
+    if ((int)NumInlines++ == InlineLimit) {      // CUTE hack huh?
       cerr << "Infinite (?) recursion halted\n";
+      cerr << "Not inlining: " << F->getName() << "\n";
+      CN->dump();
+      
       return;
     }
 
@@ -166,40 +179,26 @@ void FunctionDSGraph::computeClosure(const DataStructure &DS) {
       // StartNode - The first node of the incorporated graph, last node of the
       // preexisting data structure graph...
       //
-      unsigned StartArgNode   = ArgNodes.size();
       unsigned StartAllocNode = AllocNodes.size();
 
       // Incorporate a copy of the called function graph into the current graph,
       // allowing us to do local transformations to local graph to link
       // arguments to call values, and call node to return value...
       //
-      RetVals = cloneFunctionIntoSelf(NewFunction, false);
+      vector<PointerValSet> Args;
+      RetVals = cloneFunctionIntoSelf(NewFunction, false, Args);
       CallMap.push_back(make_pair(CallDescriptor(CN->getArgs(), CN->getCall()),
                                   RetVals));
 
       // If the call node has arguments, process them now!
-      if (CN->getNumArgs()) {
-        // The ArgNodes of the incorporated graph should be the nodes starting
-        // at StartNode, ordered the same way as the call arguments.  The arg
-        // nodes are seperated by a single shadow node, but that shadow node
-        // might get eliminated in the process of optimization.
-        //
-        for (unsigned i = 0, e = CN->getNumArgs(); i != e; ++i) {
-          // Get the arg node of the incorporated method...
-          ArgDSNode *ArgNode = ArgNodes[StartArgNode];
-          
-          // Now we make all of the nodes inside of the incorporated method
-          // point to the real arguments values, not to the shadow nodes for the
-          // argument.
-          //
-          ResolveNodeTo(ArgNode, CN->getArgValues(i));
-          
-          // Remove the argnode from the set of nodes in this method...
-          ArgNodes.erase(ArgNodes.begin()+StartArgNode);
-            
-          // ArgNode is no longer useful, delete now!
-          delete ArgNode;
-        }
+      assert(Args.size() == CN->getNumArgs()-1 &&
+             "Call node doesn't match function?");
+
+      for (unsigned i = 0, e = Args.size(); i != e; ++i) {
+        // Now we make all of the nodes inside of the incorporated method
+        // point to the real arguments values, not to the shadow nodes for the
+        // argument.
+        ResolveNodesTo(Args[i], CN->getArgValues(i+1));
       }
 
       // Loop through the nodes, deleting alloca nodes in the inlined function.
@@ -242,4 +241,18 @@ void FunctionDSGraph::computeClosure(const DataStructure &DS) {
     // Move on to the next call node...
     NI = std::find_if(CallNodes.begin(), CallNodes.end(), isResolvableCallNode);
   }
+
+  // Drop references to globals...
+  CallMap.clear();
+
+  bool Changed = true;
+  while (Changed) {
+    // Eliminate shadow nodes that are not distinguishable from some other
+    // node in the graph...
+    //
+    Changed = UnlinkUndistinguishableNodes();
+
+    // Eliminate shadow nodes that are now extraneous due to linking...
+    Changed |= RemoveUnreachableNodes();
+  }
 }