#include "llvm/Analysis/RegionPass.h"
#include "llvm/Analysis/RegionInfo.h"
#include "llvm/IR/OptBisect.h"
#include "llvm/IR/PassTimingInfo.h"
#include "llvm/IR/PrintPasses.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/Timer.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
#define DEBUG_TYPE "regionpassmgr"
char RGPassManager::ID = 0;
RGPassManager::RGPassManager() : FunctionPass(ID) {
RI = nullptr;
CurrentRegion = nullptr;
}
static void addRegionIntoQueue(Region &R, std::deque<Region *> &RQ) {
RQ.push_back(&R);
for (const auto &E : R)
addRegionIntoQueue(*E, RQ);
}
void RGPassManager::getAnalysisUsage(AnalysisUsage &Info) const {
Info.addRequired<RegionInfoPass>();
Info.setPreservesAll();
}
bool RGPassManager::runOnFunction(Function &F) {
RI = &getAnalysis<RegionInfoPass>().getRegionInfo();
bool Changed = false;
populateInheritedAnalysis(TPM->activeStack);
addRegionIntoQueue(*RI->getTopLevelRegion(), RQ);
if (RQ.empty()) return false;
for (Region *R : RQ) {
for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) {
RegionPass *RP = (RegionPass *)getContainedPass(Index);
Changed |= RP->doInitialization(R, *this);
}
}
while (!RQ.empty()) {
CurrentRegion = RQ.back();
for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) {
RegionPass *P = (RegionPass*)getContainedPass(Index);
if (isPassDebuggingExecutionsOrMore()) {
dumpPassInfo(P, EXECUTION_MSG, ON_REGION_MSG,
CurrentRegion->getNameStr());
dumpRequiredSet(P);
}
initializeAnalysisImpl(P);
bool LocalChanged = false;
{
PassManagerPrettyStackEntry X(P, *CurrentRegion->getEntry());
TimeRegion PassTimer(getPassTimer(P));
#ifdef EXPENSIVE_CHECKS
uint64_t RefHash = P->structuralHash(F);
#endif
LocalChanged = P->runOnRegion(CurrentRegion, *this);
#ifdef EXPENSIVE_CHECKS
if (!LocalChanged && (RefHash != P->structuralHash(F))) {
llvm::errs() << "Pass modifies its input and doesn't report it: "
<< P->getPassName() << "\n";
llvm_unreachable("Pass modifies its input and doesn't report it");
}
#endif
Changed |= LocalChanged;
}
if (isPassDebuggingExecutionsOrMore()) {
if (LocalChanged)
dumpPassInfo(P, MODIFICATION_MSG, ON_REGION_MSG,
CurrentRegion->getNameStr());
dumpPreservedSet(P);
}
{
TimeRegion PassTimer(getPassTimer(P));
CurrentRegion->verifyRegion();
}
verifyPreservedAnalysis(P);
if (LocalChanged)
removeNotPreservedAnalysis(P);
recordAvailableAnalysis(P);
removeDeadPasses(P,
(!isPassDebuggingExecutionsOrMore())
? "<deleted>"
: CurrentRegion->getNameStr(),
ON_REGION_MSG);
}
RQ.pop_back();
RI->clearNodeCache();
}
for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) {
RegionPass *P = (RegionPass*)getContainedPass(Index);
Changed |= P->doFinalization();
}
LLVM_DEBUG(dbgs() << "\nRegion tree of function " << F.getName()
<< " after all region Pass:\n";
RI->dump(); dbgs() << "\n";);
return Changed;
}
void RGPassManager::dumpPassStructure(unsigned Offset) {
errs().indent(Offset*2) << "Region Pass Manager\n";
for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) {
Pass *P = getContainedPass(Index);
P->dumpPassStructure(Offset + 1);
dumpLastUses(P, Offset+1);
}
}
namespace {
class PrintRegionPass : public RegionPass {
private:
std::string Banner;
raw_ostream &Out;
public:
static char ID;
PrintRegionPass(const std::string &B, raw_ostream &o)
: RegionPass(ID), Banner(B), Out(o) {}
void getAnalysisUsage(AnalysisUsage &AU) const override {
AU.setPreservesAll();
}
bool runOnRegion(Region *R, RGPassManager &RGM) override {
if (!isFunctionInPrintList(R->getEntry()->getParent()->getName()))
return false;
Out << Banner;
for (const auto *BB : R->blocks()) {
if (BB)
BB->print(Out);
else
Out << "Printing <null> Block";
}
return false;
}
StringRef getPassName() const override { return "Print Region IR"; }
};
char PrintRegionPass::ID = 0;
}
void RegionPass::preparePassManager(PMStack &PMS) {
while (!PMS.empty() &&
PMS.top()->getPassManagerType() > PMT_RegionPassManager)
PMS.pop();
if (PMS.top()->getPassManagerType() == PMT_RegionPassManager &&
!PMS.top()->preserveHigherLevelAnalysis(this))
PMS.pop();
}
void RegionPass::assignPassManager(PMStack &PMS,
PassManagerType PreferredType) {
while (!PMS.empty() &&
PMS.top()->getPassManagerType() > PMT_RegionPassManager)
PMS.pop();
RGPassManager *RGPM;
if (PMS.top()->getPassManagerType() == PMT_RegionPassManager)
RGPM = (RGPassManager*)PMS.top();
else {
assert (!PMS.empty() && "Unable to create Region Pass Manager");
PMDataManager *PMD = PMS.top();
RGPM = new RGPassManager();
RGPM->populateInheritedAnalysis(PMS);
PMTopLevelManager *TPM = PMD->getTopLevelManager();
TPM->addIndirectPassManager(RGPM);
TPM->schedulePass(RGPM);
PMS.push(RGPM);
}
RGPM->add(this);
}
Pass *RegionPass::createPrinterPass(raw_ostream &O,
const std::string &Banner) const {
return new PrintRegionPass(Banner, O);
}
static std::string getDescription(const Region &R) {
return "region";
}
bool RegionPass::skipRegion(Region &R) const {
Function &F = *R.getEntry()->getParent();
OptPassGate &Gate = F.getContext().getOptPassGate();
if (Gate.isEnabled() && !Gate.shouldRunPass(this, getDescription(R)))
return true;
if (F.hasOptNone()) {
if (R.getEntry() == &F.getEntryBlock())
LLVM_DEBUG(dbgs() << "Skipping pass '" << getPassName()
<< "' on function " << F.getName() << "\n");
return true;
}
return false;
}