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::createFlattenSchedulePass();
|
||||||
polly::createForwardOpTreeWrapperPass();
|
polly::createForwardOpTreeWrapperPass();
|
||||||
polly::createDeLICMWrapperPass();
|
polly::createDeLICMWrapperPass();
|
||||||
polly::createDumpModulePass("", true);
|
polly::createDumpModuleWrapperPass("", true);
|
||||||
polly::createSimplifyWrapperPass(0);
|
polly::createSimplifyWrapperPass(0);
|
||||||
polly::createPruneUnprofitableWrapperPass();
|
polly::createPruneUnprofitableWrapperPass();
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,8 +13,10 @@
|
||||||
#ifndef POLLY_SUPPORT_DUMPMODULEPASS_H
|
#ifndef POLLY_SUPPORT_DUMPMODULEPASS_H
|
||||||
#define POLLY_SUPPORT_DUMPMODULEPASS_H
|
#define POLLY_SUPPORT_DUMPMODULEPASS_H
|
||||||
|
|
||||||
|
#include "llvm/IR/PassManager.h"
|
||||||
|
#include <string>
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
class StringRef;
|
|
||||||
class ModulePass;
|
class ModulePass;
|
||||||
} // namespace llvm
|
} // namespace llvm
|
||||||
|
|
||||||
|
@ -28,12 +30,25 @@ namespace polly {
|
||||||
/// The intent of IsSuffix is to avoid the file being overwritten when
|
/// The intent of IsSuffix is to avoid the file being overwritten when
|
||||||
/// processing multiple modules and/or with multiple dump passes in the
|
/// processing multiple modules and/or with multiple dump passes in the
|
||||||
/// pipeline.
|
/// 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 polly
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
class PassRegistry;
|
class PassRegistry;
|
||||||
void initializeDumpModulePass(llvm::PassRegistry &);
|
void initializeDumpModuleWrapperPassPass(llvm::PassRegistry &);
|
||||||
} // namespace llvm
|
} // namespace llvm
|
||||||
|
|
||||||
#endif /* POLLY_SUPPORT_DUMPMODULEPASS_H */
|
#endif /* POLLY_SUPPORT_DUMPMODULEPASS_H */
|
||||||
|
|
|
@ -25,10 +25,34 @@ using namespace polly;
|
||||||
|
|
||||||
namespace {
|
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:
|
private:
|
||||||
DumpModule(const DumpModule &) = delete;
|
DumpModuleWrapperPass(const DumpModuleWrapperPass &) = delete;
|
||||||
const DumpModule &operator=(const DumpModule &) = delete;
|
const DumpModuleWrapperPass &
|
||||||
|
operator=(const DumpModuleWrapperPass &) = delete;
|
||||||
|
|
||||||
std::string Filename;
|
std::string Filename;
|
||||||
bool IsSuffix;
|
bool IsSuffix;
|
||||||
|
@ -39,10 +63,11 @@ public:
|
||||||
/// This constructor is used e.g. if using opt -polly-dump-module.
|
/// This constructor is used e.g. if using opt -polly-dump-module.
|
||||||
///
|
///
|
||||||
/// Provide a default suffix to not overwrite the original file.
|
/// 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)
|
explicit DumpModuleWrapperPass(std::string Filename, bool IsSuffix)
|
||||||
: ModulePass(ID), Filename(Filename), IsSuffix(IsSuffix) {}
|
: ModulePass(ID), Filename(std::move(Filename)), IsSuffix(IsSuffix) {}
|
||||||
|
|
||||||
/// @name ModulePass interface
|
/// @name ModulePass interface
|
||||||
//@{
|
//@{
|
||||||
|
@ -51,41 +76,27 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool runOnModule(llvm::Module &M) override {
|
virtual bool runOnModule(llvm::Module &M) override {
|
||||||
std::string Dumpfile;
|
runDumpModule(M, Filename, IsSuffix);
|
||||||
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();
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
//@}
|
//@}
|
||||||
};
|
};
|
||||||
|
|
||||||
char DumpModule::ID;
|
char DumpModuleWrapperPass::ID;
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
ModulePass *polly::createDumpModulePass(llvm::StringRef Filename,
|
ModulePass *polly::createDumpModuleWrapperPass(std::string Filename,
|
||||||
bool IsSuffix) {
|
bool IsSuffix) {
|
||||||
return new DumpModule(Filename, IsSuffix);
|
return new DumpModuleWrapperPass(std::move(Filename), IsSuffix);
|
||||||
}
|
}
|
||||||
|
|
||||||
INITIALIZE_PASS_BEGIN(DumpModule, "polly-dump-module", "Polly - Dump Module",
|
llvm::PreservedAnalyses DumpModulePass::run(llvm::Module &M,
|
||||||
false, false)
|
llvm::ModuleAnalysisManager &AM) {
|
||||||
INITIALIZE_PASS_END(DumpModule, "polly-dump-module", "Polly - Dump Module",
|
runDumpModule(M, Filename, IsSuffix);
|
||||||
false, false)
|
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);
|
initializeForwardOpTreeWrapperPassPass(Registry);
|
||||||
initializeDeLICMWrapperPassPass(Registry);
|
initializeDeLICMWrapperPassPass(Registry);
|
||||||
initializeSimplifyWrapperPassPass(Registry);
|
initializeSimplifyWrapperPassPass(Registry);
|
||||||
initializeDumpModulePass(Registry);
|
initializeDumpModuleWrapperPassPass(Registry);
|
||||||
initializePruneUnprofitableWrapperPassPass(Registry);
|
initializePruneUnprofitableWrapperPassPass(Registry);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -302,10 +302,11 @@ void initializePollyPasses(PassRegistry &Registry) {
|
||||||
static void registerPollyPasses(llvm::legacy::PassManagerBase &PM,
|
static void registerPollyPasses(llvm::legacy::PassManagerBase &PM,
|
||||||
bool EnableForOpt) {
|
bool EnableForOpt) {
|
||||||
if (DumpBefore)
|
if (DumpBefore)
|
||||||
PM.add(polly::createDumpModulePass("-before", true));
|
PM.add(polly::createDumpModuleWrapperPass("-before", true));
|
||||||
for (auto &Filename : DumpBeforeFile)
|
for (auto &Filename : DumpBeforeFile)
|
||||||
PM.add(polly::createDumpModulePass(Filename, false));
|
PM.add(polly::createDumpModuleWrapperPass(Filename, false));
|
||||||
|
|
||||||
|
PM.add(polly::createCodePreparationPass());
|
||||||
PM.add(polly::createScopDetectionWrapperPassPass());
|
PM.add(polly::createScopDetectionWrapperPassPass());
|
||||||
|
|
||||||
if (PollyDetectOnly)
|
if (PollyDetectOnly)
|
||||||
|
@ -397,9 +398,9 @@ static void registerPollyPasses(llvm::legacy::PassManagerBase &PM,
|
||||||
PM.add(createBarrierNoopPass());
|
PM.add(createBarrierNoopPass());
|
||||||
|
|
||||||
if (DumpAfter)
|
if (DumpAfter)
|
||||||
PM.add(polly::createDumpModulePass("-after", true));
|
PM.add(polly::createDumpModuleWrapperPass("-after", true));
|
||||||
for (auto &Filename : DumpAfterFile)
|
for (auto &Filename : DumpAfterFile)
|
||||||
PM.add(polly::createDumpModulePass(Filename, false));
|
PM.add(polly::createDumpModuleWrapperPass(Filename, false));
|
||||||
|
|
||||||
if (CFGPrinter)
|
if (CFGPrinter)
|
||||||
PM.add(llvm::createCFGPrinterLegacyPassPass());
|
PM.add(llvm::createCFGPrinterLegacyPassPass());
|
||||||
|
@ -429,7 +430,6 @@ registerPollyEarlyAsPossiblePasses(const llvm::PassManagerBuilder &Builder,
|
||||||
return;
|
return;
|
||||||
|
|
||||||
registerCanonicalicationPasses(PM);
|
registerCanonicalicationPasses(PM);
|
||||||
PM.add(polly::createCodePreparationPass());
|
|
||||||
registerPollyPasses(PM, EnableForOpt);
|
registerPollyPasses(PM, EnableForOpt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -444,7 +444,6 @@ registerPollyLoopOptimizerEndPasses(const llvm::PassManagerBuilder &Builder,
|
||||||
if (!shouldEnablePollyForDiagnostic() && !EnableForOpt)
|
if (!shouldEnablePollyForDiagnostic() && !EnableForOpt)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
PM.add(polly::createCodePreparationPass());
|
|
||||||
registerPollyPasses(PM, EnableForOpt);
|
registerPollyPasses(PM, EnableForOpt);
|
||||||
if (EnableForOpt)
|
if (EnableForOpt)
|
||||||
PM.add(createCodegenCleanupPass());
|
PM.add(createCodegenCleanupPass());
|
||||||
|
@ -461,7 +460,6 @@ registerPollyScalarOptimizerLatePasses(const llvm::PassManagerBuilder &Builder,
|
||||||
if (!shouldEnablePollyForDiagnostic() && !EnableForOpt)
|
if (!shouldEnablePollyForDiagnostic() && !EnableForOpt)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
PM.add(polly::createCodePreparationPass());
|
|
||||||
polly::registerPollyPasses(PM, EnableForOpt);
|
polly::registerPollyPasses(PM, EnableForOpt);
|
||||||
if (EnableForOpt)
|
if (EnableForOpt)
|
||||||
PM.add(createCodegenCleanupPass());
|
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
|
// TODO add utility passes for the various command line options, once they're
|
||||||
// ported
|
// 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) {
|
if (PollyDetectOnly) {
|
||||||
// Don't add more passes other than the ScopPassManager's detection passes.
|
// 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);
|
FunctionPassManager FPM = buildCanonicalicationPassesForNPM(MPM, Level);
|
||||||
|
|
||||||
if (DumpBefore)
|
if (DumpBefore || !DumpBeforeFile.empty()) {
|
||||||
report_fatal_error("Option -polly-dump-before not supported with NPM",
|
MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
|
||||||
false);
|
|
||||||
if (!DumpBeforeFile.empty())
|
if (DumpBefore)
|
||||||
report_fatal_error("Option -polly-dump-before-file not supported with NPM",
|
MPM.addPass(DumpModulePass("-before", true));
|
||||||
false);
|
for (auto &Filename : DumpBeforeFile)
|
||||||
|
MPM.addPass(DumpModulePass(Filename, false));
|
||||||
|
|
||||||
|
FPM = FunctionPassManager();
|
||||||
|
}
|
||||||
|
|
||||||
buildCommonPollyPipeline(FPM, Level, EnableForOpt);
|
buildCommonPollyPipeline(FPM, Level, EnableForOpt);
|
||||||
MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
|
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