[clang] 85af42d - [lld] add context-sensitive PGO options for MachO

Ellis Hoag via cfe-commits cfe-commits at lists.llvm.org
Wed May 31 17:53:54 PDT 2023


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"
+
+ at __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",


        


More information about the cfe-commits mailing list