mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-15 04:30:12 +00:00
* Remove the concept of a critical shadow node
* Make the function pointer argument explicit for a call nodes * Eliminate unreachable global values * Merge call nodes that are identical git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@2266 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
28c238636e
commit
7650b94c75
@ -100,6 +100,8 @@ void FunctionDSGraph::computeClosure(const DataStructure &DS) {
|
|||||||
NI = std::find_if(CallNodes.begin(), CallNodes.end(), isResolvableCallNode);
|
NI = std::find_if(CallNodes.begin(), CallNodes.end(), isResolvableCallNode);
|
||||||
while (NI != CallNodes.end()) {
|
while (NI != CallNodes.end()) {
|
||||||
CallDSNode *CN = *NI;
|
CallDSNode *CN = *NI;
|
||||||
|
// FIXME: This should work based on the pointer val set of the first arg
|
||||||
|
// link (which is the function to call)
|
||||||
Function *F = CN->getCall()->getCalledFunction();
|
Function *F = CN->getCall()->getCalledFunction();
|
||||||
|
|
||||||
if (NumInlines++ == 100) { // CUTE hack huh?
|
if (NumInlines++ == 100) { // CUTE hack huh?
|
||||||
@ -181,14 +183,14 @@ void FunctionDSGraph::computeClosure(const DataStructure &DS) {
|
|||||||
RetVals));
|
RetVals));
|
||||||
|
|
||||||
// If the call node has arguments, process them now!
|
// If the call node has arguments, process them now!
|
||||||
assert(Args.size() == CN->getNumArgs() &&
|
assert(Args.size() == CN->getNumArgs()-1 &&
|
||||||
"Call node doesn't match function?");
|
"Call node doesn't match function?");
|
||||||
|
|
||||||
for (unsigned i = 0, e = Args.size(); i != e; ++i) {
|
for (unsigned i = 0, e = Args.size(); i != e; ++i) {
|
||||||
// Now we make all of the nodes inside of the incorporated method
|
// Now we make all of the nodes inside of the incorporated method
|
||||||
// point to the real arguments values, not to the shadow nodes for the
|
// point to the real arguments values, not to the shadow nodes for the
|
||||||
// argument.
|
// argument.
|
||||||
ResolveNodesTo(Args[i], CN->getArgValues(i));
|
ResolveNodesTo(Args[i], CN->getArgValues(i+1));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Loop through the nodes, deleting alloca nodes in the inlined function.
|
// Loop through the nodes, deleting alloca nodes in the inlined function.
|
||||||
@ -231,4 +233,18 @@ void FunctionDSGraph::computeClosure(const DataStructure &DS) {
|
|||||||
// Move on to the next call node...
|
// Move on to the next call node...
|
||||||
NI = std::find_if(CallNodes.begin(), CallNodes.end(), isResolvableCallNode);
|
NI = std::find_if(CallNodes.begin(), CallNodes.end(), isResolvableCallNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Drop references to globals...
|
||||||
|
CallMap.clear();
|
||||||
|
|
||||||
|
bool Changed = true;
|
||||||
|
while (Changed) {
|
||||||
|
// Eliminate shadow nodes that are not distinguishable from some other
|
||||||
|
// node in the graph...
|
||||||
|
//
|
||||||
|
Changed = UnlinkUndistinguishableNodes();
|
||||||
|
|
||||||
|
// Eliminate shadow nodes that are now extraneous due to linking...
|
||||||
|
Changed |= RemoveUnreachableNodes();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -56,7 +56,7 @@ void DataStructure::print(std::ostream &O, Module *M) const {
|
|||||||
if (!(*I)->isExternal()) {
|
if (!(*I)->isExternal()) {
|
||||||
|
|
||||||
string Filename = "ds." + (*I)->getName() + ".dot";
|
string Filename = "ds." + (*I)->getName() + ".dot";
|
||||||
O << "Writing '" << Filename << "'...\n";
|
O << "Writing '" << Filename << "'...";
|
||||||
ofstream F(Filename.c_str());
|
ofstream F(Filename.c_str());
|
||||||
if (F.good()) {
|
if (F.good()) {
|
||||||
F << "digraph DataStructures {\n"
|
F << "digraph DataStructures {\n"
|
||||||
@ -72,9 +72,12 @@ void DataStructure::print(std::ostream &O, Module *M) const {
|
|||||||
} else {
|
} else {
|
||||||
O << " error opening file for writing!\n";
|
O << " error opening file for writing!\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
O << (*I)->getName() << " " << getDSGraph(*I).getGraphSize() << " "
|
if (Time)
|
||||||
<< getClosedDSGraph(*I).getGraphSize() << "\n";
|
O << " [" << getDSGraph(*I).getGraphSize() << ", "
|
||||||
|
<< getClosedDSGraph(*I).getGraphSize() << "]\n";
|
||||||
|
else
|
||||||
|
O << "\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,23 +53,6 @@ static void DestroyFirstNodeOfPair(DSNode *N1, DSNode *N2) {
|
|||||||
assert(RanOnce && "Node on user set but cannot find the use!");
|
assert(RanOnce && "Node on user set but cannot find the use!");
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we are about to eliminate a call node that returns a pointer, make the
|
|
||||||
// shadow node it points to not be critical anymore!
|
|
||||||
//
|
|
||||||
if (isa<CallDSNode>(N1) && N1->getNumLinks()) {
|
|
||||||
assert(N1->getNumLinks() == 1 && "Call node can only return one pointer!");
|
|
||||||
PointerValSet &PVS = N1->getLink(0);
|
|
||||||
|
|
||||||
for (unsigned i = 0, e = PVS.size(); i != e; ++i)
|
|
||||||
if (ShadowDSNode *Shad = dyn_cast<ShadowDSNode>(PVS[i].Node))
|
|
||||||
if (Shad->isCriticalNode()) {
|
|
||||||
Shad->resetCriticalMark(); // Only unmark _ONE_ node..
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
N1->removeAllIncomingEdges();
|
N1->removeAllIncomingEdges();
|
||||||
delete N1;
|
delete N1;
|
||||||
}
|
}
|
||||||
@ -80,9 +63,10 @@ static void DestroyFirstNodeOfPair(DSNode *N1, DSNode *N2) {
|
|||||||
//
|
//
|
||||||
static bool isIndistinguishableNode(DSNode *DN) {
|
static bool isIndistinguishableNode(DSNode *DN) {
|
||||||
if (DN->getReferrers().empty()) { // No referrers...
|
if (DN->getReferrers().empty()) { // No referrers...
|
||||||
if (isa<ShadowDSNode>(DN) || isa<AllocDSNode>(DN))
|
if (isa<ShadowDSNode>(DN) || isa<AllocDSNode>(DN)) {
|
||||||
|
delete DN;
|
||||||
return true; // Node is trivially dead
|
return true; // Node is trivially dead
|
||||||
else
|
} else
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -328,17 +312,30 @@ bool FunctionDSGraph::RemoveUnreachableNodes() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Loop over the global nodes, removing nodes that have no edges into them.
|
// Loop over the global nodes, removing nodes that have no edges into them or
|
||||||
//
|
// out of them.
|
||||||
|
//
|
||||||
for (std::vector<GlobalDSNode*>::iterator I = GlobalNodes.begin();
|
for (std::vector<GlobalDSNode*>::iterator I = GlobalNodes.begin();
|
||||||
I != GlobalNodes.end(); )
|
I != GlobalNodes.end(); )
|
||||||
if ((*I)->getReferrers().empty()) { // No referrers...
|
if ((*I)->getReferrers().empty()) {
|
||||||
delete *I;
|
GlobalDSNode *GDN = *I;
|
||||||
I = GlobalNodes.erase(I); // Remove the node...
|
bool NoLinks = true; // Make sure there are no outgoing links...
|
||||||
Changed = true;
|
for (unsigned i = 0, e = GDN->getNumLinks(); i != e; ++i)
|
||||||
|
if (!GDN->getLink(i).empty()) {
|
||||||
|
NoLinks = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (NoLinks) {
|
||||||
|
delete GDN;
|
||||||
|
I = GlobalNodes.erase(I); // Remove the node...
|
||||||
|
Changed = true;
|
||||||
|
} else {
|
||||||
|
++I;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
++I;
|
++I;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Changed;
|
return Changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,7 +69,7 @@ void InitVisitor::visitCallInst(CallInst *CI) {
|
|||||||
// Create a critical shadow node to represent the memory object that the
|
// Create a critical shadow node to represent the memory object that the
|
||||||
// return value points to...
|
// return value points to...
|
||||||
ShadowDSNode *Shad = new ShadowDSNode(PT->getElementType(),
|
ShadowDSNode *Shad = new ShadowDSNode(PT->getElementType(),
|
||||||
Func->getParent(), true);
|
Func->getParent());
|
||||||
Rep->ShadowNodes.push_back(Shad);
|
Rep->ShadowNodes.push_back(Shad);
|
||||||
|
|
||||||
// The return value of the function is a pointer to the shadow value
|
// The return value of the function is a pointer to the shadow value
|
||||||
@ -88,7 +88,7 @@ void InitVisitor::visitCallInst(CallInst *CI) {
|
|||||||
// Loop over all of the operands of the call instruction (except the first
|
// Loop over all of the operands of the call instruction (except the first
|
||||||
// one), to look for global variable references...
|
// one), to look for global variable references...
|
||||||
//
|
//
|
||||||
for_each(CI->op_begin()+1, CI->op_end(), // Skip first arg
|
for_each(CI->op_begin(), CI->op_end(),
|
||||||
bind_obj(this, &InitVisitor::visitOperand));
|
bind_obj(this, &InitVisitor::visitOperand));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -150,7 +150,7 @@ void FunctionRepBuilder::initializeWorkList(Function *Func) {
|
|||||||
// Add a shadow value for it to represent what it is pointing to and add
|
// Add a shadow value for it to represent what it is pointing to and add
|
||||||
// this to the value map...
|
// this to the value map...
|
||||||
ShadowDSNode *Shad = new ShadowDSNode(PT->getElementType(),
|
ShadowDSNode *Shad = new ShadowDSNode(PT->getElementType(),
|
||||||
Func->getParent(), true);
|
Func->getParent());
|
||||||
ShadowNodes.push_back(Shad);
|
ShadowNodes.push_back(Shad);
|
||||||
ValueMap[Arg].add(PointerVal(Shad), Arg);
|
ValueMap[Arg].add(PointerVal(Shad), Arg);
|
||||||
|
|
||||||
@ -296,12 +296,8 @@ void FunctionRepBuilder::visitStoreInst(StoreInst *SI) {
|
|||||||
|
|
||||||
void FunctionRepBuilder::visitCallInst(CallInst *CI) {
|
void FunctionRepBuilder::visitCallInst(CallInst *CI) {
|
||||||
CallDSNode *DSN = CallMap[CI];
|
CallDSNode *DSN = CallMap[CI];
|
||||||
|
unsigned PtrNum = 0;
|
||||||
unsigned PtrNum = 0, i = 0;
|
for (unsigned i = 0, e = CI->getNumOperands(); i != e; ++i)
|
||||||
if (isa<Function>(CI->getOperand(0)))
|
|
||||||
++i; // Not an Indirect function call? Skip the function pointer...
|
|
||||||
|
|
||||||
for (unsigned e = CI->getNumOperands(); i != e; ++i)
|
|
||||||
if (isa<PointerType>(CI->getOperand(i)->getType()))
|
if (isa<PointerType>(CI->getOperand(i)->getType()))
|
||||||
DSN->addArgValue(PtrNum++, ValueMap[CI->getOperand(i)]);
|
DSN->addArgValue(PtrNum++, ValueMap[CI->getOperand(i)]);
|
||||||
}
|
}
|
||||||
@ -333,6 +329,22 @@ FunctionDSGraph::FunctionDSGraph(Function *F) : Func(F) {
|
|||||||
RetNode = Builder.getRetNode();
|
RetNode = Builder.getRetNode();
|
||||||
ValueMap = Builder.getValueMap();
|
ValueMap = Builder.getValueMap();
|
||||||
|
|
||||||
|
// Remove all entries in the value map that consist of global values pointing
|
||||||
|
// at things. They can only point to their node, so there is no use keeping
|
||||||
|
// them.
|
||||||
|
//
|
||||||
|
for (map<Value*, PointerValSet>::iterator I = ValueMap.begin(),
|
||||||
|
E = ValueMap.end(); I != E;)
|
||||||
|
if (isa<GlobalValue>(I->first)) {
|
||||||
|
#if MAP_DOESNT_HAVE_BROKEN_ERASE_MEMBER
|
||||||
|
I = ValueMap.erase(I);
|
||||||
|
#else
|
||||||
|
ValueMap.erase(I); // This is really lame.
|
||||||
|
I = ValueMap.begin(); // GCC's stdc++ lib doesn't return an it!
|
||||||
|
#endif
|
||||||
|
} else
|
||||||
|
++I;
|
||||||
|
|
||||||
bool Changed = true;
|
bool Changed = true;
|
||||||
while (Changed) {
|
while (Changed) {
|
||||||
// Eliminate shadow nodes that are not distinguishable from some other
|
// Eliminate shadow nodes that are not distinguishable from some other
|
||||||
|
@ -40,8 +40,8 @@ bool GlobalDSNode::isEquivalentTo(DSNode *Node) const {
|
|||||||
//
|
//
|
||||||
bool CallDSNode::isEquivalentTo(DSNode *Node) const {
|
bool CallDSNode::isEquivalentTo(DSNode *Node) const {
|
||||||
if (CallDSNode *C = dyn_cast<CallDSNode>(Node)) {
|
if (CallDSNode *C = dyn_cast<CallDSNode>(Node)) {
|
||||||
if (C->CI->getCalledFunction() != CI->getCalledFunction() ||
|
if (getReferrers().size() != C->getReferrers().size() ||
|
||||||
getReferrers().size() != C->getReferrers().size())
|
C->getType() != getType())
|
||||||
return false; // Quick check...
|
return false; // Quick check...
|
||||||
|
|
||||||
// Check that the outgoing links are identical...
|
// Check that the outgoing links are identical...
|
||||||
@ -70,7 +70,6 @@ bool CallDSNode::isEquivalentTo(DSNode *Node) const {
|
|||||||
//
|
//
|
||||||
bool ShadowDSNode::isEquivalentTo(DSNode *Node) const {
|
bool ShadowDSNode::isEquivalentTo(DSNode *Node) const {
|
||||||
return getType() == Node->getType();
|
return getType() == Node->getType();
|
||||||
return !isCriticalNode(); // Must not be a critical node...
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -237,31 +236,31 @@ GlobalDSNode::GlobalDSNode(GlobalValue *V)
|
|||||||
|
|
||||||
string GlobalDSNode::getCaption() const {
|
string GlobalDSNode::getCaption() const {
|
||||||
stringstream OS;
|
stringstream OS;
|
||||||
|
if (isa<Function>(Val))
|
||||||
|
OS << "fn ";
|
||||||
|
else
|
||||||
|
OS << "global ";
|
||||||
|
|
||||||
WriteTypeSymbolic(OS, getType(), Val->getParent());
|
WriteTypeSymbolic(OS, getType(), Val->getParent());
|
||||||
return "global " + OS.str() + " %" + Val->getName();
|
return OS.str() + " %" + Val->getName();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
ShadowDSNode::ShadowDSNode(const Type *Ty, Module *M, bool C = false)
|
ShadowDSNode::ShadowDSNode(const Type *Ty, Module *M) : DSNode(ShadowNode, Ty) {
|
||||||
: DSNode(ShadowNode, Ty) {
|
|
||||||
Mod = M;
|
Mod = M;
|
||||||
ShadowParent = 0;
|
ShadowParent = 0;
|
||||||
CriticalNode = C;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ShadowDSNode::ShadowDSNode(const Type *Ty, Module *M, ShadowDSNode *ShadParent)
|
ShadowDSNode::ShadowDSNode(const Type *Ty, Module *M, ShadowDSNode *ShadParent)
|
||||||
: DSNode(ShadowNode, Ty) {
|
: DSNode(ShadowNode, Ty) {
|
||||||
Mod = M;
|
Mod = M;
|
||||||
ShadowParent = ShadParent;
|
ShadowParent = ShadParent;
|
||||||
CriticalNode = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string ShadowDSNode::getCaption() const {
|
std::string ShadowDSNode::getCaption() const {
|
||||||
stringstream OS;
|
stringstream OS;
|
||||||
if (CriticalNode) OS << "# ";
|
|
||||||
OS << "shadow ";
|
OS << "shadow ";
|
||||||
WriteTypeSymbolic(OS, getType(), Mod);
|
WriteTypeSymbolic(OS, getType(), Mod);
|
||||||
if (CriticalNode) OS << " #";
|
|
||||||
return OS.str();
|
return OS.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -281,10 +280,7 @@ void ShadowDSNode::mapNode(map<const DSNode*, DSNode*> &NodeMap,
|
|||||||
|
|
||||||
CallDSNode::CallDSNode(CallInst *ci) : DSNode(CallNode, ci->getType()), CI(ci) {
|
CallDSNode::CallDSNode(CallInst *ci) : DSNode(CallNode, ci->getType()), CI(ci) {
|
||||||
unsigned NumPtrs = 0;
|
unsigned NumPtrs = 0;
|
||||||
if (!isa<Function>(ci->getOperand(0)))
|
for (unsigned i = 0, e = ci->getNumOperands(); i != e; ++i)
|
||||||
NumPtrs++; // Include the method pointer...
|
|
||||||
|
|
||||||
for (unsigned i = 1, e = ci->getNumOperands(); i != e; ++i)
|
|
||||||
if (isa<PointerType>(ci->getOperand(i)->getType()))
|
if (isa<PointerType>(ci->getOperand(i)->getType()))
|
||||||
NumPtrs++;
|
NumPtrs++;
|
||||||
ArgLinks.resize(NumPtrs);
|
ArgLinks.resize(NumPtrs);
|
||||||
@ -334,7 +330,7 @@ void FunctionDSGraph::printFunction(std::ostream &O,
|
|||||||
O << "\n";
|
O << "\n";
|
||||||
for (std::map<Value*, PointerValSet>::const_iterator I = ValueMap.begin(),
|
for (std::map<Value*, PointerValSet>::const_iterator I = ValueMap.begin(),
|
||||||
E = ValueMap.end(); I != E; ++I) {
|
E = ValueMap.end(); I != E; ++I) {
|
||||||
if (I->second.size()) { // Only output nodes with edges...
|
if (I->second.size()) { // Only output nodes with edges...
|
||||||
stringstream OS;
|
stringstream OS;
|
||||||
WriteTypeSymbolic(OS, I->first->getType(), Func->getParent());
|
WriteTypeSymbolic(OS, I->first->getType(), Func->getParent());
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user