Switch from using CallInst's to represent call sites to using the LLVM

CallSite class.  Now we can represent function calls by invoke instructions
too!

llvm-svn: 8629
This commit is contained in:
Chris Lattner 2003-09-20 16:34:13 +00:00
parent 36b877ae7f
commit 04d9cb6770
9 changed files with 87 additions and 73 deletions

View File

@ -7,11 +7,9 @@
#ifndef LLVM_ANALYSIS_DSSUPPORT_H
#define LLVM_ANALYSIS_DSSUPPORT_H
#include <vector>
#include <functional>
#include <string>
#include <cassert>
#include "Support/hash_set"
#include "llvm/Support/CallSite.h"
class Function;
class CallInst;
@ -127,7 +125,7 @@ namespace std {
/// the DSNode handles for the function arguments.
///
class DSCallSite {
CallInst *Inst; // Actual call site
CallSite Site; // Actual call site
Function *CalleeF; // The function called (direct call)
DSNodeHandle CalleeN; // The function node called (indirect call)
DSNodeHandle RetVal; // Returned value
@ -160,21 +158,21 @@ public:
/// Constructor. Note - This ctor destroys the argument vector passed in. On
/// exit, the argument vector is empty.
///
DSCallSite(CallInst &inst, const DSNodeHandle &rv, DSNode *Callee,
DSCallSite(CallSite CS, const DSNodeHandle &rv, DSNode *Callee,
std::vector<DSNodeHandle> &Args)
: Inst(&inst), CalleeF(0), CalleeN(Callee), RetVal(rv) {
: Site(CS), CalleeF(0), CalleeN(Callee), RetVal(rv) {
assert(Callee && "Null callee node specified for call site!");
Args.swap(CallArgs);
}
DSCallSite(CallInst &inst, const DSNodeHandle &rv, Function *Callee,
DSCallSite(CallSite CS, const DSNodeHandle &rv, Function *Callee,
std::vector<DSNodeHandle> &Args)
: Inst(&inst), CalleeF(Callee), RetVal(rv) {
: Site(CS), CalleeF(Callee), RetVal(rv) {
assert(Callee && "Null callee function specified for call site!");
Args.swap(CallArgs);
}
DSCallSite(const DSCallSite &DSCS) // Simple copy ctor
: Inst(DSCS.Inst), CalleeF(DSCS.CalleeF), CalleeN(DSCS.CalleeN),
: Site(DSCS.Site), CalleeF(DSCS.CalleeF), CalleeN(DSCS.CalleeN),
RetVal(DSCS.RetVal), CallArgs(DSCS.CallArgs) {}
/// Mapping copy constructor - This constructor takes a preexisting call site
@ -183,7 +181,7 @@ public:
///
template<typename MapTy>
DSCallSite(const DSCallSite &FromCall, const MapTy &NodeMap) {
Inst = FromCall.Inst;
Site = FromCall.Site;
InitNH(RetVal, FromCall.RetVal, NodeMap);
InitNH(CalleeN, FromCall.CalleeN, NodeMap);
CalleeF = FromCall.CalleeF;
@ -194,7 +192,7 @@ public:
}
const DSCallSite &operator=(const DSCallSite &RHS) {
Inst = RHS.Inst;
Site = RHS.Site;
CalleeF = RHS.CalleeF;
CalleeN = RHS.CalleeN;
RetVal = RHS.RetVal;
@ -212,7 +210,7 @@ public:
// Accessor functions...
Function &getCaller() const;
CallInst &getCallInst() const { return *Inst; }
CallSite getCallSite() const { return Site; }
DSNodeHandle &getRetVal() { return RetVal; }
const DSNodeHandle &getRetVal() const { return RetVal; }
@ -236,7 +234,7 @@ public:
void swap(DSCallSite &CS) {
if (this != &CS) {
std::swap(Inst, CS.Inst);
std::swap(Site, CS.Site);
std::swap(RetVal, CS.RetVal);
std::swap(CalleeN, CS.CalleeN);
std::swap(CalleeF, CS.CalleeF);

View File

@ -11,10 +11,9 @@
#include "Support/hash_set"
class Type;
class CallInst;
class Instruction;
class DSGraph;
class DSNode;
class DSCallSite;
// FIXME: move this stuff to a private header
namespace DataStructureAnalysis {
@ -75,7 +74,7 @@ class BUDataStructures : public Pass {
// DSInfo, one graph for each function
hash_map<Function*, DSGraph*> DSInfo;
DSGraph *GlobalsGraph;
hash_multimap<CallInst*, Function*> ActualCallees;
hash_multimap<Instruction*, Function*> ActualCallees;
public:
~BUDataStructures() { releaseMemory(); }
@ -106,7 +105,7 @@ public:
AU.addRequired<LocalDataStructures>();
}
typedef hash_multimap<CallInst*, Function*> ActualCalleesTy;
typedef hash_multimap<Instruction*, Function*> ActualCalleesTy;
const ActualCalleesTy &getActualCallees() const {
return ActualCallees;
}

View File

@ -45,7 +45,10 @@
class Module;
class Function;
class CallSite;
class Instruction;
class CallInst;
class InvokeInst;
class DSNode;
class DSGraph;
class DSNodeHandle;
@ -117,15 +120,15 @@ class FunctionModRefInfo {
IPModRef& IPModRefObj; // The IPModRef Object owning this
DSGraph* funcTDGraph; // Top-down DS graph for function
ModRefInfo funcModRefInfo; // ModRefInfo for the function body
std::map<const CallInst*, ModRefInfo*>
std::map<const Instruction*, ModRefInfo*>
callSiteModRefInfo; // ModRefInfo for each callsite
std::map<const DSNode*, unsigned> NodeIds;
friend class IPModRef;
void computeModRef (const Function &func);
void computeModRef (const CallInst& callInst);
DSGraph *ResolveCallSiteModRefInfo(CallInst &CI,
void computeModRef (CallSite call);
DSGraph *ResolveCallSiteModRefInfo(CallSite CS,
hash_map<const DSNode*, DSNodeHandle> &NodeMap);
public:
@ -145,9 +148,14 @@ public:
return &funcModRefInfo;
}
const ModRefInfo* getModRefInfo (const CallInst& callInst) const {
std::map<const CallInst*, ModRefInfo*>::const_iterator I =
callSiteModRefInfo.find(&callInst);
return (I == callSiteModRefInfo.end())? NULL : I->second;
std::map<const Instruction*, ModRefInfo*>::const_iterator I =
callSiteModRefInfo.find((Instruction*)&callInst);
return (I == callSiteModRefInfo.end()) ? NULL : I->second;
}
const ModRefInfo* getModRefInfo (const InvokeInst& II) const {
std::map<const Instruction*, ModRefInfo*>::const_iterator I =
callSiteModRefInfo.find((Instruction*)&II);
return (I == callSiteModRefInfo.end()) ? NULL : I->second;
}
// Get the nodeIds used to index all Mod/Ref information for current function

View File

@ -253,7 +253,8 @@ void BUDataStructures::calculateGraph(DSGraph &Graph) {
Graph.mergeInGraph(CS, *Callee, Graph, 0);
} else {
ActualCallees.insert(std::make_pair(&CS.getCallInst(), Callee));
ActualCallees.insert(std::make_pair(CS.getCallSite().getInstruction(),
Callee));
// Get the data structure graph for the called function.
//

View File

@ -709,7 +709,7 @@ void DSNode::mergeWith(const DSNodeHandle &NH, unsigned Offset) {
// Define here to avoid including iOther.h and BasicBlock.h in DSGraph.h
Function &DSCallSite::getCaller() const {
return *Inst->getParent()->getParent();
return *Site.getInstruction()->getParent()->getParent();
}
@ -1044,7 +1044,7 @@ DSCallSite DSGraph::getCallSiteForArguments(Function &F) const {
if (isPointerType(I->getType()))
Args.push_back(getScalarMap().find(I)->second);
return DSCallSite(*(CallInst*)0, getReturnNodeFor(F), &F, Args);
return DSCallSite(CallSite(), getReturnNodeFor(F), &F, Args);
}

View File

@ -68,7 +68,7 @@ void DSGraphStats::countCallees(const Function& F) {
const std::vector<DSCallSite> &callSites = TDGraph->getFunctionCalls();
for (unsigned i = 0, N = callSites.size(); i != N; ++i)
if (isIndirectCallee(callSites[i].getCallInst().getCalledValue())) {
if (isIndirectCallee(callSites[i].getCallSite().getCalledValue())) {
// This is an indirect function call
const std::vector<GlobalValue*> &Callees =
callSites[i].getCalleeNode()->getGlobals();
@ -76,8 +76,9 @@ void DSGraphStats::countCallees(const Function& F) {
totalNumCallees += Callees.size();
++numIndirectCalls;
} else
std::cerr << "WARNING: No callee in Function " << F.getName()
<< "at call:\n" << callSites[i].getCallInst();
std::cerr << "WARNING: No callee in Function '" << F.getName()
<< "' at call: \n"
<< *callSites[i].getCallSite().getInstruction();
}
TotalNumCallees += totalNumCallees;

View File

@ -7,14 +7,11 @@
#include "llvm/Analysis/DataStructure.h"
#include "llvm/Analysis/DSGraph.h"
#include "llvm/iMemory.h"
#include "llvm/iTerminators.h"
#include "llvm/iPHINode.h"
#include "llvm/iOther.h"
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Function.h"
#include "llvm/GlobalVariable.h"
#include "llvm/Instructions.h"
#include "llvm/Support/InstVisitor.h"
#include "llvm/Target/TargetData.h"
#include "Support/CommandLine.h"
@ -96,11 +93,13 @@ namespace {
void visitLoadInst(LoadInst &LI);
void visitStoreInst(StoreInst &SI);
void visitCallInst(CallInst &CI);
void visitInvokeInst(InvokeInst &II);
void visitSetCondInst(SetCondInst &SCI) {} // SetEQ & friends are ignored
void visitFreeInst(FreeInst &FI);
void visitCastInst(CastInst &CI);
void visitInstruction(Instruction &I);
void visitCallSite(CallSite CS);
private:
// Helper functions used to implement the visitation functions...
@ -405,29 +404,38 @@ void GraphBuilder::visitReturnInst(ReturnInst &RI) {
}
void GraphBuilder::visitCallInst(CallInst &CI) {
visitCallSite(&CI);
}
void GraphBuilder::visitInvokeInst(InvokeInst &II) {
visitCallSite(&II);
}
void GraphBuilder::visitCallSite(CallSite CS) {
// Set up the return value...
DSNodeHandle RetVal;
if (isPointerType(CI.getType()))
RetVal = getValueDest(CI);
Instruction *I = CS.getInstruction();
if (isPointerType(I->getType()))
RetVal = getValueDest(*I);
DSNode *Callee = 0;
if (DisableDirectCallOpt || !isa<Function>(CI.getOperand(0)))
Callee = getValueDest(*CI.getOperand(0)).getNode();
if (DisableDirectCallOpt || !isa<Function>(CS.getCalledValue()))
Callee = getValueDest(*CS.getCalledValue()).getNode();
std::vector<DSNodeHandle> Args;
Args.reserve(CI.getNumOperands()-1);
Args.reserve(CS.arg_end()-CS.arg_begin());
// Calculate the arguments vector...
for (unsigned i = 1, e = CI.getNumOperands(); i != e; ++i)
if (isPointerType(CI.getOperand(i)->getType()))
Args.push_back(getValueDest(*CI.getOperand(i)));
for (CallSite::arg_iterator I = CS.arg_begin(), E = CS.arg_end(); I != E; ++I)
if (isPointerType((*I)->getType()))
Args.push_back(getValueDest(**I));
// Add a new function call entry...
if (Callee)
FunctionCalls.push_back(DSCallSite(CI, RetVal, Callee, Args));
FunctionCalls.push_back(DSCallSite(CS, RetVal, Callee, Args));
else
FunctionCalls.push_back(DSCallSite(CI, RetVal,
cast<Function>(CI.getOperand(0)), Args));
FunctionCalls.push_back(DSCallSite(CS, RetVal, CS.getCalledFunction(),
Args));
}
void GraphBuilder::visitFreeInst(FreeInst &FI) {

View File

@ -96,9 +96,10 @@ void TDDataStructures::ComputePostOrder(Function &F,hash_set<DSGraph*> &Visited,
const std::vector<DSCallSite> &FunctionCalls = G.getFunctionCalls();
for (unsigned i = 0, e = FunctionCalls.size(); i != e; ++i) {
Instruction *CallI = FunctionCalls[i].getCallSite().getInstruction();
std::pair<BUDataStructures::ActualCalleesTy::const_iterator,
BUDataStructures::ActualCalleesTy::const_iterator>
IP = ActualCallees.equal_range(&FunctionCalls[i].getCallInst());
IP = ActualCallees.equal_range(CallI);
for (BUDataStructures::ActualCalleesTy::const_iterator I = IP.first;
I != IP.second; ++I)
@ -191,10 +192,11 @@ void TDDataStructures::inlineGraphIntoCallees(DSGraph &Graph) {
// Clone and merge the reachable subgraph from the call into callee's graph.
//
for (unsigned i = 0, e = FunctionCalls.size(); i != e; ++i) {
Instruction *CallI = FunctionCalls[i].getCallSite().getInstruction();
// For each function in the invoked function list at this call site...
std::pair<BUDataStructures::ActualCalleesTy::const_iterator,
BUDataStructures::ActualCalleesTy::const_iterator>
IP = ActualCallees.equal_range(&FunctionCalls[i].getCallInst());
IP = ActualCallees.equal_range(CallI);
// Multiple callees may have the same graph, so try to inline and merge
// only once for each <callSite,calleeGraph> pair, not once for each

View File

@ -61,7 +61,7 @@ FunctionModRefInfo::FunctionModRefInfo(const Function& func,
FunctionModRefInfo::~FunctionModRefInfo()
{
for(std::map<const CallInst*, ModRefInfo*>::iterator
for(std::map<const Instruction*, ModRefInfo*>::iterator
I=callSiteModRefInfo.begin(), E=callSiteModRefInfo.end(); I != E; ++I)
delete(I->second);
@ -98,7 +98,7 @@ void FunctionModRefInfo::computeModRef(const Function &func)
// The call sites are recorded in the TD graph.
const std::vector<DSCallSite>& callSites = funcTDGraph->getFunctionCalls();
for (unsigned i = 0, N = callSites.size(); i < N; ++i)
computeModRef(callSites[i].getCallInst());
computeModRef(callSites[i].getCallSite());
}
@ -117,25 +117,22 @@ void FunctionModRefInfo::computeModRef(const Function &func)
// requested information (because the call site calls an external
// function or we cannot determine the complete set of functions invoked).
//
DSGraph* FunctionModRefInfo::ResolveCallSiteModRefInfo(CallInst &CI,
DSGraph* FunctionModRefInfo::ResolveCallSiteModRefInfo(CallSite CS,
hash_map<const DSNode*, DSNodeHandle> &NodeMap)
{
// Step #0: Quick check if we are going to fail anyway: avoid
// all the graph cloning and map copying in steps #1 and #2.
//
if (const Function *F = CI.getCalledFunction())
{
if (F->isExternal())
return 0; // We cannot compute Mod/Ref info for this callsite...
}
else
{
// Eventually, should check here if any callee is external.
// For now we are not handling this case anyway.
std::cerr << "IP Mod/Ref indirect call not implemented yet: "
<< "Being conservative\n";
if (const Function *F = CS.getCalledFunction()) {
if (F->isExternal())
return 0; // We cannot compute Mod/Ref info for this callsite...
}
} else {
// Eventually, should check here if any callee is external.
// For now we are not handling this case anyway.
std::cerr << "IP Mod/Ref indirect call not implemented yet: "
<< "Being conservative\n";
return 0; // We cannot compute Mod/Ref info for this callsite...
}
// Step #1: Clone the top-down graph...
DSGraph *Result = new DSGraph(*funcTDGraph, NodeMap);
@ -144,7 +141,7 @@ DSGraph* FunctionModRefInfo::ResolveCallSiteModRefInfo(CallInst &CI,
Result->maskNodeTypes(~(DSNode::Modified | DSNode::Read));
// Step #3: clone the bottom up graphs for the callees into the caller graph
if (Function *F = CI.getCalledFunction())
if (Function *F = CS.getCalledFunction())
{
assert(!F->isExternal());
@ -152,17 +149,18 @@ DSGraph* FunctionModRefInfo::ResolveCallSiteModRefInfo(CallInst &CI,
// If the call returns a value, make sure to merge the nodes...
DSNodeHandle RetVal;
if (DS::isPointerType(CI.getType()))
RetVal = Result->getNodeForValue(&CI);
if (DS::isPointerType(CS.getInstruction()->getType()))
RetVal = Result->getNodeForValue(CS.getInstruction());
// Populate the arguments list...
std::vector<DSNodeHandle> Args;
for (unsigned i = 1, e = CI.getNumOperands(); i != e; ++i)
if (DS::isPointerType(CI.getOperand(i)->getType()))
Args.push_back(Result->getNodeForValue(CI.getOperand(i)));
for (CallSite::arg_iterator I = CS.arg_begin(), E = CS.arg_end();
I != E; ++I)
if (DS::isPointerType((*I)->getType()))
Args.push_back(Result->getNodeForValue(*I));
// Build the call site...
DSCallSite CS(CI, RetVal, F, Args);
DSCallSite CS(CS, RetVal, F, Args);
// Perform the merging now of the graph for the callee, which will
// come with mod/ref bits set...
@ -187,16 +185,15 @@ DSGraph* FunctionModRefInfo::ResolveCallSiteModRefInfo(CallInst &CI,
// and then inlining the callee's BU graph into the caller's TD graph.
//
void
FunctionModRefInfo::computeModRef(const CallInst& callInst)
FunctionModRefInfo::computeModRef(CallSite CS)
{
// Allocate the mod/ref info for the call site. Bits automatically cleared.
ModRefInfo* callModRefInfo = new ModRefInfo(funcTDGraph->getGraphSize());
callSiteModRefInfo[&callInst] = callModRefInfo;
callSiteModRefInfo[CS.getInstruction()] = callModRefInfo;
// Get a copy of the graph for the callee with the callee inlined
hash_map<const DSNode*, DSNodeHandle> NodeMap;
DSGraph* csgp = ResolveCallSiteModRefInfo(const_cast<CallInst&>(callInst),
NodeMap);
DSGraph* csgp = ResolveCallSiteModRefInfo(CS, NodeMap);
if (!csgp)
{ // Callee's side effects are unknown: mark all nodes Mod and Ref.
// Eventually this should only mark nodes visible to the callee, i.e.,
@ -323,7 +320,7 @@ void FunctionModRefInfo::print(std::ostream &O) const
// Second: Print Globals and Locals modified at each call site in function
//
for (std::map<const CallInst*, ModRefInfo*>::const_iterator
for (std::map<const Instruction *, ModRefInfo*>::const_iterator
CI = callSiteModRefInfo.begin(), CE = callSiteModRefInfo.end();
CI != CE; ++CI)
{