// // Method: getLocalPoolNodes() // // Description: // For a given function, determine which DSNodes for that function should have // local pools created for them. // void Heuristic::getLocalPoolNodes (const Function & F, DSNodeList_t & Nodes) { // // Get the DSGraph of the specified function. If the DSGraph has no nodes, // then there is nothing we need to do. // DSGraph* G = Graphs->getDSGraph(F); if (G->node_begin() == G->node_end()) return; // // Calculate which DSNodes are reachable from globals. If a node is reachable // from a global, we will create a global pool for it, so no argument passage // is required. Graphs->getGlobalsGraph(); // Map all node reachable from this global to the corresponding nodes in // the globals graph. DSGraph::NodeMapTy GlobalsGraphNodeMapping; G->computeGToGGMapping(GlobalsGraphNodeMapping); // // Loop over all of the nodes which are non-escaping, adding pool-allocatable // ones to the NodesToPA vector. In other words, scan over the DSGraph and // find nodes for which a new pool must be created within this function. // for (DSGraph::node_iterator I = G->node_begin(), E = G->node_end(); I != E; ++I){ // Get the DSNode and, if applicable, its mirror in the globals graph DSNode * N = I; DSNode * GGN = GlobalsGraphNodeMapping[N].getNode(); // // Only the following nodes are pool allocated: // 1) Local Heap nodes // 2) Nodes which are mirrored in the globals graph and, in the globals // graph, are heap nodes. // if ((N->isHeapNode()) || (GGN && GGN->isHeapNode())) { if (!(GlobalPoolNodes.count (N) || GlobalPoolNodes.count (GGN))) { // Otherwise, if it was not passed in from outside the function, it must // be a local pool! assert((!N->isGlobalNode() || N->isPtrToIntNode()) && "Should be in global mapping!"); if(!N->isPtrToIntNode()) { Nodes.push_back (N); } } } } return; }
// // Method: findGlobalPoolNodes() // // Description: // This method finds DSNodes that are reachable from globals and that need a // pool. The Automatic Pool Allocation transform will use the returned // information to build global pools for the DSNodes in question. // // Note that this method does not assign DSNodes to pools; it merely decides // which DSNodes are reachable from globals and will need a pool of global // scope. // // Outputs: // Nodes - The DSNodes that are both reachable from globals and which should // have global pools will be *added* to this container. // void AllHeapNodesHeuristic::findGlobalPoolNodes (DSNodeSet_t & Nodes) { // Get the globals graph for the program. DSGraph* GG = Graphs->getGlobalsGraph(); // Get all of the nodes reachable from globals. DenseSet<const DSNode*> GlobalHeapNodes; GetNodesReachableFromGlobals (GG, GlobalHeapNodes); // // Create a global pool for each global DSNode. // for (DenseSet<const DSNode *>::iterator NI = GlobalHeapNodes.begin(); NI != GlobalHeapNodes.end();++NI) { const DSNode * N = *NI; PoolMap[N] = OnePool(N); } // // Now find all DSNodes belonging to function-local DSGraphs which are // mirrored in the globals graph. These DSNodes require a global pool, too. // for (Module::iterator F = M->begin(); F != M->end(); ++F) { if (Graphs->hasDSGraph(*F)) { DSGraph* G = Graphs->getDSGraph(*F); DSGraph::NodeMapTy NodeMap; G->computeGToGGMapping (NodeMap); // // Scan through all DSNodes in the local graph. If a local DSNode has a // corresponding DSNode in the globals graph that is reachable from a // global, then add the local DSNode to the set of DSNodes reachable from // a global. // DSGraph::node_iterator ni = G->node_begin(); for (; ni != G->node_end(); ++ni) { DSNode * N = ni; DSNode * GGN = NodeMap[N].getNode(); //assert (!GGN || GlobalHeapNodes.count (GGN)); if (GGN && GlobalHeapNodes.count (GGN)) PoolMap[GGN].NodesInPool.push_back (N); } } } // // Copy the values into the output container. Note that DenseSet has no // iterator traits (or whatever allows us to treat DenseSet has a generic // container), so we have to use a loop to copy values from the DenseSet into // the output container. // for (DenseSet<const DSNode*>::iterator I = GlobalHeapNodes.begin(), E = GlobalHeapNodes.end(); I != E; ++I) { Nodes.insert (*I); } return; }
// // Function: GetNodesReachableFromGlobals() // // Description: // This function finds all DSNodes which are reachable from globals. It finds // DSNodes both within the local DSGraph as well as in the Globals graph that // are reachable from globals. // // Inputs: // G - The Globals Graph. // // Outputs: // NodesFromGlobals - A reference to a container object in which to record // DSNodes reachable from globals. DSNodes are *added* to // this container; it is not cleared by this function. // DSNodes from both the local and globals graph are added. static void GetNodesReachableFromGlobals (DSGraph* G, DenseSet<const DSNode*> &NodesFromGlobals) { // // Ensure that G is the globals graph. // assert (G->getGlobalsGraph() == 0); DSGraph * GlobalsGraph = G; // // Find all DSNodes which are reachable in the globals graph. // for (DSGraph::node_iterator NI = GlobalsGraph->node_begin(); NI != GlobalsGraph->node_end(); ++NI) { NI->markReachableNodes(NodesFromGlobals); } }
// Get all nodes in all function DSGraphs and the global DSGraph that contain // global values. void CSDataRando::findGlobalNodes(Module &M) { DSGraph *GG = DSA->getGlobalsGraph(); for (auto i = GG->node_begin(), e = GG->node_end(); i != e; i++) { GlobalNodes.insert(&*i); } for (Function &F : M) { if ((!F.isDeclaration()) && DSA->hasDSGraph(F)) { DSGraph *G = DSA->getDSGraph(F); FuncInfo &FI = FunctionInfo[&F]; DSGraph::NodeMapTy NodeMap; G->computeGToGGMapping(NodeMap); for (auto i : NodeMap) { GlobalNodes.insert(i.first); FI.ToGlobalNodeMap[i.first] = i.second.getNode(); } } } }
// // Function: FoldNodesInDSGraph() // // Description: // This function will take the specified DSGraph and fold all DSNodes within // it that are marked with the heap flag. // static void FoldNodesInDSGraph (DSGraph & Graph) { // Worklist of heap nodes to process std::vector<DSNodeHandle> HeapNodes; // // Go find all of the heap nodes. // DSGraph::node_iterator i; DSGraph::node_iterator e = Graph.node_end(); for (i = Graph.node_begin(); i != e; ++i) { DSNode * Node = i; if (Node->isHeapNode()) HeapNodes.push_back (DSNodeHandle(Node)); } // // Fold all of the heap nodes; this makes them type-unknown. // for (unsigned i = 0; i < HeapNodes.size(); ++i) HeapNodes[i].getNode()->foldNodeCompletely(); return; }
// // Function: GetNodesReachableFromGlobals() // // Description: // This function finds all DSNodes which are reachable from globals. It finds // DSNodes both within the local DSGraph as well as in the Globals graph that // are reachable from globals. It does, however, filter out those DSNodes // which are of no interest to automatic pool allocation. // // Inputs: // G - The DSGraph for which to find DSNodes which are reachable by globals. // This DSGraph can either by a DSGraph associated with a function *or* // it can be the globals graph itself. // // Outputs: // NodesFromGlobals - A reference to a container object in which to record // DSNodes reachable from globals. DSNodes are *added* to // this container; it is not cleared by this function. // DSNodes from both the local and globals graph are added. void AllHeapNodesHeuristic::GetNodesReachableFromGlobals (DSGraph* G, DenseSet<const DSNode*> &NodesFromGlobals) { // // Get the globals graph associated with this DSGraph. If the globals graph // is NULL, then the graph that was passed in *is* the globals graph. // DSGraph * GlobalsGraph = G->getGlobalsGraph(); if (!GlobalsGraph) GlobalsGraph = G; // // Find all DSNodes which are reachable in the globals graph. // for (DSGraph::node_iterator NI = GlobalsGraph->node_begin(); NI != GlobalsGraph->node_end(); ++NI) { NI->markReachableNodes(NodesFromGlobals); } // // Remove those global nodes which we know will never be pool allocated. // std::vector<const DSNode *> toRemove; for (DenseSet<const DSNode*>::iterator I = NodesFromGlobals.begin(), E = NodesFromGlobals.end(); I != E; ) { DenseSet<const DSNode*>::iterator Last = I; ++I; const DSNode *tmp = *Last; if (!(tmp->isHeapNode())) toRemove.push_back (tmp); // Do not poolallocate nodes that are cast to Int. // As we do not track through ints, these could be escaping if (tmp->isPtrToIntNode()) toRemove.push_back(tmp); } // // Remove all globally reachable DSNodes which do not require pools. // for (unsigned index = 0; index < toRemove.size(); ++index) { NodesFromGlobals.erase(toRemove[index]); } // // Now the fun part. Find DSNodes in the local graph that correspond to // those nodes reachable in the globals graph. Add them to the set of // reachable nodes, too. // if (G->getGlobalsGraph()) { // // Compute a mapping between local DSNodes and DSNodes in the globals // graph. // DSGraph::NodeMapTy NodeMap; G->computeGToGGMapping (NodeMap); // // Scan through all DSNodes in the local graph. If a local DSNode has a // corresponding DSNode in the globals graph that is reachable from a // global, then add the local DSNode to the set of DSNodes reachable from a // global. // // FIXME: A node's existance within the global DSGraph is probably // sufficient evidence that it is reachable from a global. // DSGraph::node_iterator ni = G->node_begin(); for (; ni != G->node_end(); ++ni) { DSNode * N = ni; if (NodesFromGlobals.count (NodeMap[N].getNode())) NodesFromGlobals.insert (N); } } }
// // Method: findGlobalPoolNodes() // // Description: // This method finds DSNodes that are reachable from globals and that need a // pool. The Automatic Pool Allocation transform will use the returned // information to build global pools for the DSNodes in question. // // For efficiency, this method also determines which DSNodes should be in the // same pool. // // Outputs: // Nodes - The DSNodes that are both reachable from globals and which should // have global pools will be *added* to this container. // void AllNodesHeuristic::findGlobalPoolNodes (DSNodeSet_t & Nodes) { // Get the globals graph for the program. DSGraph* GG = Graphs->getGlobalsGraph(); // // Get all of the nodes reachable from globals. // DenseSet<const DSNode*> GlobalNodes; GetNodesReachableFromGlobals (GG, GlobalNodes); // // Create a global pool for each global DSNode. // for (DenseSet<const DSNode *>::iterator NI = GlobalNodes.begin(); NI != GlobalNodes.end(); ++NI) { const DSNode * N = *NI; PoolMap[N] = OnePool(N); } // // Now find all DSNodes belonging to function-local DSGraphs which are // mirrored in the globals graph. These DSNodes require a global pool, too, // but must use the same pool as the one assigned to the corresponding global // DSNode. // for (Module::iterator F = M->begin(); F != M->end(); ++F) { // // Ignore functions that have no DSGraph. // if (!(Graphs->hasDSGraph(*F))) continue; // // Compute a mapping between local DSNodes and DSNodes in the globals // graph. // DSGraph* G = Graphs->getDSGraph(*F); DSGraph::NodeMapTy NodeMap; G->computeGToGGMapping (NodeMap); // // Scan through all DSNodes in the local graph. If a local DSNode has a // corresponding DSNode in the globals graph that is reachable from a // global, then add the local DSNode to the set of DSNodes reachable from // a global. // DSGraph::node_iterator ni = G->node_begin(); for (; ni != G->node_end(); ++ni) { DSNode * N = ni; DSNode * GGN = NodeMap[N].getNode(); assert (!GGN || GlobalNodes.count (GGN)); if (GGN && GlobalNodes.count (GGN)) PoolMap[GGN].NodesInPool.push_back (N); } } // // Scan through all the local graphs looking for DSNodes which may be // reachable by a global. These nodes may not end up in the globals graph // because of the fact that DSA doesn't actually know what is happening to // them. // // FIXME: I believe this code causes a condition in which a local DSNode is // given a local pool in one function but not in other functions. // Someone needs to investigate whether DSA is being consistent here, // and if not, if that inconsistency is correct. // #if 0 for (Module::iterator F = M->begin(); F != M->end(); ++F) { if (F->isDeclaration()) continue; DSGraph* G = Graphs->getDSGraph(*F); for (DSGraph::node_iterator I = G->node_begin(), E = G->node_end(); I != E; ++I) { DSNode * Node = I; if (Node->isExternalNode() || Node->isUnknownNode()) { GlobalNodes.insert (Node); } } } #endif // // Copy the values into the output container. Note that DenseSet has no // iterator traits (or whatever allows us to treat DenseSet has a generic // container), so we have to use a loop to copy values from the DenseSet into // the output container. // // Note that we do not copy local DSNodes into the output container; we // merely copy those nodes in the globals graph. // for (DenseSet<const DSNode*>::iterator I = GlobalNodes.begin(), E = GlobalNodes.end(); I != E; ++I) { Nodes.insert (*I); } return; }
static void printCollection(const Collection &C, llvm::raw_ostream &O, const Module *M, const std::string &Prefix) { if (M == 0) { O << "Null Module pointer, cannot continue!\n"; return; } unsigned TotalNumNodes = 0, TotalCallNodes = 0; for (Module::const_iterator I = M->begin(), E = M->end(); I != E; ++I) if (C.hasDSGraph(*I)) { DSGraph* Gr = C.getDSGraph((const Function&)*I); unsigned NumCalls = Gr->shouldUseAuxCalls() ? Gr->getAuxFunctionCalls().size() : Gr->getFunctionCalls().size(); bool IsDuplicateGraph = false; //if no only print options, print everything bool doPrint = OnlyPrint.begin() == OnlyPrint.end(); //otherwise check the name if (!doPrint) doPrint = OnlyPrint.end() != std::find(OnlyPrint.begin(), OnlyPrint.end(), I->getName().str()); if (doPrint) { const Function *SCCFn = Gr->retnodes_begin()->first; if (&*I == SCCFn) { Gr->writeGraphToFile(O, Prefix+I->getName().str()); } else { IsDuplicateGraph = true; // Don't double count node/call nodes. O << "Didn't write '" << Prefix+I->getName().str() << ".dot' - Graph already emitted to '" << Prefix+SCCFn->getName().str() << "\n"; } } else { const Function *SCCFn = Gr->retnodes_begin()->first; if (&*I == SCCFn) { //O << "Skipped Writing '" << Prefix+I->getName().str() << ".dot'... [" // << Gr->getGraphSize() << "+" << NumCalls << "]\n"; } else { IsDuplicateGraph = true; // Don't double count node/call nodes. } } if (!IsDuplicateGraph) { unsigned GraphSize = Gr->getGraphSize(); if (MaxGraphSize < GraphSize) MaxGraphSize = GraphSize; TotalNumNodes += Gr->getGraphSize(); TotalCallNodes += NumCalls; for (DSGraph::node_iterator NI = Gr->node_begin(), E = Gr->node_end(); NI != E; ++NI) if (NI->isNodeCompletelyFolded()) ++NumFoldedNodes; } } DSGraph* GG = C.getGlobalsGraph(); TotalNumNodes += GG->getGraphSize(); TotalCallNodes += GG->getFunctionCalls().size(); GG->writeGraphToFile(O, Prefix + "GlobalsGraph"); O << "\nGraphs contain [" << TotalNumNodes << "+" << TotalCallNodes << "] nodes total\n"; }