forked from OSchip/llvm-project
[PGO] Add PGO support at -O0 in the experimental new pass manager
Add PGO support at -O0 in the experimental new pass manager to sync the behavior of the legacy pass manager. Also change the test of gcc-flag-compatibility.c for more complete test: (1) change the match string to "profc" and "profd" to ensure the instrumentation is happening. (2) add IR format proftext so that PGO use compilation is tested. Differential Revision: https://reviews.llvm.org/D64029 llvm-svn: 367628
This commit is contained in:
parent
c69c46ff7a
commit
ca161fa008
|
@ -1117,6 +1117,16 @@ void EmitAssemblyHelper::EmitAssemblyWithNewPassManager(
|
|||
// code generation.
|
||||
MPM.addPass(AlwaysInlinerPass(/*InsertLifetimeIntrinsics=*/false));
|
||||
|
||||
// At -O0, we can still do PGO. Add all the requested passes for
|
||||
// instrumentation PGO, if requested.
|
||||
if (PGOOpt && (PGOOpt->Action == PGOOptions::IRInstr ||
|
||||
PGOOpt->Action == PGOOptions::IRUse))
|
||||
PB.addPGOInstrPassesForO0(
|
||||
MPM, CodeGenOpts.DebugPassManager,
|
||||
/* RunProfileGen */ (PGOOpt->Action == PGOOptions::IRInstr),
|
||||
/* IsCS */ false, PGOOpt->ProfileFile,
|
||||
PGOOpt->ProfileRemappingFile);
|
||||
|
||||
// At -O0 we directly run necessary sanitizer passes.
|
||||
if (LangOpts.Sanitize.has(SanitizerKind::LocalBounds))
|
||||
MPM.addPass(createModuleToFunctionPassAdaptor(BoundsCheckingPass()));
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
# IR level Instrumentation Flag
|
||||
:ir
|
||||
main
|
||||
# Func Hash:
|
||||
34137660316
|
||||
# Num Counters:
|
||||
2
|
||||
# Counter Values:
|
||||
100
|
||||
1
|
||||
|
|
@ -7,26 +7,50 @@
|
|||
// -fprofile-use=<dir> Uses the profile file <dir>/default.profdata
|
||||
// -fprofile-use=<dir>/file Uses the profile file <dir>/file
|
||||
|
||||
// RUN: %clang %s -c -S -o - -emit-llvm -fprofile-generate | FileCheck -check-prefix=PROFILE-GEN %s
|
||||
// PROFILE-GEN: __llvm_profile_filename
|
||||
// RUN: %clang %s -c -S -o - -emit-llvm -fprofile-generate -fno-experimental-new-pass-manager | FileCheck -check-prefix=PROFILE-GEN %s
|
||||
// RUN: %clang %s -c -S -o - -emit-llvm -fprofile-generate -fexperimental-new-pass-manager | FileCheck -check-prefix=PROFILE-GEN %s
|
||||
// PROFILE-GEN: @__profc_main = private global [2 x i64] zeroinitializer, section "__llvm_prf_cnts", align 8
|
||||
// PROFILE-GEN: @__profd_main = private global
|
||||
|
||||
// Check that -fprofile-generate=/path/to generates /path/to/default.profraw
|
||||
// RUN: %clang %s -c -S -o - -emit-llvm -fprofile-generate=/path/to | FileCheck -check-prefix=PROFILE-GEN-EQ %s
|
||||
// RUN: %clang %s -c -S -o - -emit-llvm -fprofile-generate=/path/to -fno-experimental-new-pass-manager | FileCheck -check-prefixes=PROFILE-GEN,PROFILE-GEN-EQ %s
|
||||
// RxUN: %clang %s -c -S -o - -emit-llvm -fprofile-generate=/path/to -fexperimental-new-pass-manager | FileCheck -check-prefixes=PROFILE-GEN,PROFILE-GEN-EQ %s
|
||||
// PROFILE-GEN-EQ: constant [{{.*}} x i8] c"/path/to{{/|\\5C}}{{.*}}\00"
|
||||
|
||||
// Check that -fprofile-use=some/path reads some/path/default.profdata
|
||||
// This uses Clang FE format profile.
|
||||
// RUN: rm -rf %t.dir
|
||||
// RUN: mkdir -p %t.dir/some/path
|
||||
// RUN: llvm-profdata merge %S/Inputs/gcc-flag-compatibility.proftext -o %t.dir/some/path/default.profdata
|
||||
// RUN: %clang %s -o - -Xclang -disable-llvm-passes -emit-llvm -S -fprofile-use=%t.dir/some/path | FileCheck -check-prefix=PROFILE-USE-2 %s
|
||||
// PROFILE-USE-2: = !{!"branch_weights", i32 101, i32 2}
|
||||
// RUN: %clang %s -o - -Xclang -disable-llvm-passes -emit-llvm -S -fprofile-use=%t.dir/some/path -fno-experimental-new-pass-manager | FileCheck -check-prefix=PROFILE-USE %s
|
||||
// RUN: %clang %s -o - -Xclang -disable-llvm-passes -emit-llvm -S -fprofile-use=%t.dir/some/path -fexperimental-new-pass-manager | FileCheck -check-prefix=PROFILE-USE %s
|
||||
|
||||
// Check that -fprofile-use=some/path/file.prof reads some/path/file.prof
|
||||
// This uses Clang FE format profile.
|
||||
// RUN: rm -rf %t.dir
|
||||
// RUN: mkdir -p %t.dir/some/path
|
||||
// RUN: llvm-profdata merge %S/Inputs/gcc-flag-compatibility.proftext -o %t.dir/some/path/file.prof
|
||||
// RUN: %clang %s -o - -Xclang -disable-llvm-passes -emit-llvm -S -fprofile-use=%t.dir/some/path/file.prof | FileCheck -check-prefix=PROFILE-USE-3 %s
|
||||
// PROFILE-USE-3: = !{!"branch_weights", i32 101, i32 2}
|
||||
// RUN: %clang %s -o - -Xclang -disable-llvm-passes -emit-llvm -S -fprofile-use=%t.dir/some/path/file.prof -fno-experimental-new-pass-manager | FileCheck -check-prefix=PROFILE-USE %s
|
||||
// RUN: %clang %s -o - -Xclang -disable-llvm-passes -emit-llvm -S -fprofile-use=%t.dir/some/path/file.prof -fexperimental-new-pass-manager | FileCheck -check-prefix=PROFILE-USE %s
|
||||
// PROFILE-USE: = !{!"branch_weights", i32 101, i32 2}
|
||||
|
||||
// Check that -fprofile-use=some/path reads some/path/default.profdata
|
||||
// This uses LLVM IR format profile.
|
||||
// RUN: rm -rf %t.dir
|
||||
// RUN: mkdir -p %t.dir/some/path
|
||||
// RUN: llvm-profdata merge %S/Inputs/gcc-flag-compatibility_IR.proftext -o %t.dir/some/path/default.profdata
|
||||
// RUN: %clang %s -o - -emit-llvm -S -fprofile-use=%t.dir/some/path -fno-experimental-new-pass-manager | FileCheck -check-prefix=PROFILE-USE-IR %s
|
||||
// RUN: %clang %s -o - -emit-llvm -S -fprofile-use=%t.dir/some/path -fexperimental-new-pass-manager | FileCheck -check-prefix=PROFILE-USE-IR %s
|
||||
|
||||
// Check that -fprofile-use=some/path/file.prof reads some/path/file.prof
|
||||
// This uses LLVM IR format profile.
|
||||
// RUN: rm -rf %t.dir
|
||||
// RUN: mkdir -p %t.dir/some/path
|
||||
// RUN: llvm-profdata merge %S/Inputs/gcc-flag-compatibility_IR.proftext -o %t.dir/some/path/file.prof
|
||||
// RUN: %clang %s -o - -emit-llvm -S -fprofile-use=%t.dir/some/path/file.prof -fno-experimental-new-pass-manager | FileCheck -check-prefix=PROFILE-USE-IR %s
|
||||
// RUN: %clang %s -o - -emit-llvm -S -fprofile-use=%t.dir/some/path/file.prof -fexperimental-new-pass-manager | FileCheck -check-prefix=PROFILE-USE-IR %s
|
||||
|
||||
// PROFILE-USE-IR: = !{!"branch_weights", i32 100, i32 1}
|
||||
|
||||
int X = 0;
|
||||
|
||||
|
|
|
@ -629,6 +629,12 @@ public:
|
|||
TopLevelPipelineParsingCallbacks.push_back(C);
|
||||
}
|
||||
|
||||
/// Add PGOInstrumenation passes for O0 only.
|
||||
void addPGOInstrPassesForO0(ModulePassManager &MPM, bool DebugLogging,
|
||||
bool RunProfileGen, bool IsCS,
|
||||
std::string ProfileFile,
|
||||
std::string ProfileRemappingFile);
|
||||
|
||||
private:
|
||||
static Optional<std::vector<PipelineElement>>
|
||||
parsePipelineText(StringRef Text);
|
||||
|
@ -660,7 +666,6 @@ private:
|
|||
OptimizationLevel Level, bool RunProfileGen, bool IsCS,
|
||||
std::string ProfileFile,
|
||||
std::string ProfileRemappingFile);
|
||||
|
||||
void invokePeepholeEPCallbacks(FunctionPassManager &, OptimizationLevel);
|
||||
|
||||
// Extension Point callbacks
|
||||
|
|
|
@ -541,6 +541,7 @@ void PassBuilder::addPGOInstrPasses(ModulePassManager &MPM, bool DebugLogging,
|
|||
bool RunProfileGen, bool IsCS,
|
||||
std::string ProfileFile,
|
||||
std::string ProfileRemappingFile) {
|
||||
assert(Level != O0 && "Not expecting O0 here!");
|
||||
// Generally running simplification passes and the inliner with an high
|
||||
// threshold results in smaller executables, but there may be cases where
|
||||
// the size grows, so let's be conservative here and skip this simplification
|
||||
|
@ -571,34 +572,62 @@ void PassBuilder::addPGOInstrPasses(ModulePassManager &MPM, bool DebugLogging,
|
|||
CGPipeline.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM)));
|
||||
|
||||
MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPipeline)));
|
||||
|
||||
// Delete anything that is now dead to make sure that we don't instrument
|
||||
// dead code. Instrumentation can end up keeping dead code around and
|
||||
// dramatically increase code size.
|
||||
MPM.addPass(GlobalDCEPass());
|
||||
}
|
||||
|
||||
// Delete anything that is now dead to make sure that we don't instrument
|
||||
// dead code. Instrumentation can end up keeping dead code around and
|
||||
// dramatically increase code size.
|
||||
MPM.addPass(GlobalDCEPass());
|
||||
|
||||
if (RunProfileGen) {
|
||||
MPM.addPass(PGOInstrumentationGen(IsCS));
|
||||
|
||||
FunctionPassManager FPM;
|
||||
FPM.addPass(
|
||||
createFunctionToLoopPassAdaptor(LoopRotatePass(), DebugLogging));
|
||||
MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
|
||||
|
||||
// Add the profile lowering pass.
|
||||
InstrProfOptions Options;
|
||||
if (!ProfileFile.empty())
|
||||
Options.InstrProfileOutput = ProfileFile;
|
||||
Options.DoCounterPromotion = true;
|
||||
Options.UseBFIInPromotion = IsCS;
|
||||
MPM.addPass(InstrProfiling(Options, IsCS));
|
||||
} else if (!ProfileFile.empty()) {
|
||||
if (!RunProfileGen) {
|
||||
assert(!ProfileFile.empty() && "Profile use expecting a profile file!");
|
||||
MPM.addPass(PGOInstrumentationUse(ProfileFile, ProfileRemappingFile, IsCS));
|
||||
// Cache ProfileSummaryAnalysis once to avoid the potential need to insert
|
||||
// RequireAnalysisPass for PSI before subsequent non-module passes.
|
||||
MPM.addPass(RequireAnalysisPass<ProfileSummaryAnalysis, Module>());
|
||||
return;
|
||||
}
|
||||
|
||||
// Perform PGO instrumentation.
|
||||
MPM.addPass(PGOInstrumentationGen(IsCS));
|
||||
|
||||
FunctionPassManager FPM;
|
||||
FPM.addPass(createFunctionToLoopPassAdaptor(LoopRotatePass(), DebugLogging));
|
||||
MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
|
||||
|
||||
// Add the profile lowering pass.
|
||||
InstrProfOptions Options;
|
||||
if (!ProfileFile.empty())
|
||||
Options.InstrProfileOutput = ProfileFile;
|
||||
// Do counter promotion at Level greater than O0.
|
||||
Options.DoCounterPromotion = true;
|
||||
Options.UseBFIInPromotion = IsCS;
|
||||
MPM.addPass(InstrProfiling(Options, IsCS));
|
||||
}
|
||||
|
||||
void PassBuilder::addPGOInstrPassesForO0(ModulePassManager &MPM,
|
||||
bool DebugLogging, bool RunProfileGen,
|
||||
bool IsCS, std::string ProfileFile,
|
||||
std::string ProfileRemappingFile) {
|
||||
if (!RunProfileGen) {
|
||||
assert(!ProfileFile.empty() && "Profile use expecting a profile file!");
|
||||
MPM.addPass(PGOInstrumentationUse(ProfileFile, ProfileRemappingFile, IsCS));
|
||||
// Cache ProfileSummaryAnalysis once to avoid the potential need to insert
|
||||
// RequireAnalysisPass for PSI before subsequent non-module passes.
|
||||
MPM.addPass(RequireAnalysisPass<ProfileSummaryAnalysis, Module>());
|
||||
return;
|
||||
}
|
||||
|
||||
// Perform PGO instrumentation.
|
||||
MPM.addPass(PGOInstrumentationGen(IsCS));
|
||||
// Add the profile lowering pass.
|
||||
InstrProfOptions Options;
|
||||
if (!ProfileFile.empty())
|
||||
Options.InstrProfileOutput = ProfileFile;
|
||||
// Do not do counter promotion at O0.
|
||||
Options.DoCounterPromotion = false;
|
||||
Options.UseBFIInPromotion = IsCS;
|
||||
MPM.addPass(InstrProfiling(Options, IsCS));
|
||||
}
|
||||
|
||||
static InlineParams
|
||||
|
@ -1801,9 +1830,19 @@ Error PassBuilder::parseModulePass(ModulePassManager &MPM,
|
|||
.Case("O3", O3)
|
||||
.Case("Os", Os)
|
||||
.Case("Oz", Oz);
|
||||
if (L == O0)
|
||||
// At O0 we do nothing at all!
|
||||
if (L == O0) {
|
||||
// Add instrumentation PGO passes -- at O0 we can still do PGO.
|
||||
if (PGOOpt && Matches[1] != "thinlto" &&
|
||||
(PGOOpt->Action == PGOOptions::IRInstr ||
|
||||
PGOOpt->Action == PGOOptions::IRUse))
|
||||
addPGOInstrPassesForO0(
|
||||
MPM, DebugLogging,
|
||||
/* RunProfileGen */ (PGOOpt->Action == PGOOptions::IRInstr),
|
||||
/* IsCS */ false, PGOOpt->ProfileFile,
|
||||
PGOOpt->ProfileRemappingFile);
|
||||
// Do nothing else at all!
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
if (Matches[1] == "default") {
|
||||
MPM.addPass(buildPerModuleDefaultPipeline(L, DebugLogging));
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
; RUN: opt -debug-pass-manager -passes='default<O0>' -pgo-kind=pgo-instr-gen-pipeline -profile-file='temp' %s 2>&1 |FileCheck %s --check-prefixes=GEN
|
||||
; RUN: llvm-profdata merge %S/Inputs/new-pm-pgo.proftext -o %t.profdata
|
||||
; RUN: opt -debug-pass-manager -passes='default<O0>' -pgo-kind=pgo-instr-use-pipeline -profile-file='%t.profdata' %s 2>&1 |FileCheck %s --check-prefixes=USE_DEFAULT,USE
|
||||
; RUN: opt -debug-pass-manager -passes='thinlto-pre-link<O0>' -pgo-kind=pgo-instr-use-pipeline -profile-file='%t.profdata' %s 2>&1 \
|
||||
; RUN: |FileCheck %s --check-prefixes=USE_PRE_LINK,USE
|
||||
; RUN: opt -debug-pass-manager -passes='lto-pre-link<O0>' -pgo-kind=pgo-instr-use-pipeline -profile-file='%t.profdata' %s 2>&1 \
|
||||
; RUN: |FileCheck %s --check-prefixes=USE_PRE_LINK,USE
|
||||
; RUN: opt -debug-pass-manager -passes='thinlto<O0>' -pgo-kind=pgo-instr-use-pipeline -profile-file='%t.profdata' %s 2>&1 \
|
||||
; RUN: |FileCheck %s --check-prefixes=USE_POST_LINK,USE
|
||||
|
||||
;
|
||||
; GEN: Running pass: PGOInstrumentationGen
|
||||
; USE_DEFAULT: Running pass: PGOInstrumentationUse
|
||||
; USE_PRE_LINK: Running pass: PGOInstrumentationUse
|
||||
; USE_POST_LINK-NOT: Running pass: PGOInstrumentationUse
|
||||
; USE-NOT: Running pass: PGOIndirectCallPromotion
|
||||
; USE-NOT: Running pass: PGOMemOPSizeOpt
|
||||
|
||||
define void @foo() {
|
||||
ret void
|
||||
}
|
Loading…
Reference in New Issue