* 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:
Chris Lattner 2002-04-16 20:39:59 +00:00
parent 28c238636e
commit 7650b94c75
5 changed files with 79 additions and 55 deletions

View File

@ -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();
}
} }

View File

@ -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";
} }
} }

View File

@ -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;
} }

View File

@ -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

View File

@ -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());