diff options
Diffstat (limited to 'lib/Analysis/DataStructure/Steensgaard.cpp')
-rw-r--r-- | lib/Analysis/DataStructure/Steensgaard.cpp | 278 |
1 files changed, 0 insertions, 278 deletions
diff --git a/lib/Analysis/DataStructure/Steensgaard.cpp b/lib/Analysis/DataStructure/Steensgaard.cpp deleted file mode 100644 index 5ff3c3f852..0000000000 --- a/lib/Analysis/DataStructure/Steensgaard.cpp +++ /dev/null @@ -1,278 +0,0 @@ -//===- Steensgaard.cpp - Context Insensitive Alias Analysis ---------------===// -// -// The LLVM Compiler Infrastructure -// -// This file was developed by the LLVM research group and is distributed under -// the University of Illinois Open Source License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This pass uses the data structure graphs to implement a simple context -// insensitive alias analysis. It does this by computing the local analysis -// graphs for all of the functions, then merging them together into a single big -// graph without cloning. -// -//===----------------------------------------------------------------------===// - -#include "llvm/Analysis/DataStructure/DataStructure.h" -#include "llvm/Analysis/DataStructure/DSGraph.h" -#include "llvm/Analysis/AliasAnalysis.h" -#include "llvm/Analysis/Passes.h" -#include "llvm/Module.h" -#include "llvm/Support/Debug.h" -#include <ostream> -using namespace llvm; - -namespace { - class Steens : public ModulePass, public AliasAnalysis { - DSGraph *ResultGraph; - - EquivalenceClasses<GlobalValue*> GlobalECs; // Always empty - public: - Steens() : ResultGraph(0) {} - ~Steens() { - releaseMyMemory(); - assert(ResultGraph == 0 && "releaseMemory not called?"); - } - - //------------------------------------------------ - // Implement the Pass API - // - - // run - Build up the result graph, representing the pointer graph for the - // program. - // - bool runOnModule(Module &M); - - virtual void releaseMyMemory() { delete ResultGraph; ResultGraph = 0; } - - virtual void getAnalysisUsage(AnalysisUsage &AU) const { - AliasAnalysis::getAnalysisUsage(AU); - AU.setPreservesAll(); // Does not transform code... - AU.addRequired<LocalDataStructures>(); // Uses local dsgraph - } - - // print - Implement the Pass::print method... - void print(OStream O, const Module *M) const { - if (O.stream()) print(*O.stream(), M); - } - void print(std::ostream &O, const Module *M) const { - assert(ResultGraph && "Result graph has not yet been computed!"); - ResultGraph->writeGraphToFile(O, "steensgaards"); - } - - //------------------------------------------------ - // Implement the AliasAnalysis API - // - - AliasResult alias(const Value *V1, unsigned V1Size, - const Value *V2, unsigned V2Size); - - virtual ModRefResult getModRefInfo(CallSite CS, Value *P, unsigned Size); - virtual ModRefResult getModRefInfo(CallSite CS1, CallSite CS2); - - private: - void ResolveFunctionCall(Function *F, const DSCallSite &Call, - DSNodeHandle &RetVal); - }; - - // Register the pass... - RegisterPass<Steens> X("steens-aa", - "Steensgaard's alias analysis (DSGraph based)"); - - // Register as an implementation of AliasAnalysis - RegisterAnalysisGroup<AliasAnalysis> Y(X); -} - -ModulePass *llvm::createSteensgaardPass() { return new Steens(); } - -/// ResolveFunctionCall - Resolve the actual arguments of a call to function F -/// with the specified call site descriptor. This function links the arguments -/// and the return value for the call site context-insensitively. -/// -void Steens::ResolveFunctionCall(Function *F, const DSCallSite &Call, - DSNodeHandle &RetVal) { - assert(ResultGraph != 0 && "Result graph not allocated!"); - DSGraph::ScalarMapTy &ValMap = ResultGraph->getScalarMap(); - - // Handle the return value of the function... - if (Call.getRetVal().getNode() && RetVal.getNode()) - RetVal.mergeWith(Call.getRetVal()); - - // Loop over all pointer arguments, resolving them to their provided pointers - unsigned PtrArgIdx = 0; - for (Function::arg_iterator AI = F->arg_begin(), AE = F->arg_end(); - AI != AE && PtrArgIdx < Call.getNumPtrArgs(); ++AI) { - DSGraph::ScalarMapTy::iterator I = ValMap.find(AI); - if (I != ValMap.end()) // If its a pointer argument... - I->second.mergeWith(Call.getPtrArg(PtrArgIdx++)); - } -} - - -/// run - Build up the result graph, representing the pointer graph for the -/// program. -/// -bool Steens::runOnModule(Module &M) { - InitializeAliasAnalysis(this); - assert(ResultGraph == 0 && "Result graph already allocated!"); - LocalDataStructures &LDS = getAnalysis<LocalDataStructures>(); - - // Create a new, empty, graph... - ResultGraph = new DSGraph(GlobalECs, getTargetData()); - ResultGraph->spliceFrom(LDS.getGlobalsGraph()); - - // Loop over the rest of the module, merging graphs for non-external functions - // into this graph. - // - for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) - if (!I->isExternal()) - ResultGraph->spliceFrom(LDS.getDSGraph(*I)); - - ResultGraph->removeTriviallyDeadNodes(); - - // FIXME: Must recalculate and use the Incomplete markers!! - - // Now that we have all of the graphs inlined, we can go about eliminating - // call nodes... - // - std::list<DSCallSite> &Calls = ResultGraph->getAuxFunctionCalls(); - assert(Calls.empty() && "Aux call list is already in use??"); - - // Start with a copy of the original call sites. - Calls = ResultGraph->getFunctionCalls(); - - for (std::list<DSCallSite>::iterator CI = Calls.begin(), E = Calls.end(); - CI != E;) { - DSCallSite &CurCall = *CI++; - - // Loop over the called functions, eliminating as many as possible... - std::vector<Function*> CallTargets; - if (CurCall.isDirectCall()) - CallTargets.push_back(CurCall.getCalleeFunc()); - else - CurCall.getCalleeNode()->addFullFunctionList(CallTargets); - - for (unsigned c = 0; c != CallTargets.size(); ) { - // If we can eliminate this function call, do so! - Function *F = CallTargets[c]; - if (!F->isExternal()) { - ResolveFunctionCall(F, CurCall, ResultGraph->getReturnNodes()[F]); - CallTargets[c] = CallTargets.back(); - CallTargets.pop_back(); - } else - ++c; // Cannot eliminate this call, skip over it... - } - - if (CallTargets.empty()) { // Eliminated all calls? - std::list<DSCallSite>::iterator I = CI; - Calls.erase(--I); // Remove entry - } - } - - // Remove our knowledge of what the return values of the functions are, except - // for functions that are externally visible from this module (e.g. main). We - // keep these functions so that their arguments are marked incomplete. - for (DSGraph::ReturnNodesTy::iterator I = - ResultGraph->getReturnNodes().begin(), - E = ResultGraph->getReturnNodes().end(); I != E; ) - if (I->first->hasInternalLinkage()) - ResultGraph->getReturnNodes().erase(I++); - else - ++I; - - // Update the "incomplete" markers on the nodes, ignoring unknownness due to - // incoming arguments... - ResultGraph->maskIncompleteMarkers(); - ResultGraph->markIncompleteNodes(DSGraph::IgnoreGlobals | - DSGraph::MarkFormalArgs); - - // Remove any nodes that are dead after all of the merging we have done... - // FIXME: We should be able to disable the globals graph for steens! - //ResultGraph->removeDeadNodes(DSGraph::KeepUnreachableGlobals); - - print(DOUT, &M); - return false; -} - -AliasAnalysis::AliasResult Steens::alias(const Value *V1, unsigned V1Size, - const Value *V2, unsigned V2Size) { - assert(ResultGraph && "Result graph has not been computed yet!"); - - DSGraph::ScalarMapTy &GSM = ResultGraph->getScalarMap(); - - DSGraph::ScalarMapTy::iterator I = GSM.find(const_cast<Value*>(V1)); - DSGraph::ScalarMapTy::iterator J = GSM.find(const_cast<Value*>(V2)); - if (I != GSM.end() && !I->second.isNull() && - J != GSM.end() && !J->second.isNull()) { - DSNodeHandle &V1H = I->second; - DSNodeHandle &V2H = J->second; - - // If at least one of the nodes is complete, we can say something about - // this. If one is complete and the other isn't, then they are obviously - // different nodes. If they are both complete, we can't say anything - // useful. - if (I->second.getNode()->isComplete() || - J->second.getNode()->isComplete()) { - // If the two pointers point to different data structure graph nodes, they - // cannot alias! - if (V1H.getNode() != V2H.getNode()) - return NoAlias; - - // See if they point to different offsets... if so, we may be able to - // determine that they do not alias... - unsigned O1 = I->second.getOffset(), O2 = J->second.getOffset(); - if (O1 != O2) { - if (O2 < O1) { // Ensure that O1 <= O2 - std::swap(V1, V2); - std::swap(O1, O2); - std::swap(V1Size, V2Size); - } - - if (O1+V1Size <= O2) - return NoAlias; - } - } - } - - // If we cannot determine alias properties based on our graph, fall back on - // some other AA implementation. - // - return AliasAnalysis::alias(V1, V1Size, V2, V2Size); -} - -AliasAnalysis::ModRefResult -Steens::getModRefInfo(CallSite CS, Value *P, unsigned Size) { - AliasAnalysis::ModRefResult Result = ModRef; - - // Find the node in question. - DSGraph::ScalarMapTy &GSM = ResultGraph->getScalarMap(); - DSGraph::ScalarMapTy::iterator I = GSM.find(P); - - if (I != GSM.end() && !I->second.isNull()) { - DSNode *N = I->second.getNode(); - if (N->isComplete()) { - // If this is a direct call to an external function, and if the pointer - // points to a complete node, the external function cannot modify or read - // the value (we know it's not passed out of the program!). - if (Function *F = CS.getCalledFunction()) - if (F->isExternal()) - return NoModRef; - - // Otherwise, if the node is complete, but it is only M or R, return this. - // This can be useful for globals that should be marked const but are not. - if (!N->isModified()) - Result = (ModRefResult)(Result & ~Mod); - if (!N->isRead()) - Result = (ModRefResult)(Result & ~Ref); - } - } - - return (ModRefResult)(Result & AliasAnalysis::getModRefInfo(CS, P, Size)); -} - -AliasAnalysis::ModRefResult -Steens::getModRefInfo(CallSite CS1, CallSite CS2) -{ - return AliasAnalysis::getModRefInfo(CS1,CS2); -} |