- Add "ResolvingCaller" to the CallSite record. This keeps track of which
authorChris Lattner <sabre@nondot.org>
Mon, 21 Oct 2002 19:47:18 +0000 (19:47 +0000)
committerChris Lattner <sabre@nondot.org>
Mon, 21 Oct 2002 19:47:18 +0000 (19:47 +0000)
    function was finally able to resolve the function call.  Adding this allows
    the TD pass to actually work right!
  - Temporarily disable dead node pruning.  This will be reenabled soon.

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

include/llvm/Analysis/DSGraph.h
include/llvm/Analysis/DataStructure.h
include/llvm/Analysis/DataStructure/DSGraph.h
include/llvm/Analysis/DataStructure/DataStructure.h
lib/Analysis/DataStructure/BottomUpClosure.cpp
lib/Analysis/DataStructure/TopDownClosure.cpp

index 2a6836558518a3481b83456e624c8315a3a46a83..6eed55ddf7eb665d0fac7d6c16caa436356a531c 100644 (file)
@@ -361,19 +361,40 @@ inline void DSNodeHandle::mergeWith(const DSNodeHandle &Node) {
 /// DSCallSite - Representation of a call site via its call instruction,
 /// the DSNode handle for the callee function (or function pointer), and
 /// the DSNode handles for the function arguments.
+///
+/// One unusual aspect of this callsite record is the ResolvingCaller member.
+/// If this is non-null, then it indicates the function that allowed a call-site
+/// to finally be resolved.  Because of indirect calls, this function may not
+/// actually be the function that contains the Call instruction itself.  This is
+/// used by the BU and TD passes to communicate.
 /// 
 class DSCallSite {
   CallInst    *Inst;                    // Actual call site
   DSNodeHandle RetVal;                  // Returned value
   DSNodeHandle Callee;                  // The function node called
   std::vector<DSNodeHandle> CallArgs;   // The pointer arguments
+  Function    *ResolvingCaller;         // See comments above
+
+  static void InitNH(DSNodeHandle &NH, const DSNodeHandle &Src,
+                     const std::map<const DSNode*, DSNode*> &NodeMap) {
+    if (DSNode *N = Src.getNode()) {
+      std::map<const DSNode*, DSNode*>::const_iterator I = NodeMap.find(N);
+      assert(I != NodeMap.end() && "Not not in mapping!");
+
+      NH.setOffset(Src.getOffset());
+      NH.setNode(I->second);
+    }
+  }
 
-  static DSNode *mapLookup(const DSNode *Node,
-                           const std::map<const DSNode*, DSNode*> &NodeMap) {
-    if (Node == 0) return 0;
-    std::map<const DSNode*, DSNode*>::const_iterator I = NodeMap.find(Node);
-    assert(I != NodeMap.end() && "Not not in mapping!");
-    return I->second;
+  static void InitNH(DSNodeHandle &NH, const DSNodeHandle &Src,
+                     const std::map<const DSNode*, DSNodeHandle> &NodeMap) {
+    if (DSNode *N = Src.getNode()) {
+      std::map<const DSNode*, DSNodeHandle>::const_iterator I = NodeMap.find(N);
+      assert(I != NodeMap.end() && "Not not in mapping!");
+
+      NH.setOffset(Src.getOffset()+I->second.getOffset());
+      NH.setNode(I->second.getNode());
+    }
   }
 
   DSCallSite();                         // DO NOT IMPLEMENT
@@ -383,32 +404,29 @@ public:
   ///
   DSCallSite(CallInst &inst, const DSNodeHandle &rv, const DSNodeHandle &callee,
              std::vector<DSNodeHandle> &Args)
-    : Inst(&inst), RetVal(rv), Callee(callee) {
+    : Inst(&inst), RetVal(rv), Callee(callee), ResolvingCaller(0) {
     Args.swap(CallArgs);
   }
 
   DSCallSite(const DSCallSite &DSCS)   // Simple copy ctor
     : Inst(DSCS.Inst), RetVal(DSCS.RetVal),
-      Callee(DSCS.Callee), CallArgs(DSCS.CallArgs) {}
+      Callee(DSCS.Callee), CallArgs(DSCS.CallArgs),
+      ResolvingCaller(DSCS.ResolvingCaller) {}
 
   /// Mapping copy constructor - This constructor takes a preexisting call site
   /// to copy plus a map that specifies how the links should be transformed.
   /// This is useful when moving a call site from one graph to another.
   ///
-  DSCallSite(const DSCallSite &FromCall,
-             const std::map<const DSNode*, DSNode*> &NodeMap) {
+  template<typename MapTy>
+  DSCallSite(const DSCallSite &FromCall, const MapTy &NodeMap) {
     Inst = FromCall.Inst;
-    RetVal.setOffset(FromCall.RetVal.getOffset());
-    RetVal.setNode(mapLookup(FromCall.RetVal.getNode(), NodeMap));
-    Callee.setOffset(FromCall.Callee.getOffset());
-    Callee.setNode(mapLookup(FromCall.Callee.getNode(), NodeMap));
-    CallArgs.reserve(FromCall.CallArgs.size());
-
-    for (unsigned i = 0, e = FromCall.CallArgs.size(); i != e; ++i) {
-      const DSNodeHandle &OldNH = FromCall.CallArgs[i];
-      CallArgs.push_back(DSNodeHandle(mapLookup(OldNH.getNode(), NodeMap),
-                                      OldNH.getOffset()));
-    }
+    InitNH(RetVal, FromCall.RetVal, NodeMap);
+    InitNH(Callee, FromCall.Callee, NodeMap);
+
+    CallArgs.resize(FromCall.CallArgs.size());
+    for (unsigned i = 0, e = FromCall.CallArgs.size(); i != e; ++i)
+      InitNH(CallArgs[i], FromCall.CallArgs[i], NodeMap);
+    ResolvingCaller = FromCall.ResolvingCaller;
   }
 
   // Accessor functions...
@@ -420,6 +438,9 @@ public:
   const DSNodeHandle &getCallee()     const { return Callee; }
   unsigned            getNumPtrArgs() const { return CallArgs.size(); }
 
+  Function           *getResolvingCaller() const { return ResolvingCaller; }
+  void setResolvingCaller(Function *F) { ResolvingCaller = F; }
+
   DSNodeHandle &getPtrArg(unsigned i) {
     assert(i < CallArgs.size() && "Argument to getPtrArgNode is out of range!");
     return CallArgs[i];
@@ -478,7 +499,7 @@ public:
   // destination graph, you may optionally do this by specifying a map to record
   // this into.
   DSGraph(const DSGraph &DSG);
-  DSGraph(const DSGraph &DSG, std::map<const DSNode*, DSNode*> &BUNodeMapTy);
+  DSGraph(const DSGraph &DSG, std::map<const DSNode*, DSNode*> &BUNodeMap);
   ~DSGraph();
 
   bool hasFunction() const { return Func != 0; }
index 2dc4ce4d1e8701e5b6fbf5c80c6cff6ce35b5322..d44732a486349f5c202e27ffa98ead54ba0c1e91 100644 (file)
@@ -11,6 +11,7 @@
 
 class Type;
 class DSGraph;
+class DSNode;
 class DSNodeHandle;
 class DSCallSite;
 class LocalDataStructures;     // A collection of local graphs for a program
@@ -108,6 +109,15 @@ private:
 class TDDataStructures : public Pass {
   // DSInfo, one graph for each function
   std::map<const Function*, DSGraph*> DSInfo;
+
+  // Each graph in DSInfo is based on a graph in the BUDS object.  The BUMaps
+  // member keeps the mappings from the BU graphs to the TD graphs as they are
+  // calculated by calculateGraph.  This information is used to properly
+  // implement resolving of call sites, where the call sites in the BUGraph are
+  // in terms of the caller function's graph in the BUGraph.
+  //
+  typedef std::map<const DSNode*, DSNodeHandle> BUNodeMapTy;
+  std::map<const Function*, BUNodeMapTy> BUMaps;
 public:
   ~TDDataStructures() { releaseMemory(); }
 
@@ -134,8 +144,7 @@ public:
 private:
   DSGraph &calculateGraph(Function &F);
 
-  void ResolveCallSite(DSGraph &Graph,
-                       const DSCallSite &CallSite);
+  void ResolveCallSite(DSGraph &Graph, const DSCallSite &CallSite);
 };
 
 #if 0
index 2a6836558518a3481b83456e624c8315a3a46a83..6eed55ddf7eb665d0fac7d6c16caa436356a531c 100644 (file)
@@ -361,19 +361,40 @@ inline void DSNodeHandle::mergeWith(const DSNodeHandle &Node) {
 /// DSCallSite - Representation of a call site via its call instruction,
 /// the DSNode handle for the callee function (or function pointer), and
 /// the DSNode handles for the function arguments.
+///
+/// One unusual aspect of this callsite record is the ResolvingCaller member.
+/// If this is non-null, then it indicates the function that allowed a call-site
+/// to finally be resolved.  Because of indirect calls, this function may not
+/// actually be the function that contains the Call instruction itself.  This is
+/// used by the BU and TD passes to communicate.
 /// 
 class DSCallSite {
   CallInst    *Inst;                    // Actual call site
   DSNodeHandle RetVal;                  // Returned value
   DSNodeHandle Callee;                  // The function node called
   std::vector<DSNodeHandle> CallArgs;   // The pointer arguments
+  Function    *ResolvingCaller;         // See comments above
+
+  static void InitNH(DSNodeHandle &NH, const DSNodeHandle &Src,
+                     const std::map<const DSNode*, DSNode*> &NodeMap) {
+    if (DSNode *N = Src.getNode()) {
+      std::map<const DSNode*, DSNode*>::const_iterator I = NodeMap.find(N);
+      assert(I != NodeMap.end() && "Not not in mapping!");
+
+      NH.setOffset(Src.getOffset());
+      NH.setNode(I->second);
+    }
+  }
 
-  static DSNode *mapLookup(const DSNode *Node,
-                           const std::map<const DSNode*, DSNode*> &NodeMap) {
-    if (Node == 0) return 0;
-    std::map<const DSNode*, DSNode*>::const_iterator I = NodeMap.find(Node);
-    assert(I != NodeMap.end() && "Not not in mapping!");
-    return I->second;
+  static void InitNH(DSNodeHandle &NH, const DSNodeHandle &Src,
+                     const std::map<const DSNode*, DSNodeHandle> &NodeMap) {
+    if (DSNode *N = Src.getNode()) {
+      std::map<const DSNode*, DSNodeHandle>::const_iterator I = NodeMap.find(N);
+      assert(I != NodeMap.end() && "Not not in mapping!");
+
+      NH.setOffset(Src.getOffset()+I->second.getOffset());
+      NH.setNode(I->second.getNode());
+    }
   }
 
   DSCallSite();                         // DO NOT IMPLEMENT
@@ -383,32 +404,29 @@ public:
   ///
   DSCallSite(CallInst &inst, const DSNodeHandle &rv, const DSNodeHandle &callee,
              std::vector<DSNodeHandle> &Args)
-    : Inst(&inst), RetVal(rv), Callee(callee) {
+    : Inst(&inst), RetVal(rv), Callee(callee), ResolvingCaller(0) {
     Args.swap(CallArgs);
   }
 
   DSCallSite(const DSCallSite &DSCS)   // Simple copy ctor
     : Inst(DSCS.Inst), RetVal(DSCS.RetVal),
-      Callee(DSCS.Callee), CallArgs(DSCS.CallArgs) {}
+      Callee(DSCS.Callee), CallArgs(DSCS.CallArgs),
+      ResolvingCaller(DSCS.ResolvingCaller) {}
 
   /// Mapping copy constructor - This constructor takes a preexisting call site
   /// to copy plus a map that specifies how the links should be transformed.
   /// This is useful when moving a call site from one graph to another.
   ///
-  DSCallSite(const DSCallSite &FromCall,
-             const std::map<const DSNode*, DSNode*> &NodeMap) {
+  template<typename MapTy>
+  DSCallSite(const DSCallSite &FromCall, const MapTy &NodeMap) {
     Inst = FromCall.Inst;
-    RetVal.setOffset(FromCall.RetVal.getOffset());
-    RetVal.setNode(mapLookup(FromCall.RetVal.getNode(), NodeMap));
-    Callee.setOffset(FromCall.Callee.getOffset());
-    Callee.setNode(mapLookup(FromCall.Callee.getNode(), NodeMap));
-    CallArgs.reserve(FromCall.CallArgs.size());
-
-    for (unsigned i = 0, e = FromCall.CallArgs.size(); i != e; ++i) {
-      const DSNodeHandle &OldNH = FromCall.CallArgs[i];
-      CallArgs.push_back(DSNodeHandle(mapLookup(OldNH.getNode(), NodeMap),
-                                      OldNH.getOffset()));
-    }
+    InitNH(RetVal, FromCall.RetVal, NodeMap);
+    InitNH(Callee, FromCall.Callee, NodeMap);
+
+    CallArgs.resize(FromCall.CallArgs.size());
+    for (unsigned i = 0, e = FromCall.CallArgs.size(); i != e; ++i)
+      InitNH(CallArgs[i], FromCall.CallArgs[i], NodeMap);
+    ResolvingCaller = FromCall.ResolvingCaller;
   }
 
   // Accessor functions...
@@ -420,6 +438,9 @@ public:
   const DSNodeHandle &getCallee()     const { return Callee; }
   unsigned            getNumPtrArgs() const { return CallArgs.size(); }
 
+  Function           *getResolvingCaller() const { return ResolvingCaller; }
+  void setResolvingCaller(Function *F) { ResolvingCaller = F; }
+
   DSNodeHandle &getPtrArg(unsigned i) {
     assert(i < CallArgs.size() && "Argument to getPtrArgNode is out of range!");
     return CallArgs[i];
@@ -478,7 +499,7 @@ public:
   // destination graph, you may optionally do this by specifying a map to record
   // this into.
   DSGraph(const DSGraph &DSG);
-  DSGraph(const DSGraph &DSG, std::map<const DSNode*, DSNode*> &BUNodeMapTy);
+  DSGraph(const DSGraph &DSG, std::map<const DSNode*, DSNode*> &BUNodeMap);
   ~DSGraph();
 
   bool hasFunction() const { return Func != 0; }
index 2dc4ce4d1e8701e5b6fbf5c80c6cff6ce35b5322..d44732a486349f5c202e27ffa98ead54ba0c1e91 100644 (file)
@@ -11,6 +11,7 @@
 
 class Type;
 class DSGraph;
+class DSNode;
 class DSNodeHandle;
 class DSCallSite;
 class LocalDataStructures;     // A collection of local graphs for a program
@@ -108,6 +109,15 @@ private:
 class TDDataStructures : public Pass {
   // DSInfo, one graph for each function
   std::map<const Function*, DSGraph*> DSInfo;
+
+  // Each graph in DSInfo is based on a graph in the BUDS object.  The BUMaps
+  // member keeps the mappings from the BU graphs to the TD graphs as they are
+  // calculated by calculateGraph.  This information is used to properly
+  // implement resolving of call sites, where the call sites in the BUGraph are
+  // in terms of the caller function's graph in the BUGraph.
+  //
+  typedef std::map<const DSNode*, DSNodeHandle> BUNodeMapTy;
+  std::map<const Function*, BUNodeMapTy> BUMaps;
 public:
   ~TDDataStructures() { releaseMemory(); }
 
@@ -134,8 +144,7 @@ public:
 private:
   DSGraph &calculateGraph(Function &F);
 
-  void ResolveCallSite(DSGraph &Graph,
-                       const DSCallSite &CallSite);
+  void ResolveCallSite(DSGraph &Graph, const DSCallSite &CallSite);
 };
 
 #if 0
index 53b997f69a30b72709435c45f7ce91c4a03cad1b..73786c96c5e17add2a17916d942c2b2480d2ef18 100644 (file)
@@ -143,7 +143,9 @@ 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.
-            CallSites[&FI].push_back(Call);
+            std::vector<DSCallSite> &CallSitesForFunc = CallSites[&FI];
+            CallSitesForFunc.push_back(Call);
+            CallSitesForFunc.back().setResolvingCaller(&F);
 
             // Clone the callee's graph into the current graph, keeping
             // track of where scalars in the old graph _used_ to point,
index 653d2ca8f692ef6d3617f3f5b0f8c32b53ac4647..c573a52c9e0bd00b9ee2ee904f7c092988d92152 100644 (file)
@@ -20,6 +20,7 @@ Y("tddatastructure", "Top-down Data Structure Analysis Closure");
 // our memory... here...
 //
 void TDDataStructures::releaseMemory() {
+  BUMaps.clear();
   for (std::map<const Function*, DSGraph*>::iterator I = DSInfo.begin(),
          E = DSInfo.end(); I != E; ++I)
     delete I->second;
@@ -76,7 +77,14 @@ DSGraph &TDDataStructures::calculateGraph(Function &F) {
 
   BUDataStructures &BU = getAnalysis<BUDataStructures>();
   DSGraph &BUGraph = BU.getDSGraph(F);
-  Graph = new DSGraph(BUGraph);
+  
+  // Copy the BU graph, keeping a mapping from the BUGraph to the current Graph
+  std::map<const DSNode*, DSNode*> BUNodeMap;
+  Graph = new DSGraph(BUGraph, BUNodeMap);
+
+  // Convert the mapping from a node-to-node map into a node-to-nodehandle map
+  BUMaps[&F].insert(BUNodeMap.begin(), BUNodeMap.end());
+  BUNodeMap.clear();   // We are done with the temporary map.
 
   const std::vector<DSCallSite> *CallSitesP = BU.getCallSites(F);
   if (CallSitesP == 0) {
@@ -90,14 +98,19 @@ DSGraph &TDDataStructures::calculateGraph(Function &F) {
   DEBUG(std::cerr << "  [TD] Inlining callers for: " << F.getName() << "\n");
   const std::vector<DSCallSite> &CallSites = *CallSitesP;
   for (unsigned c = 0, ce = CallSites.size(); c != ce; ++c) {
-    const DSCallSite &CallSite = CallSites[c];  // Copy
-    Function &Caller = CallSite.getCaller();
-    assert(!Caller.isExternal() && "Externals function cannot 'call'!");
+    const DSCallSite &CallSite = CallSites[c];
+    Function &Caller = *CallSite.getResolvingCaller();
+    assert(&Caller && !Caller.isExternal() &&
+           "Externals function cannot 'call'!");
     
     DEBUG(std::cerr << "\t [TD] Inlining caller #" << c << " '"
           << Caller.getName() << "' into callee: " << F.getName() << "\n");
     
-    if (&Caller != &F) {
+    if (&Caller == &F) {
+      // Self-recursive call: this can happen after a cycle of calls is inlined.
+      ResolveCallSite(*Graph, CallSite);
+    } else {
+
       // Recursively compute the graph for the Caller.  It should be fully
       // resolved except if there is mutual recursion...
       //
@@ -111,6 +124,9 @@ DSGraph &TDDataStructures::calculateGraph(Function &F) {
       std::map<Value*, DSNodeHandle> OldValMap;
       std::map<const DSNode*, DSNode*> OldNodeMap;
 
+      // Translate call site from having links into the BU graph
+      DSCallSite CallSiteInCG(CallSite, BUMaps[&Caller]);
+
       // Clone the Caller's graph into the current graph, keeping
       // track of where scalars in the old graph _used_ to point...
       // Do this here because it only needs to happens once for each Caller!
@@ -121,20 +137,17 @@ DSGraph &TDDataStructures::calculateGraph(Function &F) {
                                              /*StripAllocas*/ false,
                                              /*CopyCallers*/  true,
                                              /*CopyOrigCalls*/false);
-
-      // Make a temporary copy of the call site, and transform the argument node
-      // pointers.
-      //
+      ResolveCallSite(*Graph, DSCallSite(CallSiteInCG, OldNodeMap));
     }
-    ResolveCallSite(*Graph, CallSite); 
   }
 
   // Recompute the Incomplete markers and eliminate unreachable nodes.
+#if 0
   Graph->maskIncompleteMarkers();
   Graph->markIncompleteNodes(/*markFormals*/ !F.hasInternalLinkage()
                              /*&& FIXME: NEED TO CHECK IF ALL CALLERS FOUND!*/);
   Graph->removeDeadNodes(/*KeepAllGlobals*/ false, /*KeepCalls*/ false);
-
+#endif
   DEBUG(std::cerr << "  [TD] Done inlining callers for: " << F.getName() << " ["
         << Graph->getGraphSize() << "+" << Graph->getFunctionCalls().size()
         << "]\n");