[llvm-commits] CVS: llvm-poolalloc/lib/DSA/BottomUpClosure.cpp DataStructure.cpp Local.cpp Steensgaard.cpp TopDownClosure.cpp
Andrew Lenharth
alenhar2 at cs.uiuc.edu
Wed Apr 11 10:38:05 PDT 2007
Changes in directory llvm-poolalloc/lib/DSA:
BottomUpClosure.cpp updated: 1.130 -> 1.131
DataStructure.cpp updated: 1.259 -> 1.260
Local.cpp updated: 1.168 -> 1.169
Steensgaard.cpp updated: 1.69 -> 1.70
TopDownClosure.cpp updated: 1.98 -> 1.99
---
Log message:
Minor refactoring, and cutting out stuff that should be (and is) in another branch
---
Diffs of the changes: (+396 -821)
BottomUpClosure.cpp | 198 ------------
DataStructure.cpp | 219 ++++++++++++--
Local.cpp | 797 ++++++++++++----------------------------------------
Steensgaard.cpp | 1
TopDownClosure.cpp | 2
5 files changed, 396 insertions(+), 821 deletions(-)
Index: llvm-poolalloc/lib/DSA/BottomUpClosure.cpp
diff -u llvm-poolalloc/lib/DSA/BottomUpClosure.cpp:1.130 llvm-poolalloc/lib/DSA/BottomUpClosure.cpp:1.131
--- llvm-poolalloc/lib/DSA/BottomUpClosure.cpp:1.130 Fri Feb 23 16:49:32 2007
+++ llvm-poolalloc/lib/DSA/BottomUpClosure.cpp Wed Apr 11 12:37:43 2007
@@ -30,120 +30,8 @@
STATISTIC (NumBUInlines, "Number of graphs inlined");
STATISTIC (NumCallEdges, "Number of 'actual' call edges");
- cl::opt<bool>
- AddGlobals("budatastructures-annotate-calls", cl::Hidden,
- cl::desc("Annotate call sites with functions as they are resolved"));
- cl::opt<bool>
- UpdateGlobals("budatastructures-update-from-globals", cl::Hidden,
- cl::desc("Update local graph from global graph when processing function"));
-
RegisterPass<BUDataStructures>
- X("budatastructure", "Bottom-up Data Structure Analysis");
-}
-
-static bool GetAllCalleesN(const DSCallSite &CS,
- std::vector<Function*> &Callees);
-
-/// BuildGlobalECs - Look at all of the nodes in the globals graph. If any node
-/// contains multiple globals, DSA will never, ever, be able to tell the globals
-/// apart. Instead of maintaining this information in all of the graphs
-/// throughout the entire program, store only a single global (the "leader") in
-/// the graphs, and build equivalence classes for the rest of the globals.
-static void BuildGlobalECs(DSGraph &GG, std::set<GlobalValue*> &ECGlobals) {
- DSScalarMap &SM = GG.getScalarMap();
- EquivalenceClasses<GlobalValue*> &GlobalECs = SM.getGlobalECs();
- for (DSGraph::node_iterator I = GG.node_begin(), E = GG.node_end();
- I != E; ++I) {
- if (I->getGlobalsList().size() <= 1) continue;
-
- // First, build up the equivalence set for this block of globals.
- const std::vector<GlobalValue*> &GVs = I->getGlobalsList();
- GlobalValue *First = GVs[0];
- for (unsigned i = 1, e = GVs.size(); i != e; ++i)
- GlobalECs.unionSets(First, GVs[i]);
-
- // Next, get the leader element.
- assert(First == GlobalECs.getLeaderValue(First) &&
- "First did not end up being the leader?");
-
- // Next, remove all globals from the scalar map that are not the leader.
- assert(GVs[0] == First && "First had to be at the front!");
- for (unsigned i = 1, e = GVs.size(); i != e; ++i) {
- ECGlobals.insert(GVs[i]);
- SM.erase(SM.find(GVs[i]));
- }
-
- // Finally, change the global node to only contain the leader.
- I->clearGlobals();
- I->addGlobal(First);
- }
-
- DEBUG(GG.AssertGraphOK());
-}
-
-/// EliminateUsesOfECGlobals - Once we have determined that some globals are in
-/// really just equivalent to some other globals, remove the globals from the
-/// specified DSGraph (if present), and merge any nodes with their leader nodes.
-static void EliminateUsesOfECGlobals(DSGraph &G,
- const std::set<GlobalValue*> &ECGlobals) {
- DSScalarMap &SM = G.getScalarMap();
- EquivalenceClasses<GlobalValue*> &GlobalECs = SM.getGlobalECs();
-
- bool MadeChange = false;
- for (DSScalarMap::global_iterator GI = SM.global_begin(), E = SM.global_end();
- GI != E; ) {
- GlobalValue *GV = *GI++;
- if (!ECGlobals.count(GV)) continue;
-
- const DSNodeHandle &GVNH = SM[GV];
- assert(!GVNH.isNull() && "Global has null NH!?");
-
- // Okay, this global is in some equivalence class. Start by finding the
- // leader of the class.
- GlobalValue *Leader = GlobalECs.getLeaderValue(GV);
-
- // If the leader isn't already in the graph, insert it into the node
- // corresponding to GV.
- if (!SM.global_count(Leader)) {
- GVNH.getNode()->addGlobal(Leader);
- SM[Leader] = GVNH;
- } else {
- // Otherwise, the leader is in the graph, make sure the nodes are the
- // merged in the specified graph.
- const DSNodeHandle &LNH = SM[Leader];
- if (LNH.getNode() != GVNH.getNode())
- LNH.mergeWith(GVNH);
- }
-
- // Next step, remove the global from the DSNode.
- GVNH.getNode()->removeGlobal(GV);
-
- // Finally, remove the global from the ScalarMap.
- SM.erase(GV);
- MadeChange = true;
- }
-
- DEBUG(if(MadeChange) G.AssertGraphOK());
-}
-
-static void AddGlobalToNode(BUDataStructures* B, DSCallSite D, Function* F) {
- if(!AddGlobals)
- return;
- if(D.isIndirectCall()) {
- DSGraph* GI = &B->getDSGraph(D.getCaller());
- DSNodeHandle& NHF = GI->getNodeForValue(F);
- DSCallSite DL = GI->getDSCallSiteForCallSite(D.getCallSite());
- if (DL.getCalleeNode() != NHF.getNode() || NHF.isNull()) {
- if (NHF.isNull()) {
- DSNode *N = new DSNode(F->getType()->getElementType(), GI); // Create the node
- N->addGlobal(F);
- NHF.setTo(N,0);
- DOUT << "Adding " << F->getName() << " to a call node in "
- << D.getCaller().getName() << "\n";
- }
- DL.getCalleeNode()->mergeWith(NHF, 0);
- }
- }
+ X("dsa-bu", "Bottom-up Data Structure Analysis");
}
// run - Calculate the bottom up data structure graphs for each function in the
@@ -151,6 +39,9 @@
//
bool BUDataStructures::runOnModule(Module &M) {
LocalDataStructures &LocalDSA = getAnalysis<LocalDataStructures>();
+ setGraphSource(&LocalDSA);
+ setTargetData(LocalDSA.getTargetData());
+ setGraphClone(false);
GlobalECs = LocalDSA.getGlobalECs();
GlobalsGraph = new DSGraph(LocalDSA.getGlobalsGraph(), GlobalECs);
@@ -197,17 +88,7 @@
// Mark external globals incomplete.
GlobalsGraph->markIncompleteNodes(DSGraph::IgnoreGlobals);
- // Grow the equivalence classes for the globals to include anything that we
- // now know to be aliased.
- std::set<GlobalValue*> ECGlobals;
- BuildGlobalECs(*GlobalsGraph, ECGlobals);
- if (!ECGlobals.empty()) {
- NamedRegionTimer X("Bottom-UP EC Cleanup");
- DOUT << "Eliminating " << ECGlobals.size() << " EC Globals!\n";
- for (hash_map<Function*, DSGraph*>::iterator I = DSInfo.begin(),
- E = DSInfo.end(); I != E; ++I)
- EliminateUsesOfECGlobals(*I->second, ECGlobals);
- }
+ formGlobalECs();
// Merge the globals variables (not the calls) from the globals graph back
// into the main function's graph so that the main function contains all of
@@ -228,23 +109,6 @@
MainGraph.maskIncompleteMarkers();
MainGraph.markIncompleteNodes(DSGraph::MarkFormalArgs |
DSGraph::IgnoreGlobals);
-
- //Debug messages if along the way we didn't resolve a call site
- //also update the call graph and callsites we did find.
- for(DSGraph::afc_iterator ii = MainGraph.afc_begin(),
- ee = MainGraph.afc_end(); ii != ee; ++ii) {
- std::vector<Function*> Funcs;
- GetAllCalleesN(*ii, Funcs);
- DOUT << "Lost site\n";
- DEBUG(ii->getCallSite().getInstruction()->dump());
- for (std::vector<Function*>::iterator iif = Funcs.begin(), eef = Funcs.end();
- iif != eef; ++iif) {
- AddGlobalToNode(this, *ii, *iif);
- DOUT << "Adding\n";
- ActualCallees.insert(std::make_pair(ii->getCallSite().getInstruction(), *iif));
- }
- }
-
}
NumCallEdges += ActualCallees.size();
@@ -252,25 +116,6 @@
return false;
}
-DSGraph &BUDataStructures::getOrCreateGraph(Function *F) {
- // Has the graph already been created?
- DSGraph *&Graph = DSInfo[F];
- if (Graph) return *Graph;
-
- DSGraph &LocGraph = getAnalysis<LocalDataStructures>().getDSGraph(*F);
-
- // Steal the local graph.
- Graph = new DSGraph(GlobalECs, LocGraph.getTargetData());
- Graph->spliceFrom(LocGraph);
-
- Graph->setGlobalsGraph(GlobalsGraph);
- Graph->setPrintAuxCalls();
-
- // Start with a copy of the original call sites...
- Graph->getAuxFunctionCalls() = Graph->getFunctionCalls();
- return *Graph;
-}
-
static bool isVAHackFn(const Function *F) {
return F->getName() == "printf" || F->getName() == "sscanf" ||
F->getName() == "fprintf" || F->getName() == "open" ||
@@ -302,33 +147,6 @@
}
}
-//returns true if all callees were resolved
-static bool GetAllCalleesN(const DSCallSite &CS,
- std::vector<Function*> &Callees) {
- if (CS.isDirectCall()) {
- if (isResolvableFunc(CS.getCalleeFunc())) {
- Callees.push_back(CS.getCalleeFunc());
- return true;
- } else
- return false;
- } else {
- // Get all callees.
- bool retval = CS.getCalleeNode()->isComplete();
- unsigned OldSize = Callees.size();
- CS.getCalleeNode()->addFullFunctionList(Callees);
-
- // If any of the callees are unresolvable, remove that one
- for (unsigned i = OldSize; i != Callees.size(); ++i)
- if (!isResolvableFunc(Callees[i])) {
- Callees.erase(Callees.begin()+i);
- --i;
- retval = false;
- }
- return retval;
- //return false;
- }
-}
-
/// GetAllAuxCallees - Return a list containing all of the resolvable callees in
/// the aux list for the specified graph in the Callees vector.
static void GetAllAuxCallees(DSGraph &G, std::vector<Function*> &Callees) {
@@ -357,8 +175,6 @@
}
DSGraph &Graph = getOrCreateGraph(F);
- if (UpdateGlobals)
- Graph.updateFromGlobalGraph();
// Find all callee functions.
std::vector<Function*> CalleeFunctions;
@@ -496,8 +312,8 @@
if (F->getName() == "free") { // Taking the address of free.
// Free should take a single pointer argument, mark it as heap memory.
- DSNode *N = new DSNode(0, DSG);
- N->setHeapNodeMarker();
+ DSNodeHandle N(new DSNode(0, DSG));
+ N.getNode()->setHeapNodeMarker();
DSG->getNodeForValue(F->arg_begin()).mergeWith(N);
} else {
Index: llvm-poolalloc/lib/DSA/DataStructure.cpp
diff -u llvm-poolalloc/lib/DSA/DataStructure.cpp:1.259 llvm-poolalloc/lib/DSA/DataStructure.cpp:1.260
--- llvm-poolalloc/lib/DSA/DataStructure.cpp:1.259 Fri Feb 23 16:49:32 2007
+++ llvm-poolalloc/lib/DSA/DataStructure.cpp Wed Apr 11 12:37:43 2007
@@ -1,4 +1,3 @@
-#define JTC 0
//===- DataStructure.cpp - Implement the core data structure analysis -----===//
//
// The LLVM Compiler Infrastructure
@@ -30,7 +29,6 @@
#include "llvm/ADT/Statistic.h"
#include "llvm/Support/Timer.h"
#include "llvm/ADT/hash_map"
-#include "poolalloc/Config/config.h"
#include <iostream>
#include <algorithm>
@@ -1471,9 +1469,7 @@
AuxFunctionCalls.clear();
ScalarMap.clear();
ReturnNodes.clear();
-#ifdef LLVA_KERNEL
- PoolDescriptors.clear();
-#endif
+
// Drop all intra-node references, so that assertions don't fail...
for (node_iterator NI = node_begin(), E = node_end(); NI != E; ++NI)
NI->dropAllReferences();
@@ -1514,7 +1510,7 @@
if (GlobalValue *GV = dyn_cast<GlobalValue>(Ptr)) {
N->addGlobal(GV);
} else if (isa<MallocInst>(Ptr)) {
- N->setHeapNodeMarker();
+ N->setHeapNodeMarker();
} else if (isa<AllocaInst>(Ptr)) {
N->setAllocaNodeMarker();
} else {
@@ -1630,17 +1626,6 @@
// Merge the scalar map in.
ScalarMap.spliceFrom(RHS.ScalarMap);
-
-#ifdef LLVA_KERNEL
- //Take all from the pooldescriptor map
-#if 0
- PoolDescriptors.swap(RHS.getPoolDescriptorsMap());
-#else
- hash_map<const DSNode *, MetaPoolHandle*>& rhsmap = RHS.getPoolDescriptorsMap();
- PoolDescriptors.insert(rhsmap.begin(), rhsmap.end());
-#endif
- RHS.getPoolDescriptorsMap().clear();
-#endif
}
/// spliceFrom - Copy all entries from RHS, then clear RHS.
@@ -1670,7 +1655,7 @@
Args.push_back(getReturnNodeFor(*F));
for (Function::arg_iterator AI = F->arg_begin(), E = F->arg_end();
AI != E; ++AI)
- if (isPointerType(AI->getType())) {
+ if (isa<PointerType>(AI->getType())) {
Args.push_back(getNodeForValue(AI));
assert(!Args.back().isNull() && "Pointer argument w/o scalarmap entry!?");
}
@@ -1897,7 +1882,7 @@
std::vector<DSNodeHandle> Args;
for (Function::arg_iterator I = F.arg_begin(), E = F.arg_end(); I != E; ++I)
- if (isPointerType(I->getType()))
+ if (isa<PointerType>(I->getType()))
Args.push_back(getNodeForValue(I));
return DSCallSite(CallSite(), getReturnNodeFor(F), &F, Args);
@@ -1908,7 +1893,7 @@
DSCallSite DSGraph::getDSCallSiteForCallSite(CallSite CS) const {
DSNodeHandle RetVal;
Instruction *I = CS.getInstruction();
- if (isPointerType(I->getType()))
+ if (isa<PointerType>(I->getType()))
RetVal = getNodeForValue(I);
std::vector<DSNodeHandle> Args;
@@ -1916,7 +1901,7 @@
// Calculate the arguments vector...
for (CallSite::arg_iterator I = CS.arg_begin(), E = CS.arg_end(); I != E; ++I)
- if (isPointerType((*I)->getType()))
+ if (isa<PointerType>((*I)->getType()))
if (isa<ConstantPointerNull>(*I))
Args.push_back(DSNodeHandle());
else
@@ -1978,7 +1963,7 @@
Function &F = *FI->first;
for (Function::arg_iterator I = F.arg_begin(), E = F.arg_end();
I != E; ++I)
- if (isPointerType(I->getType()))
+ if (isa<PointerType>(I->getType()))
markIncompleteNode(getNodeForValue(I).getNode());
markIncompleteNode(FI->second.getNode());
}
@@ -2548,7 +2533,7 @@
RI != E; ++RI) {
Function &F = *RI->first;
for (Function::arg_iterator AI = F.arg_begin(); AI != F.arg_end(); ++AI)
- if (isPointerType(AI->getType()))
+ if (isa<PointerType>(AI->getType()))
assert(!getNodeForValue(AI).isNull() &&
"Pointer argument must be in the scalar map!");
}
@@ -2678,3 +2663,191 @@
RC.merge(getNodeForValue(*I), It->second);
}
}
+
+
+////////////////////////////////////////////////////////////////////////////////
+//Base DataStructures impl:
+////////////////////////////////////////////////////////////////////////////////
+
+static const Function *getFnForValue(const Value *V) {
+ if (const Instruction *I = dyn_cast<Instruction>(V))
+ return I->getParent()->getParent();
+ else if (const Argument *A = dyn_cast<Argument>(V))
+ return A->getParent();
+ else if (const BasicBlock *BB = dyn_cast<BasicBlock>(V))
+ return BB->getParent();
+ return 0;
+}
+
+/// deleteValue/copyValue - Interfaces to update the DSGraphs in the program.
+/// These correspond to the interfaces defined in the AliasAnalysis class.
+void DataStructures::deleteValue(Value *V) {
+ if (const Function *F = getFnForValue(V)) { // Function local value?
+ // If this is a function local value, just delete it from the scalar map!
+ getDSGraph(*F).getScalarMap().eraseIfExists(V);
+ return;
+ }
+
+ if (Function *F = dyn_cast<Function>(V)) {
+ assert(getDSGraph(*F).getReturnNodes().size() == 1 &&
+ "cannot handle scc's");
+ delete DSInfo[F];
+ DSInfo.erase(F);
+ return;
+ }
+
+ assert(!isa<GlobalVariable>(V) && "Do not know how to delete GV's yet!");
+}
+
+void DataStructures::copyValue(Value *From, Value *To) {
+ if (From == To) return;
+ if (const Function *F = getFnForValue(From)) { // Function local value?
+ // If this is a function local value, just delete it from the scalar map!
+ getDSGraph(*F).getScalarMap().copyScalarIfExists(From, To);
+ return;
+ }
+
+ if (Function *FromF = dyn_cast<Function>(From)) {
+ Function *ToF = cast<Function>(To);
+ assert(!DSInfo.count(ToF) && "New Function already exists!");
+ DSGraph *NG = new DSGraph(getDSGraph(*FromF), GlobalECs);
+ DSInfo[ToF] = NG;
+ assert(NG->getReturnNodes().size() == 1 && "Cannot copy SCC's yet!");
+
+ // Change the Function* is the returnnodes map to the ToF.
+ DSNodeHandle Ret = NG->retnodes_begin()->second;
+ NG->getReturnNodes().clear();
+ NG->getReturnNodes()[ToF] = Ret;
+ return;
+ }
+
+ if (const Function *F = getFnForValue(To)) {
+ DSGraph &G = getDSGraph(*F);
+ G.getScalarMap().copyScalarIfExists(From, To);
+ return;
+ }
+
+ cerr << *From;
+ cerr << *To;
+ assert(0 && "Do not know how to copy this yet!");
+ abort();
+}
+
+DSGraph& DataStructures::getOrCreateGraph(Function* F) {
+ assert(F && "No function");
+ DSGraph *&G = DSInfo[F];
+ if (!G) {
+ //Clone or Steal the Source Graph
+ DSGraph &BaseGraph = GraphSource->getDSGraph(*F);
+ if (Clone) {
+ G = new DSGraph(BaseGraph, GlobalECs, DSGraph::DontCloneAuxCallNodes);
+ } else {
+ G = new DSGraph(GlobalECs, GraphSource->getTargetData());
+ G->spliceFrom(BaseGraph);
+ G->getAuxFunctionCalls() = G->getFunctionCalls();
+ }
+ G->setPrintAuxCalls();
+ G->setGlobalsGraph(GlobalsGraph);
+
+ // Note that this graph is the graph for ALL of the function in the SCC, not
+ // just F.
+ for (DSGraph::retnodes_iterator RI = G->retnodes_begin(),
+ E = G->retnodes_end(); RI != E; ++RI)
+ if (RI->first != F)
+ DSInfo[RI->first] = G;
+ }
+ return *G;
+}
+
+
+void DataStructures::formGlobalECs() {
+ // Grow the equivalence classes for the globals to include anything that we
+ // now know to be aliased.
+ std::set<GlobalValue*> ECGlobals;
+ buildGlobalECs(ECGlobals);
+ if (!ECGlobals.empty()) {
+ DOUT << "Eliminating " << ECGlobals.size() << " EC Globals!\n";
+ for (hash_map<Function*, DSGraph*>::iterator I = DSInfo.begin(),
+ E = DSInfo.end(); I != E; ++I)
+ eliminateUsesOfECGlobals(*I->second, ECGlobals);
+ }
+}
+
+/// BuildGlobalECs - Look at all of the nodes in the globals graph. If any node
+/// contains multiple globals, DSA will never, ever, be able to tell the globals
+/// apart. Instead of maintaining this information in all of the graphs
+/// throughout the entire program, store only a single global (the "leader") in
+/// the graphs, and build equivalence classes for the rest of the globals.
+void DataStructures::buildGlobalECs(std::set<GlobalValue*> &ECGlobals) {
+ DSScalarMap &SM = GlobalsGraph->getScalarMap();
+ EquivalenceClasses<GlobalValue*> &GlobalECs = SM.getGlobalECs();
+ for (DSGraph::node_iterator I = GlobalsGraph->node_begin(),
+ E = GlobalsGraph->node_end();
+ I != E; ++I) {
+ if (I->getGlobalsList().size() <= 1) continue;
+
+ // First, build up the equivalence set for this block of globals.
+ DSNode::globals_iterator i = I->globals_begin();
+ GlobalValue *First = *i++;
+ for( ; i != I->globals_end(); ++i) {
+ GlobalECs.unionSets(First, *i);
+ ECGlobals.insert(*i);
+ SM.erase(SM.find(*i));
+ }
+
+ // Next, get the leader element.
+ assert(First == GlobalECs.getLeaderValue(First) &&
+ "First did not end up being the leader?");
+
+ // Finally, change the global node to only contain the leader.
+ I->clearGlobals();
+ I->addGlobal(First);
+ }
+
+ DEBUG(GlobalsGraph->AssertGraphOK());
+}
+
+/// EliminateUsesOfECGlobals - Once we have determined that some globals are in
+/// really just equivalent to some other globals, remove the globals from the
+/// specified DSGraph (if present), and merge any nodes with their leader nodes.
+void DataStructures::eliminateUsesOfECGlobals(DSGraph &G,
+ const std::set<GlobalValue*> &ECGlobals) {
+ DSScalarMap &SM = G.getScalarMap();
+ EquivalenceClasses<GlobalValue*> &GlobalECs = SM.getGlobalECs();
+
+ bool MadeChange = false;
+ for (DSScalarMap::global_iterator GI = SM.global_begin(), E = SM.global_end();
+ GI != E; ) {
+ GlobalValue *GV = *GI++;
+ if (!ECGlobals.count(GV)) continue;
+
+ const DSNodeHandle &GVNH = SM[GV];
+ assert(!GVNH.isNull() && "Global has null NH!?");
+
+ // Okay, this global is in some equivalence class. Start by finding the
+ // leader of the class.
+ GlobalValue *Leader = GlobalECs.getLeaderValue(GV);
+
+ // If the leader isn't already in the graph, insert it into the node
+ // corresponding to GV.
+ if (!SM.global_count(Leader)) {
+ GVNH.getNode()->addGlobal(Leader);
+ SM[Leader] = GVNH;
+ } else {
+ // Otherwise, the leader is in the graph, make sure the nodes are the
+ // merged in the specified graph.
+ const DSNodeHandle &LNH = SM[Leader];
+ if (LNH.getNode() != GVNH.getNode())
+ LNH.mergeWith(GVNH);
+ }
+
+ // Next step, remove the global from the DSNode.
+ GVNH.getNode()->removeGlobal(GV);
+
+ // Finally, remove the global from the ScalarMap.
+ SM.erase(GV);
+ MadeChange = true;
+ }
+
+ DEBUG(if(MadeChange) G.AssertGraphOK());
+}
Index: llvm-poolalloc/lib/DSA/Local.cpp
diff -u llvm-poolalloc/lib/DSA/Local.cpp:1.168 llvm-poolalloc/lib/DSA/Local.cpp:1.169
--- llvm-poolalloc/lib/DSA/Local.cpp:1.168 Fri Feb 23 16:49:32 2007
+++ llvm-poolalloc/lib/DSA/Local.cpp Wed Apr 11 12:37:43 2007
@@ -1,4 +1,3 @@
-#define JTC 0
//===- Local.cpp - Compute a local data structure graph for a function ----===//
//
// The LLVM Compiler Infrastructure
@@ -26,7 +25,6 @@
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/Timer.h"
-#include "poolalloc/Config/config.h"
#include <iostream>
// FIXME: This should eventually be a FunctionPass that is automatically
@@ -36,18 +34,8 @@
using namespace llvm;
-#ifdef LLVA_KERNEL
-static STATISTIC (CacheAllocs , "Number of kmem_cache_alloc calls");
-static STATISTIC (KMallocs , "Number of kmalloc calls");
-static STATISTIC (GlobalPools , "Number of global pools");
-#endif
-
static RegisterPass<LocalDataStructures>
-X("datastructure", "Local Data Structure Analysis");
-
-static cl::opt<bool>
-TrackIntegersAsPointers("dsa-track-integers", cl::Hidden,
- cl::desc("If this is set, track integers as potential pointers"));
+X("dsa-local", "Local Data Structure Analysis");
static cl::opt<bool>
IgnoreSetCC("dsa-ignore-setcc", cl::Hidden,
@@ -65,29 +53,7 @@
cl::desc("List of functions that free memory from the heap"),
cl::CommaSeparated, cl::Hidden);
-namespace llvm {
-namespace DS {
- // isPointerType - Return true if this type is big enough to hold a pointer.
- bool isPointerType(const Type *Ty) {
- if (isa<PointerType>(Ty))
- return true;
- else if (TrackIntegersAsPointers && Ty->isPrimitiveType() &&Ty->isInteger())
- return Ty->getPrimitiveSizeInBits() >= PointerSize;
- return false;
- }
-}}
-
-using namespace DS;
-
namespace {
- cl::opt<bool>
- DisableDirectCallOpt("disable-direct-call-dsopt", cl::Hidden,
- cl::desc("Disable direct call optimization in "
- "DSGraph construction"));
- cl::opt<bool>
- DisableFieldSensitivity("disable-ds-field-sensitivity", cl::Hidden,
- cl::desc("Disable field sensitivity in DSGraphs"));
-
//===--------------------------------------------------------------------===//
// GraphBuilder Class
//===--------------------------------------------------------------------===//
@@ -97,109 +63,21 @@
///
class GraphBuilder : InstVisitor<GraphBuilder> {
DSGraph &G;
- DSNodeHandle *RetNode; // Node that gets returned...
- DSScalarMap &ScalarMap;
- std::list<DSCallSite> *FunctionCalls;
- Value * KMallocPool;
- public:
- GraphBuilder(Function &f, DSGraph &g, DSNodeHandle &retNode,
- std::list<DSCallSite> &fc)
- : G(g), RetNode(&retNode), ScalarMap(G.getScalarMap()),
- FunctionCalls(&fc) {
- // Find the type unsafe pool in the program
- KMallocPool = f.getParent()->getNamedGlobal ("KmallocPool");
-
-#if 1
- //
- // Determine if the function somehow escapes
- //
- bool escapes = false;
- if (!(f.hasInternalLinkage())) {
- escapes = true;
- }
- Value::use_iterator U;
- for (U=f.use_begin(); U != f.use_end(); ++U) {
- if (isa<GlobalValue>(U)) {
- std::cerr << "LLVA: isa: " << f.getName() << " " << *U << std::endl;
- escapes = true;
- break;
- }
- }
-#endif
- // Create scalar nodes for all pointer arguments...
- for (Function::arg_iterator I = f.arg_begin(), E = f.arg_end();
- I != E; ++I) {
- if (isPointerType(I->getType())) {
- DSNode * Node = getValueDest(*I).getNode();
- if (!(f.hasInternalLinkage())) {
- Node->setExternalMarker();
- }
- }
- }
-
- visit(f); // Single pass over the function
-#if JTC
-std::cerr << "LLVA: Function " << f.getName() << "\n";
- for (DSScalarMap::iterator I = ScalarMap.begin(), E=ScalarMap.end();
- I != E;
- ++I)
- {
- std::cerr << "LLVA:\t" << I->first->getName() << ": " << (void *)(I->second.getNode()) << "\n";
- }
-#endif
- }
-
- // GraphBuilder ctor for working on the globals graph
- GraphBuilder(DSGraph &g)
- : G(g), RetNode(0), ScalarMap(G.getScalarMap()), FunctionCalls(0) {
- }
- void mergeInGlobalInitializer(GlobalVariable *GV);
+ Function* FB;
- private:
- // Visitor functions, used to handle each instruction type we encounter...
- friend class InstVisitor<GraphBuilder>;
- void visitMallocInst(MallocInst &MI) { handleAlloc(MI, true); }
- void visitAllocaInst(AllocaInst &AI) { handleAlloc(AI, false); }
- void handleAlloc(AllocationInst &AI, bool isHeap);
-
- void visitPHINode(PHINode &PN);
- void visitSelectInst(SelectInst &SI);
-
- void visitGetElementPtrInst(User &GEP);
- void visitReturnInst(ReturnInst &RI);
- void visitLoadInst(LoadInst &LI);
- void visitStoreInst(StoreInst &SI);
- void visitCallInst(CallInst &CI);
- void visitInvokeInst(InvokeInst &II);
- void visitICmpInst(ICmpInst &I);
- void visitFCmpInst(FCmpInst &I);
- void visitFreeInst(FreeInst &FI);
- void visitCastInst(CastInst &CI);
- void visitInstruction(Instruction &I);
-
- bool visitIntrinsic(CallSite CS, Function* F);
- bool visitExternal(CallSite CS, Function* F);
- void visitCallSite(CallSite CS);
- void visitVAArgInst(VAArgInst &I);
+ ////////////////////////////////////////////////////////////////////////////
+ // Helper functions used to implement the visitation functions...
void MergeConstantInitIntoNode(DSNodeHandle &NH, Constant *C);
- private:
- // Helper functions used to implement the visitation functions...
/// createNode - Create a new DSNode, ensuring that it is properly added to
/// the graph.
///
- DSNode *createNode(const Type *Ty = 0) {
- DSNode *N = new DSNode(Ty, &G); // Create the node
- if (DisableFieldSensitivity) {
- // Create node handle referring to the old node so that it is
- // immediately removed from the graph when the node handle is destroyed.
- DSNodeHandle OldNNH = N;
- N->foldNodeCompletely();
- if (DSNode *FN = N->getForwardNode())
- N = FN;
- }
- return N;
+ DSNode *createNode(const Type *Ty = 0)
+ {
+ DSNode* ret = new DSNode(Ty, &G);
+ assert(ret->getParentGraph() && "No parent?");
+ return ret;
}
/// setDestTo - Set the ScalarMap entry for the specified value to point to
@@ -217,45 +95,89 @@
/// null), then we create a new node, link it, then return it.
///
DSNodeHandle &getLink(const DSNodeHandle &Node, unsigned Link = 0);
- };
-}
-using namespace DS;
+ ////////////////////////////////////////////////////////////////////////////
+ // Visitor functions, used to handle each instruction type we encounter...
+ friend class InstVisitor<GraphBuilder>;
-//===----------------------------------------------------------------------===//
-// DSGraph constructor - Simply use the GraphBuilder to construct the local
-// graph.
-DSGraph::DSGraph(EquivalenceClasses<GlobalValue*> &ECs, const TargetData &td,
- Function &F, DSGraph *GG)
- : GlobalsGraph(GG), ScalarMap(ECs), TD(td) {
- PrintAuxCalls = false;
-
- DOUT << " [Loc] Calculating graph for: " << F.getName() << "\n";
-
- // Use the graph builder to construct the local version of the graph
- GraphBuilder B(F, *this, ReturnNodes[&F], FunctionCalls);
-#ifndef NDEBUG
- Timer::addPeakMemoryMeasurement();
-#endif
+ void visitMallocInst(MallocInst &MI)
+ { setDestTo(MI, createNode()->setHeapNodeMarker()); }
- // If there are any constant globals referenced in this function, merge their
- // initializers into the local graph from the globals graph.
- if (ScalarMap.global_begin() != ScalarMap.global_end()) {
- ReachabilityCloner RC(*this, *GG, 0);
-
- for (DSScalarMap::global_iterator I = ScalarMap.global_begin();
- I != ScalarMap.global_end(); ++I)
- if (GlobalVariable *GV = dyn_cast<GlobalVariable>(*I))
- if (!GV->isDeclaration() && GV->isConstant())
- RC.merge(ScalarMap[GV], GG->ScalarMap[GV]);
- }
+ void visitAllocaInst(AllocaInst &AI)
+ { setDestTo(AI, createNode()->setAllocaNodeMarker()); }
- markIncompleteNodes(DSGraph::MarkFormalArgs);
+ void visitFreeInst(FreeInst &FI)
+ { if (DSNode *N = getValueDest(*FI.getOperand(0)).getNode())
+ N->setHeapNodeMarker();
+ }
- // Remove any nodes made dead due to merging...
- removeDeadNodes(DSGraph::KeepUnreachableGlobals);
-}
+ //the simple ones
+ void visitPHINode(PHINode &PN);
+ void visitSelectInst(SelectInst &SI);
+ void visitLoadInst(LoadInst &LI);
+ void visitStoreInst(StoreInst &SI);
+ void visitReturnInst(ReturnInst &RI);
+ void visitVAArgInst(VAArgInst &I);
+ void visitIntToPtrInst(IntToPtrInst &I);
+ void visitPtrToIntInst(PtrToIntInst &I);
+ void visitBitCastInst(BitCastInst &I);
+ //the nasty ones
+ void visitGetElementPtrInst(User &GEP);
+ void visitCallInst(CallInst &CI);
+ void visitInvokeInst(InvokeInst &II);
+ void visitInstruction(Instruction &I);
+
+ bool visitIntrinsic(CallSite CS, Function* F);
+ bool visitExternal(llvm::CallSite, llvm::Function*);
+ void visitCallSite(CallSite CS);
+
+ public:
+ GraphBuilder(Function &f, DSGraph &g)
+ : G(g), FB(&f) {
+ // Create scalar nodes for all pointer arguments...
+ for (Function::arg_iterator I = f.arg_begin(), E = f.arg_end();
+ I != E; ++I) {
+ if (isa<PointerType>(I->getType())) {
+ DSNode * Node = getValueDest(*I).getNode();
+
+ if (!(f.hasInternalLinkage())) {
+ Node->setExternalMarker();
+ }
+ }
+ }
+
+ // Create an entry for the return, which tracks which functions are in the graph
+ g.getOrCreateReturnNodeFor(f);
+
+ visit(f); // Single pass over the function
+
+ // If there are any constant globals referenced in this function, merge their
+ // initializers into the local graph from the globals graph.
+ if (g.getScalarMap().global_begin() != g.getScalarMap().global_end()) {
+ ReachabilityCloner RC(g, *g.getGlobalsGraph(), 0);
+
+ for (DSScalarMap::global_iterator I = g.getScalarMap().global_begin();
+ I != g.getScalarMap().global_end(); ++I)
+ if (GlobalVariable *GV = dyn_cast<GlobalVariable>(*I))
+ if (!GV->isDeclaration() && GV->isConstant())
+ RC.merge(g.getNodeForValue(GV), g.getGlobalsGraph()->getNodeForValue(GV));
+ }
+
+ g.markIncompleteNodes(DSGraph::MarkFormalArgs);
+
+ // Remove any nodes made dead due to merging...
+ g.removeDeadNodes(DSGraph::KeepUnreachableGlobals);
+ }
+
+ // GraphBuilder ctor for working on the globals graph
+ explicit GraphBuilder(DSGraph& g)
+ :G(g), FB(0)
+ {}
+
+ void mergeInGlobalInitializer(GlobalVariable *GV);
+ };
+}
//===----------------------------------------------------------------------===//
// Helper method implementations...
@@ -265,10 +187,10 @@
///
DSNodeHandle GraphBuilder::getValueDest(Value &Val) {
Value *V = &Val;
- if (isa<Constant>(V) && cast<Constant>(V)->isNullValue())
+ if (isa<Constant>(V) && cast<Constant>(V)->isNullValue())
return 0; // Null doesn't point to anything, don't add to ScalarMap!
- DSNodeHandle &NH = ScalarMap[V];
+ DSNodeHandle &NH = G.getNodeForValue(V);
if (!NH.isNull())
return NH; // Already have a node? Just return it...
@@ -289,20 +211,19 @@
NH = createNode()->setUnknownNodeMarker();
} else if (CE->getOpcode() == Instruction::GetElementPtr) {
visitGetElementPtrInst(*CE);
- DSScalarMap::iterator I = ScalarMap.find(CE);
- assert(I != ScalarMap.end() && "GEP didn't get processed right?");
- NH = I->second;
+ assert(G.hasNodeForValue(CE) && "GEP didn't get processed right?");
+ NH = G.getNodeForValue(CE);
} else {
// This returns a conservative unknown node for any unhandled ConstExpr
return NH = createNode()->setUnknownNodeMarker();
}
if (NH.isNull()) { // (getelementptr null, X) returns null
- ScalarMap.erase(V);
+ G.eraseNodeForValue(V);
return 0;
}
return NH;
} else if (isa<UndefValue>(C)) {
- ScalarMap.erase(V);
+ G.eraseNodeForValue(V);
return 0;
} else {
assert(0 && "Unknown constant type!");
@@ -340,7 +261,7 @@
/// merge the two destinations together.
///
void GraphBuilder::setDestTo(Value &V, const DSNodeHandle &NH) {
- ScalarMap[&V].mergeWith(NH);
+ G.getNodeForValue(&V).mergeWith(NH);
}
@@ -348,73 +269,93 @@
// Specific instruction type handler implementations...
//
-/// Alloca & Malloc instruction implementation - Simply create a new memory
-/// object, pointing the scalar to it.
-///
-void GraphBuilder::handleAlloc(AllocationInst &AI, bool isHeap) {
- DSNode *N = createNode();
- if (isHeap)
- N->setHeapNodeMarker();
- else
- N->setAllocaNodeMarker();
- setDestTo(AI, N);
-}
-
// PHINode - Make the scalar for the PHI node point to all of the things the
// incoming values point to... which effectively causes them to be merged.
//
void GraphBuilder::visitPHINode(PHINode &PN) {
- if (!isPointerType(PN.getType())) return; // Only pointer PHIs
+ if (!isa<PointerType>(PN.getType())) return; // Only pointer PHIs
- DSNodeHandle &PNDest = ScalarMap[&PN];
+ DSNodeHandle &PNDest = G.getNodeForValue(&PN);
for (unsigned i = 0, e = PN.getNumIncomingValues(); i != e; ++i)
PNDest.mergeWith(getValueDest(*PN.getIncomingValue(i)));
}
void GraphBuilder::visitSelectInst(SelectInst &SI) {
- if (!isPointerType(SI.getType())) return; // Only pointer Selects
+ if (!isa<PointerType>(SI.getType())) return; // Only pointer Selects
- DSNodeHandle &Dest = ScalarMap[&SI];
+ DSNodeHandle &Dest = G.getNodeForValue(&SI);
Dest.mergeWith(getValueDest(*SI.getOperand(1)));
Dest.mergeWith(getValueDest(*SI.getOperand(2)));
}
-void GraphBuilder::visitICmpInst(ICmpInst &SCI) {
- if (!isPointerType(SCI.getOperand(0)->getType()) ||
- isa<ConstantPointerNull>(SCI.getOperand(1))) return; // Only pointers
- if(!IgnoreSetCC)
- ScalarMap[SCI.getOperand(0)].mergeWith(getValueDest(*SCI.getOperand(1)));
+void GraphBuilder::visitLoadInst(LoadInst &LI) {
+ DSNodeHandle Ptr = getValueDest(*LI.getOperand(0));
+
+ // Make that the node is read from...
+ Ptr.getNode()->setReadMarker();
+
+ // Ensure a typerecord exists...
+ Ptr.getNode()->mergeTypeInfo(LI.getType(), Ptr.getOffset(), false);
+
+ if (isa<PointerType>(LI.getType()))
+ setDestTo(LI, getLink(Ptr));
}
-void GraphBuilder::visitFCmpInst(FCmpInst &SCI) {
- if (!isPointerType(SCI.getOperand(0)->getType()) ||
- isa<ConstantPointerNull>(SCI.getOperand(1))) return; // Only pointers
- if(!IgnoreSetCC)
- ScalarMap[SCI.getOperand(0)].mergeWith(getValueDest(*SCI.getOperand(1)));
+void GraphBuilder::visitStoreInst(StoreInst &SI) {
+ const Type *StoredTy = SI.getOperand(0)->getType();
+ DSNodeHandle Dest = getValueDest(*SI.getOperand(1));
+ if (Dest.isNull()) return;
+
+ // Mark that the node is written to...
+ Dest.getNode()->setModifiedMarker();
+
+ // Ensure a type-record exists...
+ Dest.getNode()->mergeTypeInfo(StoredTy, Dest.getOffset());
+
+ // Avoid adding edges from null, or processing non-"pointer" stores
+ if (isa<PointerType>(StoredTy))
+ Dest.addEdgeTo(getValueDest(*SI.getOperand(0)));
}
+void GraphBuilder::visitReturnInst(ReturnInst &RI) {
+ if (RI.getNumOperands() && isa<PointerType>(RI.getOperand(0)->getType()))
+ G.getOrCreateReturnNodeFor(*FB).mergeWith(getValueDest(*RI.getOperand(0)));
+}
-void GraphBuilder::visitGetElementPtrInst(User &GEP) {
+void GraphBuilder::visitVAArgInst(VAArgInst &I) {
+ //FIXME: also updates the argument
+ DSNodeHandle Ptr = getValueDest(*I.getOperand(0));
+ if (Ptr.isNull()) return;
-#ifdef LLVA_KERNEL
-#if 1
- int debug = 0;
- if (isa<Instruction>(GEP)) {
- Instruction * IGEP = (Instruction *)(&GEP);
- if (IGEP->getParent()->getParent()->getName() == "alloc_vfsmnt")
- {
-#if 0
- if (G.getPoolDescriptorsMap().count(N) != 0)
- if (G.getPoolDescriptorsMap()[N])
- std::cerr << "LLVA: GEP[" << count << "]: Pool for " << GEP.getName() << " is " << G.getPoolDescriptorsMap()[N]->getMetaPoolValue()->getName() << "\n";
-#else
- debug = 1;
-#endif
- }
- }
-#endif
-#endif
+ // Make that the node is read and written
+ Ptr.getNode()->setReadMarker()->setModifiedMarker();
+
+ // Ensure a type record exists.
+ DSNode *PtrN = Ptr.getNode();
+ PtrN->mergeTypeInfo(I.getType(), Ptr.getOffset(), false);
+
+ if (isa<PointerType>(I.getType()))
+ setDestTo(I, getLink(Ptr));
+}
+void GraphBuilder::visitIntToPtrInst(IntToPtrInst &I) {
+ setDestTo(I, createNode()->setUnknownNodeMarker()); //->setIntToPtrMarker());
+}
+
+void GraphBuilder::visitPtrToIntInst(PtrToIntInst& I) {
+// if (DSNode* N = getValueDest(*I.getOperand(0)).getNode())
+// N->setPtrToIntMarker();
+}
+
+
+void GraphBuilder::visitBitCastInst(BitCastInst &I) {
+ if (!isa<PointerType>(I.getType())) return; // Only pointers
+ DSNodeHandle Ptr = getValueDest(*I.getOperand(0));
+ if (Ptr.isNull()) return;
+ setDestTo(I, Ptr);
+}
+
+void GraphBuilder::visitGetElementPtrInst(User &GEP) {
DSNodeHandle Value = getValueDest(*GEP.getOperand(0));
if (Value.isNull())
Value = createNode();
@@ -434,11 +375,6 @@
if (AllZeros || (!Value.isNull() &&
Value.getNode()->isNodeCompletelyFolded())) {
setDestTo(GEP, Value);
-#if 0
-if (debug) std::cerr << "LLVA: GEP: All Zeros\n";
- if (G.getPoolDescriptorsMap()[Value.getNode()])
- std::cerr << "LLVA: GEP: Pool for " << GEP.getName() << " is " << G.getPoolDescriptorsMap()[Value.getNode()]->getName() << "\n";
-#endif
return;
}
@@ -570,74 +506,6 @@
}
-void GraphBuilder::visitLoadInst(LoadInst &LI) {
- DSNodeHandle Ptr = getValueDest(*LI.getOperand(0));
- if (Ptr.isNull())
- Ptr = createNode();
-
- // Make that the node is read from...
- Ptr.getNode()->setReadMarker();
-
- // Ensure a typerecord exists...
- Ptr.getNode()->mergeTypeInfo(LI.getType(), Ptr.getOffset(), false);
-
- if (isPointerType(LI.getType()))
- setDestTo(LI, getLink(Ptr));
-#if 0
- if (G.getPoolDescriptorsMap()[getLink(Ptr).getNode()])
- std::cerr << "LLVA: Load: Pool for " << LI.getName() << " is " << G.getPoolDescriptorsMap()[getLink(Ptr).getNode()]->getName() << "\n";
-#endif
-}
-
-void GraphBuilder::visitStoreInst(StoreInst &SI) {
- const Type *StoredTy = SI.getOperand(0)->getType();
- DSNodeHandle Dest = getValueDest(*SI.getOperand(1));
- if (Dest.isNull()) return;
-
- // Mark that the node is written to...
- Dest.getNode()->setModifiedMarker();
-
- // Ensure a type-record exists...
- Dest.getNode()->mergeTypeInfo(StoredTy, Dest.getOffset());
-
- // Avoid adding edges from null, or processing non-"pointer" stores
- if (isPointerType(StoredTy))
- Dest.addEdgeTo(getValueDest(*SI.getOperand(0)));
-#ifdef LLVA_KERNEL
-#if 1
- {
- if (SI.getParent()->getParent()->getName() == "alloc_vfsmnt") {
- DSNode * N = getValueDest(*SI.getOperand(1)).getNode();
- if (G.getPoolDescriptorsMap().count(N) != 0)
- if (G.getPoolDescriptorsMap()[N])
- std::cerr << "LLVA: Store: Pool for " << SI.getName() << " is " << G.getPoolDescriptorsMap()[N]->getName() << "\n";
- }
- }
-#endif
-#endif
-}
-
-void GraphBuilder::visitReturnInst(ReturnInst &RI) {
- if (RI.getNumOperands() && isPointerType(RI.getOperand(0)->getType()))
- RetNode->mergeWith(getValueDest(*RI.getOperand(0)));
-}
-
-void GraphBuilder::visitVAArgInst(VAArgInst &I) {
- //FIXME: also updates the argument
- DSNodeHandle Ptr = getValueDest(*I.getOperand(0));
- if (Ptr.isNull()) return;
-
- // Make that the node is read from.
- Ptr.getNode()->setReadMarker();
-
- // Ensure a type record exists.
- DSNode *PtrN = Ptr.getNode();
- PtrN->mergeTypeInfo(I.getType(), Ptr.getOffset(), false);
-
- if (isPointerType(I.getType()))
- setDestTo(I, getLink(Ptr));
-}
-
void GraphBuilder::visitCallInst(CallInst &CI) {
visitCallSite(&CI);
@@ -730,7 +598,7 @@
// These functions read all of their pointer operands.
for (CallSite::arg_iterator AI = CS.arg_begin(), E = CS.arg_end();
AI != E; ++AI) {
- if (isPointerType((*AI)->getType()))
+ if (isa<PointerType>((*AI)->getType()))
if (DSNode *N = getValueDest(**AI).getNode())
N->setReadMarker();
}
@@ -748,7 +616,7 @@
// These functions write all of their pointer operands.
for (CallSite::arg_iterator AI = CS.arg_begin(), E = CS.arg_end();
AI != E; ++AI) {
- if (isPointerType((*AI)->getType()))
+ if (isa<PointerType>((*AI)->getType()))
if (DSNode *N = getValueDest(**AI).getNode())
N->setModifiedMarker();
}
@@ -757,7 +625,7 @@
F->getName() == "lstat") {
// These functions read their first operand if its a pointer.
CallSite::arg_iterator AI = CS.arg_begin();
- if (isPointerType((*AI)->getType())) {
+ if (isa<PointerType>((*AI)->getType())) {
DSNodeHandle Path = getValueDest(**AI);
if (DSNode *N = Path.getNode()) N->setReadMarker();
}
@@ -793,7 +661,7 @@
// These functions read all of their pointer operands.
for (CallSite::arg_iterator AI = CS.arg_begin(), E = CS.arg_end();
AI != E; ++AI)
- if (isPointerType((*AI)->getType()))
+ if (isa<PointerType>((*AI)->getType()))
if (DSNode *N = getValueDest(**AI).getNode())
N->setReadMarker();
@@ -903,7 +771,7 @@
// Any pointer arguments are read.
for (CallSite::arg_iterator AI = CS.arg_begin(), E = CS.arg_end();
AI != E; ++AI)
- if (isPointerType((*AI)->getType()))
+ if (isa<PointerType>((*AI)->getType()))
if (DSNode *N = getValueDest(**AI).getNode())
N->setReadMarker();
return true;
@@ -922,7 +790,7 @@
// Any pointer arguments are read.
for (CallSite::arg_iterator AI = CS.arg_begin(), E = CS.arg_end();
AI != E; ++AI)
- if (isPointerType((*AI)->getType()))
+ if (isa<PointerType>((*AI)->getType()))
if (DSNode *N = getValueDest(**AI).getNode())
N->setReadMarker()->setModifiedMarker();
return true;
@@ -953,7 +821,7 @@
for (; AI != E; ++AI) {
// printf reads all pointer arguments.
- if (isPointerType((*AI)->getType()))
+ if (isa<PointerType>((*AI)->getType()))
if (DSNode *N = getValueDest(**AI).getNode())
N->setReadMarker();
}
@@ -986,14 +854,14 @@
// Read the format
if (AI != E) {
- if (isPointerType((*AI)->getType()))
+ if (isa<PointerType>((*AI)->getType()))
if (DSNode *N = getValueDest(**AI).getNode())
N->setReadMarker();
++AI;
}
// Read the valist, and the pointed-to objects.
- if (AI != E && isPointerType((*AI)->getType())) {
+ if (AI != E && isa<PointerType>((*AI)->getType())) {
const DSNodeHandle &VAList = getValueDest(**AI);
if (DSNode *N = VAList.getNode()) {
N->setReadMarker();
@@ -1033,7 +901,7 @@
for (; AI != E; ++AI) {
// scanf writes all pointer arguments.
- if (isPointerType((*AI)->getType()))
+ if (isa<PointerType>((*AI)->getType()))
if (DSNode *N = getValueDest(**AI).getNode())
N->setModifiedMarker();
}
@@ -1068,7 +936,7 @@
for (CallSite::arg_iterator AI = CS.arg_begin(), E = CS.arg_end();
AI != E; ++AI)
- if (isPointerType((*AI)->getType()))
+ if (isa<PointerType>((*AI)->getType()))
if (DSNode *N = getValueDest(**AI).getNode())
N->setReadMarker();
@@ -1078,7 +946,7 @@
} else if (F->getName() == "__assert_fail") {
for (CallSite::arg_iterator AI = CS.arg_begin(), E = CS.arg_end();
AI != E; ++AI)
- if (isPointerType((*AI)->getType()))
+ if (isa<PointerType>((*AI)->getType()))
if (DSNode *N = getValueDest(**AI).getNode())
N->setReadMarker();
return true;
@@ -1269,167 +1137,7 @@
Value *Callee = CS.getCalledValue();
// Special case handling of certain libc allocation functions here.
- if (Function *F = dyn_cast<Function>(Callee)) {
-#ifdef LLVA_KERNEL
- if (F->getName() == "kmem_cache_alloc") {
- DEBUG(std::cerr << "LLVA: kmem_cache_alloc" << std::endl);
- // Update the statistics count
- ++CacheAllocs;
-
- // Create a new DSNode for this memory allocation
- DSNode *N = createNode();
- N->setHeapNodeMarker();
- setDestTo(*CS.getInstruction(), N);
-
- // Get the pool handle
- if (CS.arg_begin() == CS.arg_end()) {
- abort(); //Handle this later
- // Treat it as a kmalloc
- N->foldNodeCompletely();
- //This becomes a kmalloc pool
- MetaPoolHandle* mpvh = new MetaPoolHandle(new MetaPool(KMallocPool));
- G.getPoolDescriptorsMap()[N] = mpvh;
- } else {
- Value *actualPD = *(CS.arg_begin());
- if (!isa<GlobalValue>(actualPD)) {
- std::cerr << "WARNING: Pool is not global. Function = " << CS.getCaller()->getName() << "\n";
- } else {
- ++GlobalPools;
- }
- Value *TheMetaPool = actualPD;
- //Get the Module first
- Module * M = F->getParent();
- if (G.getPoolDescriptorsMap().count(N)== 0) {
- //Here we insert a global meta pool
- //Now create a meta pool for this value, DSN Node
- const Type * VoidPtrType = PointerType::get(Type::Int8Ty);
- TheMetaPool = new GlobalVariable(
- /*type=*/ VoidPtrType,
- /*isConstant=*/ false,
- /*Linkage=*/ GlobalValue::InternalLinkage,
- /*initializer=*/ Constant::getNullValue(VoidPtrType),
- /*name=*/ "_metaPool_",
- /*parent=*/ M );
- //Inserted a global meta pool
- }
-#if 1
- else {
- // Lookup the meta pool
- TheMetaPool = G.getPoolForNode(N)->getMetaPoolValue();
- }
-#endif
- //Now insert a function call that takes care of adding this pool to the global pool
-
- //First get the Insert point
- Instruction *InsertPoint = CS.getInstruction();
-
- //Assumes AddPoolDescToMetaPool is in the module
- const Type * VoidPtrType = PointerType::get(Type::Int8Ty);
- const Type * VoidPtrPtrType = PointerType::get(VoidPtrType);
- CastInst *CastMetaPool =
- CastInst::createPointerCast (TheMetaPool,
- VoidPtrPtrType, "metapool.casted", InsertPoint);
- CastInst *CastActualPD =
- CastInst::createPointerCast (actualPD,
- PointerType::get(Type::Int8Ty), "poolhandle.lscasted", InsertPoint);
-
- // Create the call to AddPoolDescToMetaPool
- std::vector<Value *> args(1,CastMetaPool);
- args.push_back(CastActualPD);
-
- //Get the AddPoolDescToMetaPool function from the module
- //FIXME optimize it by getting it once per module
- std::vector<const Type *> Arg(1, VoidPtrPtrType);
- Arg.push_back(VoidPtrType);
- FunctionType *AddPoolDescToMetaPoolTy =
- FunctionType::get(Type::VoidTy,Arg, false);
- Function *AddPoolDescToMetaPool = M->getOrInsertFunction("AddPoolDescToMetaPool", AddPoolDescToMetaPoolTy);
-
-
- new CallInst(AddPoolDescToMetaPool,args,"", InsertPoint);
-#if 0
- MetaPoolHandle* tmpvh = new MetaPoolHandle(new MetaPool(TheMetaPool));
-#else
- MetaPoolHandle* tmpvh = new MetaPoolHandle(new MetaPool(TheMetaPool), CS.getInstruction());
-#endif
- G.getPoolDescriptorsMap()[N] = tmpvh;
- }
- return;
- } else if (F->getName() == "poolalloc") {
- if (CS.getCaller()->getName() == "kmem_cache_alloc")
- return;
- // Update the statistics
- ++KMallocs;
-
- // Create a DSNode for the memory allocated by this function call
- DSNode *N = createNode();
- N->setHeapNodeMarker();
- setDestTo(*CS.getInstruction(), N);
-
- // Get the pool handle, if possible
- if (CS.arg_begin() == CS.arg_end()) {
- abort() ; //Handle this later
- // Treat it as kmalloc
- N->foldNodeCompletely();
- //This becomes a kmalloc pool
- //So get the kmalloc pool
- MetaPoolHandle* tmpvh = new MetaPoolHandle(new MetaPool(KMallocPool));
- G.getPoolDescriptorsMap()[N] = tmpvh;
- } else {
- Value *actualPD = *(CS.arg_begin());
- if (!isa<GlobalValue>(actualPD)) {
- std::cerr << "WARNING: Pool is not global. Function = " << CS.getCaller()->getName() << "\n";
- } else {
- ++GlobalPools;
- }
- Value *TheMetaPool = actualPD;
- Module * M = F->getParent();
- if (G.getPoolDescriptorsMap().count(N)== 0) {
- //Here we insert a global meta pool
- //Get the Module first
- //Now create a meta pool for this value, DSN Node
- const Type * VoidPtrType = PointerType::get(Type::Int8Ty);
- TheMetaPool = new GlobalVariable(
- /*type=*/ VoidPtrType,
- /*isConstant=*/ false,
- /*Linkage=*/ GlobalValue::InternalLinkage,
- /*initializer=*/ Constant::getNullValue(VoidPtrType),
- /*name=*/ "_metaPool_",
- /*parent=*/ M );
- //Inserted a global meta pool
- }
- //Now insert a function call that takes care of adding this pool to the global pool
- //First get the Insert point
- Instruction *InsertPoint = CS.getInstruction();
-
- //Assumes AddPoolDescToMetaPool is in the module
- const Type * VoidPtrType = PointerType::get(Type::Int8Ty);
- const Type * VoidPtrPtrType = PointerType::get(VoidPtrType);
- CastInst *CastMetaPool =
- CastInst::createPointerCast (TheMetaPool,
- VoidPtrPtrType, "metapool.casted", InsertPoint);
- CastInst *CastActualPD =
- CastInst::createPointerCast (actualPD,
- PointerType::get(Type::Int8Ty), "poolhandle.lscasted", InsertPoint);
-
- // Create the call to AddPoolDescToMetaPool
- std::vector<Value *> args(1,CastMetaPool);
- args.push_back(CastActualPD);
-
- //FIXME optimize it by getting it once per module
- std::vector<const Type *> Arg(1, VoidPtrPtrType);
- Arg.push_back(VoidPtrType);
- FunctionType *AddPoolDescToMetaPoolTy =
- FunctionType::get(Type::VoidTy,Arg, false);
- Function *AddPoolDescToMetaPool = M->getOrInsertFunction("AddPoolDescToMetaPool", AddPoolDescToMetaPoolTy);
-
- new CallInst(AddPoolDescToMetaPool,args,"", InsertPoint);
- MetaPoolHandle* tmpvh = new MetaPoolHandle(new MetaPool(TheMetaPool));
- G.getPoolDescriptorsMap()[N] = tmpvh;
- }
- return;
- }
-#endif
+ if (Function *F = dyn_cast<Function>(Callee))
if (F->isDeclaration())
if (F->isIntrinsic() && visitIntrinsic(CS, F))
return;
@@ -1457,11 +1165,11 @@
// Unknown function, warn if it returns a pointer type or takes a
// pointer argument.
- bool Warn = isPointerType(CS.getInstruction()->getType());
+ bool Warn = isa<PointerType>(CS.getInstruction()->getType());
if (!Warn)
for (CallSite::arg_iterator I = CS.arg_begin(), E = CS.arg_end();
I != E; ++I)
- if (isPointerType((*I)->getType())) {
+ if (isa<PointerType>((*I)->getType())) {
Warn = true;
break;
}
@@ -1470,16 +1178,15 @@
<< F->getName() << "' will cause pessimistic results!\n";
}
}
- }
// Set up the return value...
DSNodeHandle RetVal;
Instruction *I = CS.getInstruction();
- if (isPointerType(I->getType()))
+ if (isa<PointerType>(I->getType()))
RetVal = getValueDest(*I);
DSNode *CalleeNode = 0;
- if (DisableDirectCallOpt || !isa<Function>(Callee)) {
+ if (!isa<Function>(Callee)) {
CalleeNode = getValueDest(*Callee).getNode();
if (CalleeNode == 0) {
cerr << "WARNING: Program is calling through a null pointer?\n"<< *I;
@@ -1492,58 +1199,26 @@
// Calculate the arguments vector...
for (CallSite::arg_iterator I = CS.arg_begin(), E = CS.arg_end(); I != E; ++I)
- if (isPointerType((*I)->getType()))
+ if (isa<PointerType>((*I)->getType()))
Args.push_back(getValueDest(**I));
// Add a new function call entry...
if (CalleeNode)
- FunctionCalls->push_back(DSCallSite(CS, RetVal, CalleeNode, Args));
+ G.getFunctionCalls().push_back(DSCallSite(CS, RetVal, CalleeNode, Args));
else
- FunctionCalls->push_back(DSCallSite(CS, RetVal, cast<Function>(Callee),
- Args));
+ G.getFunctionCalls().push_back(DSCallSite(CS, RetVal, cast<Function>(Callee),
+ Args));
}
-void GraphBuilder::visitFreeInst(FreeInst &FI) {
- // Mark that the node is written to...
- if (DSNode *N = getValueDest(*FI.getOperand(0)).getNode())
- N->setModifiedMarker()->setHeapNodeMarker();
-}
-
-/// Handle casts...
-void GraphBuilder::visitCastInst(CastInst &CI) {
- // Pointers can only be cast with BitCast so check that the instruction
- // is a BitConvert. If not, its guaranteed not to involve any pointers so
- // we don't do anything.
- switch (CI.getOpcode()) {
- default: break;
- case Instruction::BitCast:
- case Instruction::IntToPtr:
- if (isPointerType(CI.getType()))
- if (isPointerType(CI.getOperand(0)->getType())) {
- DSNodeHandle Ptr = getValueDest(*CI.getOperand(0));
- if (Ptr.getNode() == 0) return;
- // Cast one pointer to the other, just act like a copy instruction
- setDestTo(CI, Ptr);
- } else {
- // Cast something (floating point, small integer) to a pointer. We
- // need to track the fact that the node points to SOMETHING, just
- // something we don't know about. Make an "Unknown" node.
- setDestTo(CI, createNode()->setUnknownNodeMarker());
- }
- break;
- }
-}
-
-
// visitInstruction - For all other instruction types, if we have any arguments
// that are of pointer type, make them have unknown composition bits, and merge
// the nodes together.
void GraphBuilder::visitInstruction(Instruction &Inst) {
DSNodeHandle CurNode;
- if (isPointerType(Inst.getType()))
+ if (isa<PointerType>(Inst.getType()))
CurNode = getValueDest(Inst);
for (User::op_iterator I = Inst.op_begin(), E = Inst.op_end(); I != E; ++I)
- if (isPointerType((*I)->getType()))
+ if (isa<PointerType>((*I)->getType()))
CurNode.mergeWith(getValueDest(**I));
if (DSNode *N = CurNode.getNode())
@@ -1564,7 +1239,7 @@
NHN->mergeTypeInfo(C->getType(), NH.getOffset());
if (C->getType()->isFirstClassType()) {
- if (isPointerType(C->getType()))
+ if (isa<PointerType>(C->getType()))
// Avoid adding edges from null, or processing non-"pointer" stores
NH.addEdgeTo(getValueDest(*C));
return;
@@ -1606,93 +1281,11 @@
}
-/// BuildGlobalECs - Look at all of the nodes in the globals graph. If any node
-/// contains multiple globals, DSA will never, ever, be able to tell the globals
-/// apart. Instead of maintaining this information in all of the graphs
-/// throughout the entire program, store only a single global (the "leader") in
-/// the graphs, and build equivalence classes for the rest of the globals.
-static void BuildGlobalECs(DSGraph &GG, std::set<GlobalValue*> &ECGlobals) {
- DSScalarMap &SM = GG.getScalarMap();
- EquivalenceClasses<GlobalValue*> &GlobalECs = SM.getGlobalECs();
- for (DSGraph::node_iterator I = GG.node_begin(), E = GG.node_end();
- I != E; ++I) {
- if (I->getGlobalsList().size() <= 1) continue;
-
- // First, build up the equivalence set for this block of globals.
- const std::vector<GlobalValue*> &GVs = I->getGlobalsList();
- GlobalValue *First = GVs[0];
- for (unsigned i = 1, e = GVs.size(); i != e; ++i)
- GlobalECs.unionSets(First, GVs[i]);
-
- // Next, get the leader element.
- assert(First == GlobalECs.getLeaderValue(First) &&
- "First did not end up being the leader?");
-
- // Next, remove all globals from the scalar map that are not the leader.
- assert(GVs[0] == First && "First had to be at the front!");
- for (unsigned i = 1, e = GVs.size(); i != e; ++i) {
- ECGlobals.insert(GVs[i]);
- SM.erase(SM.find(GVs[i]));
- }
-
- // Finally, change the global node to only contain the leader.
- I->clearGlobals();
- I->addGlobal(First);
- }
-
- DEBUG(GG.AssertGraphOK());
-}
-
-/// EliminateUsesOfECGlobals - Once we have determined that some globals are in
-/// really just equivalent to some other globals, remove the globals from the
-/// specified DSGraph (if present), and merge any nodes with their leader nodes.
-static void EliminateUsesOfECGlobals(DSGraph &G,
- const std::set<GlobalValue*> &ECGlobals) {
- DSScalarMap &SM = G.getScalarMap();
- EquivalenceClasses<GlobalValue*> &GlobalECs = SM.getGlobalECs();
-
- bool MadeChange = false;
- for (DSScalarMap::global_iterator GI = SM.global_begin(), E = SM.global_end();
- GI != E; ) {
- GlobalValue *GV = *GI++;
- if (!ECGlobals.count(GV)) continue;
-
- const DSNodeHandle &GVNH = SM[GV];
- assert(!GVNH.isNull() && "Global has null NH!?");
-
- // Okay, this global is in some equivalence class. Start by finding the
- // leader of the class.
- GlobalValue *Leader = GlobalECs.getLeaderValue(GV);
-
- // If the leader isn't already in the graph, insert it into the node
- // corresponding to GV.
- if (!SM.global_count(Leader)) {
- GVNH.getNode()->addGlobal(Leader);
- SM[Leader] = GVNH;
- } else {
- // Otherwise, the leader is in the graph, make sure the nodes are the
- // merged in the specified graph.
- const DSNodeHandle &LNH = SM[Leader];
- if (LNH.getNode() != GVNH.getNode())
- LNH.mergeWith(GVNH);
- }
-
- // Next step, remove the global from the DSNode.
- GVNH.getNode()->removeGlobal(GV);
-
- // Finally, remove the global from the ScalarMap.
- SM.erase(GV);
- MadeChange = true;
- }
-
- DEBUG(if(MadeChange) G.AssertGraphOK());
-}
-
bool LocalDataStructures::runOnModule(Module &M) {
- const TargetData &TD = getAnalysis<TargetData>();
+ setTargetData(getAnalysis<TargetData>());
// First step, build the globals graph.
- GlobalsGraph = new DSGraph(GlobalECs, TD);
+ GlobalsGraph = new DSGraph(GlobalECs, getTargetData());
{
GraphBuilder GGB(*GlobalsGraph);
@@ -1705,16 +1298,16 @@
// Next step, iterate through the nodes in the globals graph, unioning
// together the globals into equivalence classes.
- std::set<GlobalValue*> ECGlobals;
- BuildGlobalECs(*GlobalsGraph, ECGlobals);
- DOUT << "Eliminating " << ECGlobals.size() << " EC Globals!\n";
- ECGlobals.clear();
+ formGlobalECs();
// Calculate all of the graphs...
for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I)
- if (!I->isDeclaration())
- DSInfo.insert(std::make_pair(I, new DSGraph(GlobalECs, TD, *I,
- GlobalsGraph)));
+ if (!I->isDeclaration()) {
+ DSGraph* G = new DSGraph(GlobalECs, getTargetData(), GlobalsGraph);
+ GraphBuilder GGB(*I, *G);
+ DSInfo.insert(std::make_pair(I, G));
+ }
+
GlobalsGraph->removeTriviallyDeadNodes();
GlobalsGraph->markIncompleteNodes(DSGraph::MarkFormalArgs);
@@ -1722,13 +1315,7 @@
// the globals graph, see if we have further constrained the globals in the
// program if so, update GlobalECs and remove the extraneous globals from the
// program.
- BuildGlobalECs(*GlobalsGraph, ECGlobals);
- if (!ECGlobals.empty()) {
- DOUT << "Eliminating " << ECGlobals.size() << " EC Globals!\n";
- for (hash_map<Function*, DSGraph*>::iterator I = DSInfo.begin(),
- E = DSInfo.end(); I != E; ++I)
- EliminateUsesOfECGlobals(*I->second, ECGlobals);
- }
+ formGlobalECs();
return false;
}
Index: llvm-poolalloc/lib/DSA/Steensgaard.cpp
diff -u llvm-poolalloc/lib/DSA/Steensgaard.cpp:1.69 llvm-poolalloc/lib/DSA/Steensgaard.cpp:1.70
--- llvm-poolalloc/lib/DSA/Steensgaard.cpp:1.69 Fri Feb 23 16:49:32 2007
+++ llvm-poolalloc/lib/DSA/Steensgaard.cpp Wed Apr 11 12:37:43 2007
@@ -28,7 +28,6 @@
DSGraph *ResultGraph;
EquivalenceClasses<GlobalValue*> GlobalECs; // Always empty
- PoolDescriptorMapType PoolDescriptors;
public:
Steens() : ResultGraph(0) {}
~Steens() {
Index: llvm-poolalloc/lib/DSA/TopDownClosure.cpp
diff -u llvm-poolalloc/lib/DSA/TopDownClosure.cpp:1.98 llvm-poolalloc/lib/DSA/TopDownClosure.cpp:1.99
--- llvm-poolalloc/lib/DSA/TopDownClosure.cpp:1.98 Fri Feb 23 16:49:32 2007
+++ llvm-poolalloc/lib/DSA/TopDownClosure.cpp Wed Apr 11 12:37:43 2007
@@ -33,7 +33,7 @@
namespace {
RegisterPass<TDDataStructures> // Register the pass
- Y("tddatastructure", "Top-down Data Structure Analysis");
+ Y("dsa-td", "Top-down Data Structure Analysis");
STATISTIC (NumTDInlines, "Number of graphs inlined");
}
More information about the llvm-commits
mailing list