diff --git a/clang/include/clang/Basic/CodeGenOptions.def b/clang/include/clang/Basic/CodeGenOptions.def --- a/clang/include/clang/Basic/CodeGenOptions.def +++ b/clang/include/clang/Basic/CodeGenOptions.def @@ -162,6 +162,7 @@ CODEGENOPT(NullPointerIsValid , 1, 0) ///< Assume Null pointer deference is defined. CODEGENOPT(CorrectlyRoundedDivSqrt, 1, 0) ///< -cl-fp32-correctly-rounded-divide-sqrt CODEGENOPT(UniqueInternalLinkageNames, 1, 0) ///< Internal Linkage symbols get unique names. +CODEGENOPT(SplitMachineFunctions, 1, 0) ///< Split machine functions using profile information. /// When false, this attempts to generate code as if the result of an /// overflowing conversion matches the overflowing behavior of a target's native diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -1996,6 +1996,9 @@ defm unique_section_names : OptOutFFlag<"unique-section-names", "", "Don't use unique names for text and data sections">; +defm split_machine_functions: OptInFFlag<"split-machine-functions", + "Enable", "Disable", " late function splitting using profile information (x86 ELF)">; + defm strict_return : OptOutFFlag<"strict-return", "", "Don't treat control flow paths that fall off the end of a non-void function as unreachable">; diff --git a/clang/lib/CodeGen/BackendUtil.cpp b/clang/lib/CodeGen/BackendUtil.cpp --- a/clang/lib/CodeGen/BackendUtil.cpp +++ b/clang/lib/CodeGen/BackendUtil.cpp @@ -514,6 +514,7 @@ Options.BBSectionsFuncListBuf = std::move(*MBOrErr); } + Options.EnableMachineFunctionSplitter = CodeGenOpts.SplitMachineFunctions; Options.FunctionSections = CodeGenOpts.FunctionSections; Options.DataSections = CodeGenOpts.DataSections; Options.UniqueSectionNames = CodeGenOpts.UniqueSectionNames; diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -4911,6 +4911,26 @@ options::OPT_fno_unique_basic_block_section_names, false)) CmdArgs.push_back("-funique-basic-block-section-names"); + if (Arg *A = Args.getLastArg(options::OPT_fsplit_machine_functions, + options::OPT_fno_split_machine_functions)) { + // This codegen pass is only available on x86-elf targets. + if (Triple.isX86() && Triple.isOSBinFormatELF()) { + if (A->getOption().matches(options::OPT_fsplit_machine_functions)) { + // If the flag is enabled but no profile information is available then + // emit a warning. + if (getLastProfileUseArg(Args) || getLastProfileSampleUseArg(Args)) { + A->render(Args, CmdArgs); + } else { + D.Diag(diag::warn_drv_diagnostics_hotness_requires_pgo) + << A->getAsString(Args); + } + } + } else { + D.Diag(diag::err_drv_unsupported_opt_for_target) + << A->getAsString(Args) << TripleStr; + } + } + Args.AddLastArg(CmdArgs, options::OPT_finstrument_functions, options::OPT_finstrument_functions_after_inlining, options::OPT_finstrument_function_entry_bare); diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -998,6 +998,8 @@ Opts.UniqueInternalLinkageNames = Args.hasArg(OPT_funique_internal_linkage_names); + Opts.SplitMachineFunctions = Args.hasArg(OPT_fsplit_machine_functions); + Opts.MergeFunctions = Args.hasArg(OPT_fmerge_functions); Opts.NoUseJumpTables = Args.hasArg(OPT_fno_jump_tables); diff --git a/clang/test/Driver/fsplit-machine-functions.c b/clang/test/Driver/fsplit-machine-functions.c new file mode 100644 --- /dev/null +++ b/clang/test/Driver/fsplit-machine-functions.c @@ -0,0 +1,9 @@ +// RUN: %clang -### -target x86_64 -fprofile-use=default.profdata -fsplit-machine-functions %s -c 2>&1 | FileCheck -check-prefix=CHECK-OPT %s +// RUN: %clang -### -target x86_64 -fprofile-use=default.profdata -fsplit-machine-functions -fno-split-machine-functions %s -c 2>&1 | FileCheck -check-prefix=CHECK-NOOPT %s +// RUN: %clang -### -target x86_64 -fsplit-machine-functions %s 2>&1 | FileCheck -check-prefix=CHECK-WARN %s +// RUN: not %clang -c -target arm-unknown-linux -fsplit-machine-functions %s 2>&1 | FileCheck -check-prefix=CHECK-TRIPLE %s + +// CHECK-OPT: "-fsplit-machine-functions" +// CHECK-NOOPT-NOT: "-fsplit-machine-functions" +// CHECK-WARN: warning: argument '-fsplit-machine-functions' requires profile-guided optimization information +// CHECK-TRIPLE: error: unsupported option '-fsplit-machine-functions' for target