2018-03-21 01:09:21 +08:00
|
|
|
//===- MustExecute.cpp - Printer for isGuaranteedToExecute ----------------===//
|
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "llvm/Analysis/LoopInfo.h"
|
|
|
|
#include "llvm/Analysis/Passes.h"
|
|
|
|
#include "llvm/Analysis/ValueTracking.h"
|
2018-03-21 02:43:44 +08:00
|
|
|
#include "llvm/IR/AssemblyAnnotationWriter.h"
|
2018-03-21 01:09:21 +08:00
|
|
|
#include "llvm/IR/DataLayout.h"
|
|
|
|
#include "llvm/IR/InstIterator.h"
|
|
|
|
#include "llvm/IR/LLVMContext.h"
|
|
|
|
#include "llvm/IR/Module.h"
|
|
|
|
#include "llvm/Support/ErrorHandling.h"
|
2018-03-21 02:43:44 +08:00
|
|
|
#include "llvm/Support/FormattedStream.h"
|
2018-03-21 01:09:21 +08:00
|
|
|
#include "llvm/Support/raw_ostream.h"
|
|
|
|
#include "llvm/Transforms/Utils/LoopUtils.h"
|
|
|
|
using namespace llvm;
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
struct MustExecutePrinter : public FunctionPass {
|
|
|
|
|
|
|
|
static char ID; // Pass identification, replacement for typeid
|
|
|
|
MustExecutePrinter() : FunctionPass(ID) {
|
|
|
|
initializeMustExecutePrinterPass(*PassRegistry::getPassRegistry());
|
|
|
|
}
|
|
|
|
void getAnalysisUsage(AnalysisUsage &AU) const override {
|
|
|
|
AU.setPreservesAll();
|
|
|
|
AU.addRequired<DominatorTreeWrapperPass>();
|
|
|
|
AU.addRequired<LoopInfoWrapperPass>();
|
|
|
|
}
|
|
|
|
bool runOnFunction(Function &F) override;
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
char MustExecutePrinter::ID = 0;
|
|
|
|
INITIALIZE_PASS_BEGIN(MustExecutePrinter, "print-mustexecute",
|
|
|
|
"Instructions which execute on loop entry", false, true)
|
|
|
|
INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
|
|
|
|
INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass)
|
|
|
|
INITIALIZE_PASS_END(MustExecutePrinter, "print-mustexecute",
|
|
|
|
"Instructions which execute on loop entry", false, true)
|
|
|
|
|
|
|
|
FunctionPass *llvm::createMustExecutePrinter() {
|
|
|
|
return new MustExecutePrinter();
|
|
|
|
}
|
|
|
|
|
2018-03-21 02:43:44 +08:00
|
|
|
bool isMustExecuteIn(const Instruction &I, Loop *L, DominatorTree *DT) {
|
2018-03-21 01:09:21 +08:00
|
|
|
// TODO: move loop specific code to analysis
|
|
|
|
//LoopSafetyInfo LSI;
|
|
|
|
//computeLoopSafetyInfo(&LSI, L);
|
|
|
|
//return isGuaranteedToExecute(I, DT, L, &LSI);
|
|
|
|
return isGuaranteedToExecuteForEveryIteration(&I, L);
|
|
|
|
}
|
|
|
|
|
2018-03-21 02:43:44 +08:00
|
|
|
/// \brief An assembly annotator class to print must execute information in
|
|
|
|
/// comments.
|
|
|
|
class MustExecuteAnnotatedWriter : public AssemblyAnnotationWriter {
|
|
|
|
DenseMap<const Value*, SmallVector<Loop*, 4> > MustExec;
|
|
|
|
|
|
|
|
public:
|
|
|
|
MustExecuteAnnotatedWriter(const Function &F,
|
|
|
|
DominatorTree &DT, LoopInfo &LI) {
|
|
|
|
for (auto &I: instructions(F)) {
|
|
|
|
Loop *L = LI.getLoopFor(I.getParent());
|
|
|
|
while (L) {
|
|
|
|
if (isMustExecuteIn(I, L, &DT)) {
|
|
|
|
MustExec[&I].push_back(L);
|
|
|
|
}
|
|
|
|
L = L->getParentLoop();
|
|
|
|
};
|
|
|
|
}
|
2018-03-21 01:09:21 +08:00
|
|
|
}
|
2018-03-21 02:43:44 +08:00
|
|
|
MustExecuteAnnotatedWriter(const Module &M,
|
|
|
|
DominatorTree &DT, LoopInfo &LI) {
|
|
|
|
for (auto &F : M)
|
|
|
|
for (auto &I: instructions(F)) {
|
|
|
|
Loop *L = LI.getLoopFor(I.getParent());
|
|
|
|
while (L) {
|
|
|
|
if (isMustExecuteIn(I, L, &DT)) {
|
|
|
|
MustExec[&I].push_back(L);
|
|
|
|
}
|
|
|
|
L = L->getParentLoop();
|
|
|
|
};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void printInfoComment(const Value &V, formatted_raw_ostream &OS) override {
|
|
|
|
if (!MustExec.count(&V))
|
|
|
|
return;
|
2018-03-21 01:09:21 +08:00
|
|
|
|
2018-03-21 02:43:44 +08:00
|
|
|
const auto &Loops = MustExec.lookup(&V);
|
|
|
|
const auto NumLoops = Loops.size();
|
2018-03-21 01:09:21 +08:00
|
|
|
if (NumLoops > 1)
|
2018-03-21 02:43:44 +08:00
|
|
|
OS << " ; (mustexec in " << NumLoops << " loops: ";
|
2018-03-21 01:09:21 +08:00
|
|
|
else
|
2018-03-21 02:43:44 +08:00
|
|
|
OS << " ; (mustexec in: ";
|
2018-03-21 01:09:21 +08:00
|
|
|
|
|
|
|
bool first = true;
|
2018-03-21 02:43:44 +08:00
|
|
|
for (const Loop *L : Loops) {
|
2018-03-21 01:09:21 +08:00
|
|
|
if (!first)
|
|
|
|
OS << ", ";
|
|
|
|
first = false;
|
|
|
|
OS << L->getHeader()->getName();
|
|
|
|
}
|
2018-03-21 02:43:44 +08:00
|
|
|
OS << ")";
|
2018-03-21 01:09:21 +08:00
|
|
|
}
|
2018-03-21 02:43:44 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
bool MustExecutePrinter::runOnFunction(Function &F) {
|
|
|
|
auto &LI = getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
|
|
|
|
auto &DT = getAnalysis<DominatorTreeWrapperPass>().getDomTree();
|
|
|
|
|
|
|
|
MustExecuteAnnotatedWriter Writer(F, DT, LI);
|
|
|
|
F.print(dbgs(), &Writer);
|
|
|
|
|
|
|
|
return false;
|
2018-03-21 01:09:21 +08:00
|
|
|
}
|