forked from OSchip/llvm-project
[Polly] Add support for -polly-dump-before(-file) with the NPM.
Only supported with -polly-position=early. Unfortunately, the extension point callpack for VectorizerStart only passes a FunctionPassManager, making it impossible to add a module pass.
This commit is contained in:
parent
9f7d552cff
commit
29bef8e4e3
|
@ -99,7 +99,7 @@ struct PollyForcePassLinking {
|
|||
polly::createFlattenSchedulePass();
|
||||
polly::createForwardOpTreeWrapperPass();
|
||||
polly::createDeLICMWrapperPass();
|
||||
polly::createDumpModulePass("", true);
|
||||
polly::createDumpModuleWrapperPass("", true);
|
||||
polly::createSimplifyWrapperPass(0);
|
||||
polly::createPruneUnprofitableWrapperPass();
|
||||
}
|
||||
|
|
|
@ -13,8 +13,10 @@
|
|||
#ifndef POLLY_SUPPORT_DUMPMODULEPASS_H
|
||||
#define POLLY_SUPPORT_DUMPMODULEPASS_H
|
||||
|
||||
#include "llvm/IR/PassManager.h"
|
||||
#include <string>
|
||||
|
||||
namespace llvm {
|
||||
class StringRef;
|
||||
class ModulePass;
|
||||
} // namespace llvm
|
||||
|
||||
|
@ -28,12 +30,25 @@ namespace polly {
|
|||
/// The intent of IsSuffix is to avoid the file being overwritten when
|
||||
/// processing multiple modules and/or with multiple dump passes in the
|
||||
/// pipeline.
|
||||
llvm::ModulePass *createDumpModulePass(llvm::StringRef Filename, bool IsSuffix);
|
||||
llvm::ModulePass *createDumpModuleWrapperPass(std::string Filename,
|
||||
bool IsSuffix);
|
||||
|
||||
/// A pass that prints the module into a file.
|
||||
struct DumpModulePass : llvm::PassInfoMixin<DumpModulePass> {
|
||||
std::string Filename;
|
||||
bool IsSuffix;
|
||||
|
||||
DumpModulePass(std::string Filename, bool IsSuffix)
|
||||
: Filename(std::move(Filename)), IsSuffix(IsSuffix) {}
|
||||
|
||||
llvm::PreservedAnalyses run(llvm::Module &M, llvm::ModuleAnalysisManager &AM);
|
||||
};
|
||||
|
||||
} // namespace polly
|
||||
|
||||
namespace llvm {
|
||||
class PassRegistry;
|
||||
void initializeDumpModulePass(llvm::PassRegistry &);
|
||||
void initializeDumpModuleWrapperPassPass(llvm::PassRegistry &);
|
||||
} // namespace llvm
|
||||
|
||||
#endif /* POLLY_SUPPORT_DUMPMODULEPASS_H */
|
||||
|
|
|
@ -25,10 +25,34 @@ using namespace polly;
|
|||
|
||||
namespace {
|
||||
|
||||
class DumpModule : public ModulePass {
|
||||
static void runDumpModule(llvm::Module &M, StringRef Filename, bool IsSuffix) {
|
||||
std::string Dumpfile;
|
||||
if (IsSuffix) {
|
||||
StringRef ModuleName = M.getName();
|
||||
StringRef Stem = sys::path::stem(ModuleName);
|
||||
Dumpfile = (Twine(Stem) + Filename + ".ll").str();
|
||||
} else {
|
||||
Dumpfile = Filename.str();
|
||||
}
|
||||
LLVM_DEBUG(dbgs() << "Dumping module to " << Dumpfile << '\n');
|
||||
|
||||
std::unique_ptr<ToolOutputFile> Out;
|
||||
std::error_code EC;
|
||||
Out.reset(new ToolOutputFile(Dumpfile, EC, sys::fs::OF_None));
|
||||
if (EC) {
|
||||
errs() << EC.message() << '\n';
|
||||
return;
|
||||
}
|
||||
|
||||
M.print(Out->os(), nullptr);
|
||||
Out->keep();
|
||||
}
|
||||
|
||||
class DumpModuleWrapperPass : public ModulePass {
|
||||
private:
|
||||
DumpModule(const DumpModule &) = delete;
|
||||
const DumpModule &operator=(const DumpModule &) = delete;
|
||||
DumpModuleWrapperPass(const DumpModuleWrapperPass &) = delete;
|
||||
const DumpModuleWrapperPass &
|
||||
operator=(const DumpModuleWrapperPass &) = delete;
|
||||
|
||||
std::string Filename;
|
||||
bool IsSuffix;
|
||||
|
@ -39,10 +63,11 @@ public:
|
|||
/// This constructor is used e.g. if using opt -polly-dump-module.
|
||||
///
|
||||
/// Provide a default suffix to not overwrite the original file.
|
||||
explicit DumpModule() : ModulePass(ID), Filename("-dump"), IsSuffix(true) {}
|
||||
explicit DumpModuleWrapperPass()
|
||||
: ModulePass(ID), Filename("-dump"), IsSuffix(true) {}
|
||||
|
||||
explicit DumpModule(llvm::StringRef Filename, bool IsSuffix)
|
||||
: ModulePass(ID), Filename(Filename), IsSuffix(IsSuffix) {}
|
||||
explicit DumpModuleWrapperPass(std::string Filename, bool IsSuffix)
|
||||
: ModulePass(ID), Filename(std::move(Filename)), IsSuffix(IsSuffix) {}
|
||||
|
||||
/// @name ModulePass interface
|
||||
//@{
|
||||
|
@ -51,41 +76,27 @@ public:
|
|||
}
|
||||
|
||||
virtual bool runOnModule(llvm::Module &M) override {
|
||||
std::string Dumpfile;
|
||||
if (IsSuffix) {
|
||||
auto ModuleName = M.getName();
|
||||
auto Stem = sys::path::stem(ModuleName);
|
||||
Dumpfile = (Twine(Stem) + Filename + ".ll").str();
|
||||
} else {
|
||||
Dumpfile = Filename;
|
||||
}
|
||||
LLVM_DEBUG(dbgs() << "Dumping module to " << Dumpfile << '\n');
|
||||
|
||||
std::unique_ptr<ToolOutputFile> Out;
|
||||
std::error_code EC;
|
||||
Out.reset(new ToolOutputFile(Dumpfile, EC, sys::fs::OF_None));
|
||||
if (EC) {
|
||||
errs() << EC.message() << '\n';
|
||||
return false;
|
||||
}
|
||||
|
||||
M.print(Out->os(), nullptr);
|
||||
Out->keep();
|
||||
|
||||
runDumpModule(M, Filename, IsSuffix);
|
||||
return false;
|
||||
}
|
||||
//@}
|
||||
};
|
||||
|
||||
char DumpModule::ID;
|
||||
char DumpModuleWrapperPass::ID;
|
||||
} // namespace
|
||||
|
||||
ModulePass *polly::createDumpModulePass(llvm::StringRef Filename,
|
||||
bool IsSuffix) {
|
||||
return new DumpModule(Filename, IsSuffix);
|
||||
ModulePass *polly::createDumpModuleWrapperPass(std::string Filename,
|
||||
bool IsSuffix) {
|
||||
return new DumpModuleWrapperPass(std::move(Filename), IsSuffix);
|
||||
}
|
||||
|
||||
INITIALIZE_PASS_BEGIN(DumpModule, "polly-dump-module", "Polly - Dump Module",
|
||||
false, false)
|
||||
INITIALIZE_PASS_END(DumpModule, "polly-dump-module", "Polly - Dump Module",
|
||||
false, false)
|
||||
llvm::PreservedAnalyses DumpModulePass::run(llvm::Module &M,
|
||||
llvm::ModuleAnalysisManager &AM) {
|
||||
runDumpModule(M, Filename, IsSuffix);
|
||||
return PreservedAnalyses::all();
|
||||
}
|
||||
|
||||
INITIALIZE_PASS_BEGIN(DumpModuleWrapperPass, "polly-dump-module",
|
||||
"Polly - Dump Module", false, false)
|
||||
INITIALIZE_PASS_END(DumpModuleWrapperPass, "polly-dump-module",
|
||||
"Polly - Dump Module", false, false)
|
||||
|
|
|
@ -269,7 +269,7 @@ void initializePollyPasses(PassRegistry &Registry) {
|
|||
initializeForwardOpTreeWrapperPassPass(Registry);
|
||||
initializeDeLICMWrapperPassPass(Registry);
|
||||
initializeSimplifyWrapperPassPass(Registry);
|
||||
initializeDumpModulePass(Registry);
|
||||
initializeDumpModuleWrapperPassPass(Registry);
|
||||
initializePruneUnprofitableWrapperPassPass(Registry);
|
||||
}
|
||||
|
||||
|
@ -302,10 +302,11 @@ void initializePollyPasses(PassRegistry &Registry) {
|
|||
static void registerPollyPasses(llvm::legacy::PassManagerBase &PM,
|
||||
bool EnableForOpt) {
|
||||
if (DumpBefore)
|
||||
PM.add(polly::createDumpModulePass("-before", true));
|
||||
PM.add(polly::createDumpModuleWrapperPass("-before", true));
|
||||
for (auto &Filename : DumpBeforeFile)
|
||||
PM.add(polly::createDumpModulePass(Filename, false));
|
||||
PM.add(polly::createDumpModuleWrapperPass(Filename, false));
|
||||
|
||||
PM.add(polly::createCodePreparationPass());
|
||||
PM.add(polly::createScopDetectionWrapperPassPass());
|
||||
|
||||
if (PollyDetectOnly)
|
||||
|
@ -397,9 +398,9 @@ static void registerPollyPasses(llvm::legacy::PassManagerBase &PM,
|
|||
PM.add(createBarrierNoopPass());
|
||||
|
||||
if (DumpAfter)
|
||||
PM.add(polly::createDumpModulePass("-after", true));
|
||||
PM.add(polly::createDumpModuleWrapperPass("-after", true));
|
||||
for (auto &Filename : DumpAfterFile)
|
||||
PM.add(polly::createDumpModulePass(Filename, false));
|
||||
PM.add(polly::createDumpModuleWrapperPass(Filename, false));
|
||||
|
||||
if (CFGPrinter)
|
||||
PM.add(llvm::createCFGPrinterLegacyPassPass());
|
||||
|
@ -429,7 +430,6 @@ registerPollyEarlyAsPossiblePasses(const llvm::PassManagerBuilder &Builder,
|
|||
return;
|
||||
|
||||
registerCanonicalicationPasses(PM);
|
||||
PM.add(polly::createCodePreparationPass());
|
||||
registerPollyPasses(PM, EnableForOpt);
|
||||
}
|
||||
|
||||
|
@ -444,7 +444,6 @@ registerPollyLoopOptimizerEndPasses(const llvm::PassManagerBuilder &Builder,
|
|||
if (!shouldEnablePollyForDiagnostic() && !EnableForOpt)
|
||||
return;
|
||||
|
||||
PM.add(polly::createCodePreparationPass());
|
||||
registerPollyPasses(PM, EnableForOpt);
|
||||
if (EnableForOpt)
|
||||
PM.add(createCodegenCleanupPass());
|
||||
|
@ -461,7 +460,6 @@ registerPollyScalarOptimizerLatePasses(const llvm::PassManagerBuilder &Builder,
|
|||
if (!shouldEnablePollyForDiagnostic() && !EnableForOpt)
|
||||
return;
|
||||
|
||||
PM.add(polly::createCodePreparationPass());
|
||||
polly::registerPollyPasses(PM, EnableForOpt);
|
||||
if (EnableForOpt)
|
||||
PM.add(createCodegenCleanupPass());
|
||||
|
@ -485,12 +483,6 @@ static void buildCommonPollyPipeline(FunctionPassManager &PM,
|
|||
|
||||
// TODO add utility passes for the various command line options, once they're
|
||||
// ported
|
||||
if (DumpBefore)
|
||||
report_fatal_error("Option -polly-dump-before not supported with NPM",
|
||||
false);
|
||||
if (!DumpBeforeFile.empty())
|
||||
report_fatal_error("Option -polly-dump-before-file not supported with NPM",
|
||||
false);
|
||||
|
||||
if (PollyDetectOnly) {
|
||||
// Don't add more passes other than the ScopPassManager's detection passes.
|
||||
|
@ -597,12 +589,16 @@ static void buildEarlyPollyPipeline(ModulePassManager &MPM,
|
|||
|
||||
FunctionPassManager FPM = buildCanonicalicationPassesForNPM(MPM, Level);
|
||||
|
||||
if (DumpBefore)
|
||||
report_fatal_error("Option -polly-dump-before not supported with NPM",
|
||||
false);
|
||||
if (!DumpBeforeFile.empty())
|
||||
report_fatal_error("Option -polly-dump-before-file not supported with NPM",
|
||||
false);
|
||||
if (DumpBefore || !DumpBeforeFile.empty()) {
|
||||
MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
|
||||
|
||||
if (DumpBefore)
|
||||
MPM.addPass(DumpModulePass("-before", true));
|
||||
for (auto &Filename : DumpBeforeFile)
|
||||
MPM.addPass(DumpModulePass(Filename, false));
|
||||
|
||||
FPM = FunctionPassManager();
|
||||
}
|
||||
|
||||
buildCommonPollyPipeline(FPM, Level, EnableForOpt);
|
||||
MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
|
||||
|
|
|
@ -0,0 +1,80 @@
|
|||
; Legacy pass manager
|
||||
; RUN: opt %loadPolly -enable-new-pm=0 -O3 -polly -polly-position=early -polly-dump-before-file=%t-legacy-early.ll --disable-output < %s && FileCheck --input-file=%t-legacy-early.ll --check-prefix=EARLY %s
|
||||
; RUN: opt %loadPolly -enable-new-pm=0 -O3 -polly -polly-position=before-vectorizer -polly-dump-before-file=%t-legacy-late.ll --disable-output < %s && FileCheck --input-file=%t-legacy-late.ll --check-prefix=LATE %s
|
||||
;
|
||||
; New pass manager
|
||||
; RUN: opt %loadPolly -enable-new-pm=1 -O3 -polly -polly-position=early -polly-dump-before-file=%t-npm-early.ll --disable-output < %s && FileCheck --input-file=%t-npm-early.ll --check-prefix=EARLY %s
|
||||
;
|
||||
; Check the module dumping before Polly at specific positions in the
|
||||
; pass pipeline.
|
||||
;
|
||||
; void callee(int n, double A[], int i) {
|
||||
; for (int j = 0; j < n; j += 1)
|
||||
; A[i+j] = 42.0;
|
||||
; }
|
||||
;
|
||||
; void caller(int n, double A[]) {
|
||||
; for (int i = 0; i < n; i += 1)
|
||||
; callee(n, A, i);
|
||||
; }
|
||||
|
||||
|
||||
define internal void @callee(i32 %n, double* noalias nonnull %A, i32 %i) {
|
||||
entry:
|
||||
br label %for
|
||||
|
||||
for:
|
||||
%j = phi i32 [0, %entry], [%j.inc, %inc]
|
||||
%j.cmp = icmp slt i32 %j, %n
|
||||
br i1 %j.cmp, label %body, label %exit
|
||||
|
||||
body:
|
||||
%idx = add i32 %i, %j
|
||||
%arrayidx = getelementptr inbounds double, double* %A, i32 %idx
|
||||
store double 42.0, double* %arrayidx
|
||||
br label %inc
|
||||
|
||||
inc:
|
||||
%j.inc = add nuw nsw i32 %j, 1
|
||||
br label %for
|
||||
|
||||
exit:
|
||||
br label %return
|
||||
|
||||
return:
|
||||
ret void
|
||||
}
|
||||
|
||||
|
||||
define void @caller(i32 %n, double* noalias nonnull %A) {
|
||||
entry:
|
||||
br label %for
|
||||
|
||||
for:
|
||||
%i = phi i32 [0, %entry], [%j.inc, %inc]
|
||||
%i.cmp = icmp slt i32 %i, %n
|
||||
br i1 %i.cmp, label %body, label %exit
|
||||
|
||||
body:
|
||||
call void @callee(i32 %n, double* %A, i32 %i)
|
||||
br label %inc
|
||||
|
||||
inc:
|
||||
%j.inc = add nuw nsw i32 %i, 1
|
||||
br label %for
|
||||
|
||||
exit:
|
||||
br label %return
|
||||
|
||||
return:
|
||||
ret void
|
||||
}
|
||||
|
||||
|
||||
; EARLY-LABEL: @callee(
|
||||
; EARLY: store double 4.200000e+01, double* %arrayidx
|
||||
; EARLY-LABEL: @caller(
|
||||
; EARLY: call void @callee(
|
||||
|
||||
; LATE-LABEL: @caller(
|
||||
; LATE: store double 4.200000e+01, double* %arrayidx
|
Loading…
Reference in New Issue