[llvm-commits] [poolalloc] r111299 - in /poolalloc/trunk/lib/PoolAllocate: PoolAllocate.cpp TransformFunctionBody.cpp

John Criswell criswell at uiuc.edu
Tue Aug 17 14:49:53 PDT 2010


Author: criswell
Date: Tue Aug 17 16:49:53 2010
New Revision: 111299

URL: http://llvm.org/viewvc/llvm-project?rev=111299&view=rev
Log:
PoolAllocate.cpp:
Modified code so that we assign DSNodes to global pools more consistently.
Also rewrote logic that determines whether we have already assigned a global
pool for a value or whether a local pool needs to be created.
Added comments.

TransformFunctionBody.cpp:
Added the verifyCallees() method to verify properties of targets of indirect
function calls.
Added code so that we attempt to look up indirect function call targets by
mapping the call instruction back to its original, non-cloned instruction and
then consulting the DSCallGraph.
Modified code that consults DSNodes directly for call graph information to grab
the first function target that has a DSGraph.
Added comments.

Modified:
    poolalloc/trunk/lib/PoolAllocate/PoolAllocate.cpp
    poolalloc/trunk/lib/PoolAllocate/TransformFunctionBody.cpp

Modified: poolalloc/trunk/lib/PoolAllocate/PoolAllocate.cpp
URL: http://llvm.org/viewvc/llvm-project/poolalloc/trunk/lib/PoolAllocate/PoolAllocate.cpp?rev=111299&r1=111298&r2=111299&view=diff
==============================================================================
--- poolalloc/trunk/lib/PoolAllocate/PoolAllocate.cpp (original)
+++ poolalloc/trunk/lib/PoolAllocate/PoolAllocate.cpp Tue Aug 17 16:49:53 2010
@@ -184,18 +184,20 @@
       ClonedFunctions.insert(Clone);
     }
   }
-  
+
   //
-  // Now that all call targets are available, rewrite the function bodies of the
-  // clones or the original function (if the original has no clone).
+  // Now that all call targets are available, rewrite the function bodies of
+  // the clones or the original function (if the original has no clone).
   //
   // FIXME: Use utility methods to make this code more readable!
-  for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I)
+  //
+  for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) {
     if (!I->isDeclaration() && !ClonedFunctions.count(I) &&
         Graphs->hasDSGraph(*I)) {
       std::map<Function*, Function*>::iterator FI = FuncMap.find(I);
       ProcessFunctionBody(*I, FI != FuncMap.end() ? *FI->second : *I);
     }
+  }
 
   //
   // Replace any remaining uses of original functions with the transformed
@@ -244,11 +246,12 @@
 
       Constant* CEnew = ConstantExpr::getPointerCast(I->second, F->getType());
 
-      // Must handle Constants specially, we cannot call replaceUsesOfWith on a
-      // constant because they are uniqued.
+      //
+      // We must handle Constants specially; we cannot call replaceUsesOfWith()
+      // on a constant because they are uniqued.
+      //
       if (Constant *C = dyn_cast<Constant>(user)) {
         if (!isa<GlobalValue>(C)) {
-
           //
           // Scan through all operands in the constant.  If they are the
           // function that we want to replace, then add them to a worklist (we
@@ -551,6 +554,11 @@
       // All DSNodes reachable from arguments must be passed in.
       //
       DSGraph::ScalarMapTy::iterator AI = G->getScalarMap().find(I);
+
+      //
+      // Assert that we either have a non-pointer parameter or that we have a
+      // an entry in the Scalar Map for this item.
+      //
       if (AI != G->getScalarMap().end()) {
         if (DSNode *N = AI->second.getNode()) {
           //
@@ -678,7 +686,7 @@
   //
   // Create the new function...
   //
-  Function *New = Function::Create(FuncTy, Function::InternalLinkage, F.getName());
+  Function *New = Function::Create(FuncTy, Function::InternalLinkage, F.getNameStr() + "_clone");
   F.getParent()->getFunctionList().insert(&F, New);
   CloneToOrigMap[New] = &F;   // Remember original function.
 
@@ -839,6 +847,13 @@
           Node->isUnknownNode()) {
         GlobalHeapNodes.insert (Node);
       }
+
+      //
+      // If a DSNode is used as an array and bounds checking is enabled,
+      // then also give it a global node.
+      //
+      if (BoundsChecksEnabled && (Node->isArrayNode()))
+        GlobalHeapNodes.insert (Node);
     }
   }
 
@@ -1050,6 +1065,7 @@
     //  3) Nodes which are mirrored in the globals graph and are heap nodes.
     //
     DSNode *N = I;
+#if 0
     if ((N->isHeapNode()) || (BoundsChecksEnabled && (N->isArrayNode())) ||
     	(GlobalsGraphNodeMapping.count(N) &&
        GlobalsGraphNodeMapping[N].getNode()->isHeapNode())) {
@@ -1065,6 +1081,23 @@
         FI.NodesToPA.push_back(N);
       }
     }
+#else
+    if ((N->isHeapNode()) || (BoundsChecksEnabled && (N->isArrayNode())) ||
+    	(GlobalsGraphNodeMapping.count(N) &&
+       GlobalsGraphNodeMapping[N].getNode()->isHeapNode())) {
+      DSNode *GGN = GlobalsGraphNodeMapping[N].getNode();
+      if (GlobalNodes[N]) {
+        FI.PoolDescriptors[N] = GlobalNodes[N];
+      } else if (GlobalNodes[GGN]) {
+        FI.PoolDescriptors[N] = GlobalNodes[GGN];
+      } else if (!MarkedNodes.count(N)) {
+        // Otherwise, if it was not passed in from outside the function, it must
+        // be a local pool!
+        assert(!N->isGlobalNode() && "Should be in global mapping!");
+        FI.NodesToPA.push_back(N);
+      }
+    }
+#endif
   }
 
   //
@@ -1088,6 +1121,11 @@
   if (!FI.NodesToPA.empty())
     InitializeAndDestroyPools(NewF, FI.NodesToPA, FI.PoolDescriptors,
                               PoolUses, PoolFrees);
+
+  //
+  // Some heuristics want to do special transformation to the function.  Let
+  // them do so here.
+  //
   CurHeuristic->HackFunctionBody(NewF, FI.PoolDescriptors);
 }
 

Modified: poolalloc/trunk/lib/PoolAllocate/TransformFunctionBody.cpp
URL: http://llvm.org/viewvc/llvm-project/poolalloc/trunk/lib/PoolAllocate/TransformFunctionBody.cpp?rev=111299&r1=111298&r2=111299&view=diff
==============================================================================
--- poolalloc/trunk/lib/PoolAllocate/TransformFunctionBody.cpp (original)
+++ poolalloc/trunk/lib/PoolAllocate/TransformFunctionBody.cpp Tue Aug 17 16:49:53 2010
@@ -132,6 +132,8 @@
     }
 
     Function* retCloneIfFunc(Value *V);
+
+    void verifyCallees (const std::vector<const Function *> & Functions);
   };
 }
 
@@ -143,6 +145,58 @@
   FuncTransform(*this, g, fi, poolUses, poolFrees).visit(F);
 }
 
+//
+// Method: verifyCallees()
+//
+// Description:
+//  This method performs various sanity checks on targets of indirect function
+//  calls.
+//
+void
+FuncTransform::verifyCallees (const std::vector<const Function *> & Functions) {
+  //
+  // There's nothing to do if there's no function call targets at all.
+  //
+  if (Functions.size() == 0)
+    return;
+
+  //
+  // Get the number of pool arguments for the first function.
+  //
+  unsigned numPoolArgs = PAInfo.getFuncInfo(*Functions[0])->ArgNodes.size();
+
+  //
+  // Get the DSGraph of the first function.
+  //
+  DataStructures& Graphs = PAInfo.getGraphs();
+  DSGraph * firstGraph = Graphs.getDSGraph (*Functions[0]);
+
+  //
+  // Scan through all other indirect function call targets.  Ensure that these
+  // functions have the same number of pool arguments and the same DSGraph as
+  // the first function.
+  //
+  for (unsigned index = 1; index < Functions.size(); ++index) {
+    //
+    // Get the function information for the function.
+    //
+    const Function * F = Functions[index];
+    FuncInfo *FI = PAInfo.getFuncInfo(*F);
+
+    //
+    // Get the DSGraph.
+    //
+    DSGraph * G = Graphs.getDSGraph (*Functions[index]);
+
+    //
+    // Assert that the graph and number of pool arguments are consistent.
+    //
+    assert (G == firstGraph);
+    assert (FI->ArgNodes.size() == numPoolArgs);
+  }
+
+  return;
+}
 
 // Returns the clone if  V is a static function (not a pointer) and belongs 
 // to an equivalence class i.e. is pool allocated
@@ -743,6 +797,7 @@
     }
   }
 
+  //
   // We need to figure out which local pool descriptors correspond to the pool
   // descriptor arguments passed into the function call.  Calculate a mapping
   // from callee DSNodes to caller DSNodes.  We construct a partial isomophism
@@ -760,11 +815,24 @@
   // merged.
   if (CF) {   // Direct calls are nice and simple.
     DEBUG(errs() << "  Handling direct call: " << *TheCall);
+
+    //
+    // Do not try to add pool handles to the function if it:
+    //  a) Already calls a cloned function; or
+    //  b) Calls a function which was never cloned.
+    //
+    // For such a call, just replace any arguments that take original functions
+    // with their cloned function poiner values.
+    //
     FuncInfo *CFI = PAInfo.getFuncInfo(*CF);
     if (CFI == 0 || CFI->Clone == 0) {   // Nothing to transform...
       visitInstruction(*TheCall);
       return;
     }
+
+    //
+    // Oh, dear.  We must add pool descriptors to this direct call.
+    //
     NewCallee = CFI->Clone;
     ArgNodes = CFI->ArgNodes;
     
@@ -781,29 +849,45 @@
     Instruction *OrigInst =
       cast<Instruction>(getOldValueIfAvailable(CS.getInstruction()));
 
-    DSCallGraph::callee_iterator I = Graphs.getCallGraph().callee_begin(CS);
-    if (I != Graphs.getCallGraph().callee_end(CS))
+    //
+    // Attempt to get one of the function targets of this indirect call site by
+    // looking at the call graph constructed by the points-to analysis.  Be
+    // sure to use the original call site from the original function; the
+    // points-to analysis has no information on the clones we've created.
+    //
+    const DSCallGraph & callGraph = Graphs.getCallGraph();
+    DSCallGraph::callee_iterator I = callGraph.callee_begin(OrigInst);
+    if (I != callGraph.callee_end(OrigInst))
       CF = *I;
-    
+
+    //
     // If we didn't find the callee in the constructed call graph, try
     // checking in the DSNode itself.
     // This isn't ideal as it means that this call site didn't have inlining
     // happen.
+    //
     if (!CF) {
       DSGraph* dg = Graphs.getDSGraph(*OrigInst->getParent()->getParent());
       DSNode* d = dg->getNodeForValue(OrigInst->getOperand(0)).getNode();
       assert (d && "No DSNode!\n");
       std::vector<const Function*> g;
       d->addFullFunctionList(g);
-      if (g.size()) {
-        EquivalenceClasses< const GlobalValue *> & EC = dg->getGlobalECs();
-        for(std::vector<const Function*>::const_iterator ii = g.begin(), ee = g.end();
-            !CF && ii != ee; ++ii) {
-          for (EquivalenceClasses<const GlobalValue *>::member_iterator MI = EC.findLeader(*ii);
-               MI != EC.member_end(); ++MI)   // Loop over members in this set.
-            if ((CF = dyn_cast<Function>(*MI))) {
-              break;
-            }
+
+      //
+      // Perform some consistency checks on the callees.
+      //
+      verifyCallees (g);
+
+      //
+      // If we found any callees, grab the first one with a DSGraph and use it.
+      // Since we're using EQBU/EQTD, all potential targets should have the
+      // same DSGraph, so it doesn't matter which one we use as long as we use
+      // a function that *has* a DSGraph.
+      //
+      for (unsigned index = 0; index < g.size(); ++index) {
+        if (Graphs.hasDSGraph (*(g[index]))) {
+          CF = g[index];
+          break;
         }
       }
     }
@@ -834,10 +918,13 @@
 #ifndef NDEBUG
     // Verify that all potential callees at call site have the same DS graph.
     DSCallGraph::callee_iterator E = Graphs.getCallGraph().callee_end(OrigInst);
-    for (; I != E; ++I)
-      if (!(*I)->isDeclaration())
+    for (; I != E; ++I) {
+      const Function * F = *I;
+      assert (F);
+      if (!(F)->isDeclaration())
         assert(CalleeGraph == Graphs.getDSGraph(**I) &&
                "Callees at call site do not have a common graph!");
+    }
 #endif    
 
     // Find the DS nodes for the arguments that need to be added, if any.
@@ -998,13 +1085,17 @@
     UpdateNewToOldValueMap(TheCall, NewCall);
   }
 
+  //
+  // Copy over the calling convention and attributes of the original call
+  // instruction to the new call instruction.
+  //
   CallSite(NewCall).setCallingConv(CallSite(TheCall).getCallingConv());
 
   TheCall->eraseFromParent();
   visitInstruction(*NewCall);
 }
 
-
+//
 // visitInstruction - For all instructions in the transformed function bodies,
 // replace any references to the original calls with references to the
 // transformed calls.  Many instructions can "take the address of" a function,
@@ -1012,6 +1103,7 @@
 // reference to the new, transformed, function.
 // FIXME: Don't rename uses of function names that escape
 // FIXME: Special-case when external user is pthread_create (or similar)?
+//
 void FuncTransform::visitInstruction(Instruction &I) {
   for (unsigned i = 0, e = I.getNumOperands(); i != e; ++i)
     if (Function *clonedFunc = retCloneIfFunc(I.getOperand(i))) {





More information about the llvm-commits mailing list