#include "llvm/Analysis/LoopPass.h"
#include "llvm/DebugInfoProbe.h"
#include "llvm/Assembly/PrintModulePass.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/Timer.h"
using namespace llvm;
namespace {
class PrintLoopPass : public LoopPass {
private:
std::string Banner;
raw_ostream &Out;
public:
static char ID;
PrintLoopPass(const std::string &B, raw_ostream &o)
: LoopPass(ID), Banner(B), Out(o) {}
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
AU.setPreservesAll();
}
bool runOnLoop(Loop *L, LPPassManager &) {
Out << Banner;
for (Loop::block_iterator b = L->block_begin(), be = L->block_end();
b != be;
++b) {
(*b)->print(Out);
}
return false;
}
};
char PrintLoopPass::ID = 0;
}
static DebugInfoProbeInfo *TheDebugProbe;
static void createDebugInfoProbe() {
if (TheDebugProbe) return;
static ManagedStatic<DebugInfoProbeInfo> DIP;
TheDebugProbe = &*DIP;
}
char LPPassManager::ID = 0;
LPPassManager::LPPassManager()
: FunctionPass(ID), PMDataManager() {
skipThisLoop = false;
redoThisLoop = false;
LI = NULL;
CurrentLoop = NULL;
}
void LPPassManager::deleteLoopFromQueue(Loop *L) {
LI->updateUnloop(L);
if (CurrentLoop == L)
skipThisLoop = true;
delete L;
if (skipThisLoop)
return;
for (std::deque<Loop *>::iterator I = LQ.begin(),
E = LQ.end(); I != E; ++I) {
if (*I == L) {
LQ.erase(I);
break;
}
}
}
void LPPassManager::insertLoop(Loop *L, Loop *ParentLoop) {
assert (CurrentLoop != L && "Cannot insert CurrentLoop");
if (ParentLoop)
ParentLoop->addChildLoop(L);
else
LI->addTopLevelLoop(L);
insertLoopIntoQueue(L);
}
void LPPassManager::insertLoopIntoQueue(Loop *L) {
if (L == CurrentLoop)
redoLoop(L);
else if (!L->getParentLoop())
LQ.push_front(L);
else {
for (std::deque<Loop *>::iterator I = LQ.begin(),
E = LQ.end(); I != E; ++I) {
if (*I == L->getParentLoop()) {
++I;
LQ.insert(I, 1, L);
break;
}
}
}
}
void LPPassManager::redoLoop(Loop *L) {
assert (CurrentLoop == L && "Can redo only CurrentLoop");
redoThisLoop = true;
}
void LPPassManager::cloneBasicBlockSimpleAnalysis(BasicBlock *From,
BasicBlock *To, Loop *L) {
for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) {
LoopPass *LP = getContainedPass(Index);
LP->cloneBasicBlockAnalysis(From, To, L);
}
}
void LPPassManager::deleteSimpleAnalysisValue(Value *V, Loop *L) {
if (BasicBlock *BB = dyn_cast<BasicBlock>(V)) {
for (BasicBlock::iterator BI = BB->begin(), BE = BB->end(); BI != BE;
++BI) {
Instruction &I = *BI;
deleteSimpleAnalysisValue(&I, L);
}
}
for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) {
LoopPass *LP = getContainedPass(Index);
LP->deleteAnalysisValue(V, L);
}
}
static void addLoopIntoQueue(Loop *L, std::deque<Loop *> &LQ) {
LQ.push_back(L);
for (Loop::iterator I = L->begin(), E = L->end(); I != E; ++I)
addLoopIntoQueue(*I, LQ);
}
void LPPassManager::getAnalysisUsage(AnalysisUsage &Info) const {
Info.addRequired<LoopInfo>();
Info.setPreservesAll();
}
bool LPPassManager::runOnFunction(Function &F) {
LI = &getAnalysis<LoopInfo>();
bool Changed = false;
createDebugInfoProbe();
populateInheritedAnalysis(TPM->activeStack);
for (LoopInfo::iterator I = LI->begin(), E = LI->end(); I != E; ++I)
addLoopIntoQueue(*I, LQ);
if (LQ.empty()) return false;
for (std::deque<Loop *>::const_iterator I = LQ.begin(), E = LQ.end();
I != E; ++I) {
Loop *L = *I;
for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) {
LoopPass *P = getContainedPass(Index);
Changed |= P->doInitialization(L, *this);
}
}
while (!LQ.empty()) {
CurrentLoop = LQ.back();
skipThisLoop = false;
redoThisLoop = false;
for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) {
LoopPass *P = getContainedPass(Index);
dumpPassInfo(P, EXECUTION_MSG, ON_LOOP_MSG,
CurrentLoop->getHeader()->getName());
dumpRequiredSet(P);
initializeAnalysisImpl(P);
if (TheDebugProbe)
TheDebugProbe->initialize(P, F);
{
PassManagerPrettyStackEntry X(P, *CurrentLoop->getHeader());
TimeRegion PassTimer(getPassTimer(P));
Changed |= P->runOnLoop(CurrentLoop, *this);
}
if (TheDebugProbe)
TheDebugProbe->finalize(P, F);
if (Changed)
dumpPassInfo(P, MODIFICATION_MSG, ON_LOOP_MSG,
skipThisLoop ? "<deleted>" :
CurrentLoop->getHeader()->getName());
dumpPreservedSet(P);
if (!skipThisLoop) {
{
TimeRegion PassTimer(getPassTimer(LI));
CurrentLoop->verifyLoop();
}
verifyPreservedAnalysis(P);
}
removeNotPreservedAnalysis(P);
recordAvailableAnalysis(P);
removeDeadPasses(P,
skipThisLoop ? "<deleted>" :
CurrentLoop->getHeader()->getName(),
ON_LOOP_MSG);
if (skipThisLoop)
break;
}
if (skipThisLoop)
for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) {
Pass *P = getContainedPass(Index);
freePass(P, "<deleted>", ON_LOOP_MSG);
}
LQ.pop_back();
if (redoThisLoop)
LQ.push_back(CurrentLoop);
}
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 PrintLoopPass(Banner, O);
}
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);
}