Several changes here:

1. Increase max node size from 64->256 to avoid collapsing an important
   structure in 181.mcf
2. If we have multiple calls to an indirect call node with an indirect
   callee, fold these call nodes together, to avoid DSA turning apoc into
   a flaming fireball of death when analyzing 176.gcc.
  With this change, 176.gcc now takes ~7s to analyze for loc+bu+td, with
  5.7s of that in the BU pass.

llvm-svn: 20775
This commit is contained in:
Chris Lattner 2005-03-22 23:54:52 +00:00
parent 5c971a0072
commit 310d1a3882
1 changed files with 42 additions and 19 deletions

View File

@ -39,7 +39,7 @@ namespace {
Statistic<> NumTrivialGlobalDNE("dsa", "Number of globals trivially removed"); Statistic<> NumTrivialGlobalDNE("dsa", "Number of globals trivially removed");
}; };
#if 1 #if 0
#define TIME_REGION(VARNAME, DESC) \ #define TIME_REGION(VARNAME, DESC) \
NamedRegionTimer VARNAME(DESC) NamedRegionTimer VARNAME(DESC)
#else #else
@ -467,7 +467,7 @@ bool DSNode::mergeTypeInfo(const Type *NewTy, unsigned Offset,
// collapse it. This can occur for fortran common blocks, which have stupid // collapse it. This can occur for fortran common blocks, which have stupid
// things like { [100000000 x double], [1000000 x double] }. // things like { [100000000 x double], [1000000 x double] }.
unsigned NumFields = (NewTySize+DS::PointerSize-1) >> DS::PointerShift; unsigned NumFields = (NewTySize+DS::PointerSize-1) >> DS::PointerShift;
if (NumFields > 64) { if (NumFields > 256) {
foldNodeCompletely(); foldNodeCompletely();
return true; return true;
} }
@ -509,7 +509,7 @@ bool DSNode::mergeTypeInfo(const Type *NewTy, unsigned Offset,
// collapse it. This can occur for fortran common blocks, which have stupid // collapse it. This can occur for fortran common blocks, which have stupid
// things like { [100000000 x double], [1000000 x double] }. // things like { [100000000 x double], [1000000 x double] }.
unsigned NumFields = (NewTySize+DS::PointerSize-1) >> DS::PointerShift; unsigned NumFields = (NewTySize+DS::PointerSize-1) >> DS::PointerShift;
if (NumFields > 64) { if (NumFields > 256) {
foldNodeCompletely(); foldNodeCompletely();
return true; return true;
} }
@ -1574,22 +1574,20 @@ static inline void killIfUselessEdge(DSNodeHandle &Edge) {
Edge.setTo(0, 0); // Kill the edge! Edge.setTo(0, 0); // Kill the edge!
} }
#if 0
static inline bool nodeContainsExternalFunction(const DSNode *N) { static inline bool nodeContainsExternalFunction(const DSNode *N) {
const std::vector<GlobalValue*> &Globals = N->getGlobals(); std::vector<Function*> Funcs;
for (unsigned i = 0, e = Globals.size(); i != e; ++i) N->addFullFunctionList(Funcs);
if (Globals[i]->isExternal() && isa<Function>(Globals[i])) for (unsigned i = 0, e = Funcs.size(); i != e; ++i)
return true; if (Funcs[i]->isExternal()) return true;
return false; return false;
} }
#endif
static void removeIdenticalCalls(std::list<DSCallSite> &Calls) { static void removeIdenticalCalls(std::list<DSCallSite> &Calls) {
// Remove trivially identical function calls // Remove trivially identical function calls
Calls.sort(); // Sort by callee as primary key! Calls.sort(); // Sort by callee as primary key!
// Scan the call list cleaning it up as necessary... // Scan the call list cleaning it up as necessary...
DSNode *LastCalleeNode = 0; DSNodeHandle LastCalleeNode;
Function *LastCalleeFunc = 0; Function *LastCalleeFunc = 0;
unsigned NumDuplicateCalls = 0; unsigned NumDuplicateCalls = 0;
bool LastCalleeContainsExternalFunction = false; bool LastCalleeContainsExternalFunction = false;
@ -1600,17 +1598,41 @@ static void removeIdenticalCalls(std::list<DSCallSite> &Calls) {
DSCallSite &CS = *I; DSCallSite &CS = *I;
std::list<DSCallSite>::iterator OldIt = I++; std::list<DSCallSite>::iterator OldIt = I++;
// If the Callee is a useless edge, this must be an unreachable call site, if (!CS.isIndirectCall()) {
// eliminate it. LastCalleeNode = 0;
if (CS.isIndirectCall() && CS.getCalleeNode()->getNumReferrers() == 1 && } else {
CS.getCalleeNode()->isComplete() && DSNode *Callee = CS.getCalleeNode();
CS.getCalleeNode()->getGlobalsList().empty()) { // No useful info?
// If the Callee is a useless edge, this must be an unreachable call site,
// eliminate it.
if (Callee->getNumReferrers() == 1 && Callee->isComplete() &&
Callee->getGlobalsList().empty()) { // No useful info?
#ifndef NDEBUG #ifndef NDEBUG
std::cerr << "WARNING: Useless call site found.\n"; std::cerr << "WARNING: Useless call site found.\n";
#endif #endif
Calls.erase(OldIt); Calls.erase(OldIt);
++NumDeleted; ++NumDeleted;
continue; continue;
}
// If the last call site in the list has the same callee as this one, and
// if the callee contains an external function, it will never be
// resolvable, just merge the call sites.
if (!LastCalleeNode.isNull() && LastCalleeNode.getNode() == Callee) {
LastCalleeContainsExternalFunction =
nodeContainsExternalFunction(Callee);
std::list<DSCallSite>::iterator PrevIt = OldIt;
--PrevIt;
PrevIt->mergeWith(CS);
// No need to keep this call anymore.
Calls.erase(OldIt);
++NumDeleted;
continue;
} else {
LastCalleeNode = Callee;
}
} }
// If the return value or any arguments point to a void node with no // If the return value or any arguments point to a void node with no
@ -1676,6 +1698,7 @@ static void removeIdenticalCalls(std::list<DSCallSite> &Calls) {
#endif #endif
if (I != Calls.end() && CS == *I) { if (I != Calls.end() && CS == *I) {
LastCalleeNode = 0;
Calls.erase(OldIt); Calls.erase(OldIt);
++NumDeleted; ++NumDeleted;
continue; continue;