Correctly transform dependant arguments, allowing the perimeter bm to work.
authorChris Lattner <sabre@nondot.org>
Thu, 18 Apr 2002 14:43:30 +0000 (14:43 +0000)
committerChris Lattner <sabre@nondot.org>
Thu, 18 Apr 2002 14:43:30 +0000 (14:43 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@2282 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Transforms/IPO/OldPoolAllocate.cpp

index 2b5ba858154d8aa752bba18aead5bca1dd69d56e..1e63381c893c57c6df112df78d80743fabcb1d87 100644 (file)
@@ -177,6 +177,23 @@ namespace {
       // pool entries for the same argument) are kept in depth first order.
       stable_sort(ArgInfo.begin(), ArgInfo.end());
     }
+
+    // addCallInfo - For a specified function call CI, figure out which pool
+    // descriptors need to be passed in as arguments, and which arguments need
+    // to be transformed into indices.  If Arg != -1, the specified call
+    // argument is passed in as a pointer to a data structure.
+    //
+    void addCallInfo(DataStructure *DS, CallInst *CI, int Arg,
+                     DSNode *GraphNode, map<DSNode*, PoolInfo> &PoolDescs);
+
+    // Make sure that all dependant arguments are added to this transformation
+    // info.  For example, if we call foo(null, P) and foo treats it's first and
+    // second arguments as belonging to the same data structure, the we MUST add
+    // entries to know that the null needs to be transformed into an index as
+    // well.
+    //
+    void ensureDependantArgumentsIncluded(DataStructure *DS,
+                                          map<DSNode*, PoolInfo> &PoolDescs);
   };
 
 
@@ -332,6 +349,10 @@ bool PoolAllocate::processFunction(Function *F) {
 
   if (Allocs.empty()) return false;  // Nothing to do.
 
+#ifdef DEBUG_TRANSFORM_PROGRESS
+  cerr << "Transforming Function: " << F->getName() << "\n";
+#endif
+
   // Insert instructions into the function we are processing to create all of
   // the memory pool objects themselves.  This also inserts destruction code.
   // This fills in the PoolDescs map to associate the alloc node with the
@@ -381,6 +402,8 @@ class NewInstructionCreator : public InstVisitor<NewInstructionCreator> {
   const ScalarInfo &getScalarRef(const Value *V) {
     for (unsigned i = 0, e = Scalars.size(); i != e; ++i)
       if (Scalars[i].Val == V) return Scalars[i];
+
+    cerr << "Could not find scalar " << V << " in scalar map!\n";
     assert(0 && "Scalar not found in getScalar!");
     abort();
     return Scalars[0];
@@ -740,29 +763,281 @@ public:
   }
 };
 
+static void addNodeMapping(DSNode *SrcNode, const PointerValSet &PVS,
+                           map<DSNode*, PointerValSet> &NodeMapping) {
+  for (unsigned i = 0, e = PVS.size(); i != e; ++i)
+    if (NodeMapping[SrcNode].add(PVS[i])) {  // Not in map yet?
+      assert(PVS[i].Index == 0 && "Node indexing not supported yet!");
+      DSNode *DestNode = PVS[i].Node;
+
+      // Loop over all of the outgoing links in the mapped graph
+      for (unsigned l = 0, le = DestNode->getNumOutgoingLinks(); l != le; ++l) {
+        PointerValSet &SrcSet = SrcNode->getOutgoingLink(l);
+        const PointerValSet &DestSet = DestNode->getOutgoingLink(l);
 
+        // Add all of the node mappings now!
+        for (unsigned si = 0, se = SrcSet.size(); si != se; ++si) {
+          assert(SrcSet[si].Index == 0 && "Can't handle node offset!");
+          addNodeMapping(SrcSet[si].Node, DestSet, NodeMapping);
+        }
+      }
+    }
+}
 
-static void addCallInfo(DataStructure *DS,
-                        TransformFunctionInfo &TFI, CallInst *CI, int Arg, 
-                        DSNode *GraphNode,
-                        map<DSNode*, PoolInfo> &PoolDescs) {
+// CalculateNodeMapping - There is a partial isomorphism between the graph
+// passed in and the graph that is actually used by the function.  We need to
+// figure out what this mapping is so that we can transformFunctionBody the
+// instructions in the function itself.  Note that every node in the graph that
+// we are interested in must be both in the local graph of the called function,
+// and in the local graph of the calling function.  Because of this, we only
+// define the mapping for these nodes [conveniently these are the only nodes we
+// CAN define a mapping for...]
+//
+// The roots of the graph that we are transforming is rooted in the arguments
+// passed into the function from the caller.  This is where we start our
+// mapping calculation.
+//
+// The NodeMapping calculated maps from the callers graph to the called graph.
+//
+static void CalculateNodeMapping(Function *F, TransformFunctionInfo &TFI,
+                                 FunctionDSGraph &CallerGraph,
+                                 FunctionDSGraph &CalledGraph, 
+                                 map<DSNode*, PointerValSet> &NodeMapping) {
+  int LastArgNo = -2;
+  for (unsigned i = 0, e = TFI.ArgInfo.size(); i != e; ++i) {
+    // Figure out what nodes in the called graph the TFI.ArgInfo[i].Node node
+    // corresponds to...
+    //
+    // Only consider first node of sequence.  Extra nodes may may be added
+    // to the TFI if the data structure requires more nodes than just the
+    // one the argument points to.  We are only interested in the one the
+    // argument points to though.
+    //
+    if (TFI.ArgInfo[i].ArgNo != LastArgNo) {
+      if (TFI.ArgInfo[i].ArgNo == -1) {
+        addNodeMapping(TFI.ArgInfo[i].Node, CalledGraph.getRetNodes(),
+                       NodeMapping);
+      } else {
+        // Figure out which node argument # ArgNo points to in the called graph.
+        Value *Arg = F->getArgumentList()[TFI.ArgInfo[i].ArgNo];     
+        addNodeMapping(TFI.ArgInfo[i].Node, CalledGraph.getValueMap()[Arg],
+                       NodeMapping);
+      }
+      LastArgNo = TFI.ArgInfo[i].ArgNo;
+    }
+  }
+}
+
+
+
+
+// addCallInfo - For a specified function call CI, figure out which pool
+// descriptors need to be passed in as arguments, and which arguments need to be
+// transformed into indices.  If Arg != -1, the specified call argument is
+// passed in as a pointer to a data structure.
+//
+void TransformFunctionInfo::addCallInfo(DataStructure *DS, CallInst *CI,
+                                        int Arg, DSNode *GraphNode,
+                                        map<DSNode*, PoolInfo> &PoolDescs) {
   assert(CI->getCalledFunction() && "Cannot handle indirect calls yet!");
-  assert(TFI.Func == 0 || TFI.Func == CI->getCalledFunction() &&
+  assert(Func == 0 || Func == CI->getCalledFunction() &&
          "Function call record should always call the same function!");
-  assert(TFI.Call == 0 || TFI.Call == CI &&
+  assert(Call == 0 || Call == CI &&
          "Call element already filled in with different value!");
-  TFI.Func = CI->getCalledFunction();
-  TFI.Call = CI;
-  //FunctionDSGraph &CalledGraph = DS->getClosedDSGraph(TFI.Func);
+  Func = CI->getCalledFunction();
+  Call = CI;
+  //FunctionDSGraph &CalledGraph = DS->getClosedDSGraph(Func);
 
   // For now, add the entire graph that is pointed to by the call argument.
   // This graph can and should be pruned to only what the function itself will
   // use, because often this will be a dramatically smaller subset of what we
   // are providing.
   //
+  // FIXME: This should use pool links instead of extra arguments!
+  //
   for (df_iterator<DSNode*> I = df_begin(GraphNode), E = df_end(GraphNode);
        I != E; ++I)
-    TFI.ArgInfo.push_back(CallArgInfo(Arg, *I, PoolDescs[*I].Handle));
+    ArgInfo.push_back(CallArgInfo(Arg, *I, PoolDescs[*I].Handle));
+}
+
+static void markReachableNodes(const PointerValSet &Vals,
+                               set<DSNode*> &ReachableNodes) {
+  for (unsigned n = 0, ne = Vals.size(); n != ne; ++n) {
+    DSNode *N = Vals[n].Node;
+    if (ReachableNodes.count(N) == 0)   // Haven't already processed node?
+      ReachableNodes.insert(df_begin(N), df_end(N)); // Insert all
+  }
+}
+
+// Make sure that all dependant arguments are added to this transformation info.
+// For example, if we call foo(null, P) and foo treats it's first and second
+// arguments as belonging to the same data structure, the we MUST add entries to
+// know that the null needs to be transformed into an index as well.
+//
+void TransformFunctionInfo::ensureDependantArgumentsIncluded(DataStructure *DS,
+                                           map<DSNode*, PoolInfo> &PoolDescs) {
+  // FIXME: This does not work for indirect function calls!!!
+  if (Func == 0) return;  // FIXME!
+
+  // Make sure argument entries are sorted.
+  finalizeConstruction();
+
+  // Loop over the function signature, checking to see if there are any pointer
+  // arguments that we do not convert...  if there is something we haven't
+  // converted, set done to false.
+  //
+  unsigned PtrNo = 0;
+  bool Done = true;
+  if (isa<PointerType>(Func->getReturnType()))    // Make sure we convert retval
+    if (PtrNo < ArgInfo.size() && ArgInfo[PtrNo++].ArgNo == -1) {
+      // We DO transform the ret val... skip all possible entries for retval
+      while (PtrNo < ArgInfo.size() && ArgInfo[PtrNo].ArgNo == -1)
+        PtrNo++;
+    } else {
+      Done = false;
+    }
+
+  for (unsigned i = 0, e = Func->getArgumentList().size(); i != e; ++i) {
+    Argument *Arg = Func->getArgumentList()[i];
+    if (isa<PointerType>(Arg->getType())) {
+      if (PtrNo < ArgInfo.size() && ArgInfo[PtrNo++].ArgNo == (int)i) {
+        // We DO transform this arg... skip all possible entries for argument
+        while (PtrNo < ArgInfo.size() && ArgInfo[PtrNo].ArgNo == (int)i)
+          PtrNo++;
+      } else {
+        Done = false;
+        break;
+      }
+    }
+  }
+
+  // If we already have entries for all pointer arguments and retvals, there
+  // certainly is no work to do.  Bail out early to avoid building relatively
+  // expensive data structures.
+  //
+  if (Done) return;
+
+#ifdef DEBUG_TRANSFORM_PROGRESS
+  cerr << "Must ensure dependant arguments for: " << Func->getName() << "\n";
+#endif
+
+  // Otherwise, we MIGHT have to add the arguments/retval if they are part of
+  // the same datastructure graph as some other argument or retval that we ARE
+  // processing.
+  //
+  // Get the data structure graph for the called function.
+  //
+  FunctionDSGraph &CalledDS = DS->getClosedDSGraph(Func);
+
+  // Build a mapping between the nodes in our current graph and the nodes in the
+  // called function's graph.  We build it based on our _incomplete_
+  // transformation information, because it contains all of the info that we
+  // should need.
+  //
+  map<DSNode*, PointerValSet> NodeMapping;
+  CalculateNodeMapping(Func, *this,
+                       DS->getClosedDSGraph(Call->getParent()->getParent()),
+                       CalledDS, NodeMapping);
+
+  // Build the inverted version of the node mapping, that maps from a node in
+  // the called functions graph to a single node in the caller graph.
+  // 
+  map<DSNode*, DSNode*> InverseNodeMap;
+  for (map<DSNode*, PointerValSet>::iterator I = NodeMapping.begin(),
+         E = NodeMapping.end(); I != E; ++I) {
+    PointerValSet &CalledNodes = I->second;
+    for (unsigned i = 0, e = CalledNodes.size(); i != e; ++i)
+      InverseNodeMap[CalledNodes[i].Node] = I->first;
+  }
+  NodeMapping.clear();  // Done with information, free memory
+  
+  // Build a set of reachable nodes from the arguments/retval that we ARE
+  // passing in...
+  set<DSNode*> ReachableNodes;
+
+  // Loop through all of the arguments, marking all of the reachable data
+  // structure nodes reachable if they are from this pointer...
+  //
+  for (unsigned i = 0, e = ArgInfo.size(); i != e; ++i) {
+    if (ArgInfo[i].ArgNo == -1) {
+      if (i == 0)   // Only process retvals once (performance opt)
+        markReachableNodes(CalledDS.getRetNodes(), ReachableNodes);
+    } else {  // If it's an argument value...
+      Argument *Arg = Func->getArgumentList()[ArgInfo[i].ArgNo];
+      if (isa<PointerType>(Arg->getType()))
+        markReachableNodes(CalledDS.getValueMap()[Arg], ReachableNodes);
+    }
+  }
+
+  // Now that we know which nodes are already reachable, see if any of the
+  // arguments that we are not passing values in for can reach one of the
+  // existing nodes...
+  //
+
+  // <FIXME> IN THEORY, we should allow arbitrary paths from the argument to
+  // nodes we know about.  The problem is that if we do this, then I don't know
+  // how to get pool pointers for this head list.  Since we are completely
+  // deadline driven, I'll just allow direct accesses to the graph. </FIXME>
+  //
+  
+  PtrNo = 0;
+  if (isa<PointerType>(Func->getReturnType()))    // Make sure we convert retval
+    if (PtrNo < ArgInfo.size() && ArgInfo[PtrNo++].ArgNo == -1) {
+      // We DO transform the ret val... skip all possible entries for retval
+      while (PtrNo < ArgInfo.size() && ArgInfo[PtrNo].ArgNo == -1)
+        PtrNo++;
+    } else {
+      // See what the return value points to...
+
+      // FIXME: This should generalize to any number of nodes, just see if any
+      // are reachable.
+      assert(CalledDS.getRetNodes().size() == 1 &&
+             "Assumes only one node is returned");
+      DSNode *N = CalledDS.getRetNodes()[0].Node;
+      
+      // If the return value is not marked as being passed in, but it NEEDS to
+      // be transformed, then make it known now.
+      //
+      if (ReachableNodes.count(N)) {
+#ifdef DEBUG_TRANSFORM_PROGRESS
+        cerr << "ensure dependant arguments adds return value entry!\n";
+#endif
+        addCallInfo(DS, Call, -1, InverseNodeMap[N], PoolDescs);
+
+        // Keep sorted!
+        finalizeConstruction();
+      }
+    }
+
+  for (unsigned i = 0, e = Func->getArgumentList().size(); i != e; ++i) {
+    Argument *Arg = Func->getArgumentList()[i];
+    if (isa<PointerType>(Arg->getType())) {
+      if (PtrNo < ArgInfo.size() && ArgInfo[PtrNo++].ArgNo == (int)i) {
+        // We DO transform this arg... skip all possible entries for argument
+        while (PtrNo < ArgInfo.size() && ArgInfo[PtrNo].ArgNo == (int)i)
+          PtrNo++;
+      } else {
+        // This should generalize to any number of nodes, just see if any are
+        // reachable.
+        assert(CalledDS.getValueMap()[Arg].size() == 1 &&
+               "Only handle case where pointing to one node so far!");
+
+        // If the arg is not marked as being passed in, but it NEEDS to
+        // be transformed, then make it known now.
+        //
+        DSNode *N = CalledDS.getValueMap()[Arg][0].Node;
+        if (ReachableNodes.count(N)) {
+#ifdef DEBUG_TRANSFORM_PROGRESS
+          cerr << "ensure dependant arguments adds for arg #" << i << "\n";
+#endif
+          addCallInfo(DS, Call, i, InverseNodeMap[N], PoolDescs);
+
+          // Keep sorted!
+          finalizeConstruction();
+        }
+      }
+    }
+  }
 }
 
 
@@ -833,7 +1108,7 @@ void PoolAllocate::transformFunctionBody(Function *F, FunctionDSGraph &IPFGraph,
     // Check to see if the scalar _IS_ a call...
     if (CallInst *CI = dyn_cast<CallInst>(ScalarVal))
       // If so, add information about the pool it will be returning...
-      addCallInfo(DS, CallMap[CI], CI, -1, Scalars[i].Pool.Node, PoolDescs);
+      CallMap[CI].addCallInfo(DS, CI, -1, Scalars[i].Pool.Node, PoolDescs);
 
     // Check to see if the scalar is an operand to a call...
     for (Value::use_iterator UI = ScalarVal->use_begin(),
@@ -848,18 +1123,26 @@ void PoolAllocate::transformFunctionBody(Function *F, FunctionDSGraph &IPFGraph,
         // than once!  It will get multiple entries for the first pointer.
 
         // Add the operand number and pool handle to the call table...
-        addCallInfo(DS, CallMap[CI], CI, OI-CI->op_begin()-1,
-                    Scalars[i].Pool.Node, PoolDescs);
+        CallMap[CI].addCallInfo(DS, CI, OI-CI->op_begin()-1,
+                                Scalars[i].Pool.Node, PoolDescs);
       }
     }
   }
 
+  // Make sure that all dependant arguments are added as well.  For example, if
+  // we call foo(null, P) and foo treats it's first and second arguments as
+  // belonging to the same data structure, the we MUST set up the CallMap to
+  // know that the null needs to be transformed into an index as well.
+  //
+  for (map<CallInst*, TransformFunctionInfo>::iterator I = CallMap.begin();
+       I != CallMap.end(); ++I)
+    I->second.ensureDependantArgumentsIncluded(DS, PoolDescs);
+
 #ifdef DEBUG_TRANSFORM_PROGRESS
   // Print out call map...
   for (map<CallInst*, TransformFunctionInfo>::iterator I = CallMap.begin();
        I != CallMap.end(); ++I) {
     cerr << "For call: " << I->first;
-    I->second.finalizeConstruction();
     cerr << I->second.Func->getName() << " must pass pool pointer for args #";
     for (unsigned i = 0; i < I->second.ArgInfo.size(); ++i)
       cerr << I->second.ArgInfo[i].ArgNo << ", ";
@@ -873,9 +1156,6 @@ void PoolAllocate::transformFunctionBody(Function *F, FunctionDSGraph &IPFGraph,
   //
   for (map<CallInst*, TransformFunctionInfo>::iterator I = CallMap.begin(),
          E = CallMap.end(); I != E; ++I) {
-    // Make sure the entries are sorted.
-    I->second.finalizeConstruction();
-
     // Transform all of the functions we need, or at least ensure there is a
     // cached version available.
     transformFunction(I->second, IPFGraph, PoolDescs);
@@ -965,7 +1245,6 @@ void PoolAllocate::transformFunctionBody(Function *F, FunctionDSGraph &IPFGraph,
       Argument *NewArg = new Argument(*TI, Arg->getName());
       XFormMap[Arg] = NewArg;  // Map old arg into new arg...
 
-
       // Replace the old argument and then delete it...
       delete F->getArgumentList().replaceWith(I, NewArg);
     }
@@ -994,70 +1273,6 @@ void PoolAllocate::transformFunctionBody(Function *F, FunctionDSGraph &IPFGraph,
   DS->invalidateFunction(F);
 }
 
-static void addNodeMapping(DSNode *SrcNode, const PointerValSet &PVS,
-                           map<DSNode*, PointerValSet> &NodeMapping) {
-  for (unsigned i = 0, e = PVS.size(); i != e; ++i)
-    if (NodeMapping[SrcNode].add(PVS[i])) {  // Not in map yet?
-      assert(PVS[i].Index == 0 && "Node indexing not supported yet!");
-      DSNode *DestNode = PVS[i].Node;
-
-      // Loop over all of the outgoing links in the mapped graph
-      for (unsigned l = 0, le = DestNode->getNumOutgoingLinks(); l != le; ++l) {
-        PointerValSet &SrcSet = SrcNode->getOutgoingLink(l);
-        const PointerValSet &DestSet = DestNode->getOutgoingLink(l);
-
-        // Add all of the node mappings now!
-        for (unsigned si = 0, se = SrcSet.size(); si != se; ++si) {
-          assert(SrcSet[si].Index == 0 && "Can't handle node offset!");
-          addNodeMapping(SrcSet[si].Node, DestSet, NodeMapping);
-        }
-      }
-    }
-}
-
-// CalculateNodeMapping - There is a partial isomorphism between the graph
-// passed in and the graph that is actually used by the function.  We need to
-// figure out what this mapping is so that we can transformFunctionBody the
-// instructions in the function itself.  Note that every node in the graph that
-// we are interested in must be both in the local graph of the called function,
-// and in the local graph of the calling function.  Because of this, we only
-// define the mapping for these nodes [conveniently these are the only nodes we
-// CAN define a mapping for...]
-//
-// The roots of the graph that we are transforming is rooted in the arguments
-// passed into the function from the caller.  This is where we start our
-// mapping calculation.
-//
-// The NodeMapping calculated maps from the callers graph to the called graph.
-//
-static void CalculateNodeMapping(Function *F, TransformFunctionInfo &TFI,
-                                 FunctionDSGraph &CallerGraph,
-                                 FunctionDSGraph &CalledGraph, 
-                                 map<DSNode*, PointerValSet> &NodeMapping) {
-  int LastArgNo = -2;
-  for (unsigned i = 0, e = TFI.ArgInfo.size(); i != e; ++i) {
-    // Figure out what nodes in the called graph the TFI.ArgInfo[i].Node node
-    // corresponds to...
-    //
-    // Only consider first node of sequence.  Extra nodes may may be added
-    // to the TFI if the data structure requires more nodes than just the
-    // one the argument points to.  We are only interested in the one the
-    // argument points to though.
-    //
-    if (TFI.ArgInfo[i].ArgNo != LastArgNo) {
-      if (TFI.ArgInfo[i].ArgNo == -1) {
-        addNodeMapping(TFI.ArgInfo[i].Node, CalledGraph.getRetNodes(),
-                       NodeMapping);
-      } else {
-        // Figure out which node argument # ArgNo points to in the called graph.
-        Value *Arg = F->getArgumentList()[TFI.ArgInfo[i].ArgNo];     
-        addNodeMapping(TFI.ArgInfo[i].Node, CalledGraph.getValueMap()[Arg],
-                       NodeMapping);
-      }
-      LastArgNo = TFI.ArgInfo[i].ArgNo;
-    }
-  }
-}
 
 
 // transformFunction - Transform the specified function the specified way.  It
@@ -1285,6 +1500,12 @@ void PoolAllocate::CreatePools(Function *F, const vector<AllocDSNode*> &Allocs,
     if (isa<ReturnInst>((*I)->getTerminator()))
       ReturnNodes.push_back(*I);
 
+#ifdef DEBUG_CREATE_POOLS
+  cerr << "Allocs that we are pool allocating:\n";
+  for (unsigned i = 0, e = Allocs.size(); i != e; ++i)
+    Allocs[i]->dump();
+#endif
+
   map<DSNode*, PATypeHolder> AbsPoolTyMap;
 
   // First pass over the allocations to process...