https://github.com/w2yehia updated https://github.com/llvm/llvm-project/pull/124353
>From abef90fe8f46431a5fb8b7fe717c9fb65eb30266 Mon Sep 17 00:00:00 2001 From: Wael Yehia <wye...@ca.ibm.com> Date: Thu, 23 Jan 2025 00:03:15 +0000 Subject: [PATCH 1/2] [PGO] Add a clang option -fprofile-continuous that enables PGO continuous mode --- clang/docs/UsersManual.rst | 8 ++++ clang/include/clang/Basic/CodeGenOptions.def | 1 + clang/include/clang/Driver/Options.td | 5 +++ clang/lib/CodeGen/BackendUtil.cpp | 42 +++++++++++--------- clang/lib/Driver/ToolChains/Clang.cpp | 29 ++++++++++++++ clang/test/CodeGen/profile-continuous.c | 16 ++++++++ 6 files changed, 83 insertions(+), 18 deletions(-) create mode 100644 clang/test/CodeGen/profile-continuous.c diff --git a/clang/docs/UsersManual.rst b/clang/docs/UsersManual.rst index 260e84910c6f78..1e509906733997 100644 --- a/clang/docs/UsersManual.rst +++ b/clang/docs/UsersManual.rst @@ -3033,6 +3033,14 @@ indexed format, regardeless whether it is produced by frontend or the IR pass. overhead. ``prefer-atomic`` will be transformed to ``atomic`` when supported by the target, or ``single`` otherwise. +.. option:: -fprofile-continuous + + Enables continuous PGO mode where profile counter updates are continuously + synced to a file. This option sets any neccessary modifiers (currently ``%c``) + in the default profile filename and passes any necessary flags to the + middle-end to support this mode. Value profiling is not supported in + continuous mode. + .. option:: -ftemporal-profile Enables the temporal profiling extension for IRPGO to improve startup time by diff --git a/clang/include/clang/Basic/CodeGenOptions.def b/clang/include/clang/Basic/CodeGenOptions.def index 0f4ed13d5f3d8c..bbaf8b183222e9 100644 --- a/clang/include/clang/Basic/CodeGenOptions.def +++ b/clang/include/clang/Basic/CodeGenOptions.def @@ -221,6 +221,7 @@ AFFECTING_VALUE_CODEGENOPT(OptimizationLevel, 2, 0) ///< The -O[0-3] option spec AFFECTING_VALUE_CODEGENOPT(OptimizeSize, 2, 0) ///< If -Os (==1) or -Oz (==2) is specified. CODEGENOPT(AtomicProfileUpdate , 1, 0) ///< Set -fprofile-update=atomic +CODEGENOPT(ContinuousProfileSync, 1, 0) ///< Enable continuous PGO mode /// Choose profile instrumenation kind or no instrumentation. ENUM_CODEGENOPT(ProfileInstr, ProfileInstrKind, 2, ProfileNone) /// Choose profile kind for PGO use compilation. diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 2721c1b5d8dc55..5a7e64d5b5a96f 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -1886,6 +1886,11 @@ def fprofile_update_EQ : Joined<["-"], "fprofile-update=">, Values<"atomic,prefer-atomic,single">, MetaVarName<"<method>">, HelpText<"Set update method of profile counters">, MarshallingInfoFlag<CodeGenOpts<"AtomicProfileUpdate">>; +def fprofile_continuous : Flag<["-"], "fprofile-continuous">, + Group<f_Group>, Visibility<[ClangOption, CC1Option]>, + HelpText<"Enable Continuous PGO mode">, + MarshallingInfoFlag<CodeGenOpts<"ContinuousProfileSync">>; + defm pseudo_probe_for_profiling : BoolFOption<"pseudo-probe-for-profiling", CodeGenOpts<"PseudoProbeForProfiling">, DefaultFalse, PosFlag<SetTrue, [], [ClangOption], "Emit">, diff --git a/clang/lib/CodeGen/BackendUtil.cpp b/clang/lib/CodeGen/BackendUtil.cpp index 3951ad01497cca..afafa8af585c71 100644 --- a/clang/lib/CodeGen/BackendUtil.cpp +++ b/clang/lib/CodeGen/BackendUtil.cpp @@ -133,6 +133,16 @@ std::string getDefaultProfileGenName() { : "default_%m.profraw"; } +// Path and name of file used for profile generation +std::string getProfileGenName(const CodeGenOptions &CodeGenOpts) { + std::string FileName = CodeGenOpts.InstrProfileOutput.empty() + ? getDefaultProfileGenName() + : CodeGenOpts.InstrProfileOutput; + if (CodeGenOpts.ContinuousProfileSync) + FileName = "%c" + FileName; + return FileName; +} + class EmitAssemblyHelper { CompilerInstance &CI; DiagnosticsEngine &Diags; @@ -550,7 +560,9 @@ getInstrProfOptions(const CodeGenOptions &CodeGenOpts, return std::nullopt; InstrProfOptions Options; Options.NoRedZone = CodeGenOpts.DisableRedZone; - Options.InstrProfileOutput = CodeGenOpts.InstrProfileOutput; + Options.InstrProfileOutput = CodeGenOpts.ContinuousProfileSync + ? ("%c" + CodeGenOpts.InstrProfileOutput) + : CodeGenOpts.InstrProfileOutput; Options.Atomic = CodeGenOpts.AtomicProfileUpdate; return Options; } @@ -811,13 +823,12 @@ void EmitAssemblyHelper::RunOptimizationPipeline( if (CodeGenOpts.hasProfileIRInstr()) // -fprofile-generate. - PGOOpt = PGOOptions( - CodeGenOpts.InstrProfileOutput.empty() ? getDefaultProfileGenName() - : CodeGenOpts.InstrProfileOutput, - "", "", CodeGenOpts.MemoryProfileUsePath, nullptr, PGOOptions::IRInstr, - PGOOptions::NoCSAction, ClPGOColdFuncAttr, - CodeGenOpts.DebugInfoForProfiling, - /*PseudoProbeForProfiling=*/false, CodeGenOpts.AtomicProfileUpdate); + PGOOpt = PGOOptions(getProfileGenName(CodeGenOpts), "", "", + CodeGenOpts.MemoryProfileUsePath, nullptr, + PGOOptions::IRInstr, PGOOptions::NoCSAction, + ClPGOColdFuncAttr, CodeGenOpts.DebugInfoForProfiling, + /*PseudoProbeForProfiling=*/false, + CodeGenOpts.AtomicProfileUpdate); else if (CodeGenOpts.hasProfileIRUse()) { // -fprofile-use. auto CSAction = CodeGenOpts.hasProfileCSIRUse() ? PGOOptions::CSIRUse @@ -861,18 +872,13 @@ void EmitAssemblyHelper::RunOptimizationPipeline( PGOOpt->Action != PGOOptions::SampleUse && "Cannot run CSProfileGen pass with ProfileGen or SampleUse " " pass"); - PGOOpt->CSProfileGenFile = CodeGenOpts.InstrProfileOutput.empty() - ? getDefaultProfileGenName() - : CodeGenOpts.InstrProfileOutput; + PGOOpt->CSProfileGenFile = getProfileGenName(CodeGenOpts); PGOOpt->CSAction = PGOOptions::CSIRInstr; } else - PGOOpt = PGOOptions("", - CodeGenOpts.InstrProfileOutput.empty() - ? getDefaultProfileGenName() - : CodeGenOpts.InstrProfileOutput, - "", /*MemoryProfile=*/"", nullptr, - PGOOptions::NoAction, PGOOptions::CSIRInstr, - ClPGOColdFuncAttr, CodeGenOpts.DebugInfoForProfiling); + PGOOpt = PGOOptions("", getProfileGenName(CodeGenOpts), "", + /*MemoryProfile=*/"", nullptr, PGOOptions::NoAction, + PGOOptions::CSIRInstr, ClPGOColdFuncAttr, + CodeGenOpts.DebugInfoForProfiling); } if (TM) TM->setPGOOption(PGOOpt); diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index 33f08cf28feca1..8aefa82951edbc 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -580,6 +580,7 @@ static void addPGOAndCoverageFlags(const ToolChain &TC, Compilation &C, const ArgList &Args, SanitizerArgs &SanArgs, ArgStringList &CmdArgs) { const Driver &D = TC.getDriver(); + const llvm::Triple &T = TC.getTriple(); auto *PGOGenerateArg = Args.getLastArg(options::OPT_fprofile_generate, options::OPT_fprofile_generate_EQ, options::OPT_fno_profile_generate); @@ -785,6 +786,34 @@ static void addPGOAndCoverageFlags(const ToolChain &TC, Compilation &C, D.Diag(diag::err_drv_unsupported_option_argument) << A->getSpelling() << Val; } + if (const auto *A = Args.getLastArg(options::OPT_fprofile_continuous)) { + if (!PGOGenerateArg && !CSPGOGenerateArg && !ProfileGenerateArg) + D.Diag(clang::diag::err_drv_argument_only_allowed_with) + << A->getSpelling() + << "-fprofile-generate, -fprofile-instr-generate, or " + "-fcs-profile-generate"; + else { + CmdArgs.push_back("-fprofile-continuous"); + // Platforms that require a bias variable: + if (T.isOSFuchsia() || T.isOSBinFormatELF() || T.isOSAIX()) { + CmdArgs.push_back("-mllvm"); + CmdArgs.push_back("-runtime-counter-relocation"); + } + // -fprofile-instr-generate does not decide the profile file name in the + // FE, and so it does not define the filename symbol + // (__llvm_profile_filename). Instead, the runtime uses the name + // "default.profraw" for the profile file. When continuous mode is ON, we + // will create the filename symbol so that we can insert the "%c" + // modifier. + if (ProfileGenerateArg && + (ProfileGenerateArg->getOption().matches( + options::OPT_fprofile_instr_generate) || + (ProfileGenerateArg->getOption().matches( + options::OPT_fprofile_instr_generate_EQ) && + strlen(ProfileGenerateArg->getValue()) == 0))) + CmdArgs.push_back("-fprofile-instrument-path=default.profraw"); + } + } int FunctionGroups = 1; int SelectedFunctionGroup = 0; diff --git a/clang/test/CodeGen/profile-continuous.c b/clang/test/CodeGen/profile-continuous.c new file mode 100644 index 00000000000000..1db31c2f162b27 --- /dev/null +++ b/clang/test/CodeGen/profile-continuous.c @@ -0,0 +1,16 @@ +// RUN: %clang %s -S -emit-llvm -fprofile-generate -fprofile-continuous -o - | FileCheck %s --check-prefix=IRPGO +// RUN: %clang %s -S -emit-llvm -fprofile-generate=mydir -fprofile-continuous -o - | FileCheck %s --check-prefix=IRPGO_EQ +// RUN: %clang %s -S -emit-llvm -fcs-profile-generate -fprofile-continuous -O -o - | FileCheck %s --check-prefix=CSIRPGO +// RUN: %clang %s -S -emit-llvm -fprofile-instr-generate -fprofile-continuous -o - | FileCheck %s --check-prefix=CLANG_PGO +// RUN: %clang %s -S -emit-llvm -fprofile-instr-generate= -fprofile-continuous -o - | FileCheck %s --check-prefix=CLANG_PGO +// RUN: %clang %s -S -emit-llvm -fprofile-instr-generate=foo.profraw -fprofile-continuous -o - | FileCheck %s --check-prefix=CLANG_PGO_EQ + +// RUN: not %clang -### %s -fprofile-continuous -c 2>&1 | FileCheck %s --check-prefix=ERROR + +// IRPGO: @__llvm_profile_filename = {{.*}} c"%cdefault_%m.profraw\00" +// IRPGO_EQ: @__llvm_profile_filename = {{.*}} c"%cmydir/default_%m.profraw\00" +// CSIRPGO: @__llvm_profile_filename = {{.*}} c"%cdefault_%m.profraw\00" +// CLANG_PGO: @__llvm_profile_filename = {{.*}} c"%cdefault.profraw\00" +// CLANG_PGO_EQ: @__llvm_profile_filename = {{.*}} c"%cfoo.profraw\00" +// ERROR: clang: error: invalid argument '-fprofile-continuous' only allowed with '-fprofile-generate, -fprofile-instr-generate, or -fcs-profile-generate' +void foo(){} >From 5d9db9a4c3dd33d26a5e8578807d81242ae476ce Mon Sep 17 00:00:00 2001 From: Wael Yehia <wye...@ca.ibm.com> Date: Mon, 27 Jan 2025 17:18:37 +0000 Subject: [PATCH 2/2] Add example to the user documenation --- clang/docs/UsersManual.rst | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/clang/docs/UsersManual.rst b/clang/docs/UsersManual.rst index 1e509906733997..d9b29433468f93 100644 --- a/clang/docs/UsersManual.rst +++ b/clang/docs/UsersManual.rst @@ -3041,6 +3041,16 @@ indexed format, regardeless whether it is produced by frontend or the IR pass. middle-end to support this mode. Value profiling is not supported in continuous mode. + .. code-block:: console + + $ clang++ -O2 -fprofile-generate -fprofile-continuous code.cc -o code + + Running `./code` will collect the profile and write it to the + `default_xxxx.profraw` file. However, if `./code` abruptly terminates or does + not call `exit()`, in continuous mode the profile collected up to the point of + termination will be available in `default_xxxx.profraw` while in the + non-continuous mode, no profile file is generated. + .. option:: -ftemporal-profile Enables the temporal profiling extension for IRPGO to improve startup time by _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits