https://github.com/wlei-llvm created https://github.com/llvm/llvm-project/pull/110330
None >From d660d3b9a043a3530a735c1b95790116f6366062 Mon Sep 17 00:00:00 2001 From: wlei <w...@fb.com> Date: Sun, 22 Sep 2024 20:23:20 -0700 Subject: [PATCH 1/2] [InstrPGO] Instrument sampling profile based cold function --- clang/include/clang/Driver/Options.td | 6 +++++ clang/lib/Driver/ToolChain.cpp | 4 +++- clang/lib/Driver/ToolChains/Clang.cpp | 13 ++++++++++ llvm/lib/Passes/PassBuilderPipelines.cpp | 17 +++++++++++++ .../Instrumentation/PGOInstrumentation.cpp | 14 +++++++++++ .../PGOProfile/instr-gen-cold-function.ll | 24 +++++++++++++++++++ 6 files changed, 77 insertions(+), 1 deletion(-) create mode 100644 llvm/test/Transforms/PGOProfile/instr-gen-cold-function.ll diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index aedc4c16d4e9d5..230b9604b8a8aa 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -1785,6 +1785,12 @@ defm debug_info_for_profiling : BoolFOption<"debug-info-for-profiling", PosFlag<SetTrue, [], [ClangOption, CC1Option], "Emit extra debug info to make sample profile more accurate">, NegFlag<SetFalse>>; +def fprofile_sample_cold_function : Flag<["-"], "fprofile-sample-cold-function">, + Group<f_Group>, Visibility<[ClangOption, CLOption]>, + HelpText<"Generate instrumented code to cold functions guided by sampling-based profile into default.profraw file (overridden by '=' form of option or LLVM_PROFILE_FILE env var)">; +def fprofile_sample_cold_function_EQ : Joined<["-"], "fprofile-sample-cold-function=">, + Group<f_Group>, Visibility<[ClangOption, CLOption]>, MetaVarName<"<file>">, + HelpText<"Generate instrumented code to cold functions guided by sampling-based profile into <file> (overridden by LLVM_PROFILE_FILE env var)">; def fprofile_instr_generate : Flag<["-"], "fprofile-instr-generate">, Group<f_Group>, Visibility<[ClangOption, CLOption]>, HelpText<"Generate instrumented code to collect execution counts into default.profraw file (overridden by '=' form of option or LLVM_PROFILE_FILE env var)">; diff --git a/clang/lib/Driver/ToolChain.cpp b/clang/lib/Driver/ToolChain.cpp index 16f9b629fc538c..5cd821cfe780c4 100644 --- a/clang/lib/Driver/ToolChain.cpp +++ b/clang/lib/Driver/ToolChain.cpp @@ -889,7 +889,9 @@ bool ToolChain::needsProfileRT(const ArgList &Args) { Args.hasArg(options::OPT_fprofile_instr_generate) || Args.hasArg(options::OPT_fprofile_instr_generate_EQ) || Args.hasArg(options::OPT_fcreate_profile) || - Args.hasArg(options::OPT_forder_file_instrumentation); + Args.hasArg(options::OPT_forder_file_instrumentation) || + Args.hasArg(options::OPT_fprofile_sample_cold_function) || + Args.hasArg(options::OPT_fprofile_sample_cold_function_EQ); } bool ToolChain::needsGCovInstrumentation(const llvm::opt::ArgList &Args) { diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index b9987288d82d10..fced94833aaf79 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -649,6 +649,19 @@ static void addPGOAndCoverageFlags(const ToolChain &TC, Compilation &C, } } + if (auto *SampleColdArg = + Args.getLastArg(options::OPT_fprofile_sample_cold_function, + options::OPT_fprofile_sample_cold_function_EQ)) { + SmallString<128> Path(SampleColdArg->getOption().matches( + options::OPT_fprofile_sample_cold_function_EQ) + ? SampleColdArg->getValue() + : ""); + llvm::sys::path::append(Path, "default_%m.profraw"); + CmdArgs.push_back("-mllvm"); + CmdArgs.push_back(Args.MakeArgString( + Twine("--instrument-sample-cold-function-path=") + Path)); + } + Arg *PGOGenArg = nullptr; if (PGOGenerateArg) { assert(!CSPGOGenerateArg); diff --git a/llvm/lib/Passes/PassBuilderPipelines.cpp b/llvm/lib/Passes/PassBuilderPipelines.cpp index 8f151a99b11709..0514d17db20721 100644 --- a/llvm/lib/Passes/PassBuilderPipelines.cpp +++ b/llvm/lib/Passes/PassBuilderPipelines.cpp @@ -296,7 +296,13 @@ static cl::opt<bool> UseLoopVersioningLICM( "enable-loop-versioning-licm", cl::init(false), cl::Hidden, cl::desc("Enable the experimental Loop Versioning LICM pass")); +static cl::opt<std::string> InstrumentSampleColdFuncPath( + "instrument-sample-cold-function-path", cl::init(""), + cl::desc("File path for instrumenting sampling PGO guided cold functions"), + cl::Hidden); + extern cl::opt<std::string> UseCtxProfile; +extern cl::opt<bool> InstrumentColdFunction; namespace llvm { extern cl::opt<bool> EnableMemProfContextDisambiguation; @@ -1119,6 +1125,17 @@ PassBuilder::buildModuleSimplificationPipeline(OptimizationLevel Level, // removed. MPM.addPass( PGOIndirectCallPromotion(true /* IsInLTO */, true /* SamplePGO */)); + + if (InstrumentSampleColdFuncPath.getNumOccurrences() && + Phase != ThinOrFullLTOPhase::ThinLTOPostLink) { + assert(!InstrumentSampleColdFuncPath.empty() && + "File path is requeired for instrumentation generation"); + InstrumentColdFunction = true; + addPreInlinerPasses(MPM, Level, Phase); + addPGOInstrPasses(MPM, Level, /* RunProfileGen */ true, + /* IsCS */ false, /* AtomicCounterUpdate */ false, + InstrumentSampleColdFuncPath, "", PGOOpt->FS); + } } // Try to perform OpenMP specific optimizations on the module. This is a diff --git a/llvm/lib/Transforms/Instrumentation/PGOInstrumentation.cpp b/llvm/lib/Transforms/Instrumentation/PGOInstrumentation.cpp index 10442fa0bb9003..cbd14567d97c95 100644 --- a/llvm/lib/Transforms/Instrumentation/PGOInstrumentation.cpp +++ b/llvm/lib/Transforms/Instrumentation/PGOInstrumentation.cpp @@ -319,6 +319,16 @@ static cl::opt<unsigned> PGOFunctionCriticalEdgeThreshold( cl::desc("Do not instrument functions with the number of critical edges " " greater than this threshold.")); +cl::opt<bool> InstrumentColdFunction( + "instrument-cold-function", cl::init(false), cl::Hidden, + cl::desc("Instrument cold functions (currently only used under sampling " + " PGO pipeline))")); + +static cl::opt<uint64_t> InstrumentColdFuncMaxEntryCount( + "instrument-cold-function-max-entry-count", cl::init(0), cl::Hidden, + cl::desc("When using --instrument-cold-function, skip instrumenting the " + "function whose entry count is above the given value")); + extern cl::opt<unsigned> MaxNumVTableAnnotations; namespace llvm { @@ -1891,6 +1901,10 @@ static bool skipPGOGen(const Function &F) { return true; if (F.getInstructionCount() < PGOFunctionSizeThreshold) return true; + if (InstrumentColdFunction && + (!F.getEntryCount() || + F.getEntryCount()->getCount() > InstrumentColdFuncMaxEntryCount)) + return true; return false; } diff --git a/llvm/test/Transforms/PGOProfile/instr-gen-cold-function.ll b/llvm/test/Transforms/PGOProfile/instr-gen-cold-function.ll new file mode 100644 index 00000000000000..14d3b3c7e9b6fa --- /dev/null +++ b/llvm/test/Transforms/PGOProfile/instr-gen-cold-function.ll @@ -0,0 +1,24 @@ +; RUN: opt < %s --passes=pgo-instr-gen -instrument-cold-function -S | FileCheck --check-prefixes=COLD %s +; RUN: opt < %s --passes=pgo-instr-gen -instrument-cold-function -instrument-cold-function-max-entry-count=1 -S | FileCheck --check-prefixes=ENTRY-COUNT %s + +; COLD: call void @llvm.instrprof.increment(ptr @__profn_foo, i64 [[#]], i32 1, i32 0) +; COLD-NOT: __profn_main + +; ENTRY-COUNT: call void @llvm.instrprof.increment(ptr @__profn_foo, i64 [[#]], i32 1, i32 0) +; ENTRY-COUNT: call void @llvm.instrprof.increment(ptr @__profn_main, i64 [[#]], i32 1, i32 0) + +target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +define void @foo() !prof !0 { +entry: + ret void +} + +define i32 @main() !prof !1 { +entry: + ret i32 0 +} + +!0 = !{!"function_entry_count", i64 0} +!1 = !{!"function_entry_count", i64 1} >From e3bbabf759b6b38ebcdd1512d845aa6a1c4d6f90 Mon Sep 17 00:00:00 2001 From: wlei <w...@fb.com> Date: Fri, 27 Sep 2024 14:27:18 -0700 Subject: [PATCH 2/2] use -fprofile-generate to specify the profile path --- clang/include/clang/Driver/Options.td | 5 +---- clang/lib/Driver/ToolChain.cpp | 4 +--- clang/lib/Driver/ToolChains/Clang.cpp | 30 +++++++++++++-------------- 3 files changed, 17 insertions(+), 22 deletions(-) diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 230b9604b8a8aa..b7ad1c6a008087 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -1787,10 +1787,7 @@ defm debug_info_for_profiling : BoolFOption<"debug-info-for-profiling", NegFlag<SetFalse>>; def fprofile_sample_cold_function : Flag<["-"], "fprofile-sample-cold-function">, Group<f_Group>, Visibility<[ClangOption, CLOption]>, - HelpText<"Generate instrumented code to cold functions guided by sampling-based profile into default.profraw file (overridden by '=' form of option or LLVM_PROFILE_FILE env var)">; -def fprofile_sample_cold_function_EQ : Joined<["-"], "fprofile-sample-cold-function=">, - Group<f_Group>, Visibility<[ClangOption, CLOption]>, MetaVarName<"<file>">, - HelpText<"Generate instrumented code to cold functions guided by sampling-based profile into <file> (overridden by LLVM_PROFILE_FILE env var)">; + HelpText<"Generate instrumented code to cold functions guided by sampling-based profile">; def fprofile_instr_generate : Flag<["-"], "fprofile-instr-generate">, Group<f_Group>, Visibility<[ClangOption, CLOption]>, HelpText<"Generate instrumented code to collect execution counts into default.profraw file (overridden by '=' form of option or LLVM_PROFILE_FILE env var)">; diff --git a/clang/lib/Driver/ToolChain.cpp b/clang/lib/Driver/ToolChain.cpp index 5cd821cfe780c4..16f9b629fc538c 100644 --- a/clang/lib/Driver/ToolChain.cpp +++ b/clang/lib/Driver/ToolChain.cpp @@ -889,9 +889,7 @@ bool ToolChain::needsProfileRT(const ArgList &Args) { Args.hasArg(options::OPT_fprofile_instr_generate) || Args.hasArg(options::OPT_fprofile_instr_generate_EQ) || Args.hasArg(options::OPT_fcreate_profile) || - Args.hasArg(options::OPT_forder_file_instrumentation) || - Args.hasArg(options::OPT_fprofile_sample_cold_function) || - Args.hasArg(options::OPT_fprofile_sample_cold_function_EQ); + Args.hasArg(options::OPT_forder_file_instrumentation); } bool ToolChain::needsGCovInstrumentation(const llvm::opt::ArgList &Args) { diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index fced94833aaf79..254e7c952b8398 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -649,26 +649,24 @@ static void addPGOAndCoverageFlags(const ToolChain &TC, Compilation &C, } } - if (auto *SampleColdArg = - Args.getLastArg(options::OPT_fprofile_sample_cold_function, - options::OPT_fprofile_sample_cold_function_EQ)) { - SmallString<128> Path(SampleColdArg->getOption().matches( - options::OPT_fprofile_sample_cold_function_EQ) - ? SampleColdArg->getValue() - : ""); - llvm::sys::path::append(Path, "default_%m.profraw"); + auto *SampleColdArg = + Args.getLastArg(options::OPT_fprofile_sample_cold_function); + + Arg *PGOGenArg = nullptr; + if (SampleColdArg) { + SmallString<128> Path( + PGOGenerateArg->getOption().matches(options::OPT_fprofile_generate_EQ) + ? PGOGenerateArg->getValue() + : ""); + Path.append("default_%m.profraw"); CmdArgs.push_back("-mllvm"); CmdArgs.push_back(Args.MakeArgString( Twine("--instrument-sample-cold-function-path=") + Path)); - } - - Arg *PGOGenArg = nullptr; - if (PGOGenerateArg) { + } else if (PGOGenerateArg) { assert(!CSPGOGenerateArg); PGOGenArg = PGOGenerateArg; CmdArgs.push_back("-fprofile-instrument=llvm"); - } - if (CSPGOGenerateArg) { + } else if (CSPGOGenerateArg) { assert(!PGOGenerateArg); PGOGenArg = CSPGOGenerateArg; CmdArgs.push_back("-fprofile-instrument=csllvm"); @@ -7037,7 +7035,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, options::OPT_fcs_profile_generate, options::OPT_fcs_profile_generate_EQ, options::OPT_fprofile_use, options::OPT_fprofile_use_EQ); - if (PGOArg) + auto *SampleColdArg = + Args.getLastArg(options::OPT_fprofile_sample_cold_function); + if (PGOArg && !SampleColdArg) D.Diag(diag::err_drv_argument_not_allowed_with) << "SampleUse with PGO options"; _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits