#include "llvm/Support/Timer.h"
#include "llvm/Module.h"
#include "llvm/ModuleProvider.h"
+#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Streams.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/raw_ostream.h"
+#include "llvm/System/Mutex.h"
+#include "llvm/System/Threading.h"
#include "llvm/Analysis/Dominators.h"
#include "llvm-c/Core.h"
#include <algorithm>
None, Arguments, Structure, Executions, Details
};
+// Always verify dominfo if expensive checking is enabled.
+#ifdef XDEBUG
+bool VerifyDomInfo = true;
+#else
bool VerifyDomInfo = false;
+#endif
static cl::opt<bool,true>
VerifyDomInfoX("verify-dom-info", cl::location(VerifyDomInfo),
cl::desc("Verify dominator info (time consuming)"));
class FunctionPassManagerImpl : public Pass,
public PMDataManager,
public PMTopLevelManager {
+private:
+ bool wasRun;
public:
static char ID;
explicit FunctionPassManagerImpl(int Depth) :
Pass(&ID), PMDataManager(Depth),
- PMTopLevelManager(TLM_Function) { }
+ PMTopLevelManager(TLM_Function), wasRun(false) { }
/// add - Add a pass to the queue of passes to run. This passes ownership of
/// the Pass to the PassManager. When the PassManager is destroyed, the pass
schedulePass(P);
}
+ // Prepare for running an on the fly pass, freeing memory if needed
+ // from a previous run.
+ void releaseMemoryOnTheFly();
+
/// run - Execute all of the passes scheduled for execution. Keep track of
/// whether any of the passes modifies the module, and if so, return true.
bool run(Function &F);
for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) {
ModulePass *MP = getContainedPass(Index);
MP->dumpPassStructure(Offset + 1);
- if (FunctionPassManagerImpl *FPP = OnTheFlyManagers[MP])
- FPP->dumpPassStructure(Offset + 2);
+ std::map<Pass *, FunctionPassManagerImpl *>::const_iterator I =
+ OnTheFlyManagers.find(MP);
+ if (I != OnTheFlyManagers.end())
+ I->second->dumpPassStructure(Offset + 2);
dumpLastUses(MP, Offset+1);
}
}
/// amount of time each pass takes to execute. This only happens when
/// -time-passes is enabled on the command line.
///
+
+static ManagedStatic<sys::SmartMutex<true> > TimingInfoMutex;
+
class VISIBILITY_HIDDEN TimingInfo {
std::map<Pass*, Timer> TimingData;
TimerGroup TG;
if (dynamic_cast<PMDataManager *>(P))
return;
+ sys::SmartScopedLock<true> Lock(*TimingInfoMutex);
std::map<Pass*, Timer>::iterator I = TimingData.find(P);
if (I == TimingData.end())
I=TimingData.insert(std::make_pair(P, Timer(P->getPassName(), TG))).first;
I->second.startTimer();
}
+
void passEnded(Pass *P) {
if (dynamic_cast<PMDataManager *>(P))
return;
+ sys::SmartScopedLock<true> Lock(*TimingInfoMutex);
std::map<Pass*, Timer>::iterator I = TimingData.find(P);
assert(I != TimingData.end() && "passStarted/passEnded not nested right!");
I->second.stopTimer();
OtherDT.dump();
cerr << "----- Invalid -----\n";
DT->dump();
- assert(0 && "Invalid dominator info");
+ LLVM_UNREACHABLE("Invalid dominator info");
}
DominanceFrontier *DF = P.getAnalysisIfAvailable<DominanceFrontier>();
OtherDF.dump();
cerr << "----- Invalid -----\n";
DF->dump();
- assert(0 && "Invalid dominator info");
+ LLVM_UNREACHABLE("Invalid dominator info");
}
}
// Keep track of higher level analysis used by this manager.
HigherLevelAnalysis.push_back(PRequired);
} else
- assert(0 && "Unable to accomodate Required Pass");
+ LLVM_UNREACHABLE("Unable to accomodate Required Pass");
}
// Set P as P's last user until someone starts using P.
cerr << "Unable to schedule '" << RequiredPass->getPassName();
cerr << "' required by '" << P->getPassName() << "'\n";
#endif
- assert(0 && "Unable to schedule pass");
+ LLVM_UNREACHABLE("Unable to schedule pass");
}
// Destructor
bool FunctionPassManager::run(Function &F) {
std::string errstr;
if (MP->materializeFunction(&F, &errstr)) {
- cerr << "Error reading bitcode file: " << errstr << "\n";
- abort();
+ llvm_report_error("Error reading bitcode file: " + errstr);
}
return FPM->run(F);
}
}
}
+void FunctionPassManagerImpl::releaseMemoryOnTheFly() {
+ if (!wasRun)
+ return;
+ for (unsigned Index = 0; Index < getNumContainedManagers(); ++Index) {
+ FPPassManager *FPPM = getContainedManager(Index);
+ for (unsigned Index = 0; Index < FPPM->getNumContainedPasses(); ++Index) {
+ FPPM->getContainedPass(Index)->releaseMemory();
+ }
+ }
+ wasRun = false;
+}
+
// Execute all the passes managed by this top level manager.
// Return true if any function is modified by a pass.
bool FunctionPassManagerImpl::run(Function &F) {
for (unsigned Index = 0; Index < getNumContainedManagers(); ++Index)
getContainedManager(Index)->cleanup();
+ wasRun = true;
return Changed;
}
MPPassManager::runOnModule(Module &M) {
bool Changed = false;
+ // Initialize on-the-fly passes
+ for (std::map<Pass *, FunctionPassManagerImpl *>::iterator
+ I = OnTheFlyManagers.begin(), E = OnTheFlyManagers.end();
+ I != E; ++I) {
+ FunctionPassManagerImpl *FPP = I->second;
+ Changed |= FPP->doInitialization(M);
+ }
+
for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) {
ModulePass *MP = getContainedPass(Index);
recordAvailableAnalysis(MP);
removeDeadPasses(MP, M.getModuleIdentifier().c_str(), ON_MODULE_MSG);
}
+
+ // Finalize on-the-fly passes
+ for (std::map<Pass *, FunctionPassManagerImpl *>::iterator
+ I = OnTheFlyManagers.begin(), E = OnTheFlyManagers.end();
+ I != E; ++I) {
+ FunctionPassManagerImpl *FPP = I->second;
+ // We don't know when is the last time an on-the-fly pass is run,
+ // so we need to releaseMemory / finalize here
+ FPP->releaseMemoryOnTheFly();
+ Changed |= FPP->doFinalization(M);
+ }
return Changed;
}
FunctionPassManagerImpl *FPP = OnTheFlyManagers[MP];
assert(FPP && "Unable to find on the fly pass");
+ FPP->releaseMemoryOnTheFly();
FPP->run(F);
return (dynamic_cast<PMTopLevelManager *>(FPP))->findAnalysisPass(PI);
}