Index: include/llvm/Passes/PassBuilder.h =================================================================== --- include/llvm/Passes/PassBuilder.h +++ include/llvm/Passes/PassBuilder.h @@ -29,10 +29,14 @@ /// A struct capturing PGO tunables. struct PGOOptions { - std::string ProfileGenFile = ""; - std::string ProfileUseFile = ""; - std::string SampleProfileFile = ""; - bool RunProfileGen = false; + PGOOptions(std::string ProfileGenFile = "", std::string ProfileUseFile = "", + std::string SampleProfileFile = "", bool RunProfileGen = false) + : ProfileGenFile(ProfileGenFile), ProfileUseFile(ProfileUseFile), + SampleProfileFile(SampleProfileFile), RunProfileGen(RunProfileGen) {} + std::string ProfileGenFile; + std::string ProfileUseFile; + std::string SampleProfileFile; + bool RunProfileGen; }; /// \brief This class provides access to building LLVM's passes. Index: lib/Passes/PassBuilder.cpp =================================================================== --- lib/Passes/PassBuilder.cpp +++ lib/Passes/PassBuilder.cpp @@ -172,6 +172,11 @@ "enable-npm-gvn-sink", cl::init(false), cl::Hidden, cl::desc("Enable the GVN hoisting pass for the new PM (default = off)")); +static cl::opt PGOOptString( + "pgo-opt", cl::init(""), cl::Hidden, + cl::desc("PGOOpt string in the format of " + "{gen|use|sample_gen|sample_use}=value")); + static Regex DefaultAliasRegex( "^(default|thinlto-pre-link|thinlto|lto-pre-link|lto)<(O[0123sz])>$"); @@ -1101,6 +1106,27 @@ return false; } +/// Processes user specifiy -pgo-opt option to override PGOOpt. +static void processPGOOpt(Optional &PGOOpt) { + if (PGOOptString.empty()) + return; + + auto pos = PGOOptString.find('='); + if (pos == std::string::npos) + report_fatal_error("Invalid -pgo-opt."); + + std::string K = PGOOptString.substr(0, pos); + std::string V = PGOOptString.substr(pos + 1); + + PGOOpt = StringSwitch>(K) + .Case("gen", PGOOptions(V, "", "", true)) + .Case("use", PGOOptions("", V, "", false)) + .Case("sample-use", PGOOptions("", "", V, false)) + .Default(None); + if (!PGOOpt) + report_fatal_error("Invalid -pgo-opt."); +} + template static bool isModulePassName(StringRef Name, CallbacksT &Callbacks) { // Manually handle aliases for pre-configured pipeline fragments. @@ -1668,6 +1694,8 @@ if (!Pipeline || Pipeline->empty()) return false; + processPGOOpt(PGOOpt); + // If the first name isn't at the module layer, wrap the pipeline up // automatically. StringRef FirstName = Pipeline->front().Name; Index: test/Other/Inputs/new-pm-pgo.prof =================================================================== --- /dev/null +++ test/Other/Inputs/new-pm-pgo.prof @@ -0,0 +1 @@ +foo:0:0 Index: test/Other/Inputs/new-pm-pgo.proftext =================================================================== --- /dev/null +++ test/Other/Inputs/new-pm-pgo.proftext @@ -0,0 +1 @@ +:ir Index: test/Other/new-pm-pgo.ll =================================================================== --- /dev/null +++ test/Other/new-pm-pgo.ll @@ -0,0 +1,12 @@ +; RUN: opt -debug-pass-manager -passes='default' -pgo-opt='gen=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' -pgo-opt='use=%t.profdata' %s 2>&1 |FileCheck %s --check-prefixes=USE +; RUN: opt -debug-pass-manager -passes='default' -pgo-opt='sample-use=%S/Inputs/new-pm-pgo.prof' %s 2>&1 |FileCheck %s --check-prefixes=SAMPLE_USE +; +; GEN: Running pass: PGOInstrumentationGen +; USE: Running pass: PGOInstrumentationUse +; SAMPLE_USE: Running pass: SampleProfileLoaderPass + +define void @foo() { + ret void +}