From 16835b68285b46208f4327a1a9f79ec07aecd9a4 Mon Sep 17 00:00:00 2001 From: Peter Smith Date: Fri, 26 Oct 2018 11:24:35 +0100 Subject: Add command line options for marking cold functions for size optimisation There are 3 command line options To switch on the pass that marks functions for size optimisation use one of: -fprofile-opt-cold-for-size (after inlining) -fprofile-opt-cold-for-size-early (before inlining). To make the pass mark functions that are neither hot or cold for size optimisation but not minimum size optimisation use: -fmark-neutral-cold --- include/clang/Driver/Options.td | 15 +++++++++++++++ include/clang/Frontend/CodeGenOptions.def | 3 +++ lib/CodeGen/BackendUtil.cpp | 26 +++++++++++++++++++++++++- lib/CodeGen/CodeGenFunction.cpp | 3 +++ lib/Driver/ToolChains/Clang.cpp | 12 ++++++++++++ lib/Frontend/CompilerInvocation.cpp | 3 +++ 6 files changed, 61 insertions(+), 1 deletion(-) diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td index ef6e47237c..ed9dd61815 100644 --- a/include/clang/Driver/Options.td +++ b/include/clang/Driver/Options.td @@ -718,6 +718,21 @@ def fauto_profile_accurate : Flag<["-"], "fauto-profile-accurate">, Group, Alias; def fno_auto_profile_accurate : Flag<["-"], "fno-auto-profile-accurate">, Group, Alias; +def fprofile_opt_cold_for_size : Flag<["-"], "fprofile-opt-cold-for-size">, + Group, Flags<[DriverOption, CC1Option]>, + HelpText<"Use profile to optimise cold functions for size.">; +def fprofile_opt_cold_for_size_early : Flag<["-"], "fprofile-opt-cold-for-size-early">, + Group, Flags<[DriverOption, CC1Option]>, + HelpText<"Use profile to optimise cold functions for size before inlining.">; +def fno_profile_opt_cold_for_size : Flag<["-"], "fno-profile-opt-cold-for-size">, Group; +def fno_profile_opt_cold_for_size_early : Flag<["-"], "fno-profile-opt-cold-for-size-early">, Group; +def fmark_neutral_cold : Flag<["-"], "fmark-neutral-cold">, + Group, Flags<[DriverOption, CC1Option]>, + HelpText<"Mark neither hot nor cold functions for size optimization">, + DocBrief<[{When using profile information to mark functions for size optimization, mark functions that are neither hot nor cold + for size optimization. Cold functions get minimum size.}]>; +def fno_mark_neutral_cold : Flag<["-"], "fno-mark-neutral-cold">, + Group, Flags<[DriverOption]>; def fdebug_info_for_profiling : Flag<["-"], "fdebug-info-for-profiling">, Group, Flags<[CC1Option]>, HelpText<"Emit extra debug info to make sample profile more accurate.">; diff --git a/include/clang/Frontend/CodeGenOptions.def b/include/clang/Frontend/CodeGenOptions.def index cb6cc0a846..a67080b56a 100644 --- a/include/clang/Frontend/CodeGenOptions.def +++ b/include/clang/Frontend/CodeGenOptions.def @@ -119,6 +119,9 @@ CODEGENOPT(LTOUnit, 1, 0) ///< Emit IR to support LTO unit features (CFI, whole CODEGENOPT(IncrementalLinkerCompatible, 1, 0) ///< Emit an object file which can ///< be used with an incremental ///< linker. +CODEGENOPT(MarkCold, 1, 0) ///< Mark cold functions for size optimization. +CODEGENOPT(MarkColdEarly, 1, 0) ///< As Mark cold but before inlining. +CODEGENOPT(MarkNeutralCold, 1, 0) ///< Mark neither hot nor cold functions for size CODEGENOPT(MergeAllConstants , 1, 1) ///< Merge identical constants. CODEGENOPT(MergeFunctions , 1, 0) ///< Set when -fmerge-functions is enabled. CODEGENOPT(MSVolatile , 1, 0) ///< Set when /volatile:ms is enabled. diff --git a/lib/CodeGen/BackendUtil.cpp b/lib/CodeGen/BackendUtil.cpp index 698386c062..79ac49c82a 100644 --- a/lib/CodeGen/BackendUtil.cpp +++ b/lib/CodeGen/BackendUtil.cpp @@ -58,6 +58,7 @@ #include "llvm/Transforms/ObjCARC.h" #include "llvm/Transforms/Scalar.h" #include "llvm/Transforms/Scalar/GVN.h" +#include "llvm/Transforms/Scalar/MarkCold.h" #include "llvm/Transforms/Utils.h" #include "llvm/Transforms/Utils/NameAnonGlobals.h" #include "llvm/Transforms/Utils/SymbolRewriter.h" @@ -693,6 +694,15 @@ void EmitAssemblyHelper::CreatePasses(legacy::PassManager &MPM, if (!CodeGenOpts.SampleProfileFile.empty()) PMBuilder.PGOSampleUse = CodeGenOpts.SampleProfileFile; + if (CodeGenOpts.hasProfileClangUse() || CodeGenOpts.hasProfileIRUse() || + !CodeGenOpts.SampleProfileFile.empty()) { + if (CodeGenOpts.MarkCold) { + PMBuilder.EnableMarkColdAfterInline = true; + } + if (CodeGenOpts.MarkColdEarly) + PMBuilder.EnableMarkColdBeforeInline = true; + } + PMBuilder.populateFunctionPassManager(FPM); PMBuilder.populateModulePassManager(MPM); } @@ -938,7 +948,12 @@ void EmitAssemblyHelper::EmitAssemblyWithNewPassManager( // -fprofile-use. PGOOpt = PGOOptions("", CodeGenOpts.ProfileInstrumentUsePath, "", CodeGenOpts.ProfileRemappingFile, false, - CodeGenOpts.DebugInfoForProfiling); + CodeGenOpts.DebugInfoForProfiling, false); + else if (CodeGenOpts.hasProfileClangUse()) + // -fprofile-use. + PGOOpt = PGOOptions("", CodeGenOpts.ProfileInstrumentUsePath, "", + CodeGenOpts.ProfileRemappingFile, false, + CodeGenOpts.DebugInfoForProfiling, true); else if (!CodeGenOpts.SampleProfileFile.empty()) // -fprofile-sample-use PGOOpt = PGOOptions("", "", CodeGenOpts.SampleProfileFile, @@ -948,6 +963,15 @@ void EmitAssemblyHelper::EmitAssemblyWithNewPassManager( // -fdebug-info-for-profiling PGOOpt = PGOOptions("", "", "", "", false, true); + if (PGOOpt && + (CodeGenOpts.hasProfileIRUse() || CodeGenOpts.hasProfileClangUse() || + !CodeGenOpts.SampleProfileFile.empty())) { + if (CodeGenOpts.MarkCold) + PGOOpt->MarkColdAfterInline = true; + if (CodeGenOpts.MarkColdEarly) + PGOOpt->MarkColdBeforeInline = true; + } + PassBuilder PB(TM.get(), PGOOpt); LoopAnalysisManager LAM(CodeGenOpts.DebugPassManager); diff --git a/lib/CodeGen/CodeGenFunction.cpp b/lib/CodeGen/CodeGenFunction.cpp index 84d7b9e611..05c936e221 100644 --- a/lib/CodeGen/CodeGenFunction.cpp +++ b/lib/CodeGen/CodeGenFunction.cpp @@ -945,6 +945,9 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, if (CGM.getCodeGenOpts().ProfileSampleAccurate) Fn->addFnAttr("profile-sample-accurate"); + if (CGM.getCodeGenOpts().MarkNeutralCold) + Fn->addFnAttr("mark-neutral-cold"); + if (getLangOpts().OpenCL) { // Add metadata for a kernel function. if (const FunctionDecl *FD = dyn_cast_or_null(D)) diff --git a/lib/Driver/ToolChains/Clang.cpp b/lib/Driver/ToolChains/Clang.cpp index a8ddd8adc3..c2b951a58a 100644 --- a/lib/Driver/ToolChains/Clang.cpp +++ b/lib/Driver/ToolChains/Clang.cpp @@ -3706,6 +3706,18 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, true)) CmdArgs.push_back("-fno-jump-tables"); + if (Args.hasFlag(options::OPT_fprofile_opt_cold_for_size, + options::OPT_fno_profile_opt_cold_for_size, false)) + CmdArgs.push_back("-fprofile-opt-cold-for-size"); + + if (Args.hasFlag(options::OPT_fprofile_opt_cold_for_size_early, + options::OPT_fno_profile_opt_cold_for_size_early, false)) + CmdArgs.push_back("-fprofile-opt-cold-for-size-early"); + + if (Args.hasFlag(options::OPT_fmark_neutral_cold, + options::OPT_fno_mark_neutral_cold, false)) + CmdArgs.push_back("-fmark-neutral-cold"); + if (Args.hasFlag(options::OPT_fprofile_sample_accurate, options::OPT_fno_profile_sample_accurate, false)) CmdArgs.push_back("-fprofile-sample-accurate"); diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index 52c8109818..1288d4c2b3 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -763,7 +763,10 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK, Opts.NullPointerIsValid = Args.hasArg(OPT_fno_delete_null_pointer_checks); + Opts.MarkCold = Args.hasArg(OPT_fprofile_opt_cold_for_size); + Opts.MarkColdEarly = Args.hasArg(OPT_fprofile_opt_cold_for_size_early); Opts.ProfileSampleAccurate = Args.hasArg(OPT_fprofile_sample_accurate); + Opts.MarkNeutralCold = Args.hasArg(OPT_fmark_neutral_cold); Opts.PrepareForLTO = Args.hasArg(OPT_flto, OPT_flto_EQ); Opts.PrepareForThinLTO = false; -- cgit v1.2.3