diff --git a/lib/Transforms/IPO/OldPoolAllocate.cpp b/lib/Transforms/IPO/OldPoolAllocate.cpp index 2b5ba858154..1e63381c893 100644 --- a/lib/Transforms/IPO/OldPoolAllocate.cpp +++ b/lib/Transforms/IPO/OldPoolAllocate.cpp @@ -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 &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 &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 { 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 &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 &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; + } + } +} -static void addCallInfo(DataStructure *DS, - TransformFunctionInfo &TFI, CallInst *CI, int Arg, - DSNode *GraphNode, - map &PoolDescs) { + + +// 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 &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 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 &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 &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(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(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 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 InverseNodeMap; + for (map::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 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(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... + // + + // 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. + // + + PtrNo = 0; + if (isa(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(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(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::iterator I = CallMap.begin(); + I != CallMap.end(); ++I) + I->second.ensureDependantArgumentsIncluded(DS, PoolDescs); + #ifdef DEBUG_TRANSFORM_PROGRESS // Print out call map... for (map::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::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 &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 &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 &Allocs, if (isa((*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 AbsPoolTyMap; // First pass over the allocations to process...