#include "llvm/Analysis/LoopPass.h"
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/IR/Dominators.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/OptBisect.h"
#include "llvm/IR/PassTimingInfo.h"
#include "llvm/IR/PrintPasses.h"
#include "llvm/InitializePasses.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/TimeProfiler.h"
#include "llvm/Support/Timer.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
#define DEBUG_TYPE "loop-pass-manager"
namespace {
class PrintLoopPassWrapper : public LoopPass {
raw_ostream &OS;
std::string Banner;
public:
static char ID;
PrintLoopPassWrapper() : LoopPass(ID), OS(dbgs()) {}
PrintLoopPassWrapper(raw_ostream &OS, const std::string &Banner)
: LoopPass(ID), OS(OS), Banner(Banner) {}
void getAnalysisUsage(AnalysisUsage &AU) const override {
AU.setPreservesAll();
}
bool runOnLoop(Loop *L, LPPassManager &) override {
auto BBI = llvm::find_if(L->blocks(), [](BasicBlock *BB) { return BB; });
if (BBI != L->blocks().end() &&
isFunctionInPrintList((*BBI)->getParent()->getName())) {
printLoop(*L, OS, Banner);
}
return false;
}
StringRef getPassName() const override { return "Print Loop IR"; }
};
char PrintLoopPassWrapper::ID = 0;
}
char LPPassManager::ID = 0;
LPPassManager::LPPassManager() : FunctionPass(ID) {
LI = nullptr;
CurrentLoop = nullptr;
}
void LPPassManager::addLoop(Loop &L) {
if (L.isOutermost()) {
LQ.push_front(&L);
return;
}
for (auto I = LQ.begin(), E = LQ.end(); I != E; ++I) {
if (*I == L.getParentLoop()) {
++I;
LQ.insert(I, 1, &L);
return;
}
}
}
static void addLoopIntoQueue(Loop *L, std::deque<Loop *> &LQ) {
LQ.push_back(L);
for (Loop *I : reverse(*L))
addLoopIntoQueue(I, LQ);
}
void LPPassManager::getAnalysisUsage(AnalysisUsage &Info) const {
Info.addRequired<LoopInfoWrapperPass>();
Info.addRequired<DominatorTreeWrapperPass>();
Info.setPreservesAll();
}
void LPPassManager::markLoopAsDeleted(Loop &L) {
assert((&L == CurrentLoop || CurrentLoop->contains(&L)) &&
"Must not delete loop outside the current loop tree!");
assert(LQ.back() == CurrentLoop && "Loop queue back isn't the current loop!");
llvm::erase_value(LQ, &L);
if (&L == CurrentLoop) {
CurrentLoopDeleted = true;
LQ.push_back(&L);
}
}
bool LPPassManager::runOnFunction(Function &F) {
auto &LIWP = getAnalysis<LoopInfoWrapperPass>();
LI = &LIWP.getLoopInfo();
Module &M = *F.getParent();
#if 0#endif
bool Changed = false;
populateInheritedAnalysis(TPM->activeStack);
for (Loop *L : reverse(*LI))
addLoopIntoQueue(L, LQ);
if (LQ.empty()) return false;
for (Loop *L : LQ) {
for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) {
LoopPass *P = getContainedPass(Index);
Changed |= P->doInitialization(L, *this);
}
}
unsigned InstrCount, FunctionSize = 0;
StringMap<std::pair<unsigned, unsigned>> FunctionToInstrCount;
bool EmitICRemark = M.shouldEmitInstrCountChangedRemark();
if (EmitICRemark) {
InstrCount = initSizeRemarkInfo(M, FunctionToInstrCount);
FunctionSize = F.getInstructionCount();
}
while (!LQ.empty()) {
CurrentLoopDeleted = false;
CurrentLoop = LQ.back();
for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) {
LoopPass *P = getContainedPass(Index);
llvm::TimeTraceScope LoopPassScope("RunLoopPass", P->getPassName());
dumpPassInfo(P, EXECUTION_MSG, ON_LOOP_MSG,
CurrentLoop->getHeader()->getName());
dumpRequiredSet(P);
initializeAnalysisImpl(P);
bool LocalChanged = false;
{
PassManagerPrettyStackEntry X(P, *CurrentLoop->getHeader());
TimeRegion PassTimer(getPassTimer(P));
#ifdef EXPENSIVE_CHECKS
uint64_t RefHash = P->structuralHash(F);
#endif
LocalChanged = P->runOnLoop(CurrentLoop, *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 (EmitICRemark) {
unsigned NewSize = F.getInstructionCount();
if (NewSize != FunctionSize) {
int64_t Delta = static_cast<int64_t>(NewSize) -
static_cast<int64_t>(FunctionSize);
emitInstrCountChangedRemark(P, M, Delta, InstrCount,
FunctionToInstrCount, &F);
InstrCount = static_cast<int64_t>(InstrCount) + Delta;
FunctionSize = NewSize;
}
}
}
if (LocalChanged)
dumpPassInfo(P, MODIFICATION_MSG, ON_LOOP_MSG,
CurrentLoopDeleted ? "<deleted loop>"
: CurrentLoop->getName());
dumpPreservedSet(P);
if (!CurrentLoopDeleted) {
{
TimeRegion PassTimer(getPassTimer(&LIWP));
CurrentLoop->verifyLoop();
}
#if 0#endif
verifyPreservedAnalysis(P);
F.getContext().yield();
}
if (LocalChanged)
removeNotPreservedAnalysis(P);
recordAvailableAnalysis(P);
removeDeadPasses(P,
CurrentLoopDeleted ? "<deleted>"
: CurrentLoop->getHeader()->getName(),
ON_LOOP_MSG);
if (CurrentLoopDeleted)
break;
}
if (CurrentLoopDeleted) {
for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) {
Pass *P = getContainedPass(Index);
freePass(P, "<deleted>", ON_LOOP_MSG);
}
}
LQ.pop_back();
}
for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) {
LoopPass *P = getContainedPass(Index);
Changed |= P->doFinalization();
}
return Changed;
}
void LPPassManager::dumpPassStructure(unsigned Offset) {
errs().indent(Offset*2) << "Loop Pass Manager\n";
for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) {
Pass *P = getContainedPass(Index);
P->dumpPassStructure(Offset + 1);
dumpLastUses(P, Offset+1);
}
}
Pass *LoopPass::createPrinterPass(raw_ostream &O,
const std::string &Banner) const {
return new PrintLoopPassWrapper(O, Banner);
}
void LoopPass::preparePassManager(PMStack &PMS) {
while (!PMS.empty() &&
PMS.top()->getPassManagerType() > PMT_LoopPassManager)
PMS.pop();
if (PMS.top()->getPassManagerType() == PMT_LoopPassManager &&
!PMS.top()->preserveHigherLevelAnalysis(this))
PMS.pop();
}
void LoopPass::assignPassManager(PMStack &PMS,
PassManagerType PreferredType) {
while (!PMS.empty() &&
PMS.top()->getPassManagerType() > PMT_LoopPassManager)
PMS.pop();
LPPassManager *LPPM;
if (PMS.top()->getPassManagerType() == PMT_LoopPassManager)
LPPM = (LPPassManager*)PMS.top();
else {
assert (!PMS.empty() && "Unable to create Loop Pass Manager");
PMDataManager *PMD = PMS.top();
LPPM = new LPPassManager();
LPPM->populateInheritedAnalysis(PMS);
PMTopLevelManager *TPM = PMD->getTopLevelManager();
TPM->addIndirectPassManager(LPPM);
Pass *P = LPPM->getAsPass();
TPM->schedulePass(P);
PMS.push(LPPM);
}
LPPM->add(this);
}
static std::string getDescription(const Loop &L) {
return "loop";
}
bool LoopPass::skipLoop(const Loop *L) const {
const Function *F = L->getHeader()->getParent();
if (!F)
return false;
OptPassGate &Gate = F->getContext().getOptPassGate();
if (Gate.isEnabled() && !Gate.shouldRunPass(this, getDescription(*L)))
return true;
if (F->hasOptNone()) {
LLVM_DEBUG(dbgs() << "Skipping pass '" << getPassName() << "' in function "
<< F->getName() << "\n");
return true;
}
return false;
}
LCSSAVerificationPass::LCSSAVerificationPass() : FunctionPass(ID) {
initializeLCSSAVerificationPassPass(*PassRegistry::getPassRegistry());
}
char LCSSAVerificationPass::ID = 0;
INITIALIZE_PASS(LCSSAVerificationPass, "lcssa-verification", "LCSSA Verifier",
false, false)