diff --git a/llvm/test/tools/input-gen/pgo.ll b/llvm/test/tools/input-gen/pgo.ll new file mode 100644 index 0000000000000..6ee4f878d3682 --- /dev/null +++ b/llvm/test/tools/input-gen/pgo.ll @@ -0,0 +1,14 @@ +; RUN: mkdir -p %t +; RUN: input-gen --verify --output-dir %t --compile-input-gen-executables --input-gen-runtime %S/../../../../input-gen-runtimes/rt-input-gen.cpp --input-run-runtime %S/../../../../input-gen-runtimes/rt-run.cpp --pgo-instr-generate %s +; RUN: %t/input-gen.module.generate.a.out %t 0 1 i64 +; RUN: %t/input-gen.module.run.a.out %t/input-gen.module.generate.a.out.input.i64.0.bin i64 +; RUN: llvm-profdata merge default.profraw -o %t/default.profdata +; RUN: mkdir -p %t.withpgo +; RUN: input-gen --verify --output-dir %t.withpgo --compile-input-gen-executables --input-gen-runtime %S/../../../../input-gen-runtimes/rt-input-gen.cpp --input-run-runtime %S/../../../../input-gen-runtimes/rt-run.cpp --pgo-instr-use %t/default.profdata %s + +define dso_local i64 @i64(ptr noundef %LL) local_unnamed_addr #0 { +entry: + %a = load i64, ptr %LL + store i64 %a, ptr %LL + ret i64 %a +} diff --git a/llvm/tools/input-gen/input-gen.cpp b/llvm/tools/input-gen/input-gen.cpp index ebc7e4892886a..8773a45fb12c2 100644 --- a/llvm/tools/input-gen/input-gen.cpp +++ b/llvm/tools/input-gen/input-gen.cpp @@ -66,6 +66,12 @@ static cl::opt ClOptimizeBeforeInstrumenting("optimize-before-instrumenting", cl::cat(InputGenCategory)); +static cl::opt ClInstrumentedPGOGenerate("pgo-instr-generate", + cl::cat(InputGenCategory)); + +static cl::opt ClInstrumentedPGOUse("pgo-instr-use", + cl::cat(InputGenCategory)); + constexpr char ToolName[] = "input-gen"; [[noreturn]] static void fatalError(const Twine &Message) { @@ -269,8 +275,16 @@ class InputGenOrchestration { llvm::outs() << "Writing instrumented module to file failed\n"; exit(1); } + + bool InstrumentBinaryPGO = false; + std::string PGOProfilePath = ""; + if (Mode == llvm::IG_Run) { + InstrumentBinaryPGO = ClInstrumentedPGOGenerate; + PGOProfilePath = ClInstrumentedPGOUse; + } if (ClCompileInputGenExecutables) { - if (!compileExecutable(BcFileName, ExecutableFileName, RuntimeName)) { + if (!compileExecutable(BcFileName, ExecutableFileName, RuntimeName, + InstrumentBinaryPGO, PGOProfilePath)) { llvm::outs() << "Compiling instrumented module failed\n"; exit(1); } @@ -333,12 +347,22 @@ class InputGenOrchestration { } bool compileExecutable(std::string ModuleName, std::string ExecutableName, - std::string RuntimeName) { + std::string RuntimeName, + bool GenInstrumentationPGO = false, + std::string PGOProfilePath = "") { if (ClCompileInputGenExecutables) { outs() << "Compiling " << ExecutableName << "\n"; - SmallVector Args = { + SmallVector Args = { Clang, "-fopenmp", "-O2", "-ldl", "-rdynamic", RuntimeName, ModuleName, "-o", ExecutableName}; + assert(!(GenInstrumentationPGO && !PGOProfilePath.empty()) && + "Cannot instrument and use profile at the same time."); + std::string ProfileInstrUseArg = "-fprofile-instr-use=" + PGOProfilePath; + if (GenInstrumentationPGO) + Args.push_back("-fprofile-instr-generate"); + else if (!PGOProfilePath.empty()) { + Args.push_back(ProfileInstrUseArg); + } if (ClDebug) Args.push_back("-g"); std::string ErrMsg; @@ -376,6 +400,12 @@ int main(int argc, char **argv) { return 1; } + if (ClInstrumentedPGOGenerate && !ClInstrumentedPGOUse.empty()) { + ExitOnErr(make_error( + "Cannot use a PGO profile while instrumenting the program.", + errc::invalid_argument)); + } + InputGenOrchestration IGO(*M); IGO.init(argc, argv);