#include "llvm/IR/LegacyPassManager.h"
#include "llvm/ADT/MapVector.h"
#include "llvm/IR/DiagnosticInfo.h"
#include "llvm/IR/IRPrintingPasses.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/LegacyPassManagers.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/PassTimingInfo.h"
#include "llvm/IR/PrintPasses.h"
#include "llvm/Support/Chrono.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/TimeProfiler.h"
#include "llvm/Support/Timer.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
using namespace llvm;
namespace {
enum PassDebugLevel {
Disabled, Arguments, Structure, Executions, Details
};
}
static cl::opt<enum PassDebugLevel> PassDebugging(
"debug-pass", cl::Hidden,
cl::desc("Print legacy PassManager debugging information"),
cl::values(clEnumVal(Disabled, "disable debug output"),
clEnumVal(Arguments, "print pass arguments to pass to 'opt'"),
clEnumVal(Structure, "print pass structure before run()"),
clEnumVal(Executions, "print pass name before it is executed"),
clEnumVal(Details, "print pass details when it is executed")));
bool PMDataManager::isPassDebuggingExecutionsOrMore() const {
return PassDebugging >= Executions;
}
unsigned PMDataManager::initSizeRemarkInfo(
Module &M, StringMap<std::pair<unsigned, unsigned>> &FunctionToInstrCount) {
unsigned InstrCount = 0;
for (Function &F : M) {
unsigned FCount = F.getInstructionCount();
FunctionToInstrCount[F.getName().str()] =
std::pair<unsigned, unsigned>(FCount, 0);
InstrCount += FCount;
}
return InstrCount;
}
void PMDataManager::emitInstrCountChangedRemark(
Pass *P, Module &M, int64_t Delta, unsigned CountBefore,
StringMap<std::pair<unsigned, unsigned>> &FunctionToInstrCount,
Function *F) {
if (P->getAsPMDataManager())
return;
bool CouldOnlyImpactOneFunction = (F != nullptr);
auto UpdateFunctionChanges =
[&FunctionToInstrCount](Function &MaybeChangedFn) {
unsigned FnSize = MaybeChangedFn.getInstructionCount();
auto It = FunctionToInstrCount.find(MaybeChangedFn.getName());
if (It == FunctionToInstrCount.end()) {
FunctionToInstrCount[MaybeChangedFn.getName()] =
std::pair<unsigned, unsigned>(0, FnSize);
return;
}
It->second.second = FnSize;
};
if (!CouldOnlyImpactOneFunction)
std::for_each(M.begin(), M.end(), UpdateFunctionChanges);
else
UpdateFunctionChanges(*F);
if (!CouldOnlyImpactOneFunction) {
auto It = llvm::find_if(M, [](const Function &Fn) { return !Fn.empty(); });
if (It == M.end())
return;
F = &*It;
}
int64_t CountAfter = static_cast<int64_t>(CountBefore) + Delta;
BasicBlock &BB = *F->begin();
OptimizationRemarkAnalysis R("size-info", "IRSizeChange",
DiagnosticLocation(), &BB);
R << DiagnosticInfoOptimizationBase::Argument("Pass", P->getPassName())
<< ": IR instruction count changed from "
<< DiagnosticInfoOptimizationBase::Argument("IRInstrsBefore", CountBefore)
<< " to "
<< DiagnosticInfoOptimizationBase::Argument("IRInstrsAfter", CountAfter)
<< "; Delta: "
<< DiagnosticInfoOptimizationBase::Argument("DeltaInstrCount", Delta);
F->getContext().diagnose(R);
std::string PassName = P->getPassName().str();
auto EmitFunctionSizeChangedRemark = [&FunctionToInstrCount, &F, &BB,
&PassName](StringRef Fname) {
unsigned FnCountBefore, FnCountAfter;
std::pair<unsigned, unsigned> &Change = FunctionToInstrCount[Fname];
std::tie(FnCountBefore, FnCountAfter) = Change;
int64_t FnDelta = static_cast<int64_t>(FnCountAfter) -
static_cast<int64_t>(FnCountBefore);
if (FnDelta == 0)
return;
OptimizationRemarkAnalysis FR("size-info", "FunctionIRSizeChange",
DiagnosticLocation(), &BB);
FR << DiagnosticInfoOptimizationBase::Argument("Pass", PassName)
<< ": Function: "
<< DiagnosticInfoOptimizationBase::Argument("Function", Fname)
<< ": IR instruction count changed from "
<< DiagnosticInfoOptimizationBase::Argument("IRInstrsBefore",
FnCountBefore)
<< " to "
<< DiagnosticInfoOptimizationBase::Argument("IRInstrsAfter",
FnCountAfter)
<< "; Delta: "
<< DiagnosticInfoOptimizationBase::Argument("DeltaInstrCount", FnDelta);
F->getContext().diagnose(FR);
Change.first = FnCountAfter;
};
if (!CouldOnlyImpactOneFunction)
std::for_each(FunctionToInstrCount.keys().begin(),
FunctionToInstrCount.keys().end(),
EmitFunctionSizeChangedRemark);
else
EmitFunctionSizeChangedRemark(F->getName().str());
}
void PassManagerPrettyStackEntry::print(raw_ostream &OS) const {
if (!V && !M)
OS << "Releasing pass '";
else
OS << "Running pass '";
OS << P->getPassName() << "'";
if (M) {
OS << " on module '" << M->getModuleIdentifier() << "'.\n";
return;
}
if (!V) {
OS << '\n';
return;
}
OS << " on ";
if (isa<Function>(V))
OS << "function";
else if (isa<BasicBlock>(V))
OS << "basic block";
else
OS << "value";
OS << " '";
V->printAsOperand(OS, false, M);
OS << "'\n";
}
namespace llvm {
namespace legacy {
bool debugPassSpecified() { return PassDebugging != Disabled; }
class FunctionPassManagerImpl : public Pass,
public PMDataManager,
public PMTopLevelManager {
virtual void anchor();
private:
bool wasRun;
public:
static char ID;
explicit FunctionPassManagerImpl()
: Pass(PT_PassManager, ID), PMTopLevelManager(new FPPassManager()),
wasRun(false) {}
void add(Pass *P) {
schedulePass(P);
}
Pass *createPrinterPass(raw_ostream &O,
const std::string &Banner) const override {
return createPrintFunctionPass(O, Banner);
}
void releaseMemoryOnTheFly();
bool run(Function &F);
bool doInitialization(Module &M) override;
bool doFinalization(Module &M) override;
PMDataManager *getAsPMDataManager() override { return this; }
Pass *getAsPass() override { return this; }
PassManagerType getTopLevelPassManagerType() override {
return PMT_FunctionPassManager;
}
void getAnalysisUsage(AnalysisUsage &Info) const override {
Info.setPreservesAll();
}
FPPassManager *getContainedManager(unsigned N) {
assert(N < PassManagers.size() && "Pass number out of range!");
FPPassManager *FP = static_cast<FPPassManager *>(PassManagers[N]);
return FP;
}
void dumpPassStructure(unsigned Offset) override {
for (unsigned I = 0; I < getNumContainedManagers(); ++I)
getContainedManager(I)->dumpPassStructure(Offset);
}
};
void FunctionPassManagerImpl::anchor() {}
char FunctionPassManagerImpl::ID = 0;
bool FunctionPassManagerImpl::doInitialization(Module &M) {
bool Changed = false;
dumpArguments();
dumpPasses();
for (ImmutablePass *ImPass : getImmutablePasses())
Changed |= ImPass->doInitialization(M);
for (unsigned Index = 0; Index < getNumContainedManagers(); ++Index)
Changed |= getContainedManager(Index)->doInitialization(M);
return Changed;
}
bool FunctionPassManagerImpl::doFinalization(Module &M) {
bool Changed = false;
for (int Index = getNumContainedManagers() - 1; Index >= 0; --Index)
Changed |= getContainedManager(Index)->doFinalization(M);
for (ImmutablePass *ImPass : getImmutablePasses())
Changed |= ImPass->doFinalization(M);
return Changed;
}
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;
}
bool FunctionPassManagerImpl::run(Function &F) {
bool Changed = false;
initializeAllAnalysisInfo();
for (unsigned Index = 0; Index < getNumContainedManagers(); ++Index) {
Changed |= getContainedManager(Index)->runOnFunction(F);
F.getContext().yield();
}
for (unsigned Index = 0; Index < getNumContainedManagers(); ++Index)
getContainedManager(Index)->cleanup();
wasRun = true;
return Changed;
}
} }
namespace {
class MPPassManager : public Pass, public PMDataManager {
public:
static char ID;
explicit MPPassManager() : Pass(PT_PassManager, ID) {}
~MPPassManager() override {
for (auto &OnTheFlyManager : OnTheFlyManagers) {
legacy::FunctionPassManagerImpl *FPP = OnTheFlyManager.second;
delete FPP;
}
}
Pass *createPrinterPass(raw_ostream &O,
const std::string &Banner) const override {
return createPrintModulePass(O, Banner);
}
bool runOnModule(Module &M);
using llvm::Pass::doInitialization;
using llvm::Pass::doFinalization;
void getAnalysisUsage(AnalysisUsage &Info) const override {
Info.setPreservesAll();
}
void addLowerLevelRequiredPass(Pass *P, Pass *RequiredPass) override;
std::tuple<Pass *, bool> getOnTheFlyPass(Pass *MP, AnalysisID PI,
Function &F) override;
StringRef getPassName() const override { return "Module Pass Manager"; }
PMDataManager *getAsPMDataManager() override { return this; }
Pass *getAsPass() override { return this; }
void dumpPassStructure(unsigned Offset) override {
dbgs().indent(Offset*2) << "ModulePass Manager\n";
for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) {
ModulePass *MP = getContainedPass(Index);
MP->dumpPassStructure(Offset + 1);
MapVector<Pass *, legacy::FunctionPassManagerImpl *>::const_iterator I =
OnTheFlyManagers.find(MP);
if (I != OnTheFlyManagers.end())
I->second->dumpPassStructure(Offset + 2);
dumpLastUses(MP, Offset+1);
}
}
ModulePass *getContainedPass(unsigned N) {
assert(N < PassVector.size() && "Pass number out of range!");
return static_cast<ModulePass *>(PassVector[N]);
}
PassManagerType getPassManagerType() const override {
return PMT_ModulePassManager;
}
private:
MapVector<Pass *, legacy::FunctionPassManagerImpl *> OnTheFlyManagers;
};
char MPPassManager::ID = 0;
}
namespace llvm {
namespace legacy {
class PassManagerImpl : public Pass,
public PMDataManager,
public PMTopLevelManager {
virtual void anchor();
public:
static char ID;
explicit PassManagerImpl()
: Pass(PT_PassManager, ID), PMTopLevelManager(new MPPassManager()) {}
void add(Pass *P) {
schedulePass(P);
}
Pass *createPrinterPass(raw_ostream &O,
const std::string &Banner) const override {
return createPrintModulePass(O, Banner);
}
bool run(Module &M);
using llvm::Pass::doInitialization;
using llvm::Pass::doFinalization;
void getAnalysisUsage(AnalysisUsage &Info) const override {
Info.setPreservesAll();
}
PMDataManager *getAsPMDataManager() override { return this; }
Pass *getAsPass() override { return this; }
PassManagerType getTopLevelPassManagerType() override {
return PMT_ModulePassManager;
}
MPPassManager *getContainedManager(unsigned N) {
assert(N < PassManagers.size() && "Pass number out of range!");
MPPassManager *MP = static_cast<MPPassManager *>(PassManagers[N]);
return MP;
}
};
void PassManagerImpl::anchor() {}
char PassManagerImpl::ID = 0;
bool PassManagerImpl::run(Module &M) {
bool Changed = false;
dumpArguments();
dumpPasses();
for (ImmutablePass *ImPass : getImmutablePasses())
Changed |= ImPass->doInitialization(M);
initializeAllAnalysisInfo();
for (unsigned Index = 0; Index < getNumContainedManagers(); ++Index) {
Changed |= getContainedManager(Index)->runOnModule(M);
M.getContext().yield();
}
for (ImmutablePass *ImPass : getImmutablePasses())
Changed |= ImPass->doFinalization(M);
return Changed;
}
} }
PMTopLevelManager::PMTopLevelManager(PMDataManager *PMDM) {
PMDM->setTopLevelManager(this);
addPassManager(PMDM);
activeStack.push(PMDM);
}
void
PMTopLevelManager::setLastUser(ArrayRef<Pass*> AnalysisPasses, Pass *P) {
unsigned PDepth = 0;
if (P->getResolver())
PDepth = P->getResolver()->getPMDataManager().getDepth();
for (Pass *AP : AnalysisPasses) {
auto &LastUserOfAP = LastUser[AP];
if (LastUserOfAP)
InversedLastUser[LastUserOfAP].erase(AP);
LastUserOfAP = P;
InversedLastUser[P].insert(AP);
if (P == AP)
continue;
AnalysisUsage *AnUsage = findAnalysisUsage(AP);
const AnalysisUsage::VectorType &IDs = AnUsage->getRequiredTransitiveSet();
SmallVector<Pass *, 12> LastUses;
SmallVector<Pass *, 12> LastPMUses;
for (AnalysisID ID : IDs) {
Pass *AnalysisPass = findAnalysisPass(ID);
assert(AnalysisPass && "Expected analysis pass to exist.");
AnalysisResolver *AR = AnalysisPass->getResolver();
assert(AR && "Expected analysis resolver to exist.");
unsigned APDepth = AR->getPMDataManager().getDepth();
if (PDepth == APDepth)
LastUses.push_back(AnalysisPass);
else if (PDepth > APDepth)
LastPMUses.push_back(AnalysisPass);
}
setLastUser(LastUses, P);
if (P->getResolver())
setLastUser(LastPMUses, P->getResolver()->getPMDataManager().getAsPass());
auto &LastUsedByAP = InversedLastUser[AP];
for (Pass *L : LastUsedByAP)
LastUser[L] = P;
InversedLastUser[P].insert(LastUsedByAP.begin(), LastUsedByAP.end());
LastUsedByAP.clear();
}
}
void PMTopLevelManager::collectLastUses(SmallVectorImpl<Pass *> &LastUses,
Pass *P) {
auto DMI = InversedLastUser.find(P);
if (DMI == InversedLastUser.end())
return;
auto &LU = DMI->second;
LastUses.append(LU.begin(), LU.end());
}
AnalysisUsage *PMTopLevelManager::findAnalysisUsage(Pass *P) {
AnalysisUsage *AnUsage = nullptr;
auto DMI = AnUsageMap.find(P);
if (DMI != AnUsageMap.end())
AnUsage = DMI->second;
else {
AnalysisUsage AU;
P->getAnalysisUsage(AU);
AUFoldingSetNode* Node = nullptr;
FoldingSetNodeID ID;
AUFoldingSetNode::Profile(ID, AU);
void *IP = nullptr;
if (auto *N = UniqueAnalysisUsages.FindNodeOrInsertPos(ID, IP))
Node = N;
else {
Node = new (AUFoldingSetNodeAllocator.Allocate()) AUFoldingSetNode(AU);
UniqueAnalysisUsages.InsertNode(Node, IP);
}
assert(Node && "cached analysis usage must be non null");
AnUsageMap[P] = &Node->AU;
AnUsage = &Node->AU;
}
return AnUsage;
}
void PMTopLevelManager::schedulePass(Pass *P) {
P->preparePassManager(activeStack);
const PassInfo *PI = findAnalysisPassInfo(P->getPassID());
if (PI && PI->isAnalysis() && findAnalysisPass(P->getPassID())) {
AnUsageMap.erase(P);
delete P;
return;
}
AnalysisUsage *AnUsage = findAnalysisUsage(P);
bool checkAnalysis = true;
while (checkAnalysis) {
checkAnalysis = false;
const AnalysisUsage::VectorType &RequiredSet = AnUsage->getRequiredSet();
for (const AnalysisID ID : RequiredSet) {
Pass *AnalysisPass = findAnalysisPass(ID);
if (!AnalysisPass) {
const PassInfo *PI = findAnalysisPassInfo(ID);
if (!PI) {
dbgs() << "Pass '" << P->getPassName() << "' is not initialized." << "\n";
dbgs() << "Verify if there is a pass dependency cycle." << "\n";
dbgs() << "Required Passes:" << "\n";
for (const AnalysisID ID2 : RequiredSet) {
if (ID == ID2)
break;
Pass *AnalysisPass2 = findAnalysisPass(ID2);
if (AnalysisPass2) {
dbgs() << "\t" << AnalysisPass2->getPassName() << "\n";
} else {
dbgs() << "\t" << "Error: Required pass not found! Possible causes:" << "\n";
dbgs() << "\t\t" << "- Pass misconfiguration (e.g.: missing macros)" << "\n";
dbgs() << "\t\t" << "- Corruption of the global PassRegistry" << "\n";
}
}
}
assert(PI && "Expected required passes to be initialized");
AnalysisPass = PI->createPass();
if (P->getPotentialPassManagerType () ==
AnalysisPass->getPotentialPassManagerType())
schedulePass(AnalysisPass);
else if (P->getPotentialPassManagerType () >
AnalysisPass->getPotentialPassManagerType()) {
schedulePass(AnalysisPass);
checkAnalysis = true;
} else
delete AnalysisPass;
}
}
}
if (ImmutablePass *IP = P->getAsImmutablePass()) {
PMDataManager *DM = getAsPMDataManager();
AnalysisResolver *AR = new AnalysisResolver(*DM);
P->setResolver(AR);
DM->initializeAnalysisImpl(P);
addImmutablePass(IP);
DM->recordAvailableAnalysis(IP);
return;
}
if (PI && !PI->isAnalysis() && shouldPrintBeforePass(PI->getPassArgument())) {
Pass *PP =
P->createPrinterPass(dbgs(), ("*** IR Dump Before " + P->getPassName() +
" (" + PI->getPassArgument() + ") ***")
.str());
PP->assignPassManager(activeStack, getTopLevelPassManagerType());
}
P->assignPassManager(activeStack, getTopLevelPassManagerType());
if (PI && !PI->isAnalysis() && shouldPrintAfterPass(PI->getPassArgument())) {
Pass *PP =
P->createPrinterPass(dbgs(), ("*** IR Dump After " + P->getPassName() +
" (" + PI->getPassArgument() + ") ***")
.str());
PP->assignPassManager(activeStack, getTopLevelPassManagerType());
}
}
Pass *PMTopLevelManager::findAnalysisPass(AnalysisID AID) {
if (Pass *P = ImmutablePassMap.lookup(AID))
return P;
for (PMDataManager *PassManager : PassManagers)
if (Pass *P = PassManager->findAnalysisPass(AID, false))
return P;
for (PMDataManager *IndirectPassManager : IndirectPassManagers)
if (Pass *P = IndirectPassManager->findAnalysisPass(AID, false))
return P;
return nullptr;
}
const PassInfo *PMTopLevelManager::findAnalysisPassInfo(AnalysisID AID) const {
const PassInfo *&PI = AnalysisPassInfos[AID];
if (!PI)
PI = PassRegistry::getPassRegistry()->getPassInfo(AID);
else
assert(PI == PassRegistry::getPassRegistry()->getPassInfo(AID) &&
"The pass info pointer changed for an analysis ID!");
return PI;
}
void PMTopLevelManager::addImmutablePass(ImmutablePass *P) {
P->initializePass();
ImmutablePasses.push_back(P);
AnalysisID AID = P->getPassID();
ImmutablePassMap[AID] = P;
const PassInfo *PassInf = findAnalysisPassInfo(AID);
assert(PassInf && "Expected all immutable passes to be initialized");
for (const PassInfo *ImmPI : PassInf->getInterfacesImplemented())
ImmutablePassMap[ImmPI->getTypeInfo()] = P;
}
void PMTopLevelManager::dumpPasses() const {
if (PassDebugging < Structure)
return;
for (unsigned i = 0, e = ImmutablePasses.size(); i != e; ++i) {
ImmutablePasses[i]->dumpPassStructure(0);
}
for (PMDataManager *Manager : PassManagers)
Manager->getAsPass()->dumpPassStructure(1);
}
void PMTopLevelManager::dumpArguments() const {
if (PassDebugging < Arguments)
return;
dbgs() << "Pass Arguments: ";
for (ImmutablePass *P : ImmutablePasses)
if (const PassInfo *PI = findAnalysisPassInfo(P->getPassID())) {
assert(PI && "Expected all immutable passes to be initialized");
if (!PI->isAnalysisGroup())
dbgs() << " -" << PI->getPassArgument();
}
for (PMDataManager *PM : PassManagers)
PM->dumpPassArguments();
dbgs() << "\n";
}
void PMTopLevelManager::initializeAllAnalysisInfo() {
for (PMDataManager *PM : PassManagers)
PM->initializeAnalysisInfo();
for (PMDataManager *IPM : IndirectPassManagers)
IPM->initializeAnalysisInfo();
}
PMTopLevelManager::~PMTopLevelManager() {
for (PMDataManager *PM : PassManagers)
delete PM;
for (ImmutablePass *P : ImmutablePasses)
delete P;
}
void PMDataManager::recordAvailableAnalysis(Pass *P) {
AnalysisID PI = P->getPassID();
AvailableAnalysis[PI] = P;
assert(!AvailableAnalysis.empty());
const PassInfo *PInf = TPM->findAnalysisPassInfo(PI);
if (!PInf) return;
for (const PassInfo *PI : PInf->getInterfacesImplemented())
AvailableAnalysis[PI->getTypeInfo()] = P;
}
bool PMDataManager::preserveHigherLevelAnalysis(Pass *P) {
AnalysisUsage *AnUsage = TPM->findAnalysisUsage(P);
if (AnUsage->getPreservesAll())
return true;
const AnalysisUsage::VectorType &PreservedSet = AnUsage->getPreservedSet();
for (Pass *P1 : HigherLevelAnalysis) {
if (P1->getAsImmutablePass() == nullptr &&
!is_contained(PreservedSet, P1->getPassID()))
return false;
}
return true;
}
void PMDataManager::verifyPreservedAnalysis(Pass *P) {
#ifdef NDEBUG
return;
#endif
AnalysisUsage *AnUsage = TPM->findAnalysisUsage(P);
const AnalysisUsage::VectorType &PreservedSet = AnUsage->getPreservedSet();
for (AnalysisID AID : PreservedSet) {
if (Pass *AP = findAnalysisPass(AID, true)) {
TimeRegion PassTimer(getPassTimer(AP));
AP->verifyAnalysis();
}
}
}
void PMDataManager::removeNotPreservedAnalysis(Pass *P) {
AnalysisUsage *AnUsage = TPM->findAnalysisUsage(P);
if (AnUsage->getPreservesAll())
return;
const AnalysisUsage::VectorType &PreservedSet = AnUsage->getPreservedSet();
for (DenseMap<AnalysisID, Pass*>::iterator I = AvailableAnalysis.begin(),
E = AvailableAnalysis.end(); I != E; ) {
DenseMap<AnalysisID, Pass*>::iterator Info = I++;
if (Info->second->getAsImmutablePass() == nullptr &&
!is_contained(PreservedSet, Info->first)) {
if (PassDebugging >= Details) {
Pass *S = Info->second;
dbgs() << " -- '" << P->getPassName() << "' is not preserving '";
dbgs() << S->getPassName() << "'\n";
}
AvailableAnalysis.erase(Info);
}
}
for (DenseMap<AnalysisID, Pass *> *IA : InheritedAnalysis) {
if (!IA)
continue;
for (DenseMap<AnalysisID, Pass *>::iterator I = IA->begin(),
E = IA->end();
I != E;) {
DenseMap<AnalysisID, Pass *>::iterator Info = I++;
if (Info->second->getAsImmutablePass() == nullptr &&
!is_contained(PreservedSet, Info->first)) {
if (PassDebugging >= Details) {
Pass *S = Info->second;
dbgs() << " -- '" << P->getPassName() << "' is not preserving '";
dbgs() << S->getPassName() << "'\n";
}
IA->erase(Info);
}
}
}
}
void PMDataManager::removeDeadPasses(Pass *P, StringRef Msg,
enum PassDebuggingString DBG_STR) {
SmallVector<Pass *, 12> DeadPasses;
if (!TPM)
return;
TPM->collectLastUses(DeadPasses, P);
if (PassDebugging >= Details && !DeadPasses.empty()) {
dbgs() << " -*- '" << P->getPassName();
dbgs() << "' is the last user of following pass instances.";
dbgs() << " Free these instances\n";
}
for (Pass *P : DeadPasses)
freePass(P, Msg, DBG_STR);
}
void PMDataManager::freePass(Pass *P, StringRef Msg,
enum PassDebuggingString DBG_STR) {
dumpPassInfo(P, FREEING_MSG, DBG_STR, Msg);
{
PassManagerPrettyStackEntry X(P);
TimeRegion PassTimer(getPassTimer(P));
P->releaseMemory();
}
AnalysisID PI = P->getPassID();
if (const PassInfo *PInf = TPM->findAnalysisPassInfo(PI)) {
AvailableAnalysis.erase(PI);
for (const PassInfo *PI : PInf->getInterfacesImplemented()) {
DenseMap<AnalysisID, Pass *>::iterator Pos =
AvailableAnalysis.find(PI->getTypeInfo());
if (Pos != AvailableAnalysis.end() && Pos->second == P)
AvailableAnalysis.erase(Pos);
}
}
}
void PMDataManager::add(Pass *P, bool ProcessAnalysis) {
AnalysisResolver *AR = new AnalysisResolver(*this);
P->setResolver(AR);
SmallVector<Pass *, 12> TransferLastUses;
if (!ProcessAnalysis) {
PassVector.push_back(P);
return;
}
SmallVector<Pass *, 12> LastUses;
SmallVector<Pass *, 8> UsedPasses;
SmallVector<AnalysisID, 8> ReqAnalysisNotAvailable;
unsigned PDepth = this->getDepth();
collectRequiredAndUsedAnalyses(UsedPasses, ReqAnalysisNotAvailable, P);
for (Pass *PUsed : UsedPasses) {
unsigned RDepth = 0;
assert(PUsed->getResolver() && "Analysis Resolver is not set");
PMDataManager &DM = PUsed->getResolver()->getPMDataManager();
RDepth = DM.getDepth();
if (PDepth == RDepth)
LastUses.push_back(PUsed);
else if (PDepth > RDepth) {
TransferLastUses.push_back(PUsed);
HigherLevelAnalysis.push_back(PUsed);
} else
llvm_unreachable("Unable to accommodate Used Pass");
}
if (!P->getAsPMDataManager())
LastUses.push_back(P);
TPM->setLastUser(LastUses, P);
if (!TransferLastUses.empty()) {
Pass *My_PM = getAsPass();
TPM->setLastUser(TransferLastUses, My_PM);
TransferLastUses.clear();
}
for (AnalysisID ID : ReqAnalysisNotAvailable) {
const PassInfo *PI = TPM->findAnalysisPassInfo(ID);
Pass *AnalysisPass = PI->createPass();
this->addLowerLevelRequiredPass(P, AnalysisPass);
}
removeNotPreservedAnalysis(P);
recordAvailableAnalysis(P);
PassVector.push_back(P);
}
void PMDataManager::collectRequiredAndUsedAnalyses(
SmallVectorImpl<Pass *> &UP, SmallVectorImpl<AnalysisID> &RP_NotAvail,
Pass *P) {
AnalysisUsage *AnUsage = TPM->findAnalysisUsage(P);
for (const auto &UsedID : AnUsage->getUsedSet())
if (Pass *AnalysisPass = findAnalysisPass(UsedID, true))
UP.push_back(AnalysisPass);
for (const auto &RequiredID : AnUsage->getRequiredSet())
if (Pass *AnalysisPass = findAnalysisPass(RequiredID, true))
UP.push_back(AnalysisPass);
else
RP_NotAvail.push_back(RequiredID);
}
void PMDataManager::initializeAnalysisImpl(Pass *P) {
AnalysisUsage *AnUsage = TPM->findAnalysisUsage(P);
for (const AnalysisID ID : AnUsage->getRequiredSet()) {
Pass *Impl = findAnalysisPass(ID, true);
if (!Impl)
continue;
AnalysisResolver *AR = P->getResolver();
assert(AR && "Analysis Resolver is not set");
AR->addAnalysisImplsPair(ID, Impl);
}
}
Pass *PMDataManager::findAnalysisPass(AnalysisID AID, bool SearchParent) {
DenseMap<AnalysisID, Pass*>::const_iterator I = AvailableAnalysis.find(AID);
if (I != AvailableAnalysis.end())
return I->second;
if (SearchParent)
return TPM->findAnalysisPass(AID);
return nullptr;
}
void PMDataManager::dumpLastUses(Pass *P, unsigned Offset) const{
if (PassDebugging < Details)
return;
SmallVector<Pass *, 12> LUses;
if (!TPM)
return;
TPM->collectLastUses(LUses, P);
for (Pass *P : LUses) {
dbgs() << "--" << std::string(Offset*2, ' ');
P->dumpPassStructure(0);
}
}
void PMDataManager::dumpPassArguments() const {
for (Pass *P : PassVector) {
if (PMDataManager *PMD = P->getAsPMDataManager())
PMD->dumpPassArguments();
else
if (const PassInfo *PI =
TPM->findAnalysisPassInfo(P->getPassID()))
if (!PI->isAnalysisGroup())
dbgs() << " -" << PI->getPassArgument();
}
}
void PMDataManager::dumpPassInfo(Pass *P, enum PassDebuggingString S1,
enum PassDebuggingString S2,
StringRef Msg) {
if (PassDebugging < Executions)
return;
dbgs() << "[" << std::chrono::system_clock::now() << "] " << (void *)this
<< std::string(getDepth() * 2 + 1, ' ');
switch (S1) {
case EXECUTION_MSG:
dbgs() << "Executing Pass '" << P->getPassName();
break;
case MODIFICATION_MSG:
dbgs() << "Made Modification '" << P->getPassName();
break;
case FREEING_MSG:
dbgs() << " Freeing Pass '" << P->getPassName();
break;
default:
break;
}
switch (S2) {
case ON_FUNCTION_MSG:
dbgs() << "' on Function '" << Msg << "'...\n";
break;
case ON_MODULE_MSG:
dbgs() << "' on Module '" << Msg << "'...\n";
break;
case ON_REGION_MSG:
dbgs() << "' on Region '" << Msg << "'...\n";
break;
case ON_LOOP_MSG:
dbgs() << "' on Loop '" << Msg << "'...\n";
break;
case ON_CG_MSG:
dbgs() << "' on Call Graph Nodes '" << Msg << "'...\n";
break;
default:
break;
}
}
void PMDataManager::dumpRequiredSet(const Pass *P) const {
if (PassDebugging < Details)
return;
AnalysisUsage analysisUsage;
P->getAnalysisUsage(analysisUsage);
dumpAnalysisUsage("Required", P, analysisUsage.getRequiredSet());
}
void PMDataManager::dumpPreservedSet(const Pass *P) const {
if (PassDebugging < Details)
return;
AnalysisUsage analysisUsage;
P->getAnalysisUsage(analysisUsage);
dumpAnalysisUsage("Preserved", P, analysisUsage.getPreservedSet());
}
void PMDataManager::dumpUsedSet(const Pass *P) const {
if (PassDebugging < Details)
return;
AnalysisUsage analysisUsage;
P->getAnalysisUsage(analysisUsage);
dumpAnalysisUsage("Used", P, analysisUsage.getUsedSet());
}
void PMDataManager::dumpAnalysisUsage(StringRef Msg, const Pass *P,
const AnalysisUsage::VectorType &Set) const {
assert(PassDebugging >= Details);
if (Set.empty())
return;
dbgs() << (const void*)P << std::string(getDepth()*2+3, ' ') << Msg << " Analyses:";
for (unsigned i = 0; i != Set.size(); ++i) {
if (i) dbgs() << ',';
const PassInfo *PInf = TPM->findAnalysisPassInfo(Set[i]);
if (!PInf) {
dbgs() << " Uninitialized Pass";
continue;
}
dbgs() << ' ' << PInf->getPassName();
}
dbgs() << '\n';
}
void PMDataManager::addLowerLevelRequiredPass(Pass *P, Pass *RequiredPass) {
if (TPM) {
TPM->dumpArguments();
TPM->dumpPasses();
}
#ifndef NDEBUG
dbgs() << "Unable to schedule '" << RequiredPass->getPassName();
dbgs() << "' required by '" << P->getPassName() << "'\n";
#endif
llvm_unreachable("Unable to schedule pass");
}
std::tuple<Pass *, bool> PMDataManager::getOnTheFlyPass(Pass *P, AnalysisID PI,
Function &F) {
llvm_unreachable("Unable to find on the fly pass");
}
PMDataManager::~PMDataManager() {
for (Pass *P : PassVector)
delete P;
}
Pass *AnalysisResolver::getAnalysisIfAvailable(AnalysisID ID) const {
return PM.findAnalysisPass(ID, true);
}
std::tuple<Pass *, bool>
AnalysisResolver::findImplPass(Pass *P, AnalysisID AnalysisPI, Function &F) {
return PM.getOnTheFlyPass(P, AnalysisPI, F);
}
namespace llvm {
namespace legacy {
FunctionPassManager::FunctionPassManager(Module *m) : M(m) {
FPM = new legacy::FunctionPassManagerImpl();
FPM->setTopLevelManager(FPM);
AnalysisResolver *AR = new AnalysisResolver(*FPM);
FPM->setResolver(AR);
}
FunctionPassManager::~FunctionPassManager() {
delete FPM;
}
void FunctionPassManager::add(Pass *P) {
FPM->add(P);
}
bool FunctionPassManager::run(Function &F) {
handleAllErrors(F.materialize(), [&](ErrorInfoBase &EIB) {
report_fatal_error(Twine("Error reading bitcode file: ") + EIB.message());
});
return FPM->run(F);
}
bool FunctionPassManager::doInitialization() {
return FPM->doInitialization(*M);
}
bool FunctionPassManager::doFinalization() {
return FPM->doFinalization(*M);
}
} }
void FPPassManager::cleanup() {
for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) {
FunctionPass *FP = getContainedPass(Index);
AnalysisResolver *AR = FP->getResolver();
assert(AR && "Analysis Resolver is not set");
AR->clearAnalysisImpls();
}
}
char FPPassManager::ID = 0;
void FPPassManager::dumpPassStructure(unsigned Offset) {
dbgs().indent(Offset*2) << "FunctionPass Manager\n";
for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) {
FunctionPass *FP = getContainedPass(Index);
FP->dumpPassStructure(Offset + 1);
dumpLastUses(FP, Offset+1);
}
}
bool FPPassManager::runOnFunction(Function &F) {
if (F.isDeclaration())
return false;
bool Changed = false;
Module &M = *F.getParent();
populateInheritedAnalysis(TPM->activeStack);
unsigned InstrCount, FunctionSize = 0;
StringMap<std::pair<unsigned, unsigned>> FunctionToInstrCount;
bool EmitICRemark = M.shouldEmitInstrCountChangedRemark();
if (EmitICRemark) {
InstrCount = initSizeRemarkInfo(M, FunctionToInstrCount);
FunctionSize = F.getInstructionCount();
}
llvm::TimeTraceScope FunctionScope("OptFunction", F.getName());
for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) {
FunctionPass *FP = getContainedPass(Index);
bool LocalChanged = false;
llvm::TimeTraceScope PassScope("RunPass", FP->getPassName());
dumpPassInfo(FP, EXECUTION_MSG, ON_FUNCTION_MSG, F.getName());
dumpRequiredSet(FP);
initializeAnalysisImpl(FP);
{
PassManagerPrettyStackEntry X(FP, F);
TimeRegion PassTimer(getPassTimer(FP));
#ifdef EXPENSIVE_CHECKS
uint64_t RefHash = FP->structuralHash(F);
#endif
LocalChanged |= FP->runOnFunction(F);
#if defined(EXPENSIVE_CHECKS) && !defined(NDEBUG)
if (!LocalChanged && (RefHash != FP->structuralHash(F))) {
llvm::errs() << "Pass modifies its input and doesn't report it: "
<< FP->getPassName() << "\n";
llvm_unreachable("Pass modifies its input and doesn't report it");
}
#endif
if (EmitICRemark) {
unsigned NewSize = F.getInstructionCount();
if (NewSize != FunctionSize) {
int64_t Delta = static_cast<int64_t>(NewSize) -
static_cast<int64_t>(FunctionSize);
emitInstrCountChangedRemark(FP, M, Delta, InstrCount,
FunctionToInstrCount, &F);
InstrCount = static_cast<int64_t>(InstrCount) + Delta;
FunctionSize = NewSize;
}
}
}
Changed |= LocalChanged;
if (LocalChanged)
dumpPassInfo(FP, MODIFICATION_MSG, ON_FUNCTION_MSG, F.getName());
dumpPreservedSet(FP);
dumpUsedSet(FP);
verifyPreservedAnalysis(FP);
if (LocalChanged)
removeNotPreservedAnalysis(FP);
recordAvailableAnalysis(FP);
removeDeadPasses(FP, F.getName(), ON_FUNCTION_MSG);
}
return Changed;
}
bool FPPassManager::runOnModule(Module &M) {
bool Changed = false;
for (Function &F : M)
Changed |= runOnFunction(F);
return Changed;
}
bool FPPassManager::doInitialization(Module &M) {
bool Changed = false;
for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index)
Changed |= getContainedPass(Index)->doInitialization(M);
return Changed;
}
bool FPPassManager::doFinalization(Module &M) {
bool Changed = false;
for (int Index = getNumContainedPasses() - 1; Index >= 0; --Index)
Changed |= getContainedPass(Index)->doFinalization(M);
return Changed;
}
bool
MPPassManager::runOnModule(Module &M) {
llvm::TimeTraceScope TimeScope("OptModule", M.getName());
bool Changed = false;
for (auto &OnTheFlyManager : OnTheFlyManagers) {
legacy::FunctionPassManagerImpl *FPP = OnTheFlyManager.second;
Changed |= FPP->doInitialization(M);
}
for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index)
Changed |= getContainedPass(Index)->doInitialization(M);
unsigned InstrCount;
StringMap<std::pair<unsigned, unsigned>> FunctionToInstrCount;
bool EmitICRemark = M.shouldEmitInstrCountChangedRemark();
if (EmitICRemark)
InstrCount = initSizeRemarkInfo(M, FunctionToInstrCount);
for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) {
ModulePass *MP = getContainedPass(Index);
bool LocalChanged = false;
dumpPassInfo(MP, EXECUTION_MSG, ON_MODULE_MSG, M.getModuleIdentifier());
dumpRequiredSet(MP);
initializeAnalysisImpl(MP);
{
PassManagerPrettyStackEntry X(MP, M);
TimeRegion PassTimer(getPassTimer(MP));
#ifdef EXPENSIVE_CHECKS
uint64_t RefHash = MP->structuralHash(M);
#endif
LocalChanged |= MP->runOnModule(M);
#ifdef EXPENSIVE_CHECKS
assert((LocalChanged || (RefHash == MP->structuralHash(M))) &&
"Pass modifies its input and doesn't report it.");
#endif
if (EmitICRemark) {
unsigned ModuleCount = M.getInstructionCount();
if (ModuleCount != InstrCount) {
int64_t Delta = static_cast<int64_t>(ModuleCount) -
static_cast<int64_t>(InstrCount);
emitInstrCountChangedRemark(MP, M, Delta, InstrCount,
FunctionToInstrCount);
InstrCount = ModuleCount;
}
}
}
Changed |= LocalChanged;
if (LocalChanged)
dumpPassInfo(MP, MODIFICATION_MSG, ON_MODULE_MSG,
M.getModuleIdentifier());
dumpPreservedSet(MP);
dumpUsedSet(MP);
verifyPreservedAnalysis(MP);
if (LocalChanged)
removeNotPreservedAnalysis(MP);
recordAvailableAnalysis(MP);
removeDeadPasses(MP, M.getModuleIdentifier(), ON_MODULE_MSG);
}
for (int Index = getNumContainedPasses() - 1; Index >= 0; --Index)
Changed |= getContainedPass(Index)->doFinalization(M);
for (auto &OnTheFlyManager : OnTheFlyManagers) {
legacy::FunctionPassManagerImpl *FPP = OnTheFlyManager.second;
FPP->releaseMemoryOnTheFly();
Changed |= FPP->doFinalization(M);
}
return Changed;
}
void MPPassManager::addLowerLevelRequiredPass(Pass *P, Pass *RequiredPass) {
assert(RequiredPass && "No required pass?");
assert(P->getPotentialPassManagerType() == PMT_ModulePassManager &&
"Unable to handle Pass that requires lower level Analysis pass");
assert((P->getPotentialPassManagerType() <
RequiredPass->getPotentialPassManagerType()) &&
"Unable to handle Pass that requires lower level Analysis pass");
legacy::FunctionPassManagerImpl *FPP = OnTheFlyManagers[P];
if (!FPP) {
FPP = new legacy::FunctionPassManagerImpl();
FPP->setTopLevelManager(FPP);
OnTheFlyManagers[P] = FPP;
}
const PassInfo *RequiredPassPI =
TPM->findAnalysisPassInfo(RequiredPass->getPassID());
Pass *FoundPass = nullptr;
if (RequiredPassPI && RequiredPassPI->isAnalysis()) {
FoundPass =
((PMTopLevelManager*)FPP)->findAnalysisPass(RequiredPass->getPassID());
}
if (!FoundPass) {
FoundPass = RequiredPass;
FPP->add(RequiredPass);
}
SmallVector<Pass *, 1> LU;
LU.push_back(FoundPass);
FPP->setLastUser(LU, P);
}
std::tuple<Pass *, bool> MPPassManager::getOnTheFlyPass(Pass *MP, AnalysisID PI,
Function &F) {
legacy::FunctionPassManagerImpl *FPP = OnTheFlyManagers[MP];
assert(FPP && "Unable to find on the fly pass");
FPP->releaseMemoryOnTheFly();
bool Changed = FPP->run(F);
return std::make_tuple(((PMTopLevelManager *)FPP)->findAnalysisPass(PI),
Changed);
}
namespace llvm {
namespace legacy {
PassManager::PassManager() {
PM = new PassManagerImpl();
PM->setTopLevelManager(PM);
}
PassManager::~PassManager() {
delete PM;
}
void PassManager::add(Pass *P) {
PM->add(P);
}
bool PassManager::run(Module &M) {
return PM->run(M);
}
} }
void PMStack::pop() {
PMDataManager *Top = this->top();
Top->initializeAnalysisInfo();
S.pop_back();
}
void PMStack::push(PMDataManager *PM) {
assert(PM && "Unable to push. Pass Manager expected");
assert(PM->getDepth()==0 && "Pass Manager depth set too early");
if (!this->empty()) {
assert(PM->getPassManagerType() > this->top()->getPassManagerType()
&& "pushing bad pass manager to PMStack");
PMTopLevelManager *TPM = this->top()->getTopLevelManager();
assert(TPM && "Unable to find top level manager");
TPM->addIndirectPassManager(PM);
PM->setTopLevelManager(TPM);
PM->setDepth(this->top()->getDepth()+1);
} else {
assert((PM->getPassManagerType() == PMT_ModulePassManager
|| PM->getPassManagerType() == PMT_FunctionPassManager)
&& "pushing bad pass manager to PMStack");
PM->setDepth(1);
}
S.push_back(PM);
}
LLVM_DUMP_METHOD void PMStack::dump() const {
for (PMDataManager *Manager : S)
dbgs() << Manager->getAsPass()->getPassName() << ' ';
if (!S.empty())
dbgs() << '\n';
}
void ModulePass::assignPassManager(PMStack &PMS,
PassManagerType PreferredType) {
PassManagerType T;
while ((T = PMS.top()->getPassManagerType()) > PMT_ModulePassManager &&
T != PreferredType)
PMS.pop();
PMS.top()->add(this);
}
void FunctionPass::assignPassManager(PMStack &PMS,
PassManagerType ) {
PMDataManager *PM;
while (PM = PMS.top(), PM->getPassManagerType() > PMT_FunctionPassManager)
PMS.pop();
if (PM->getPassManagerType() != PMT_FunctionPassManager) {
auto *FPP = new FPPassManager;
FPP->populateInheritedAnalysis(PMS);
PM->getTopLevelManager()->addIndirectPassManager(FPP);
FPP->assignPassManager(PMS, PM->getPassManagerType());
PMS.push(FPP);
PM = FPP;
}
PM->add(this);
}
legacy::PassManagerBase::~PassManagerBase() = default;