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 @@ -1191,6 +1191,46 @@ CodeGenOpts<"CoverageMapping">, DefaultFalse, PosFlag, NegFlag, BothFlags<[CoreOption]>>; + +def fmachine_profile_generate : Flag<["-"], "fmachine-profile-generate">, Group, Flags<[CC1Option]>, + HelpText<"Generate MIP instrumented code.">; +def fno_machine_profile_generate : Flag<["-"], "fno-machine-profile-generate">, Group, Flags<[CC1Option]>, + HelpText<"Disable MIP instrumented code.">; +def fmachine_profile_function_coverage : Flag<["-"], "fmachine-profile-function-coverage">, Group, + Flags<[CC1Option]>, HelpText<"Enable MIP machine function coverage instrumentation.">; +def fno_machine_profile_function_coverage : Flag<["-"], "fno-machine-profile-function-coverage">, Group, + Flags<[CC1Option]>, HelpText<"Disable MIP machine function coverage instrumentation.">; +def fmachine_profile_block_coverage : Flag<["-"], "fmachine-profile-block-coverage">, Group, + Flags<[CC1Option]>, HelpText<"Enable MIP machine basic block coverage instrumentation.">; +def fno_machine_profile_block_coverage : Flag<["-"], "fno-machine-profile-block-coverage">, Group, + Flags<[CC1Option]>, HelpText<"Disable MIP machine basic block coverage instrumentation.">; +def fmachine_profile_call_graph : Flag<["-"], "fmachine-profile-call-graph">, Group, Flags<[CC1Option]>, + HelpText<"Enable full MIP instrumentation. Cannot be used with -fmachine-profile-function-coverage.">; +def fno_machine_profile_call_graph : Flag<["-"], "fno-machine-profile-call-graph">, Group, Flags<[CC1Option]>, + HelpText<"Disable full MIP instrumentation.">; +def fmachine_profile_runtime_buffer_EQ : Joined<["-"], "fmachine-profile-runtime-buffer=">, Group, + Flags<[CC1Option]>, MetaVarName<"">, + HelpText<"Allocate a buffer of bytes to hold machine function call samples.">; +def fmachine_profile_link_unit_name_EQ : Joined<["-"], "fmachine-profile-link-unit-name=">, + Group, Flags<[CC1Option]>, MetaVarName<"">, + HelpText<"Use to identify this link unit.">; +def fno_machine_profile_runtime : Flag<["-"], "fno-machine-profile-runtime">, Group, Flags<[CC1Option]>, + HelpText<"Do not link the machine profile runtime.">; +def fno_machine_profile_dump : Flag<["-"], "fno-machine-profile-dump">, Group, Flags<[CC1Option]>, + HelpText<"Do not dump a raw machine profile when the program exits.">; +def fmachine_profile_function_group_count_EQ : Joined<["-"], "fmachine-profile-function-group-count=">, Group, + Flags<[CC1Option]>, MetaVarName<"">, + HelpText<"Partition the machine functions into groups and instrument the group specified by -fmachine-profile-selected-function-group.">; +def fmachine_profile_selected_function_group_EQ : Joined<["-"], "fmachine-profile-selected-function-group=">, + Group, Flags<[CC1Option]>, MetaVarName<"">, + HelpText<"Instrument only group . Must be in the range [0, -fmachine-profile-function-group-count).">; +def fmachine_profile_min_instruction_count_EQ : Joined<["-"], "fmachine-profile-min-instruction-count=">, + Group, Flags<[CC1Option]>, MetaVarName<"">, + HelpText<"Do not instrument machine functions that have fewer than instructions">; +def fmachine_profile_use_EQ : Joined<["-"], "fmachine-profile-use=">, + Group, Flags<[CC1Option]>, MetaVarName<"">, + HelpText<"Use MIP profile data from for profile-guided optimization, where is a comma separated ordered list of .mip profiles.">; + def fprofile_generate : Flag<["-"], "fprofile-generate">, Group, Flags<[CoreOption]>, HelpText<"Generate instrumented code to collect execution counts into default.profraw (overridden by LLVM_PROFILE_FILE env var)">; diff --git a/clang/include/clang/Driver/ToolChain.h b/clang/include/clang/Driver/ToolChain.h --- a/clang/include/clang/Driver/ToolChain.h +++ b/clang/include/clang/Driver/ToolChain.h @@ -457,6 +457,9 @@ /// needsProfileRT - returns true if instrumentation profile is on. static bool needsProfileRT(const llvm::opt::ArgList &Args); + /// Returns true if machine profile instrumentation is on. + static bool needsMachineProfileRT(const llvm::opt::ArgList &Args); + /// Returns true if gcov instrumentation (-fprofile-arcs or --coverage) is on. static bool needsGCovInstrumentation(const llvm::opt::ArgList &Args); @@ -660,6 +663,11 @@ virtual void addProfileRTLibs(const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CmdArgs) const; + /// addMachineProfileRTLibs - When -fmachine-profile-generate is specified, + /// try to pass a suitable profile runtime library to the linker. + virtual void addMachineProfileRTLibs(const llvm::opt::ArgList &Args, + llvm::opt::ArgStringList &CmdArgs) const; + /// Add arguments to use system-specific CUDA includes. virtual void AddCudaIncludeArgs(const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args) const; diff --git a/clang/lib/Driver/ToolChain.cpp b/clang/lib/Driver/ToolChain.cpp --- a/clang/lib/Driver/ToolChain.cpp +++ b/clang/lib/Driver/ToolChain.cpp @@ -517,6 +517,12 @@ Args.hasArg(options::OPT_forder_file_instrumentation); } +bool ToolChain::needsMachineProfileRT(const ArgList &Args) { + return Args.hasFlag(options::OPT_fmachine_profile_generate, + options::OPT_fno_machine_profile_generate, false) && + !Args.hasArg(options::OPT_fno_machine_profile_runtime); +} + bool ToolChain::needsGCovInstrumentation(const llvm::opt::ArgList &Args) { return Args.hasArg(options::OPT_coverage) || Args.hasFlag(options::OPT_fprofile_arcs, options::OPT_fno_profile_arcs, @@ -749,6 +755,14 @@ CmdArgs.push_back(getCompilerRTArgString(Args, "profile")); } +void ToolChain::addMachineProfileRTLibs( + const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CmdArgs) const { + if (!needsMachineProfileRT(Args)) + return; + + CmdArgs.push_back(getCompilerRTArgString(Args, "mip")); +} + ToolChain::RuntimeLibType ToolChain::GetRuntimeLibType( const ArgList &Args) const { if (runtimeLibType) diff --git a/clang/lib/Driver/ToolChains/AIX.cpp b/clang/lib/Driver/ToolChains/AIX.cpp --- a/clang/lib/Driver/ToolChains/AIX.cpp +++ b/clang/lib/Driver/ToolChains/AIX.cpp @@ -155,6 +155,8 @@ if (getToolChain().ShouldLinkCXXStdlib(Args)) getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs); + ToolChain.addMachineProfileRTLibs(Args, CmdArgs); + if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) { AddRunTimeLibs(ToolChain, D, CmdArgs, Args); 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 @@ -967,6 +967,107 @@ } } +static void addMachineProfileFlags(const Driver &D, const ArgList &Args, + ArgStringList &CmdArgs) { + // FIXME: Machine profile generation flags need to be added to linker args + // when LTO is on. + if (!D.isUsingLTO()) { + bool HasMIPFlags = false; + if (Args.hasFlag(options::OPT_fmachine_profile_generate, + options::OPT_fno_machine_profile_generate, false)) { + CmdArgs.push_back("-mllvm"); + CmdArgs.push_back("-enable-machine-instrumentation"); + // TODO: Add a tool to run `llvm-objcopy` and `llvm-mipdata` to fully + // extract and create an empty .mip file after the link step. + HasMIPFlags = true; + } + + if (Arg *A = Args.getLastArg(options::OPT_fmachine_profile_use_EQ)) { + StringRef value = A->getValue(); + CmdArgs.push_back("-mllvm"); + CmdArgs.push_back(Args.MakeArgString("-machine-profile-use=" + value)); + HasMIPFlags = true; + } + + if (!HasMIPFlags) + return; + + std::string LinkUnitName; + if (const Arg *A = + Args.getLastArg(options::OPT_fmachine_profile_link_unit_name_EQ)) { + LinkUnitName = A->getValue(); + } else if (const Arg *A = Args.getLastArg(options::OPT_o)) { + LinkUnitName = A->getValue(); + } else { + LinkUnitName = D.getDefaultImageName(); + } + CmdArgs.push_back("-mllvm"); + CmdArgs.push_back(Args.MakeArgString("-link-unit-name=" + LinkUnitName)); + + if (Args.hasFlag(options::OPT_fmachine_profile_function_coverage, + options::OPT_fno_machine_profile_function_coverage, + false)) { + CmdArgs.push_back("-mllvm"); + CmdArgs.push_back("-enable-machine-function-coverage"); + } else if (Args.hasFlag(options::OPT_fmachine_profile_call_graph, + options::OPT_fno_machine_profile_call_graph, + true)) { + CmdArgs.push_back("-mllvm"); + CmdArgs.push_back("-enable-machine-call-graph"); + } + + if (Args.hasFlag(options::OPT_fmachine_profile_block_coverage, + options::OPT_fno_machine_profile_block_coverage, false)) { + CmdArgs.push_back("-mllvm"); + CmdArgs.push_back("-enable-machine-block-coverage"); + } + + if (const Arg *A = + Args.getLastArg(options::OPT_fmachine_profile_runtime_buffer_EQ)) { + StringRef S = A->getValue(); + unsigned RuntimeBufferSize; + if (S.getAsInteger(0, RuntimeBufferSize)) + D.Diag(clang::diag::err_drv_invalid_value) << A->getAsString(Args) << S; + CmdArgs.push_back("-mllvm"); + CmdArgs.push_back(Args.MakeArgString("-machine-profile-runtime-buffer=" + + Twine(RuntimeBufferSize))); + } + + unsigned GroupCount = 1; + if (const Arg *A = Args.getLastArg( + options::OPT_fmachine_profile_function_group_count_EQ)) { + StringRef S = A->getValue(); + if (S.getAsInteger(0, GroupCount) || GroupCount < 1) + D.Diag(clang::diag::err_drv_invalid_value) << A->getAsString(Args) << S; + // TODO: Add these args in the linker if we are using LTO. + CmdArgs.push_back("-mllvm"); + CmdArgs.push_back(Args.MakeArgString( + "-machine-profile-function-group-count=" + Twine(GroupCount))); + } + + if (const Arg *A = Args.getLastArg( + options::OPT_fmachine_profile_selected_function_group_EQ)) { + unsigned SelectedGroup; + StringRef S = A->getValue(); + if (S.getAsInteger(0, SelectedGroup) || SelectedGroup >= GroupCount) + D.Diag(clang::diag::err_drv_invalid_value) << A->getAsString(Args) << S; + CmdArgs.push_back("-mllvm"); + CmdArgs.push_back(Args.MakeArgString( + "-machine-profile-selected-function-group=" + Twine(SelectedGroup))); + } + + if (const Arg *A = Args.getLastArg( + options::OPT_fmachine_profile_min_instruction_count_EQ)) { + unsigned MinInstructionCount; + StringRef S = A->getValue(); + if (S.getAsInteger(0, MinInstructionCount) || MinInstructionCount < 1) + D.Diag(clang::diag::err_drv_invalid_value) << A->getAsString(Args) << S; + CmdArgs.push_back("-mllvm"); + CmdArgs.push_back(Args.MakeArgString("-machine-profile-min-instruction-count=" + Twine(MinInstructionCount))); + } + } +} + /// Check whether the given input tree contains any compilation actions. static bool ContainsCompileAction(const Action *A) { if (isa(A) || isa(A)) @@ -5303,6 +5404,8 @@ if (!Triple.isNVPTX() && !Triple.isAMDGCN()) addPGOAndCoverageFlags(TC, C, D, Output, Args, CmdArgs); + addMachineProfileFlags(D, Args, CmdArgs); + Args.AddLastArg(CmdArgs, options::OPT_fclang_abi_compat_EQ); // Add runtime flag for PS4 when PGO, coverage, or sanitizers are enabled. diff --git a/clang/lib/Driver/ToolChains/Darwin.h b/clang/lib/Driver/ToolChains/Darwin.h --- a/clang/lib/Driver/ToolChains/Darwin.h +++ b/clang/lib/Driver/ToolChains/Darwin.h @@ -202,6 +202,14 @@ // There aren't any profiling libs for embedded targets currently. } + /// Add any profiling runtime libraries that are needed. This is essentially a + /// MachO specific version of addMachineProfileRT in Tools.cpp. + void + addMachineProfileRTLibs(const llvm::opt::ArgList &Args, + llvm::opt::ArgStringList &CmdArgs) const override { + // There aren't any profiling libs for embedded targets currently. + } + /// } /// @name ToolChain Implementation /// { @@ -329,6 +337,10 @@ void addProfileRTLibs(const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CmdArgs) const override; + void + addMachineProfileRTLibs(const llvm::opt::ArgList &Args, + llvm::opt::ArgStringList &CmdArgs) const override; + protected: /// } /// @name Darwin specific Toolchain functions diff --git a/clang/lib/Driver/ToolChains/Darwin.cpp b/clang/lib/Driver/ToolChains/Darwin.cpp --- a/clang/lib/Driver/ToolChains/Darwin.cpp +++ b/clang/lib/Driver/ToolChains/Darwin.cpp @@ -19,6 +19,7 @@ #include "clang/Driver/Options.h" #include "clang/Driver/SanitizerArgs.h" #include "llvm/ADT/StringSwitch.h" +#include "llvm/MIP/MIP.h" #include "llvm/Option/ArgList.h" #include "llvm/ProfileData/InstrProf.h" #include "llvm/Support/Path.h" @@ -657,6 +658,7 @@ CmdArgs.push_back("-allow_stack_execute"); getMachOToolChain().addProfileRTLibs(Args, CmdArgs); + getMachOToolChain().addMachineProfileRTLibs(Args, CmdArgs); StringRef Parallelism = getLTOParallelism(Args, getToolChain().getDriver()); if (!Parallelism.empty()) { @@ -1256,6 +1258,18 @@ } } +void Darwin::addMachineProfileRTLibs(const ArgList &Args, + ArgStringList &CmdArgs) const { + if (!needsMachineProfileRT(Args)) + return; + + AddLinkRuntimeLib(Args, CmdArgs, "mip", + RuntimeLinkOptions(RLO_AlwaysLink | RLO_FirstLink)); + + if (!Args.hasArg(options::OPT_fno_machine_profile_dump)) + addExportedSymbol(CmdArgs, "_" MIP_RUNTIME_SYMBOL_NAME); +} + void DarwinClang::AddLinkSanitizerLibArgs(const ArgList &Args, ArgStringList &CmdArgs, StringRef Sanitizer, diff --git a/clang/lib/Driver/ToolChains/DragonFly.cpp b/clang/lib/Driver/ToolChains/DragonFly.cpp --- a/clang/lib/Driver/ToolChains/DragonFly.cpp +++ b/clang/lib/Driver/ToolChains/DragonFly.cpp @@ -169,6 +169,7 @@ } getToolChain().addProfileRTLibs(Args, CmdArgs); + getToolChain().addMachineProfileRTLibs(Args, CmdArgs); const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath()); C.addCommand(std::make_unique(JA, *this, diff --git a/clang/lib/Driver/ToolChains/FreeBSD.cpp b/clang/lib/Driver/ToolChains/FreeBSD.cpp --- a/clang/lib/Driver/ToolChains/FreeBSD.cpp +++ b/clang/lib/Driver/ToolChains/FreeBSD.cpp @@ -365,6 +365,7 @@ } ToolChain.addProfileRTLibs(Args, CmdArgs); + ToolChain.addMachineProfileRTLibs(Args, CmdArgs); const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath()); C.addCommand(std::make_unique(JA, *this, diff --git a/clang/lib/Driver/ToolChains/Fuchsia.h b/clang/lib/Driver/ToolChains/Fuchsia.h --- a/clang/lib/Driver/ToolChains/Fuchsia.h +++ b/clang/lib/Driver/ToolChains/Fuchsia.h @@ -74,6 +74,10 @@ void addProfileRTLibs(const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CmdArgs) const override; + void + addMachineProfileRTLibs(const llvm::opt::ArgList &Args, + llvm::opt::ArgStringList &CmdArgs) const override; + RuntimeLibType GetRuntimeLibType(const llvm::opt::ArgList &Args) const override; CXXStdlibType diff --git a/clang/lib/Driver/ToolChains/Fuchsia.cpp b/clang/lib/Driver/ToolChains/Fuchsia.cpp --- a/clang/lib/Driver/ToolChains/Fuchsia.cpp +++ b/clang/lib/Driver/ToolChains/Fuchsia.cpp @@ -14,6 +14,7 @@ #include "clang/Driver/DriverDiagnostic.h" #include "clang/Driver/Options.h" #include "clang/Driver/SanitizerArgs.h" +#include "llvm/MIP/MIP.h" #include "llvm/Option/ArgList.h" #include "llvm/ProfileData/InstrProf.h" #include "llvm/Support/FileSystem.h" @@ -128,6 +129,7 @@ bool NeedsXRayDeps = addXRayRuntime(ToolChain, Args, CmdArgs); AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA); ToolChain.addProfileRTLibs(Args, CmdArgs); + ToolChain.addMachineProfileRTLibs(Args, CmdArgs); if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) { if (Args.hasArg(options::OPT_static)) @@ -447,3 +449,14 @@ Twine("-u", llvm::getInstrProfRuntimeHookVarName()))); ToolChain::addProfileRTLibs(Args, CmdArgs); } + +void Fuchsia::addMachineProfileRTLibs(const llvm::opt::ArgList &Args, + llvm::opt::ArgStringList &CmdArgs) const { + // Add linker option -u__llvm_mip_runtime to cause runtime + // initialization module to be linked in. + if (needsMachineProfileRT(Args) && + !Args.hasArg(options::OPT_fno_machine_profile_dump)) { + CmdArgs.push_back(Args.MakeArgString("-u" MIP_RUNTIME_SYMBOL_NAME)); + } + ToolChain::addProfileRTLibs(Args, CmdArgs); +} diff --git a/clang/lib/Driver/ToolChains/Gnu.cpp b/clang/lib/Driver/ToolChains/Gnu.cpp --- a/clang/lib/Driver/ToolChains/Gnu.cpp +++ b/clang/lib/Driver/ToolChains/Gnu.cpp @@ -571,6 +571,7 @@ AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA); // The profile runtime also needs access to system libraries. getToolChain().addProfileRTLibs(Args, CmdArgs); + getToolChain().addMachineProfileRTLibs(Args, CmdArgs); if (D.CCCIsCXX() && !Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) { diff --git a/clang/lib/Driver/ToolChains/Linux.h b/clang/lib/Driver/ToolChains/Linux.h --- a/clang/lib/Driver/ToolChains/Linux.h +++ b/clang/lib/Driver/ToolChains/Linux.h @@ -49,6 +49,9 @@ SanitizerMask getSupportedSanitizers() const override; void addProfileRTLibs(const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CmdArgs) const override; + void + addMachineProfileRTLibs(const llvm::opt::ArgList &Args, + llvm::opt::ArgStringList &CmdArgs) const override; std::string computeSysRoot() const override; std::string getDynamicLinker(const llvm::opt::ArgList &Args) const override; diff --git a/clang/lib/Driver/ToolChains/Linux.cpp b/clang/lib/Driver/ToolChains/Linux.cpp --- a/clang/lib/Driver/ToolChains/Linux.cpp +++ b/clang/lib/Driver/ToolChains/Linux.cpp @@ -17,6 +17,7 @@ #include "clang/Driver/Driver.h" #include "clang/Driver/Options.h" #include "clang/Driver/SanitizerArgs.h" +#include "llvm/MIP/MIP.h" #include "llvm/Option/ArgList.h" #include "llvm/ProfileData/InstrProf.h" #include "llvm/Support/Path.h" @@ -735,6 +736,17 @@ ToolChain::addProfileRTLibs(Args, CmdArgs); } +void Linux::addMachineProfileRTLibs(const llvm::opt::ArgList &Args, + llvm::opt::ArgStringList &CmdArgs) const { + // Add linker option -u__llvm_mip_runtime to cause runtime + // initialization module to be linked in. + if (needsMachineProfileRT(Args) && + !Args.hasArg(options::OPT_fno_machine_profile_dump)) { + CmdArgs.push_back(Args.MakeArgString("-u" MIP_RUNTIME_SYMBOL_NAME)); + } + ToolChain::addMachineProfileRTLibs(Args, CmdArgs); +} + llvm::DenormalMode Linux::getDefaultDenormalModeForType(const llvm::opt::ArgList &DriverArgs, const JobAction &JA, diff --git a/clang/lib/Driver/ToolChains/NetBSD.cpp b/clang/lib/Driver/ToolChains/NetBSD.cpp --- a/clang/lib/Driver/ToolChains/NetBSD.cpp +++ b/clang/lib/Driver/ToolChains/NetBSD.cpp @@ -337,6 +337,7 @@ } ToolChain.addProfileRTLibs(Args, CmdArgs); + ToolChain.addMachineProfileRTLibs(Args, CmdArgs); const char *Exec = Args.MakeArgString(ToolChain.GetLinkerPath()); C.addCommand(std::make_unique(JA, *this, diff --git a/clang/lib/Driver/ToolChains/Solaris.cpp b/clang/lib/Driver/ToolChains/Solaris.cpp --- a/clang/lib/Driver/ToolChains/Solaris.cpp +++ b/clang/lib/Driver/ToolChains/Solaris.cpp @@ -149,6 +149,7 @@ CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath("crtn.o"))); getToolChain().addProfileRTLibs(Args, CmdArgs); + getToolChain().addMachineProfileRTLibs(Args, CmdArgs); const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath()); C.addCommand(std::make_unique(JA, *this, ResponseFileSupport::None(), diff --git a/clang/test/CMakeLists.txt b/clang/test/CMakeLists.txt --- a/clang/test/CMakeLists.txt +++ b/clang/test/CMakeLists.txt @@ -118,6 +118,7 @@ llvm-lto2 llvm-modextract llvm-nm + llvm-mipdata llvm-objcopy llvm-objdump llvm-profdata diff --git a/clang/test/Driver/clang-mip-flags.c b/clang/test/Driver/clang-mip-flags.c new file mode 100644 --- /dev/null +++ b/clang/test/Driver/clang-mip-flags.c @@ -0,0 +1,49 @@ +// REQUIRES: clang-driver +// UNSUPPORTED: windows-msvc + +// RUN: %clang -### -fmachine-profile-use=/path/to/profile.mip %s 2>&1 | FileCheck %s --check-prefix USE +// USE: "-cc1" +// USE-SAME: "-mllvm" "-machine-profile-use=/path/to/profile.mip" +// USE-SAME: "-mllvm" "-link-unit-name=a.out" + +// RUN: %clang -### -fmachine-profile-use=/path/to/profile.mip -o my-executable %s 2>&1 | FileCheck %s --check-prefix USE-OUTPUT +// RUN: %clang -### -fmachine-profile-use=/path/to/profile.mip -fmachine-profile-link-unit-name=my-executable %s 2>&1 | FileCheck %s --check-prefix USE-OUTPUT +// USE-OUTPUT: "-cc1" +// USE-OUTPUT-SAME: "-mllvm" "-link-unit-name=my-executable" + +// RUN: %clang -### -fmachine-profile-generate %s 2>&1 | FileCheck %s --check-prefix GEN +// RUN: %clang -### -fno-machine-profile-generate -fmachine-profile-generate %s 2>&1 | FileCheck %s --check-prefix GEN +// GEN: "-cc1" +// GEN-SAME: "-mllvm" "-enable-machine-instrumentation" +// GEN-SAME: "-mllvm" "-link-unit-name=a.out" + +// RUN: %clang -### %s 2>&1 | FileCheck %s --check-prefix NOGEN +// RUN: %clang -### -fno-machine-profile-generate %s 2>&1 | FileCheck %s --check-prefix NOGEN +// RUN: %clang -### -fmachine-profile-generate -fno-machine-profile-generate %s 2>&1 | FileCheck %s --check-prefix NOGEN +// NOGEN-NOT: "-enable-machine-instrumentation" + +// RUN: %clang -### -fmachine-profile-generate -fmachine-profile-function-coverage %s 2>&1 | FileCheck %s --check-prefix FUNCCOV +// FUNCCOV: "-cc1" +// FUNCCOV-SAME: "-mllvm" "-enable-machine-function-coverage" + +// RUN: %clang -### -fmachine-profile-generate -fmachine-profile-block-coverage %s 2>&1 | FileCheck %s --check-prefix BLOCKCOV +// BLOCKCOV: "-cc1" +// BLOCKCOV-SAME: "-mllvm" "-enable-machine-block-coverage" + +// RUN: %clang -### -fmachine-profile-generate %s 2>&1 | FileCheck %s --check-prefix FULL +// RUN: %clang -### -fmachine-profile-generate -fmachine-profile-call-graph %s 2>&1 | FileCheck %s --check-prefix FULL +// FULL: "-cc1" +// FULL-SAME: "-mllvm" "-enable-machine-call-graph" + +// RUN: %clang -### -fmachine-profile-generate -fmachine-profile-runtime-buffer=1024 %s 2>&1 | FileCheck %s --check-prefix RUNTIMEBUF +// RUNTIMEBUF: "-cc1" +// RUNTIMEBUF-SAME: "-mllvm" "-machine-profile-runtime-buffer=1024" + +// RUN: %clang -### -fmachine-profile-generate -fmachine-profile-function-group-count=22 -fmachine-profile-selected-function-group=11 %s 2>&1 | FileCheck %s --check-prefix GEN-GROUPS +// GEN-GROUPS: "-cc1" +// GEN-GROUPS-SAME: "-mllvm" "-machine-profile-function-group-count=22" +// GEN-GROUPS-SAME: "-mllvm" "-machine-profile-selected-function-group=11" + +// RUN: %clang -### -fmachine-profile-generate -fmachine-profile-min-instruction-count=50 %s 2>&1 | FileCheck %s --check-prefix MIN-INSTR +// MIN-INSTR: "-cc1" +// MIN-INSTR-SAME: "-mllvm" "-machine-profile-min-instruction-count=50"