blob: 8169ab0e037c0cb27590a984f48e8d91afadd39c [file] [log] [blame]
//===- DataStructure.h - Build data structure graphs ------------*- C++ -*-===//
//
// 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.
//
//===----------------------------------------------------------------------===//
//
// Implement the LLVM data structure analysis library.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_ANALYSIS_DATA_STRUCTURE_H
#define LLVM_ANALYSIS_DATA_STRUCTURE_H
#include "llvm/Pass.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Support/CallSite.h"
#include "llvm/ADT/EquivalenceClasses.h"
#include "dsa/EntryPointAnalysis.h"
#include "dsa/DSCallGraph.h"
#include "dsa/sv/set.h"
#include "dsa/sv/super_set.h"
#include <map>
namespace llvm {
class Type;
class Instruction;
class GlobalValue;
class DSGraph;
class DSCallSite;
class DSNode;
class DSNodeHandle;
FunctionPass *createDataStructureStatsPass();
FunctionPass *createDataStructureGraphCheckerPass();
class DataStructures : public ModulePass {
typedef std::map<const Function*, DSGraph*> DSInfoTy;
/// TargetData, comes in handy
TargetData* TD;
/// Pass to get Graphs from
DataStructures* GraphSource;
/// Do we clone Graphs or steal them?
bool Clone;
/// do we reset the aux list to the func list?
bool resetAuxCalls;
/// Were are DSGraphs stolen by another pass?
bool DSGraphsStolen;
void buildGlobalECs(sv::set<const GlobalValue*>& ECGlobals);
void eliminateUsesOfECGlobals(DSGraph& G, const sv::set<const GlobalValue*> &ECGlobals);
// DSInfo, one graph for each function
DSInfoTy DSInfo;
// Name for printing
const char* printname;
protected:
/// The Globals Graph contains all information on the globals
DSGraph *GlobalsGraph;
/// GlobalECs - The equivalence classes for each global value that is merged
/// with other global values in the DSGraphs.
EquivalenceClasses<const GlobalValue*> GlobalECs;
SuperSet<const Type*>* TypeSS;
// Callgraph, as computed so far
DSCallGraph callgraph;
void init(DataStructures* D, bool clone, bool printAuxCalls, bool copyGlobalAuxCalls, bool resetAux);
void init(TargetData* T);
void formGlobalECs();
DataStructures(intptr_t id, const char* name)
: ModulePass(id), TD(0), GraphSource(0), printname(name), GlobalsGraph(0) {
// For now, the graphs are owned by this pass
DSGraphsStolen = false;
}
public:
/// print - Print out the analysis results...
///
void print(llvm::raw_ostream &O, const Module *M) const;
void dumpCallGraph() const;
virtual void releaseMemory();
virtual bool hasDSGraph(const Function &F) const {
return DSInfo.find(&F) != DSInfo.end();
}
/// getDSGraph - Return the data structure graph for the specified function.
///
virtual DSGraph *getDSGraph(const Function &F) const {
std::map<const Function*, DSGraph*>::const_iterator I = DSInfo.find(&F);
assert(I != DSInfo.end() && "Function not in module!");
return I->second;
}
void setDSGraph(const Function& F, DSGraph* G) {
DSInfo[&F] = G;
}
DSGraph* getOrCreateGraph(const Function* F);
DSGraph* getGlobalsGraph() const { return GlobalsGraph; }
EquivalenceClasses<const GlobalValue*> &getGlobalECs() { return GlobalECs; }
TargetData& getTargetData() const { return *TD; }
const DSCallGraph& getCallGraph() const { return callgraph; }
SuperSet<const Type*>& getTypeSS() const { return *TypeSS; }
/// deleteValue/copyValue - Interfaces to update the DSGraphs in the program.
/// These correspond to the interfaces defined in the AliasAnalysis class.
void deleteValue(Value *V);
void copyValue(Value *From, Value *To);
};
// BasicDataStructures - The analysis is a dummy one -- all pointers can points
// to all possible locations.
//
class BasicDataStructures : public DataStructures {
public:
static char ID;
BasicDataStructures() : DataStructures((intptr_t)&ID, "basic.") {}
~BasicDataStructures() { releaseMemory(); }
virtual bool runOnModule(Module &M);
/// getAnalysisUsage - This obviously provides a data structure graph.
///
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
AU.addRequired<TargetData>();
AU.setPreservesAll();
}
};
// LocalDataStructures - The analysis that computes the local data structure
// graphs for all of the functions in the program.
//
// FIXME: This should be a Function pass that can be USED by a Pass, and would
// be automatically preserved. Until we can do that, this is a Pass.
//
class LocalDataStructures : public DataStructures {
public:
static char ID;
LocalDataStructures() : DataStructures((intptr_t)&ID, "local.") {}
~LocalDataStructures() { releaseMemory(); }
virtual bool runOnModule(Module &M);
/// getAnalysisUsage - This obviously provides a data structure graph.
///
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
AU.addRequired<TargetData>();
AU.setPreservesAll();
}
};
// StdLibDataStructures - This analysis recognizes common standard c library
// functions and generates graphs for them.
class StdLibDataStructures : public DataStructures {
void eraseCallsTo(Function* F);
public:
static char ID;
StdLibDataStructures() : DataStructures((intptr_t)&ID, "stdlib.") {}
~StdLibDataStructures() { releaseMemory(); }
virtual bool runOnModule(Module &M);
/// getAnalysisUsage - This obviously provides a data structure graph.
///
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
AU.addRequired<LocalDataStructures>();
AU.addPreserved<EntryPointAnalysis>();
AU.setPreservesCFG();
}
};
/// BUDataStructures - The analysis that computes the interprocedurally closed
/// data structure graphs for all of the functions in the program. This pass
/// only performs a "Bottom Up" propagation (hence the name).
///
class BUDataStructures : public DataStructures {
protected:
// This map is only maintained during construction of BU Graphs
std::map<std::vector<const Function*>,
std::pair<DSGraph*, std::vector<DSNodeHandle> > > IndCallGraphMap;
const char* debugname;
bool useCallGraph;
EntryPointAnalysis* EP;
public:
static char ID;
//Child constructor (CBU)
BUDataStructures(intptr_t CID, const char* name, const char* printname)
: DataStructures(CID, printname), debugname(name), useCallGraph(true) {}
//main constructor
BUDataStructures()
: DataStructures((intptr_t)&ID, "bu."), debugname("dsa-bu"),
useCallGraph(false) {}
~BUDataStructures() { releaseMemory(); }
virtual bool runOnModule(Module &M);
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
AU.addRequired<StdLibDataStructures>();
AU.addRequired<EntryPointAnalysis>();
AU.addPreserved<EntryPointAnalysis>();
AU.setPreservesCFG();
}
protected:
bool runOnModuleInternal(Module &M);
private:
void calculateGraph(DSGraph* G);
unsigned calculateGraphs(const Function *F,
std::vector<const Function*> &Stack,
unsigned &NextID,
std::map<const Function*, unsigned> &ValMap);
void CloneAuxIntoGlobal(DSGraph* G);
void cloneGlobalsInto(DSGraph* G);
void cloneIntoGlobals(DSGraph* G);
void finalizeGlobals(void);
};
/// CompleteBUDataStructures - This is the exact same as the bottom-up graphs,
/// but we use take a completed call graph and inline all indirect callees into
/// their callers graphs, making the result more useful for things like pool
/// allocation.
///
class CompleteBUDataStructures : public BUDataStructures {
protected:
void buildIndirectFunctionSets(Module &M);
public:
static char ID;
CompleteBUDataStructures(intptr_t CID = (intptr_t)&ID,
const char* name = "dsa-cbu",
const char* printname = "cbu.")
: BUDataStructures(CID, name, printname) {}
~CompleteBUDataStructures() { releaseMemory(); }
virtual bool runOnModule(Module &M);
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
AU.addRequired<BUDataStructures>();
AU.addRequired<EntryPointAnalysis > ();
AU.addPreserved<EntryPointAnalysis>();
AU.setPreservesCFG();
}
};
/// EquivBUDataStructures - This is the same as the complete bottom-up graphs, but
/// with functions partitioned into equivalence classes and a single merged
/// DS graph for all functions in an equivalence class. After this merging,
/// graphs are inlined bottom-up on the SCCs of the final (CBU) call graph.
///
class EquivBUDataStructures : public CompleteBUDataStructures {
void mergeGraphsByGlobalECs();
public:
static char ID;
EquivBUDataStructures()
: CompleteBUDataStructures((intptr_t)&ID, "dsa-eq", "eq.") {}
~EquivBUDataStructures() { releaseMemory(); }
virtual bool runOnModule(Module &M);
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
AU.addRequired<CompleteBUDataStructures>();
AU.setPreservesCFG();
}
};
/// TDDataStructures - Analysis that computes new data structure graphs
/// for each function using the closed graphs for the callers computed
/// by the bottom-up pass.
///
class TDDataStructures : public DataStructures {
sv::set<const Function*> ArgsRemainIncomplete;
/// CallerCallEdges - For a particular graph, we keep a list of these records
/// which indicates which graphs call this function and from where.
struct CallerCallEdge {
DSGraph *CallerGraph; // The graph of the caller function.
const DSCallSite *CS; // The actual call site.
const Function *CalledFunction; // The actual function being called.
CallerCallEdge(DSGraph *G, const DSCallSite *cs, const Function *CF)
: CallerGraph(G), CS(cs), CalledFunction(CF) {}
bool operator<(const CallerCallEdge &RHS) const {
return CallerGraph < RHS.CallerGraph ||
(CallerGraph == RHS.CallerGraph && CS < RHS.CS);
}
};
std::map<DSGraph*, std::vector<CallerCallEdge> > CallerEdges;
// IndCallMap - We memoize the results of indirect call inlining operations
// that have multiple targets here to avoid N*M inlining. The key to the map
// is a sorted set of callee functions, the value is the DSGraph that holds
// all of the caller graphs merged together, and the DSCallSite to merge with
// the arguments for each function.
std::map<std::vector<const Function*>, DSGraph*> IndCallMap;
bool useEQBU;
public:
static char ID;
TDDataStructures(intptr_t CID = (intptr_t)&ID, const char* printname = "td.", bool useEQ = false)
: DataStructures(CID, printname), useEQBU(useEQ) {}
~TDDataStructures();
virtual bool runOnModule(Module &M);
/// getAnalysisUsage - This obviously provides a data structure graph.
///
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
if (useEQBU) {
AU.addRequired<EquivBUDataStructures>();
} else {
AU.addRequired<BUDataStructures>();
AU.addPreserved<BUDataStructures>();
}
AU.setPreservesCFG();
}
private:
void markReachableFunctionsExternallyAccessible(DSNode *N,
sv::set<DSNode*> &Visited);
void InlineCallersIntoGraph(DSGraph* G);
void ComputePostOrder(const Function &F, sv::set<DSGraph*> &Visited,
std::vector<DSGraph*> &PostOrder);
};
/// EQTDDataStructures - Analysis that computes new data structure graphs
/// for each function using the closed graphs for the callers computed
/// by the EQ bottom-up pass.
///
class EQTDDataStructures : public TDDataStructures {
public:
static char ID;
EQTDDataStructures()
:TDDataStructures((intptr_t)&ID, "eqtd.", false)
{}
~EQTDDataStructures();
};
/// SteensgaardsDataStructures - Analysis that computes a context-insensitive
/// data structure graphs for the whole program.
///
class SteensgaardDataStructures : public DataStructures {
DSGraph * ResultGraph;
DataStructures * DS;
void ResolveFunctionCall(const Function *F, const DSCallSite &Call,
DSNodeHandle &RetVal);
bool runOnModuleInternal(Module &M);
public:
static char ID;
SteensgaardDataStructures() :
DataStructures((intptr_t)&ID, "steensgaard."),
ResultGraph(NULL) {}
~SteensgaardDataStructures();
virtual bool runOnModule(Module &M);
virtual void releaseMemory();
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
AU.addRequired<TargetData>();
AU.addRequired<StdLibDataStructures>();
AU.setPreservesAll();
}
/// getDSGraph - Return the data structure graph for the specified function.
///
virtual DSGraph *getDSGraph(const Function &F) const {
return getResultGraph();
}
virtual bool hasDSGraph(const Function &F) const {
return true;
}
/// getDSGraph - Return the data structure graph for the whole program.
///
DSGraph *getResultGraph() const {
return ResultGraph;
}
void print(llvm::raw_ostream &O, const Module *M) const;
};
} // End llvm namespace
#endif