Author: Ellis Hoag Date: 2023-05-31T17:53:46-07:00 New Revision: 85af42df5dbb964d767feb16a5551dddb36fd4f1
URL: https://github.com/llvm/llvm-project/commit/85af42df5dbb964d767feb16a5551dddb36fd4f1 DIFF: https://github.com/llvm/llvm-project/commit/85af42df5dbb964d767feb16a5551dddb36fd4f1.diff LOG: [lld] add context-sensitive PGO options for MachO Enable support for CSPGO for lld MachO targets. Since lld MachO does not support `-plugin-opt=`, we need to create the `--cs-profile-generate` and `--cs-profile-path=` options and propagate them in `Darwin.cpp`. These flags are not supported by ld64. Also outline code into `getLastCSProfileGenerateArg()` to share between `CommonArgs.cpp` and `Darwin.cpp`. CSPGO is already implemented for ELF (https://reviews.llvm.org/D56675) and COFF (https://reviews.llvm.org/D98763). Reviewed By: MaskRay Differential Revision: https://reviews.llvm.org/D151589 Added: lld/test/MachO/cspgo-gen.ll lld/test/MachO/cspgo-use.ll Modified: clang/lib/Driver/ToolChains/Clang.cpp clang/lib/Driver/ToolChains/CommonArgs.cpp clang/lib/Driver/ToolChains/CommonArgs.h clang/lib/Driver/ToolChains/Darwin.cpp clang/test/Driver/cspgo-lto.c lld/MachO/Config.h lld/MachO/Driver.cpp lld/MachO/LTO.cpp lld/MachO/Options.td lld/test/lit.cfg.py Removed: ################################################################################ diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index e22c2ce7f2ede..02eec4d59b620 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -716,12 +716,7 @@ static void addPGOAndCoverageFlags(const ToolChain &TC, Compilation &C, PGOGenerateArg->getOption().matches(options::OPT_fno_profile_generate)) PGOGenerateArg = nullptr; - 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 *CSPGOGenerateArg = getLastCSProfileGenerateArg(Args); auto *ProfileGenerateArg = Args.getLastArg( options::OPT_fprofile_instr_generate, diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp index 57bf345f1708e..a952fdbacb386 100644 --- a/clang/lib/Driver/ToolChains/CommonArgs.cpp +++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp @@ -772,16 +772,7 @@ void tools::addLTOOptions(const ToolChain &ToolChain, const ArgList &Args, "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( @@ -794,7 +785,7 @@ void tools::addLTOOptions(const ToolChain &ToolChain, const ArgList &Args, 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)) @@ -1348,6 +1339,17 @@ void tools::claimNoWarnArgs(const ArgList &Args) { 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/CommonArgs.h b/clang/lib/Driver/ToolChains/CommonArgs.h index c196cbc28e218..66948f3f586ba 100644 --- a/clang/lib/Driver/ToolChains/CommonArgs.h +++ b/clang/lib/Driver/ToolChains/CommonArgs.h @@ -143,6 +143,7 @@ void addHIPRuntimeLibArgs(const ToolChain &TC, const llvm::opt::ArgList &Args, 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/Darwin.cpp b/clang/lib/Driver/ToolChains/Darwin.cpp index 3ab8bc8c8ec9f..123057a539b5b 100644 --- a/clang/lib/Driver/ToolChains/Darwin.cpp +++ b/clang/lib/Driver/ToolChains/Darwin.cpp @@ -449,6 +449,23 @@ void darwin::Linker::AddLinkArgs(Compilation &C, const ArgList &Args, Args.AddAllArgs(CmdArgs, options::OPT_dylinker__install__name); Args.AddLastArg(CmdArgs, options::OPT_dylinker); Args.AddLastArg(CmdArgs, options::OPT_Mach); + + if (LinkerIsLLD) { + if (auto *CSPGOGenerateArg = getLastCSProfileGenerateArg(Args)) { + SmallString<128> Path(CSPGOGenerateArg->getNumValues() == 0 + ? "" + : CSPGOGenerateArg->getValue()); + llvm::sys::path::append(Path, "default_%m.profraw"); + CmdArgs.push_back("--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)); + } + } } /// Determine whether we are linking the ObjC runtime. diff --git a/clang/test/Driver/cspgo-lto.c b/clang/test/Driver/cspgo-lto.c index d793400889d85..a22b2f83c4aad 100644 --- 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 -fuse-ld=lld -fprofile-use 2>&1 | FileCheck %s --check-prefix=DARWIN-USE1 +// RUN: %clang --target=apple-arm64-ios -### %t.o -flto=thin -fuse-ld=lld -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 -fuse-ld=lld -fcs-profile-generate 2>&1 | FileCheck %s --check-prefix=DARWIN-GEN1 +// RUN: %clang --target=apple-arm64-ios -### %t.o -flto=thin -fuse-ld=lld -fcs-profile-generate=directory 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=directory{{(/|\\\\)}}default_%m.profraw" diff --git a/lld/MachO/Config.h b/lld/MachO/Config.h index 27586c8320c63..3fefafc81bc2b 100644 --- a/lld/MachO/Config.h +++ b/lld/MachO/Config.h @@ -206,6 +206,8 @@ struct Configuration { std::vector<SectionAlign> sectionAlignments; std::vector<SegmentProtection> segmentProtections; bool ltoDebugPassManager = false; + bool csProfileGenerate = false; + llvm::StringRef csProfilePath; bool callGraphProfileSort = false; llvm::StringRef printSymbolOrder; diff --git a/lld/MachO/Driver.cpp b/lld/MachO/Driver.cpp index 595a540a9cc11..ddd786e36bfc2 100644 --- a/lld/MachO/Driver.cpp +++ b/lld/MachO/Driver.cpp @@ -1637,6 +1637,8 @@ bool macho::link(ArrayRef<const char *> argsArr, llvm::raw_ostream &stdoutOS, config->ignoreAutoLinkOptions.insert(arg->getValue()); config->strictAutoLink = args.hasArg(OPT_strict_auto_link); config->ltoDebugPassManager = args.hasArg(OPT_lto_debug_pass_manager); + 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 index 0e8e1056326f9..fdae7e4bd1b7b 100644 --- a/lld/MachO/LTO.cpp +++ b/lld/MachO/LTO.cpp @@ -69,6 +69,8 @@ static lto::Config createConfig() { c.TimeTraceEnabled = config->timeTraceEnabled; c.TimeTraceGranularity = config->timeTraceGranularity; c.DebugPassManager = config->ltoDebugPassManager; + 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 index d564ebd34ef77..9970fa69bf51e 100644 --- a/lld/MachO/Options.td +++ b/lld/MachO/Options.td @@ -126,6 +126,10 @@ def check_category_conflicts : Flag<["--"], "check-category-conflicts">, Group<grp_lld>; def lto_debug_pass_manager: Flag<["--"], "lto-debug-pass-manager">, HelpText<"Debug new pass manager">, Group<grp_lld>; +def cs_profile_generate: Flag<["--"], "cs-profile-generate">, + HelpText<"Perform context senstive PGO instrumentation">, Group<grp_lld>; +def cs_profile_path: Joined<["--"], "cs-profile-path=">, + HelpText<"Context sensitive profile file path">, Group<grp_lld>; // 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 diff --git a/lld/test/MachO/cspgo-gen.ll b/lld/test/MachO/cspgo-gen.ll new file mode 100644 index 0000000000000..00c86aeb0e55f --- /dev/null +++ b/lld/test/MachO/cspgo-gen.ll @@ -0,0 +1,16 @@ +; REQUIRES: x86 + +; RUN: llvm-as %s -o %t.o +; RUN: %lld -dylib --cs-profile-generate --cs-profile-path=default_%m.profraw %t.o -o %t --lto-debug-pass-manager 2>&1 | FileCheck %s --implicit-check-not=PGOInstrumentation + +; CHECK: PGOInstrumentationGen + +target triple = "x86_64-apple-darwin" +target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" + +@__llvm_profile_runtime = global i32 0, align 4 + +define void @foo() { +entry: + ret void +} diff --git a/lld/test/MachO/cspgo-use.ll b/lld/test/MachO/cspgo-use.ll new file mode 100644 index 0000000000000..3d01cd58adaa9 --- /dev/null +++ b/lld/test/MachO/cspgo-use.ll @@ -0,0 +1,18 @@ +; REQUIRES: x86 + +; Create an empty profile +; RUN: echo > %t.proftext +; RUN: llvm-profdata merge %t.proftext -o %t.profdata + +; RUN: llvm-as %s -o %t.o +; RUN: %lld -dylib --cs-profile-path=%t.profdata %t.o -o %t --lto-debug-pass-manager 2>&1 | FileCheck %s --implicit-check-not=PGOInstrumentation + +; CHECK: Running pass: PGOInstrumentationUse + +target triple = "x86_64-apple-darwin" +target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" + +define void @foo() { +entry: + ret void +} diff --git a/lld/test/lit.cfg.py b/lld/test/lit.cfg.py index e03a6dcf47fd9..798e08e4dfb77 100644 --- a/lld/test/lit.cfg.py +++ b/lld/test/lit.cfg.py @@ -45,6 +45,7 @@ "llvm-objdump", "llvm-otool", "llvm-pdbutil", + "llvm-profdata", "llvm-dwarfdump", "llvm-readelf", "llvm-readobj", _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits