mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-01-14 00:32:55 +00:00
- Add "ResolvingCaller" to the CallSite record. This keeps track of which
function was finally able to resolve the function call. Adding this allows the TD pass to actually work right! - Temporarily disable dead node pruning. This will be reenabled soon. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@4252 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
eff0da9d33
commit
198be22cec
@ -361,19 +361,40 @@ inline void DSNodeHandle::mergeWith(const DSNodeHandle &Node) {
|
||||
/// DSCallSite - Representation of a call site via its call instruction,
|
||||
/// the DSNode handle for the callee function (or function pointer), and
|
||||
/// the DSNode handles for the function arguments.
|
||||
///
|
||||
/// One unusual aspect of this callsite record is the ResolvingCaller member.
|
||||
/// If this is non-null, then it indicates the function that allowed a call-site
|
||||
/// to finally be resolved. Because of indirect calls, this function may not
|
||||
/// actually be the function that contains the Call instruction itself. This is
|
||||
/// used by the BU and TD passes to communicate.
|
||||
///
|
||||
class DSCallSite {
|
||||
CallInst *Inst; // Actual call site
|
||||
DSNodeHandle RetVal; // Returned value
|
||||
DSNodeHandle Callee; // The function node called
|
||||
std::vector<DSNodeHandle> CallArgs; // The pointer arguments
|
||||
Function *ResolvingCaller; // See comments above
|
||||
|
||||
static DSNode *mapLookup(const DSNode *Node,
|
||||
const std::map<const DSNode*, DSNode*> &NodeMap) {
|
||||
if (Node == 0) return 0;
|
||||
std::map<const DSNode*, DSNode*>::const_iterator I = NodeMap.find(Node);
|
||||
assert(I != NodeMap.end() && "Not not in mapping!");
|
||||
return I->second;
|
||||
static void InitNH(DSNodeHandle &NH, const DSNodeHandle &Src,
|
||||
const std::map<const DSNode*, DSNode*> &NodeMap) {
|
||||
if (DSNode *N = Src.getNode()) {
|
||||
std::map<const DSNode*, DSNode*>::const_iterator I = NodeMap.find(N);
|
||||
assert(I != NodeMap.end() && "Not not in mapping!");
|
||||
|
||||
NH.setOffset(Src.getOffset());
|
||||
NH.setNode(I->second);
|
||||
}
|
||||
}
|
||||
|
||||
static void InitNH(DSNodeHandle &NH, const DSNodeHandle &Src,
|
||||
const std::map<const DSNode*, DSNodeHandle> &NodeMap) {
|
||||
if (DSNode *N = Src.getNode()) {
|
||||
std::map<const DSNode*, DSNodeHandle>::const_iterator I = NodeMap.find(N);
|
||||
assert(I != NodeMap.end() && "Not not in mapping!");
|
||||
|
||||
NH.setOffset(Src.getOffset()+I->second.getOffset());
|
||||
NH.setNode(I->second.getNode());
|
||||
}
|
||||
}
|
||||
|
||||
DSCallSite(); // DO NOT IMPLEMENT
|
||||
@ -383,32 +404,29 @@ public:
|
||||
///
|
||||
DSCallSite(CallInst &inst, const DSNodeHandle &rv, const DSNodeHandle &callee,
|
||||
std::vector<DSNodeHandle> &Args)
|
||||
: Inst(&inst), RetVal(rv), Callee(callee) {
|
||||
: Inst(&inst), RetVal(rv), Callee(callee), ResolvingCaller(0) {
|
||||
Args.swap(CallArgs);
|
||||
}
|
||||
|
||||
DSCallSite(const DSCallSite &DSCS) // Simple copy ctor
|
||||
: Inst(DSCS.Inst), RetVal(DSCS.RetVal),
|
||||
Callee(DSCS.Callee), CallArgs(DSCS.CallArgs) {}
|
||||
Callee(DSCS.Callee), CallArgs(DSCS.CallArgs),
|
||||
ResolvingCaller(DSCS.ResolvingCaller) {}
|
||||
|
||||
/// Mapping copy constructor - This constructor takes a preexisting call site
|
||||
/// to copy plus a map that specifies how the links should be transformed.
|
||||
/// This is useful when moving a call site from one graph to another.
|
||||
///
|
||||
DSCallSite(const DSCallSite &FromCall,
|
||||
const std::map<const DSNode*, DSNode*> &NodeMap) {
|
||||
template<typename MapTy>
|
||||
DSCallSite(const DSCallSite &FromCall, const MapTy &NodeMap) {
|
||||
Inst = FromCall.Inst;
|
||||
RetVal.setOffset(FromCall.RetVal.getOffset());
|
||||
RetVal.setNode(mapLookup(FromCall.RetVal.getNode(), NodeMap));
|
||||
Callee.setOffset(FromCall.Callee.getOffset());
|
||||
Callee.setNode(mapLookup(FromCall.Callee.getNode(), NodeMap));
|
||||
CallArgs.reserve(FromCall.CallArgs.size());
|
||||
InitNH(RetVal, FromCall.RetVal, NodeMap);
|
||||
InitNH(Callee, FromCall.Callee, NodeMap);
|
||||
|
||||
for (unsigned i = 0, e = FromCall.CallArgs.size(); i != e; ++i) {
|
||||
const DSNodeHandle &OldNH = FromCall.CallArgs[i];
|
||||
CallArgs.push_back(DSNodeHandle(mapLookup(OldNH.getNode(), NodeMap),
|
||||
OldNH.getOffset()));
|
||||
}
|
||||
CallArgs.resize(FromCall.CallArgs.size());
|
||||
for (unsigned i = 0, e = FromCall.CallArgs.size(); i != e; ++i)
|
||||
InitNH(CallArgs[i], FromCall.CallArgs[i], NodeMap);
|
||||
ResolvingCaller = FromCall.ResolvingCaller;
|
||||
}
|
||||
|
||||
// Accessor functions...
|
||||
@ -420,6 +438,9 @@ public:
|
||||
const DSNodeHandle &getCallee() const { return Callee; }
|
||||
unsigned getNumPtrArgs() const { return CallArgs.size(); }
|
||||
|
||||
Function *getResolvingCaller() const { return ResolvingCaller; }
|
||||
void setResolvingCaller(Function *F) { ResolvingCaller = F; }
|
||||
|
||||
DSNodeHandle &getPtrArg(unsigned i) {
|
||||
assert(i < CallArgs.size() && "Argument to getPtrArgNode is out of range!");
|
||||
return CallArgs[i];
|
||||
@ -478,7 +499,7 @@ public:
|
||||
// destination graph, you may optionally do this by specifying a map to record
|
||||
// this into.
|
||||
DSGraph(const DSGraph &DSG);
|
||||
DSGraph(const DSGraph &DSG, std::map<const DSNode*, DSNode*> &BUNodeMapTy);
|
||||
DSGraph(const DSGraph &DSG, std::map<const DSNode*, DSNode*> &BUNodeMap);
|
||||
~DSGraph();
|
||||
|
||||
bool hasFunction() const { return Func != 0; }
|
||||
|
@ -11,6 +11,7 @@
|
||||
|
||||
class Type;
|
||||
class DSGraph;
|
||||
class DSNode;
|
||||
class DSNodeHandle;
|
||||
class DSCallSite;
|
||||
class LocalDataStructures; // A collection of local graphs for a program
|
||||
@ -108,6 +109,15 @@ private:
|
||||
class TDDataStructures : public Pass {
|
||||
// DSInfo, one graph for each function
|
||||
std::map<const Function*, DSGraph*> DSInfo;
|
||||
|
||||
// Each graph in DSInfo is based on a graph in the BUDS object. The BUMaps
|
||||
// member keeps the mappings from the BU graphs to the TD graphs as they are
|
||||
// calculated by calculateGraph. This information is used to properly
|
||||
// implement resolving of call sites, where the call sites in the BUGraph are
|
||||
// in terms of the caller function's graph in the BUGraph.
|
||||
//
|
||||
typedef std::map<const DSNode*, DSNodeHandle> BUNodeMapTy;
|
||||
std::map<const Function*, BUNodeMapTy> BUMaps;
|
||||
public:
|
||||
~TDDataStructures() { releaseMemory(); }
|
||||
|
||||
@ -134,8 +144,7 @@ public:
|
||||
private:
|
||||
DSGraph &calculateGraph(Function &F);
|
||||
|
||||
void ResolveCallSite(DSGraph &Graph,
|
||||
const DSCallSite &CallSite);
|
||||
void ResolveCallSite(DSGraph &Graph, const DSCallSite &CallSite);
|
||||
};
|
||||
|
||||
#if 0
|
||||
|
@ -361,19 +361,40 @@ inline void DSNodeHandle::mergeWith(const DSNodeHandle &Node) {
|
||||
/// DSCallSite - Representation of a call site via its call instruction,
|
||||
/// the DSNode handle for the callee function (or function pointer), and
|
||||
/// the DSNode handles for the function arguments.
|
||||
///
|
||||
/// One unusual aspect of this callsite record is the ResolvingCaller member.
|
||||
/// If this is non-null, then it indicates the function that allowed a call-site
|
||||
/// to finally be resolved. Because of indirect calls, this function may not
|
||||
/// actually be the function that contains the Call instruction itself. This is
|
||||
/// used by the BU and TD passes to communicate.
|
||||
///
|
||||
class DSCallSite {
|
||||
CallInst *Inst; // Actual call site
|
||||
DSNodeHandle RetVal; // Returned value
|
||||
DSNodeHandle Callee; // The function node called
|
||||
std::vector<DSNodeHandle> CallArgs; // The pointer arguments
|
||||
Function *ResolvingCaller; // See comments above
|
||||
|
||||
static DSNode *mapLookup(const DSNode *Node,
|
||||
const std::map<const DSNode*, DSNode*> &NodeMap) {
|
||||
if (Node == 0) return 0;
|
||||
std::map<const DSNode*, DSNode*>::const_iterator I = NodeMap.find(Node);
|
||||
assert(I != NodeMap.end() && "Not not in mapping!");
|
||||
return I->second;
|
||||
static void InitNH(DSNodeHandle &NH, const DSNodeHandle &Src,
|
||||
const std::map<const DSNode*, DSNode*> &NodeMap) {
|
||||
if (DSNode *N = Src.getNode()) {
|
||||
std::map<const DSNode*, DSNode*>::const_iterator I = NodeMap.find(N);
|
||||
assert(I != NodeMap.end() && "Not not in mapping!");
|
||||
|
||||
NH.setOffset(Src.getOffset());
|
||||
NH.setNode(I->second);
|
||||
}
|
||||
}
|
||||
|
||||
static void InitNH(DSNodeHandle &NH, const DSNodeHandle &Src,
|
||||
const std::map<const DSNode*, DSNodeHandle> &NodeMap) {
|
||||
if (DSNode *N = Src.getNode()) {
|
||||
std::map<const DSNode*, DSNodeHandle>::const_iterator I = NodeMap.find(N);
|
||||
assert(I != NodeMap.end() && "Not not in mapping!");
|
||||
|
||||
NH.setOffset(Src.getOffset()+I->second.getOffset());
|
||||
NH.setNode(I->second.getNode());
|
||||
}
|
||||
}
|
||||
|
||||
DSCallSite(); // DO NOT IMPLEMENT
|
||||
@ -383,32 +404,29 @@ public:
|
||||
///
|
||||
DSCallSite(CallInst &inst, const DSNodeHandle &rv, const DSNodeHandle &callee,
|
||||
std::vector<DSNodeHandle> &Args)
|
||||
: Inst(&inst), RetVal(rv), Callee(callee) {
|
||||
: Inst(&inst), RetVal(rv), Callee(callee), ResolvingCaller(0) {
|
||||
Args.swap(CallArgs);
|
||||
}
|
||||
|
||||
DSCallSite(const DSCallSite &DSCS) // Simple copy ctor
|
||||
: Inst(DSCS.Inst), RetVal(DSCS.RetVal),
|
||||
Callee(DSCS.Callee), CallArgs(DSCS.CallArgs) {}
|
||||
Callee(DSCS.Callee), CallArgs(DSCS.CallArgs),
|
||||
ResolvingCaller(DSCS.ResolvingCaller) {}
|
||||
|
||||
/// Mapping copy constructor - This constructor takes a preexisting call site
|
||||
/// to copy plus a map that specifies how the links should be transformed.
|
||||
/// This is useful when moving a call site from one graph to another.
|
||||
///
|
||||
DSCallSite(const DSCallSite &FromCall,
|
||||
const std::map<const DSNode*, DSNode*> &NodeMap) {
|
||||
template<typename MapTy>
|
||||
DSCallSite(const DSCallSite &FromCall, const MapTy &NodeMap) {
|
||||
Inst = FromCall.Inst;
|
||||
RetVal.setOffset(FromCall.RetVal.getOffset());
|
||||
RetVal.setNode(mapLookup(FromCall.RetVal.getNode(), NodeMap));
|
||||
Callee.setOffset(FromCall.Callee.getOffset());
|
||||
Callee.setNode(mapLookup(FromCall.Callee.getNode(), NodeMap));
|
||||
CallArgs.reserve(FromCall.CallArgs.size());
|
||||
InitNH(RetVal, FromCall.RetVal, NodeMap);
|
||||
InitNH(Callee, FromCall.Callee, NodeMap);
|
||||
|
||||
for (unsigned i = 0, e = FromCall.CallArgs.size(); i != e; ++i) {
|
||||
const DSNodeHandle &OldNH = FromCall.CallArgs[i];
|
||||
CallArgs.push_back(DSNodeHandle(mapLookup(OldNH.getNode(), NodeMap),
|
||||
OldNH.getOffset()));
|
||||
}
|
||||
CallArgs.resize(FromCall.CallArgs.size());
|
||||
for (unsigned i = 0, e = FromCall.CallArgs.size(); i != e; ++i)
|
||||
InitNH(CallArgs[i], FromCall.CallArgs[i], NodeMap);
|
||||
ResolvingCaller = FromCall.ResolvingCaller;
|
||||
}
|
||||
|
||||
// Accessor functions...
|
||||
@ -420,6 +438,9 @@ public:
|
||||
const DSNodeHandle &getCallee() const { return Callee; }
|
||||
unsigned getNumPtrArgs() const { return CallArgs.size(); }
|
||||
|
||||
Function *getResolvingCaller() const { return ResolvingCaller; }
|
||||
void setResolvingCaller(Function *F) { ResolvingCaller = F; }
|
||||
|
||||
DSNodeHandle &getPtrArg(unsigned i) {
|
||||
assert(i < CallArgs.size() && "Argument to getPtrArgNode is out of range!");
|
||||
return CallArgs[i];
|
||||
@ -478,7 +499,7 @@ public:
|
||||
// destination graph, you may optionally do this by specifying a map to record
|
||||
// this into.
|
||||
DSGraph(const DSGraph &DSG);
|
||||
DSGraph(const DSGraph &DSG, std::map<const DSNode*, DSNode*> &BUNodeMapTy);
|
||||
DSGraph(const DSGraph &DSG, std::map<const DSNode*, DSNode*> &BUNodeMap);
|
||||
~DSGraph();
|
||||
|
||||
bool hasFunction() const { return Func != 0; }
|
||||
|
@ -11,6 +11,7 @@
|
||||
|
||||
class Type;
|
||||
class DSGraph;
|
||||
class DSNode;
|
||||
class DSNodeHandle;
|
||||
class DSCallSite;
|
||||
class LocalDataStructures; // A collection of local graphs for a program
|
||||
@ -108,6 +109,15 @@ private:
|
||||
class TDDataStructures : public Pass {
|
||||
// DSInfo, one graph for each function
|
||||
std::map<const Function*, DSGraph*> DSInfo;
|
||||
|
||||
// Each graph in DSInfo is based on a graph in the BUDS object. The BUMaps
|
||||
// member keeps the mappings from the BU graphs to the TD graphs as they are
|
||||
// calculated by calculateGraph. This information is used to properly
|
||||
// implement resolving of call sites, where the call sites in the BUGraph are
|
||||
// in terms of the caller function's graph in the BUGraph.
|
||||
//
|
||||
typedef std::map<const DSNode*, DSNodeHandle> BUNodeMapTy;
|
||||
std::map<const Function*, BUNodeMapTy> BUMaps;
|
||||
public:
|
||||
~TDDataStructures() { releaseMemory(); }
|
||||
|
||||
@ -134,8 +144,7 @@ public:
|
||||
private:
|
||||
DSGraph &calculateGraph(Function &F);
|
||||
|
||||
void ResolveCallSite(DSGraph &Graph,
|
||||
const DSCallSite &CallSite);
|
||||
void ResolveCallSite(DSGraph &Graph, const DSCallSite &CallSite);
|
||||
};
|
||||
|
||||
#if 0
|
||||
|
@ -143,7 +143,9 @@ DSGraph &BUDataStructures::calculateGraph(Function &F) {
|
||||
// Record that the original DSCallSite was a call site of FI.
|
||||
// This may or may not have been known when the DSCallSite was
|
||||
// originally created.
|
||||
CallSites[&FI].push_back(Call);
|
||||
std::vector<DSCallSite> &CallSitesForFunc = CallSites[&FI];
|
||||
CallSitesForFunc.push_back(Call);
|
||||
CallSitesForFunc.back().setResolvingCaller(&F);
|
||||
|
||||
// Clone the callee's graph into the current graph, keeping
|
||||
// track of where scalars in the old graph _used_ to point,
|
||||
|
@ -20,6 +20,7 @@ Y("tddatastructure", "Top-down Data Structure Analysis Closure");
|
||||
// our memory... here...
|
||||
//
|
||||
void TDDataStructures::releaseMemory() {
|
||||
BUMaps.clear();
|
||||
for (std::map<const Function*, DSGraph*>::iterator I = DSInfo.begin(),
|
||||
E = DSInfo.end(); I != E; ++I)
|
||||
delete I->second;
|
||||
@ -76,7 +77,14 @@ DSGraph &TDDataStructures::calculateGraph(Function &F) {
|
||||
|
||||
BUDataStructures &BU = getAnalysis<BUDataStructures>();
|
||||
DSGraph &BUGraph = BU.getDSGraph(F);
|
||||
Graph = new DSGraph(BUGraph);
|
||||
|
||||
// Copy the BU graph, keeping a mapping from the BUGraph to the current Graph
|
||||
std::map<const DSNode*, DSNode*> BUNodeMap;
|
||||
Graph = new DSGraph(BUGraph, BUNodeMap);
|
||||
|
||||
// Convert the mapping from a node-to-node map into a node-to-nodehandle map
|
||||
BUMaps[&F].insert(BUNodeMap.begin(), BUNodeMap.end());
|
||||
BUNodeMap.clear(); // We are done with the temporary map.
|
||||
|
||||
const std::vector<DSCallSite> *CallSitesP = BU.getCallSites(F);
|
||||
if (CallSitesP == 0) {
|
||||
@ -90,14 +98,19 @@ DSGraph &TDDataStructures::calculateGraph(Function &F) {
|
||||
DEBUG(std::cerr << " [TD] Inlining callers for: " << F.getName() << "\n");
|
||||
const std::vector<DSCallSite> &CallSites = *CallSitesP;
|
||||
for (unsigned c = 0, ce = CallSites.size(); c != ce; ++c) {
|
||||
const DSCallSite &CallSite = CallSites[c]; // Copy
|
||||
Function &Caller = CallSite.getCaller();
|
||||
assert(!Caller.isExternal() && "Externals function cannot 'call'!");
|
||||
const DSCallSite &CallSite = CallSites[c];
|
||||
Function &Caller = *CallSite.getResolvingCaller();
|
||||
assert(&Caller && !Caller.isExternal() &&
|
||||
"Externals function cannot 'call'!");
|
||||
|
||||
DEBUG(std::cerr << "\t [TD] Inlining caller #" << c << " '"
|
||||
<< Caller.getName() << "' into callee: " << F.getName() << "\n");
|
||||
|
||||
if (&Caller != &F) {
|
||||
if (&Caller == &F) {
|
||||
// Self-recursive call: this can happen after a cycle of calls is inlined.
|
||||
ResolveCallSite(*Graph, CallSite);
|
||||
} else {
|
||||
|
||||
// Recursively compute the graph for the Caller. It should be fully
|
||||
// resolved except if there is mutual recursion...
|
||||
//
|
||||
@ -111,6 +124,9 @@ DSGraph &TDDataStructures::calculateGraph(Function &F) {
|
||||
std::map<Value*, DSNodeHandle> OldValMap;
|
||||
std::map<const DSNode*, DSNode*> OldNodeMap;
|
||||
|
||||
// Translate call site from having links into the BU graph
|
||||
DSCallSite CallSiteInCG(CallSite, BUMaps[&Caller]);
|
||||
|
||||
// Clone the Caller's graph into the current graph, keeping
|
||||
// track of where scalars in the old graph _used_ to point...
|
||||
// Do this here because it only needs to happens once for each Caller!
|
||||
@ -121,20 +137,17 @@ DSGraph &TDDataStructures::calculateGraph(Function &F) {
|
||||
/*StripAllocas*/ false,
|
||||
/*CopyCallers*/ true,
|
||||
/*CopyOrigCalls*/false);
|
||||
|
||||
// Make a temporary copy of the call site, and transform the argument node
|
||||
// pointers.
|
||||
//
|
||||
ResolveCallSite(*Graph, DSCallSite(CallSiteInCG, OldNodeMap));
|
||||
}
|
||||
ResolveCallSite(*Graph, CallSite);
|
||||
}
|
||||
|
||||
// Recompute the Incomplete markers and eliminate unreachable nodes.
|
||||
#if 0
|
||||
Graph->maskIncompleteMarkers();
|
||||
Graph->markIncompleteNodes(/*markFormals*/ !F.hasInternalLinkage()
|
||||
/*&& FIXME: NEED TO CHECK IF ALL CALLERS FOUND!*/);
|
||||
Graph->removeDeadNodes(/*KeepAllGlobals*/ false, /*KeepCalls*/ false);
|
||||
|
||||
#endif
|
||||
DEBUG(std::cerr << " [TD] Done inlining callers for: " << F.getName() << " ["
|
||||
<< Graph->getGraphSize() << "+" << Graph->getFunctionCalls().size()
|
||||
<< "]\n");
|
||||
|
Loading…
x
Reference in New Issue
Block a user