bool operator<(const DSNodeHandle &H) const { // Allow sorting
return N < H.N || (N == H.N && Offset < H.Offset);
}
+ bool operator>(const DSNodeHandle &H) const { return H < *this; }
bool operator==(const DSNodeHandle &H) const { // Allow comparison
return N == H.N && Offset == H.Offset;
}
/// the DSNode handle for the callee function (or function pointer), and
/// the DSNode handles for the function arguments.
///
-class DSCallSite: public std::vector<DSNodeHandle> {
- CallInst* callInst;
- DSCallSite(); // do not implement
+class DSCallSite {
+ CallInst *Inst; // Actual call site
+ DSNodeHandle RetVal; // Returned value
+ DSNodeHandle Callee; // The function node called
+ std::vector<DSNodeHandle> CallArgs; // The pointer arguments
+ DSCallSite(); // DO NOT IMPLEMENT
public:
- DSCallSite(CallInst& _callInst) : callInst(&_callInst) { }
-
- // Copy constructor with helper for cloning nodes. The helper should be a
- // model of unary_function<const DSNodeHandle*, DSNodeHandle>, i.e., it
- // should take a pointer to DSNodeHandle and return a fresh DSNodeHandle.
- // If no helper is specified, this defaults to a simple copy constructor.
- template<typename _CopierFunction>
- DSCallSite(const DSCallSite& FromCall,
- _CopierFunction nodeCopier = *(_CopierFunction*) 0);
-
- Function& getCaller() const;
- CallInst& getCallInst() const { return *callInst; }
- DSNodeHandle getReturnValueNode() const { return (*this)[0]; }
- DSNodeHandle getCalleeNode() const { return (*this)[1]; }
- unsigned getNumPtrArgs() const { return (size() - 2); }
- DSNodeHandle getPtrArgNode(unsigned i) const { assert(i < getNumPtrArgs());
- return (*this)[i+2]; }
+ /// Note - This ctor destroys the argument vector passed in. On exit, the
+ /// argument vector is empty.
+ ///
+ DSCallSite(CallInst &inst, const DSNodeHandle &rv, const DSNodeHandle &callee,
+ std::vector<DSNodeHandle> &Args)
+ : Inst(&inst), RetVal(rv), Callee(callee) {
+ Args.swap(CallArgs);
+ }
+
+ /// Copy constructor with helper for cloning nodes. The helper should be a
+ /// model of unary_function<const DSNodeHandle*, DSNodeHandle>, i.e., it
+ /// should take a pointer to DSNodeHandle and return a fresh DSNodeHandle.
+ /// If no helper is specified, this defaults to a simple copy constructor.
+ ///
+ template<typename CopyFunctor>
+ DSCallSite(const DSCallSite &FromCall, CopyFunctor nodeCopier);
+ DSCallSite(const DSCallSite &DSCS)
+ : Inst(DSCS.Inst), RetVal(DSCS.RetVal),
+ Callee(DSCS.Callee), CallArgs(DSCS.CallArgs) {}
+
+ // Accessor functions...
+ Function &getCaller() const;
+ CallInst &getCallInst() const { return *Inst; }
+ DSNodeHandle &getRetVal() { return RetVal; }
+ DSNodeHandle &getCallee() { return Callee; }
+ const DSNodeHandle &getRetVal() const { return RetVal; }
+ const DSNodeHandle &getCallee() const { return Callee; }
+ unsigned getNumPtrArgs() const { return CallArgs.size(); }
+
+ DSNodeHandle &getPtrArg(unsigned i) {
+ assert(i < CallArgs.size() && "Argument to getPtrArgNode is out of range!");
+ return CallArgs[i];
+ }
+ const DSNodeHandle &getPtrArg(unsigned i) const {
+ assert(i < CallArgs.size() && "Argument to getPtrArgNode is out of range!");
+ return CallArgs[i];
+ }
+
+ bool operator<(const DSCallSite &CS) const {
+ if (Inst < CS.Inst) return true;
+ if (Inst > CS.Inst) return false;
+ if (RetVal < CS.RetVal) return true;
+ if (RetVal > CS.RetVal) return false;
+ if (Callee < CS.Callee) return true;
+ if (Callee > CS.Callee) return false;
+ return CallArgs < CS.CallArgs;
+ }
+
+ bool operator==(const DSCallSite &CS) const {
+ return Inst == CS.Inst && RetVal == CS.RetVal && Callee == CS.Callee &&
+ CallArgs == CS.CallArgs;
+ }
};
bool operator<(const DSNodeHandle &H) const { // Allow sorting
return N < H.N || (N == H.N && Offset < H.Offset);
}
+ bool operator>(const DSNodeHandle &H) const { return H < *this; }
bool operator==(const DSNodeHandle &H) const { // Allow comparison
return N == H.N && Offset == H.Offset;
}
/// the DSNode handle for the callee function (or function pointer), and
/// the DSNode handles for the function arguments.
///
-class DSCallSite: public std::vector<DSNodeHandle> {
- CallInst* callInst;
- DSCallSite(); // do not implement
+class DSCallSite {
+ CallInst *Inst; // Actual call site
+ DSNodeHandle RetVal; // Returned value
+ DSNodeHandle Callee; // The function node called
+ std::vector<DSNodeHandle> CallArgs; // The pointer arguments
+ DSCallSite(); // DO NOT IMPLEMENT
public:
- DSCallSite(CallInst& _callInst) : callInst(&_callInst) { }
-
- // Copy constructor with helper for cloning nodes. The helper should be a
- // model of unary_function<const DSNodeHandle*, DSNodeHandle>, i.e., it
- // should take a pointer to DSNodeHandle and return a fresh DSNodeHandle.
- // If no helper is specified, this defaults to a simple copy constructor.
- template<typename _CopierFunction>
- DSCallSite(const DSCallSite& FromCall,
- _CopierFunction nodeCopier = *(_CopierFunction*) 0);
-
- Function& getCaller() const;
- CallInst& getCallInst() const { return *callInst; }
- DSNodeHandle getReturnValueNode() const { return (*this)[0]; }
- DSNodeHandle getCalleeNode() const { return (*this)[1]; }
- unsigned getNumPtrArgs() const { return (size() - 2); }
- DSNodeHandle getPtrArgNode(unsigned i) const { assert(i < getNumPtrArgs());
- return (*this)[i+2]; }
+ /// Note - This ctor destroys the argument vector passed in. On exit, the
+ /// argument vector is empty.
+ ///
+ DSCallSite(CallInst &inst, const DSNodeHandle &rv, const DSNodeHandle &callee,
+ std::vector<DSNodeHandle> &Args)
+ : Inst(&inst), RetVal(rv), Callee(callee) {
+ Args.swap(CallArgs);
+ }
+
+ /// Copy constructor with helper for cloning nodes. The helper should be a
+ /// model of unary_function<const DSNodeHandle*, DSNodeHandle>, i.e., it
+ /// should take a pointer to DSNodeHandle and return a fresh DSNodeHandle.
+ /// If no helper is specified, this defaults to a simple copy constructor.
+ ///
+ template<typename CopyFunctor>
+ DSCallSite(const DSCallSite &FromCall, CopyFunctor nodeCopier);
+ DSCallSite(const DSCallSite &DSCS)
+ : Inst(DSCS.Inst), RetVal(DSCS.RetVal),
+ Callee(DSCS.Callee), CallArgs(DSCS.CallArgs) {}
+
+ // Accessor functions...
+ Function &getCaller() const;
+ CallInst &getCallInst() const { return *Inst; }
+ DSNodeHandle &getRetVal() { return RetVal; }
+ DSNodeHandle &getCallee() { return Callee; }
+ const DSNodeHandle &getRetVal() const { return RetVal; }
+ const DSNodeHandle &getCallee() const { return Callee; }
+ unsigned getNumPtrArgs() const { return CallArgs.size(); }
+
+ DSNodeHandle &getPtrArg(unsigned i) {
+ assert(i < CallArgs.size() && "Argument to getPtrArgNode is out of range!");
+ return CallArgs[i];
+ }
+ const DSNodeHandle &getPtrArg(unsigned i) const {
+ assert(i < CallArgs.size() && "Argument to getPtrArgNode is out of range!");
+ return CallArgs[i];
+ }
+
+ bool operator<(const DSCallSite &CS) const {
+ if (Inst < CS.Inst) return true;
+ if (Inst > CS.Inst) return false;
+ if (RetVal < CS.RetVal) return true;
+ if (RetVal > CS.RetVal) return false;
+ if (Callee < CS.Callee) return true;
+ if (Callee > CS.Callee) return false;
+ return CallArgs < CS.CallArgs;
+ }
+
+ bool operator==(const DSCallSite &CS) const {
+ return Inst == CS.Inst && RetVal == CS.RetVal && Callee == CS.Callee &&
+ CallArgs == CS.CallArgs;
+ }
};
// Add the link from the argument scalar to the provided value
DSNodeHandle &NN = ValueMap[AI];
- NN.addEdgeTo(Call.getPtrArgNode(i));
+ NN.addEdgeTo(Call.getPtrArg(i));
++AI;
}
}
DSCallSite Call = FCs[i];
// If the function list is complete...
- if ((Call.getCalleeNode().getNode()->NodeType & DSNode::Incomplete)==0) {
+ if ((Call.getCallee().getNode()->NodeType & DSNode::Incomplete)==0) {
// Start inlining all of the functions we can... some may not be
// inlinable if they are external...
//
std::vector<GlobalValue*> Callees =
- Call.getCalleeNode().getNode()->getGlobals();
+ Call.getCallee().getNode()->getGlobals();
// Loop over the functions, inlining whatever we can...
for (unsigned c = 0; c != Callees.size(); ++c) {
DEBUG(std::cerr << "\t[BU] Self Inlining: " << F.getName() << "\n");
// Handle the return value if present...
- if (Call.getReturnValueNode().getNode())
- Graph->getRetNode().mergeWith(Call.getReturnValueNode());
+ if (Call.getRetVal().getNode())
+ Graph->getRetNode().mergeWith(Call.getRetVal());
// Resolve the arguments in the call to the actual values...
ResolveArguments(Call, F, Graph->getValueMap());
// Resolve the arguments in the call to the actual values...
ResolveArguments(Call, FI, OldValMap);
- if (Call.getReturnValueNode().getNode()) // Handle the return value if present
- RetVal.mergeWith(Call.getReturnValueNode());
+ if (Call.getRetVal().getNode())// Handle the return value if present
+ RetVal.mergeWith(Call.getRetVal());
// Erase the entry in the Callees vector
Callees.erase(Callees.begin()+c--);
// Erase the call if it is resolvable...
FCs.erase(FCs.begin()+i--); // Don't skip a the next call...
Inlined = true;
- } else if (Callees.size() != Call.getCalleeNode().getNode()->getGlobals().size()) {
+ } else if (Callees.size() !=
+ Call.getCallee().getNode()->getGlobals().size()) {
// Was able to inline SOME, but not all of the functions. Construct a
// new global node here.
//
// Define here to avoid including iOther.h and BasicBlock.h in DSGraph.h
Function &DSCallSite::getCaller() const {
- return *callInst->getParent()->getParent();
+ return *Inst->getParent()->getParent();
}
template <typename CopyFunctor>
DSCallSite::DSCallSite(const DSCallSite &FromCall, CopyFunctor nodeCopier)
- : callInst(&FromCall.getCallInst()) {
+ : Inst(FromCall.Inst) {
- reserve(FromCall.size());
- for (unsigned j = 0, ej = FromCall.size(); j != ej; ++j)
- push_back(&nodeCopier == 0 ? DSNodeHandle(FromCall[j])
- : nodeCopier(&FromCall[j]));
+ RetVal = nodeCopier(&RetVal);
+ Callee = nodeCopier(&Callee);
+
+ CallArgs.reserve(FromCall.CallArgs.size());
+ for (unsigned j = 0, ej = FromCall.CallArgs.size(); j != ej; ++j)
+ CallArgs.push_back(nodeCopier(&FromCall.CallArgs[j]));
}
for (unsigned i = 0, e = FunctionCalls.size(); i != e; ++i) {
DSCallSite &Call = FunctionCalls[i];
// Then the return value is certainly incomplete!
- markIncompleteNode(Call.getReturnValueNode().getNode());
+ markIncompleteNode(Call.getRetVal().getNode());
// The call does not make the function argument incomplete...
// All arguments to the function call are incomplete though!
for (unsigned i = 0, e = Call.getNumPtrArgs(); i != e; ++i)
- markIncompleteNode(Call.getPtrArgNode(i).getNode());
+ markIncompleteNode(Call.getPtrArg(i).getNode());
}
// Mark all of the nodes pointed to by global or cast nodes as incomplete...
// Iterate, marking globals or cast nodes alive until no new live nodes
// are added to Alive
std::set<DSNode*> Visiting; // Used to identify cycles
- std::set<DSNode*>::iterator I=GlobalNodes.begin(), E=GlobalNodes.end();
+ std::set<DSNode*>::iterator I = GlobalNodes.begin(), E = GlobalNodes.end();
for (size_t liveCount = 0; liveCount < Alive.size(); ) {
liveCount = Alive.size();
for ( ; I != E; ++I)
// Since all call nodes must be live if any one is live, we have to mark
// all nodes of the call as live and continue the iteration (via recursion).
if (FilterCalls) {
- bool recurse = false;
- for (int i = 0, ei = Calls.size(); i < ei; ++i) {
+ bool Recurse = false;
+ for (unsigned i = 0, ei = Calls.size(); i < ei; ++i) {
bool CallIsDead = true, CallHasDeadArg = false;
- for (unsigned j = 0, ej = Calls[i].size(); j != ej; ++j) {
- bool argIsDead = Calls[i][j].getNode() == 0 ||
- Alive.count(Calls[i][j].getNode()) == 0;
- CallHasDeadArg |= (Calls[i][j].getNode() != 0 && argIsDead);
- CallIsDead &= argIsDead;
+ DSCallSite &CS = Calls[i];
+ for (unsigned j = 0, ej = CS.getNumPtrArgs(); j != ej; ++j)
+ if (DSNode *N = CS.getPtrArg(j).getNode()) {
+ bool ArgIsDead = !Alive.count(N);
+ CallHasDeadArg |= ArgIsDead;
+ CallIsDead &= ArgIsDead;
+ }
+
+ if (DSNode *N = CS.getRetVal().getNode()) {
+ bool RetIsDead = !Alive.count(N);
+ CallHasDeadArg |= RetIsDead;
+ CallIsDead &= RetIsDead;
}
+
+ DSNode *N = CS.getCallee().getNode();
+ bool FnIsDead = !Alive.count(N);
+ CallHasDeadArg |= FnIsDead;
+ CallIsDead &= FnIsDead;
+
if (!CallIsDead && CallHasDeadArg) {
// Some node in this call is live and another is dead.
// Mark all nodes of call as live and iterate once more.
- recurse = true;
- for (unsigned j = 0, ej = Calls[i].size(); j != ej; ++j)
- markAlive(Calls[i][j].getNode(), Alive);
+ Recurse = true;
+ for (unsigned j = 0, ej = CS.getNumPtrArgs(); j != ej; ++j)
+ markAlive(CS.getPtrArg(j).getNode(), Alive);
+ markAlive(CS.getRetVal().getNode(), Alive);
+ markAlive(CS.getCallee().getNode(), Alive);
}
}
- if (recurse)
+ if (Recurse)
markGlobalsIteration(GlobalNodes, Calls, Alive, FilterCalls);
}
}
// Add all call nodes to the same set
vector<DSCallSite> &Calls = G.getFunctionCalls();
if (FilterCalls) {
- for (unsigned i = 0, e = Calls.size(); i != e; ++i)
- for (unsigned j = 0, e = Calls[i].size(); j != e; ++j)
- if (Calls[i][j].getNode())
- GlobalNodes.insert(Calls[i][j].getNode());
+ for (unsigned i = 0, e = Calls.size(); i != e; ++i) {
+ for (unsigned j = 0, e = Calls[i].getNumPtrArgs(); j != e; ++j)
+ if (DSNode *N = Calls[i].getPtrArg(j).getNode())
+ GlobalNodes.insert(N);
+ if (DSNode *N = Calls[i].getRetVal().getNode())
+ GlobalNodes.insert(N);
+ if (DSNode *N = Calls[i].getCallee().getNode())
+ GlobalNodes.insert(N);
+ }
}
// Iterate and recurse until no new live node are discovered.
if (FilterCalls)
for (int ei = Calls.size(), i = ei-1; i >= 0; --i) {
bool CallIsDead = true;
- for (unsigned j = 0, ej = Calls[i].size(); CallIsDead && j != ej; ++j)
- CallIsDead = Alive.count(Calls[i][j].getNode()) == 0;
+ for (unsigned j = 0, ej = Calls[i].getNumPtrArgs();
+ CallIsDead && j != ej; ++j)
+ CallIsDead = Alive.count(Calls[i].getPtrArg(j).getNode()) == 0;
if (CallIsDead)
Calls.erase(Calls.begin() + i); // remove the call entirely
}
// If KeepCalls, mark all nodes reachable by call nodes as alive...
if (KeepCalls)
- for (unsigned i = 0, e = FunctionCalls.size(); i != e; ++i)
- for (unsigned j = 0, e = FunctionCalls[i].size(); j != e; ++j)
- markAlive(FunctionCalls[i][j].getNode(), Alive);
+ for (unsigned i = 0, e = FunctionCalls.size(); i != e; ++i) {
+ for (unsigned j = 0, e = FunctionCalls[i].getNumPtrArgs(); j != e; ++j)
+ markAlive(FunctionCalls[i].getPtrArg(j).getNode(), Alive);
+ markAlive(FunctionCalls[i].getRetVal().getNode(), Alive);
+ markAlive(FunctionCalls[i].getCallee().getNode(), Alive);
+ }
#if 0
for (unsigned i = 0, e = OrigFunctionCalls.size(); i != e; ++i)
// Mark all globals or cast nodes that can reach a live node as alive.
// This also marks all nodes reachable from such nodes as alive.
// Of course, if KeepAllGlobals is specified, they would be live already.
- if (! KeepAllGlobals)
+ if (!KeepAllGlobals)
markGlobalsAlive(*this, Alive, ! KeepCalls);
// Loop over all unreachable nodes, dropping their references...
/// object, pointing the scalar to it.
///
void GraphBuilder::handleAlloc(AllocationInst &AI, DSNode::NodeTy NodeType) {
+ //DSNode *New = createNode(NodeType, Type::VoidTy);
DSNode *New = createNode(NodeType, AI.getAllocatedType());
// Make the scalar point to the new node...
}
void GraphBuilder::visitCallInst(CallInst &CI) {
- // Add a new function call entry...
- FunctionCalls.push_back(CI);
- DSCallSite &Args = FunctionCalls.back();
-
// Set up the return value...
+ DSNodeHandle RetVal;
if (isPointerType(CI.getType()))
- Args.push_back(getLink(getValueNode(CI), 0, CI.getType()));
- else
- Args.push_back(DSNodeHandle());
+ RetVal = getLink(getValueNode(CI), 0, CI.getType());
- unsigned Start = 0;
+ DSNodeHandle Callee;
// Special case for a direct call, avoid creating spurious scalar node...
- if (GlobalValue *GV = dyn_cast<GlobalValue>(CI.getOperand(0))) {
- Args.push_back(getGlobalNode(*GV));
- Start = 1;
- }
+ if (GlobalValue *GV = dyn_cast<GlobalValue>(CI.getOperand(0)))
+ Callee = getGlobalNode(*GV);
+ else
+ Callee = getLink(getValueNode(*CI.getOperand(0)), 0,
+ CI.getOperand(0)->getType());
+
+ std::vector<DSNodeHandle> Args;
+ Args.reserve(CI.getNumOperands()-1);
- // Pass the arguments in...
- for (unsigned i = Start, e = CI.getNumOperands(); i != e; ++i)
+ // Calculate the arguments vector...
+ for (unsigned i = 1, e = CI.getNumOperands(); i != e; ++i)
if (isPointerType(CI.getOperand(i)->getType()))
Args.push_back(getLink(getValueNode(*CI.getOperand(i)), 0,
CI.getOperand(i)->getType()));
+
+ // Add a new function call entry...
+ FunctionCalls.push_back(DSCallSite(CI, RetVal, Callee, Args));
}
/// Handle casts...
const std::vector<DSCallSite> &FCs = G->getFunctionCalls();
for (unsigned i = 0, e = FCs.size(); i != e; ++i) {
const DSCallSite &Call = FCs[i];
- GW.emitSimpleNode(&Call, "shape=record", "call", Call.size());
+ GW.emitSimpleNode(&Call, "shape=record", "call", Call.getNumPtrArgs()+2);
- for (unsigned j = 0, e = Call.size(); j != e; ++j)
- if (Call[j].getNode()) {
- int EdgeDest = Call[j].getOffset();
+ for (unsigned j = 0, e = Call.getNumPtrArgs(); j != e; ++j)
+ if (DSNode *N = Call.getPtrArg(j).getNode()) {
+ int EdgeDest = Call.getPtrArg(j).getOffset();
if (EdgeDest == 0) EdgeDest = -1;
- GW.emitEdge(&Call, j, Call[j].getNode(), EdgeDest, "color=gray63");
+ GW.emitEdge(&Call, j+2, N, EdgeDest, "color=gray63");
}
}
}
std::map<Value*, DSNodeHandle> &ValMap = ResultGraph->getValueMap();
// Handle the return value of the function...
- if (Call.getReturnValueNode().getNode() && RetVal.getNode())
- RetVal.mergeWith(Call.getReturnValueNode());
+ 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::aiterator AI = F->abegin(), AE = F->aend(); AI != AE; ++AI) {
std::map<Value*, DSNodeHandle>::iterator I = ValMap.find(AI);
if (I != ValMap.end()) // If its a pointer argument...
- I->second.addEdgeTo(Call.getPtrArgNode(PtrArgIdx++));
+ I->second.addEdgeTo(Call.getPtrArg(PtrArgIdx++));
}
assert(PtrArgIdx == Call.getNumPtrArgs() && "Argument resolution mismatch!");
DSCallSite &CurCall = Calls[i];
// Loop over the called functions, eliminating as many as possible...
- std::vector<GlobalValue*> CallTargets = CurCall.getCalleeNode().getNode()->getGlobals();
+ std::vector<GlobalValue*> CallTargets =
+ CurCall.getCallee().getNode()->getGlobals();
for (unsigned c = 0; c != CallTargets.size(); ) {
// If we can eliminate this function call, do so!
bool Eliminated = false;
// TD ...Merge the formal arg scalar with the actual arg node
DSNodeHandle &NodeForFormal = Graph.getNodeForValue(AI);
if (NodeForFormal.getNode())
- NodeForFormal.mergeWith(CallSite.getPtrArgNode(i));
+ NodeForFormal.mergeWith(CallSite.getPtrArg(i));
}
// Merge returned node in the caller with the "return" node in callee
- if (CallSite.getReturnValueNode().getNode() && Graph.getRetNode().getNode())
- Graph.getRetNode().mergeWith(CallSite.getReturnValueNode());
+ if (CallSite.getRetVal().getNode() && Graph.getRetNode().getNode())
+ Graph.getRetNode().mergeWith(CallSite.getRetVal());
}