diff --git a/clang/lib/Driver/ToolChains/CommonArgs.h b/clang/lib/Driver/ToolChains/CommonArgs.h --- a/clang/lib/Driver/ToolChains/CommonArgs.h +++ b/clang/lib/Driver/ToolChains/CommonArgs.h @@ -148,6 +148,7 @@ const char *getAsNeededOption(const ToolChain &TC, bool as_needed); +llvm::opt::Arg *getLastCSProfileGenerateArg(const llvm::opt::ArgList &Args); llvm::opt::Arg *getLastProfileUseArg(const llvm::opt::ArgList &Args); llvm::opt::Arg *getLastProfileSampleUseArg(const llvm::opt::ArgList &Args); diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp --- a/clang/lib/Driver/ToolChains/CommonArgs.cpp +++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp @@ -786,16 +786,7 @@ "sample-profile=" + FName)); } - auto *CSPGOGenerateArg = Args.getLastArg(options::OPT_fcs_profile_generate, - options::OPT_fcs_profile_generate_EQ, - options::OPT_fno_profile_generate); - if (CSPGOGenerateArg && - CSPGOGenerateArg->getOption().matches(options::OPT_fno_profile_generate)) - CSPGOGenerateArg = nullptr; - - auto *ProfileUseArg = getLastProfileUseArg(Args); - - if (CSPGOGenerateArg) { + if (auto *CSPGOGenerateArg = getLastCSProfileGenerateArg(Args)) { CmdArgs.push_back(Args.MakeArgString(Twine(PluginOptPrefix) + ExtraDash + "cs-profile-generate")); if (CSPGOGenerateArg->getOption().matches( @@ -808,7 +799,7 @@ CmdArgs.push_back( Args.MakeArgString(Twine(PluginOptPrefix) + ExtraDash + "cs-profile-path=default_%m.profraw")); - } else if (ProfileUseArg) { + } else if (auto *ProfileUseArg = getLastProfileUseArg(Args)) { SmallString<128> Path( ProfileUseArg->getNumValues() == 0 ? "" : ProfileUseArg->getValue()); if (Path.empty() || llvm::sys::fs::is_directory(Path)) @@ -1362,6 +1353,17 @@ Args.ClaimAllArgs(options::OPT_fno_lto); } +Arg *tools::getLastCSProfileGenerateArg(const ArgList &Args) { + auto *CSPGOGenerateArg = Args.getLastArg(options::OPT_fcs_profile_generate, + options::OPT_fcs_profile_generate_EQ, + options::OPT_fno_profile_generate); + if (CSPGOGenerateArg && + CSPGOGenerateArg->getOption().matches(options::OPT_fno_profile_generate)) + CSPGOGenerateArg = nullptr; + + return CSPGOGenerateArg; +} + Arg *tools::getLastProfileUseArg(const ArgList &Args) { auto *ProfileUseArg = Args.getLastArg( options::OPT_fprofile_instr_use, options::OPT_fprofile_instr_use_EQ, 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 @@ -677,6 +677,21 @@ getMachOToolChain().addProfileRTLibs(Args, CmdArgs); + if (auto *CSPGOGenerateArg = getLastCSProfileGenerateArg(Args)) { + SmallString<128> Path(CSPGOGenerateArg->getNumValues() == 0 + ? "" + : CSPGOGenerateArg->getValue()); + llvm::sys::path::append(Path, "default_%m.profraw"); + CmdArgs.push_back(Args.MakeArgString("--cs-profile-generate")); + CmdArgs.push_back(Args.MakeArgString(Twine("--cs-profile-path=") + Path)); + } else if (auto *ProfileUseArg = getLastProfileUseArg(Args)) { + SmallString<128> Path( + ProfileUseArg->getNumValues() == 0 ? "" : ProfileUseArg->getValue()); + if (Path.empty() || llvm::sys::fs::is_directory(Path)) + llvm::sys::path::append(Path, "default.profdata"); + CmdArgs.push_back(Args.MakeArgString(Twine("--cs-profile-path=") + Path)); + } + StringRef Parallelism = getLTOParallelism(Args, getToolChain().getDriver()); if (!Parallelism.empty()) { CmdArgs.push_back("-mllvm"); diff --git a/clang/test/Driver/cspgo-lto.c b/clang/test/Driver/cspgo-lto.c --- a/clang/test/Driver/cspgo-lto.c +++ b/clang/test/Driver/cspgo-lto.c @@ -4,3 +4,17 @@ // RUN: -fprofile-use 2>&1 | FileCheck %s // CHECK: -plugin-opt=cs-profile-path=default.profdata + +// RUN: %clang -target apple-arm64-ios -### %t.o -flto=thin -fprofile-use 2>&1 | FileCheck %s --check-prefix=DARWIN-USE1 +// RUN: %clang -target apple-arm64-ios -### %t.o -flto=thin -fprofile-use=a.profdata 2>&1 | FileCheck %s --check-prefix=DARWIN-USE2 + +// DARWIN-USE1: "--cs-profile-path=default.profdata" +// DARWIN-USE2: "--cs-profile-path=a.profdata" + +// RUN: %clang -target apple-arm64-ios -### %t.o -flto=thin -fcs-profile-generate 2>&1 | FileCheck %s --check-prefix=DARWIN-GEN1 +// RUN: %clang -target apple-arm64-ios -### %t.o -flto=thin -fcs-profile-generate=/dump/here 2>&1 | FileCheck %s --check-prefix=DARWIN-GEN2 + +// DARWIN-GEN1: "--cs-profile-generate" +// DARWIN-GEN1-SAME: "--cs-profile-path=default_%m.profraw" +// DARWIN-GEN2: "--cs-profile-generate" +// DARWIN-GEN2-SAME: "--cs-profile-path=/dump/here/default_%m.profraw" diff --git a/lld/MachO/Config.h b/lld/MachO/Config.h --- a/lld/MachO/Config.h +++ b/lld/MachO/Config.h @@ -206,6 +206,8 @@ // so use a vector instead of a map. std::vector sectionAlignments; std::vector segmentProtections; + bool csProfileGenerate = false; + llvm::StringRef csProfilePath; bool callGraphProfileSort = false; llvm::StringRef printSymbolOrder; diff --git a/lld/MachO/Driver.cpp b/lld/MachO/Driver.cpp --- a/lld/MachO/Driver.cpp +++ b/lld/MachO/Driver.cpp @@ -1637,6 +1637,8 @@ for (const Arg *arg : args.filtered(OPT_ignore_auto_link_option)) config->ignoreAutoLinkOptions.insert(arg->getValue()); config->strictAutoLink = args.hasArg(OPT_strict_auto_link); + config->csProfileGenerate = args.hasArg(OPT_cs_profile_generate); + config->csProfilePath = args.getLastArgValue(OPT_cs_profile_path); for (const Arg *arg : args.filtered(OPT_alias)) { config->aliasedSymbols.push_back( diff --git a/lld/MachO/LTO.cpp b/lld/MachO/LTO.cpp --- a/lld/MachO/LTO.cpp +++ b/lld/MachO/LTO.cpp @@ -68,6 +68,8 @@ c.TimeTraceEnabled = config->timeTraceEnabled; c.TimeTraceGranularity = config->timeTraceGranularity; + c.CSIRProfile = std::string(config->csProfilePath); + c.RunCSIRInstr = config->csProfileGenerate; c.OptLevel = config->ltoo; c.CGOptLevel = config->ltoCgo; if (config->saveTemps) diff --git a/lld/MachO/Options.td b/lld/MachO/Options.td --- a/lld/MachO/Options.td +++ b/lld/MachO/Options.td @@ -124,6 +124,10 @@ def check_category_conflicts : Flag<["--"], "check-category-conflicts">, HelpText<"Check for conflicts between category & class methods">, Group; +def cs_profile_generate: Flag<["--"], "cs-profile-generate">, + HelpText<"Perform context senstive PGO instrumentation">, Group; +def cs_profile_path: Joined<["--"], "cs-profile-path=">, + HelpText<"Context sensitive profile file path">, Group; // This is a complete Options.td compiled from Apple's ld(1) manpage // dated 2018-03-07 and cross checked with ld64 source code in repo