[clang] [lld] [llvm] Add debug options to clang-linker-wrapper (PR #101008)

via cfe-commits cfe-commits at lists.llvm.org
Mon Jul 29 06:09:35 PDT 2024


https://github.com/macurtis-amd created https://github.com/llvm/llvm-project/pull/101008

New options:
```
clang-linker-wrapper
---------------------------
--lto-debug-pass-manager      Prints debug information for the new pass manager during LTO
--lto-in-process              Use in-process LTO even if linker supports LTO
--lto-print-pipeline-passes   Print a '-passes' compatible string describing the LTO pipeline (best-effort only).


lld
---------------------------
--lto-print-pipeline-passes   Print a '-passes' compatible string describing the LTO pipeline (best-effort only).
```

Also teaches `clang-linker-wrapper` to forward `-offload-opt=-<value>` as `-Wl,--mmlvm=<value>` to the device linker.

>From 63889d949a3451cfc9f9ba413f2712355cb7e1fa Mon Sep 17 00:00:00 2001
From: Matthew Curtis <macurtis at amd.com>
Date: Thu, 25 Jul 2024 15:37:25 -0500
Subject: [PATCH 1/5] [clang-linker-wrapper] Add option to force in-process LTO

---
 clang/test/Driver/linker-wrapper.c                   | 12 +++++++++---
 .../clang-linker-wrapper/ClangLinkerWrapper.cpp      |  6 +++++-
 .../tools/clang-linker-wrapper/LinkerWrapperOpts.td  |  4 ++++
 3 files changed, 18 insertions(+), 4 deletions(-)

diff --git a/clang/test/Driver/linker-wrapper.c b/clang/test/Driver/linker-wrapper.c
index 342907c1a3390..2a82b71839336 100644
--- a/clang/test/Driver/linker-wrapper.c
+++ b/clang/test/Driver/linker-wrapper.c
@@ -30,7 +30,7 @@ __attribute__((visibility("protected"), used)) int x;
 // RUN: clang-linker-wrapper --host-triple=x86_64-unknown-linux-gnu --dry-run --device-debug -O0 \
 // RUN:   --linker-path=/usr/bin/ld %t.o -o a.out 2>&1 | FileCheck %s --check-prefix=NVPTX-LINK-DEBUG
 
-// NVPTX-LINK-DEBUG: clang{{.*}} -o {{.*}}.img --target=nvptx64-nvidia-cuda -march=sm_70 -O2 {{.*}}.o {{.*}}.o -g 
+// NVPTX-LINK-DEBUG: clang{{.*}} -o {{.*}}.img --target=nvptx64-nvidia-cuda -march=sm_70 -O2 {{.*}}.o {{.*}}.o -g
 
 // RUN: clang-offload-packager -o %t.out \
 // RUN:   --image=file=%t.elf.o,kind=openmp,triple=amdgcn-amd-amdhsa,arch=gfx908 \
@@ -45,11 +45,17 @@ __attribute__((visibility("protected"), used)) int x;
 // RUN:   --image=file=%t.amdgpu.bc,kind=openmp,triple=amdgcn-amd-amdhsa,arch=gfx1030 \
 // RUN:   --image=file=%t.amdgpu.bc,kind=openmp,triple=amdgcn-amd-amdhsa,arch=gfx1030
 // RUN: %clang -cc1 %s -triple x86_64-unknown-linux-gnu -emit-obj -o %t.o -fembed-offload-object=%t.out
-// RUN: clang-linker-wrapper --host-triple=x86_64-unknown-linux-gnu --dry-run --save-temps -O2 \
+// RUN: clang-linker-wrapper --host-triple=x86_64-unknown-linux-gnu --wrapper-verbose --dry-run --save-temps -O2 \
 // RUN:   --linker-path=/usr/bin/ld %t.o -o a.out 2>&1 | FileCheck %s --check-prefix=AMDGPU-LTO-TEMPS
+// RUN: clang-linker-wrapper --host-triple=x86_64-unknown-linux-gnu --wrapper-verbose --dry-run --save-temps -O2 \
+// RUN:   --lto-in-process --linker-path=/usr/bin/ld %t.o -o a.out 2>&1 | FileCheck %s --check-prefix=AMDGPU-LTO-IN-PROC
 
+// AMDGPU-LTO-TEMPS-NOT: Linking bitcode files
 // AMDGPU-LTO-TEMPS: clang{{.*}} -o {{.*}}.img --target=amdgcn-amd-amdhsa -mcpu=gfx1030 -O2 -Wl,--no-undefined {{.*}}.o -save-temps
 
+// AMDGPU-LTO-IN-PROC: Linking bitcode files
+// AMDGPU-LTO-IN-PROC: clang{{.*}} -o {{.*}}.img --target=amdgcn-amd-amdhsa -mcpu=gfx1030 -O2 -Wl,--no-undefined {{.*}}.s -save-temps
+
 // RUN: clang-offload-packager -o %t.out \
 // RUN:   --image=file=%t.elf.o,kind=openmp,triple=x86_64-unknown-linux-gnu \
 // RUN:   --image=file=%t.elf.o,kind=openmp,triple=x86_64-unknown-linux-gnu
@@ -93,7 +99,7 @@ __attribute__((visibility("protected"), used)) int x;
 
 // CUDA: clang{{.*}} -o [[IMG_SM70:.+]] --target=nvptx64-nvidia-cuda -march=sm_70
 // CUDA: clang{{.*}} -o [[IMG_SM52:.+]] --target=nvptx64-nvidia-cuda -march=sm_52
-// CUDA: fatbinary{{.*}}-64 --create {{.*}}.fatbin --image=profile=sm_70,file=[[IMG_SM70]] --image=profile=sm_52,file=[[IMG_SM52]] 
+// CUDA: fatbinary{{.*}}-64 --create {{.*}}.fatbin --image=profile=sm_70,file=[[IMG_SM70]] --image=profile=sm_52,file=[[IMG_SM52]]
 // CUDA: usr/bin/ld{{.*}} {{.*}}.openmp.image.{{.*}}.o {{.*}}.cuda.image.{{.*}}.o
 
 // RUN: clang-offload-packager -o %t.out \
diff --git a/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp b/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp
index 4bb021eae25a8..acd0142d06f05 100644
--- a/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp
+++ b/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp
@@ -773,6 +773,8 @@ bool isValidCIdentifier(StringRef S) {
 Error linkBitcodeFiles(SmallVectorImpl<OffloadFile> &InputFiles,
                        SmallVectorImpl<StringRef> &OutputFiles,
                        const ArgList &Args) {
+  if (Verbose)
+    llvm::errs() << "Linking bitcode files\n";
   llvm::TimeTraceScope TimeScope("Link bitcode files");
   const llvm::Triple Triple(Args.getLastArgValue(OPT_triple_EQ));
   StringRef Arch = Args.getLastArgValue(OPT_arch_EQ);
@@ -1009,6 +1011,8 @@ Expected<StringRef> writeOffloadFile(const OffloadFile &File) {
 // Compile the module to an object file using the appropriate target machine for
 // the host triple.
 Expected<StringRef> compileModule(Module &M, OffloadKind Kind) {
+  if (Verbose)
+    llvm::errs() << "Compiling module\n";
   llvm::TimeTraceScope TimeScope("Compile module");
   std::string Msg;
   const Target *T = TargetRegistry::lookupTarget(M.getTargetTriple(), Msg);
@@ -1301,7 +1305,7 @@ Expected<SmallVector<StringRef>> linkAndWrapDeviceFiles(
     // First link and remove all the input files containing bitcode if
     // the target linker does not support it natively.
     SmallVector<StringRef> InputFiles;
-    if (!linkerSupportsLTO(LinkerArgs))
+    if (!linkerSupportsLTO(LinkerArgs) || Args.hasArg(OPT_lto_in_process))
       if (Error Err = linkBitcodeFiles(Input, InputFiles, LinkerArgs))
         return Err;
 
diff --git a/clang/tools/clang-linker-wrapper/LinkerWrapperOpts.td b/clang/tools/clang-linker-wrapper/LinkerWrapperOpts.td
index 9c27e588fc4f5..9522996a770c0 100644
--- a/clang/tools/clang-linker-wrapper/LinkerWrapperOpts.td
+++ b/clang/tools/clang-linker-wrapper/LinkerWrapperOpts.td
@@ -102,6 +102,10 @@ def offload_opt_eq_minus : Joined<["--", "-"], "offload-opt=-">, Flags<[HelpHidd
   HelpText<"Options passed to LLVM, not including the Clang invocation. Use "
            "'--offload-opt=--help' for a list of options.">;
 
+// Arguments for LTO
+def lto_in_process : Flag<["--"], "lto-in-process">,
+  Flags<[WrapperOnlyOption]>, HelpText<"Use in-process LTO even if linker supports LTO">;
+
 // Standard linker flags also used by the linker wrapper.
 def sysroot_EQ : Joined<["--"], "sysroot=">, HelpText<"Set the system root">;
 

>From a969173c3dbc83dd373e91bd528d887de98aa146 Mon Sep 17 00:00:00 2001
From: Matthew Curtis <macurtis at amd.com>
Date: Sun, 21 Jul 2024 11:02:04 -0500
Subject: [PATCH 2/5] [clang-linker-wrapper] Add '--lto-debug-pass-manager'
 flag

---
 clang/test/Driver/linker-wrapper.c                  |  4 ++++
 .../clang-linker-wrapper/ClangLinkerWrapper.cpp     | 13 ++++++++++---
 .../tools/clang-linker-wrapper/LinkerWrapperOpts.td |  2 ++
 3 files changed, 16 insertions(+), 3 deletions(-)

diff --git a/clang/test/Driver/linker-wrapper.c b/clang/test/Driver/linker-wrapper.c
index 2a82b71839336..d45cc749ac666 100644
--- a/clang/test/Driver/linker-wrapper.c
+++ b/clang/test/Driver/linker-wrapper.c
@@ -49,6 +49,8 @@ __attribute__((visibility("protected"), used)) int x;
 // RUN:   --linker-path=/usr/bin/ld %t.o -o a.out 2>&1 | FileCheck %s --check-prefix=AMDGPU-LTO-TEMPS
 // RUN: clang-linker-wrapper --host-triple=x86_64-unknown-linux-gnu --wrapper-verbose --dry-run --save-temps -O2 \
 // RUN:   --lto-in-process --linker-path=/usr/bin/ld %t.o -o a.out 2>&1 | FileCheck %s --check-prefix=AMDGPU-LTO-IN-PROC
+// RUN: clang-linker-wrapper --host-triple=x86_64-unknown-linux-gnu --wrapper-verbose --dry-run --save-temps -O2 \
+// RUN:   --lto-debug-pass-manager --linker-path=/usr/bin/ld %t.o -o a.out 2>&1 | FileCheck %s --check-prefix=AMDGPU-LTO-OPTS
 
 // AMDGPU-LTO-TEMPS-NOT: Linking bitcode files
 // AMDGPU-LTO-TEMPS: clang{{.*}} -o {{.*}}.img --target=amdgcn-amd-amdhsa -mcpu=gfx1030 -O2 -Wl,--no-undefined {{.*}}.o -save-temps
@@ -56,6 +58,8 @@ __attribute__((visibility("protected"), used)) int x;
 // AMDGPU-LTO-IN-PROC: Linking bitcode files
 // AMDGPU-LTO-IN-PROC: clang{{.*}} -o {{.*}}.img --target=amdgcn-amd-amdhsa -mcpu=gfx1030 -O2 -Wl,--no-undefined {{.*}}.s -save-temps
 
+// AMDGPU-LTO-OPTS: clang{{.*}} -o {{.*}}.img --target=amdgcn-amd-amdhsa -mcpu=gfx1030 -O2 -Wl,--no-undefined {{.*}}.o -save-temps -Wl,--save-temps -Wl,--lto-debug-pass-manager
+
 // RUN: clang-offload-packager -o %t.out \
 // RUN:   --image=file=%t.elf.o,kind=openmp,triple=x86_64-unknown-linux-gnu \
 // RUN:   --image=file=%t.elf.o,kind=openmp,triple=x86_64-unknown-linux-gnu
diff --git a/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp b/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp
index acd0142d06f05..262d677629045 100644
--- a/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp
+++ b/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp
@@ -573,8 +573,12 @@ Expected<StringRef> clang(ArrayRef<StringRef> InputFiles, const ArgList &Args) {
   if (SaveTemps)
     CmdArgs.push_back("-save-temps");
 
-  if (SaveTemps && linkerSupportsLTO(Args))
-    CmdArgs.push_back("-Wl,--save-temps");
+  if (linkerSupportsLTO(Args)) {
+    if (SaveTemps)
+      CmdArgs.push_back("-Wl,--save-temps");
+    if (Args.hasArg(OPT_lto_debug_pass_manager))
+      CmdArgs.push_back("-Wl,--lto-debug-pass-manager");
+  }
 
   if (Args.hasArg(OPT_embed_bitcode))
     CmdArgs.push_back("-Wl,--lto-emit-llvm");
@@ -759,6 +763,8 @@ std::unique_ptr<lto::LTO> createLTO(
   // TODO: Handle remark files
   Conf.HasWholeProgramVisibility = Args.hasArg(OPT_whole_program);
 
+  Conf.DebugPassManager = Args.hasArg(OPT_lto_debug_pass_manager);
+
   return std::make_unique<lto::LTO>(std::move(Conf), Backend);
 }
 
@@ -1193,7 +1199,8 @@ bundleLinkedOutput(ArrayRef<OffloadingImage> Images, const ArgList &Args,
   }
 }
 
-/// Returns a new ArgList containg arguments used for the device linking phase.
+/// Returns a new ArgList containing arguments used for the device linking
+/// phase.
 DerivedArgList getLinkerArgs(ArrayRef<OffloadFile> Input,
                              const InputArgList &Args) {
   DerivedArgList DAL = DerivedArgList(DerivedArgList(Args));
diff --git a/clang/tools/clang-linker-wrapper/LinkerWrapperOpts.td b/clang/tools/clang-linker-wrapper/LinkerWrapperOpts.td
index 9522996a770c0..5bdbec432b6fe 100644
--- a/clang/tools/clang-linker-wrapper/LinkerWrapperOpts.td
+++ b/clang/tools/clang-linker-wrapper/LinkerWrapperOpts.td
@@ -105,6 +105,8 @@ def offload_opt_eq_minus : Joined<["--", "-"], "offload-opt=-">, Flags<[HelpHidd
 // Arguments for LTO
 def lto_in_process : Flag<["--"], "lto-in-process">,
   Flags<[WrapperOnlyOption]>, HelpText<"Use in-process LTO even if linker supports LTO">;
+def lto_debug_pass_manager : Flag<["--"], "lto-debug-pass-manager">,
+  Flags<[WrapperOnlyOption]>, HelpText<"Prints debug information for the new pass manager during LTO">;
 
 // Standard linker flags also used by the linker wrapper.
 def sysroot_EQ : Joined<["--"], "sysroot=">, HelpText<"Set the system root">;

>From 2e535c2f4a1a4955a2361827d6b806a403515327 Mon Sep 17 00:00:00 2001
From: Matthew Curtis <macurtis at amd.com>
Date: Fri, 26 Jul 2024 15:09:05 -0500
Subject: [PATCH 3/5] [lld][LTO] Teach LTO to print pipeline passes

---
 lld/ELF/Config.h                          |  1 +
 lld/ELF/Driver.cpp                        |  1 +
 lld/ELF/LTO.cpp                           |  1 +
 lld/ELF/Options.td                        |  2 ++
 lld/test/ELF/lto/print-pipeline-passes.ll | 15 +++++++++++++++
 llvm/include/llvm/LTO/Config.h            |  3 +++
 llvm/lib/LTO/LTOBackend.cpp               | 10 ++++++++++
 7 files changed, 33 insertions(+)
 create mode 100644 lld/test/ELF/lto/print-pipeline-passes.ll

diff --git a/lld/ELF/Config.h b/lld/ELF/Config.h
index 6abd929d2343d..65216a47ecbdf 100644
--- a/lld/ELF/Config.h
+++ b/lld/ELF/Config.h
@@ -260,6 +260,7 @@ struct Config {
   bool ignoreFunctionAddressEquality;
   bool ltoCSProfileGenerate;
   bool ltoPGOWarnMismatch;
+  bool ltoPrintPipelinePasses;
   bool ltoDebugPassManager;
   bool ltoEmitAsm;
   bool ltoUniqueBasicBlockSectionNames;
diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp
index 7e0a5a1937c7f..814145ae41d95 100644
--- a/lld/ELF/Driver.cpp
+++ b/lld/ELF/Driver.cpp
@@ -1313,6 +1313,7 @@ static void readConfigs(opt::InputArgList &args) {
   config->ltoCSProfileFile = args.getLastArgValue(OPT_lto_cs_profile_file);
   config->ltoPGOWarnMismatch = args.hasFlag(OPT_lto_pgo_warn_mismatch,
                                             OPT_no_lto_pgo_warn_mismatch, true);
+  config->ltoPrintPipelinePasses = args.hasArg(OPT_lto_print_pipeline_passes);
   config->ltoDebugPassManager = args.hasArg(OPT_lto_debug_pass_manager);
   config->ltoEmitAsm = args.hasArg(OPT_lto_emit_asm);
   config->ltoNewPmPasses = args.getLastArgValue(OPT_lto_newpm_passes);
diff --git a/lld/ELF/LTO.cpp b/lld/ELF/LTO.cpp
index 935d0a9eab9ee..0e56ee4a86f88 100644
--- a/lld/ELF/LTO.cpp
+++ b/lld/ELF/LTO.cpp
@@ -127,6 +127,7 @@ static lto::Config createConfig() {
   c.SampleProfile = std::string(config->ltoSampleProfile);
   for (StringRef pluginFn : config->passPlugins)
     c.PassPlugins.push_back(std::string(pluginFn));
+  c.PrintPipelinePasses = config->ltoPrintPipelinePasses;
   c.DebugPassManager = config->ltoDebugPassManager;
   c.DwoDir = std::string(config->dwoDir);
 
diff --git a/lld/ELF/Options.td b/lld/ELF/Options.td
index 74733efb28ff5..49a86c316ec46 100644
--- a/lld/ELF/Options.td
+++ b/lld/ELF/Options.td
@@ -610,6 +610,8 @@ def lto: JJ<"lto=">, HelpText<"Set LTO backend">,
                  MetaVarName<"[full,thin]">;
 def lto_aa_pipeline: JJ<"lto-aa-pipeline=">,
   HelpText<"AA pipeline to run during LTO. Used in conjunction with -lto-newpm-passes">;
+def lto_print_pipeline_passes: FF<"lto-print-pipeline-passes">,
+  HelpText<"Print a '-passes' compatible string describing the LTO pipeline (best-effort only).">;
 def lto_debug_pass_manager: FF<"lto-debug-pass-manager">,
   HelpText<"Debug new pass manager">;
 def lto_emit_asm: FF<"lto-emit-asm">,
diff --git a/lld/test/ELF/lto/print-pipeline-passes.ll b/lld/test/ELF/lto/print-pipeline-passes.ll
new file mode 100644
index 0000000000000..0ff42eebba296
--- /dev/null
+++ b/lld/test/ELF/lto/print-pipeline-passes.ll
@@ -0,0 +1,15 @@
+; REQUIRES: x86
+
+; RUN: llvm-as %s -o %t.o
+; RUN: ld.lld --lto-print-pipeline-passes -o %t.out.o %t.o 2>&1 | FileCheck %s
+
+; CHECK: pipeline-passes: verify,{{.*}},verify
+
+target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+ at llvm.compiler.used = appending global [1 x ptr] [ptr @main], section "llvm.metadata"
+
+define hidden void @main() {
+  ret void
+}
diff --git a/llvm/include/llvm/LTO/Config.h b/llvm/include/llvm/LTO/Config.h
index 482b6e55a19d3..1e3aa92537ac9 100644
--- a/llvm/include/llvm/LTO/Config.h
+++ b/llvm/include/llvm/LTO/Config.h
@@ -165,6 +165,9 @@ struct Config {
   /// Whether to emit the pass manager debuggging informations.
   bool DebugPassManager = false;
 
+  /// Print a '-passes' compatible string describing the pipeline (best-effort only).
+  bool PrintPipelinePasses = false;
+
   /// Statistics output file path.
   std::string StatsFile;
 
diff --git a/llvm/lib/LTO/LTOBackend.cpp b/llvm/lib/LTO/LTOBackend.cpp
index d5d642f0d25e6..949850a3c791b 100644
--- a/llvm/lib/LTO/LTOBackend.cpp
+++ b/llvm/lib/LTO/LTOBackend.cpp
@@ -335,6 +335,16 @@ static void runNewPMPasses(const Config &Conf, Module &Mod, TargetMachine *TM,
   if (!Conf.DisableVerify)
     MPM.addPass(VerifierPass());
 
+  if (Conf.PrintPipelinePasses) {
+    std::string PipelineStr;
+    raw_string_ostream OS(PipelineStr);
+    MPM.printPipeline(OS, [&PIC](StringRef ClassName) {
+      auto PassName = PIC.getPassNameForClassName(ClassName);
+      return PassName.empty() ? ClassName : PassName;
+    });
+    outs() << "pipeline-passes: " << PipelineStr << '\n';
+  }
+
   MPM.run(Mod, MAM);
 }
 

>From 17481aac61cba822e2077be3dc4a180a223556ef Mon Sep 17 00:00:00 2001
From: Matthew Curtis <macurtis at amd.com>
Date: Fri, 26 Jul 2024 15:24:59 -0500
Subject: [PATCH 4/5] [clang-linker-wrapper] Add --lto-print-pipeline-passes
 flag

---
 clang/test/Driver/linker-wrapper.c                      | 6 ++++--
 clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp | 3 +++
 clang/tools/clang-linker-wrapper/LinkerWrapperOpts.td   | 2 ++
 3 files changed, 9 insertions(+), 2 deletions(-)

diff --git a/clang/test/Driver/linker-wrapper.c b/clang/test/Driver/linker-wrapper.c
index d45cc749ac666..0d938844dd116 100644
--- a/clang/test/Driver/linker-wrapper.c
+++ b/clang/test/Driver/linker-wrapper.c
@@ -50,7 +50,7 @@ __attribute__((visibility("protected"), used)) int x;
 // RUN: clang-linker-wrapper --host-triple=x86_64-unknown-linux-gnu --wrapper-verbose --dry-run --save-temps -O2 \
 // RUN:   --lto-in-process --linker-path=/usr/bin/ld %t.o -o a.out 2>&1 | FileCheck %s --check-prefix=AMDGPU-LTO-IN-PROC
 // RUN: clang-linker-wrapper --host-triple=x86_64-unknown-linux-gnu --wrapper-verbose --dry-run --save-temps -O2 \
-// RUN:   --lto-debug-pass-manager --linker-path=/usr/bin/ld %t.o -o a.out 2>&1 | FileCheck %s --check-prefix=AMDGPU-LTO-OPTS
+// RUN:   --lto-debug-pass-manager --lto-print-pipeline-passes --linker-path=/usr/bin/ld %t.o -o a.out 2>&1 | FileCheck %s --check-prefix=AMDGPU-LTO-OPTS
 
 // AMDGPU-LTO-TEMPS-NOT: Linking bitcode files
 // AMDGPU-LTO-TEMPS: clang{{.*}} -o {{.*}}.img --target=amdgcn-amd-amdhsa -mcpu=gfx1030 -O2 -Wl,--no-undefined {{.*}}.o -save-temps
@@ -58,7 +58,9 @@ __attribute__((visibility("protected"), used)) int x;
 // AMDGPU-LTO-IN-PROC: Linking bitcode files
 // AMDGPU-LTO-IN-PROC: clang{{.*}} -o {{.*}}.img --target=amdgcn-amd-amdhsa -mcpu=gfx1030 -O2 -Wl,--no-undefined {{.*}}.s -save-temps
 
-// AMDGPU-LTO-OPTS: clang{{.*}} -o {{.*}}.img --target=amdgcn-amd-amdhsa -mcpu=gfx1030 -O2 -Wl,--no-undefined {{.*}}.o -save-temps -Wl,--save-temps -Wl,--lto-debug-pass-manager
+// AMDGPU-LTO-OPTS: clang{{.*}} -o {{.*}}.img --target=amdgcn-amd-amdhsa -mcpu=gfx1030 -O2 -Wl,--no-undefined {{.*}}.o -save-temps -Wl,--save-temps
+// AMDGPU-LTO-OPTS-SAME: -Wl,--lto-debug-pass-manager
+// AMDGPU-LTO-OPTS-SAME: -Wl,--lto-print-pipeline-passes
 
 // RUN: clang-offload-packager -o %t.out \
 // RUN:   --image=file=%t.elf.o,kind=openmp,triple=x86_64-unknown-linux-gnu \
diff --git a/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp b/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp
index 262d677629045..400080fcfa6cc 100644
--- a/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp
+++ b/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp
@@ -578,6 +578,8 @@ Expected<StringRef> clang(ArrayRef<StringRef> InputFiles, const ArgList &Args) {
       CmdArgs.push_back("-Wl,--save-temps");
     if (Args.hasArg(OPT_lto_debug_pass_manager))
       CmdArgs.push_back("-Wl,--lto-debug-pass-manager");
+    if (Args.hasArg(OPT_lto_print_pipeline_passes))
+      CmdArgs.push_back("-Wl,--lto-print-pipeline-passes");
   }
 
   if (Args.hasArg(OPT_embed_bitcode))
@@ -764,6 +766,7 @@ std::unique_ptr<lto::LTO> createLTO(
   Conf.HasWholeProgramVisibility = Args.hasArg(OPT_whole_program);
 
   Conf.DebugPassManager = Args.hasArg(OPT_lto_debug_pass_manager);
+  Conf.PrintPipelinePasses = Args.hasArg(OPT_lto_print_pipeline_passes);
 
   return std::make_unique<lto::LTO>(std::move(Conf), Backend);
 }
diff --git a/clang/tools/clang-linker-wrapper/LinkerWrapperOpts.td b/clang/tools/clang-linker-wrapper/LinkerWrapperOpts.td
index 5bdbec432b6fe..29f2177b0b138 100644
--- a/clang/tools/clang-linker-wrapper/LinkerWrapperOpts.td
+++ b/clang/tools/clang-linker-wrapper/LinkerWrapperOpts.td
@@ -107,6 +107,8 @@ def lto_in_process : Flag<["--"], "lto-in-process">,
   Flags<[WrapperOnlyOption]>, HelpText<"Use in-process LTO even if linker supports LTO">;
 def lto_debug_pass_manager : Flag<["--"], "lto-debug-pass-manager">,
   Flags<[WrapperOnlyOption]>, HelpText<"Prints debug information for the new pass manager during LTO">;
+def lto_print_pipeline_passes : Flag<["--"], "lto-print-pipeline-passes">,
+  Flags<[WrapperOnlyOption]>, HelpText<"Print a '-passes' compatible string describing the LTO pipeline (best-effort only).">;
 
 // Standard linker flags also used by the linker wrapper.
 def sysroot_EQ : Joined<["--"], "sysroot=">, HelpText<"Set the system root">;

>From 651bf3e9e1120e26b61faa55f969af067d1027b4 Mon Sep 17 00:00:00 2001
From: Matthew Curtis <macurtis at amd.com>
Date: Fri, 26 Jul 2024 15:45:07 -0500
Subject: [PATCH 5/5] [clang-linker-wrapper] Forward offload options to device
 linker

---
 clang/test/Driver/linker-wrapper.c                      | 6 +++++-
 clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp | 4 ++++
 2 files changed, 9 insertions(+), 1 deletion(-)

diff --git a/clang/test/Driver/linker-wrapper.c b/clang/test/Driver/linker-wrapper.c
index 0d938844dd116..00492c0745baa 100644
--- a/clang/test/Driver/linker-wrapper.c
+++ b/clang/test/Driver/linker-wrapper.c
@@ -50,7 +50,9 @@ __attribute__((visibility("protected"), used)) int x;
 // RUN: clang-linker-wrapper --host-triple=x86_64-unknown-linux-gnu --wrapper-verbose --dry-run --save-temps -O2 \
 // RUN:   --lto-in-process --linker-path=/usr/bin/ld %t.o -o a.out 2>&1 | FileCheck %s --check-prefix=AMDGPU-LTO-IN-PROC
 // RUN: clang-linker-wrapper --host-triple=x86_64-unknown-linux-gnu --wrapper-verbose --dry-run --save-temps -O2 \
-// RUN:   --lto-debug-pass-manager --lto-print-pipeline-passes --linker-path=/usr/bin/ld %t.o -o a.out 2>&1 | FileCheck %s --check-prefix=AMDGPU-LTO-OPTS
+// RUN:   --lto-debug-pass-manager --lto-print-pipeline-passes \
+// RUN:   -offload-opt=--print-before=openmp-opt -offload-opt=--print-after=openmp-opt \
+// RUN:   --linker-path=/usr/bin/ld %t.o -o a.out 2>&1 | FileCheck %s --check-prefix=AMDGPU-LTO-OPTS
 
 // AMDGPU-LTO-TEMPS-NOT: Linking bitcode files
 // AMDGPU-LTO-TEMPS: clang{{.*}} -o {{.*}}.img --target=amdgcn-amd-amdhsa -mcpu=gfx1030 -O2 -Wl,--no-undefined {{.*}}.o -save-temps
@@ -61,6 +63,8 @@ __attribute__((visibility("protected"), used)) int x;
 // AMDGPU-LTO-OPTS: clang{{.*}} -o {{.*}}.img --target=amdgcn-amd-amdhsa -mcpu=gfx1030 -O2 -Wl,--no-undefined {{.*}}.o -save-temps -Wl,--save-temps
 // AMDGPU-LTO-OPTS-SAME: -Wl,--lto-debug-pass-manager
 // AMDGPU-LTO-OPTS-SAME: -Wl,--lto-print-pipeline-passes
+// AMDGPU-LTO-OPTS-SAME: -Wl,--mllvm=-print-before=openmp-opt
+// AMDGPU-LTO-OPTS-SAME: -Wl,--mllvm=-print-after=openmp-opt
 
 // RUN: clang-offload-packager -o %t.out \
 // RUN:   --image=file=%t.elf.o,kind=openmp,triple=x86_64-unknown-linux-gnu \
diff --git a/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp b/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp
index 400080fcfa6cc..abaad59d25202 100644
--- a/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp
+++ b/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp
@@ -580,6 +580,10 @@ Expected<StringRef> clang(ArrayRef<StringRef> InputFiles, const ArgList &Args) {
       CmdArgs.push_back("-Wl,--lto-debug-pass-manager");
     if (Args.hasArg(OPT_lto_print_pipeline_passes))
       CmdArgs.push_back("-Wl,--lto-print-pipeline-passes");
+    for (const opt::Arg *Arg : Args.filtered(OPT_offload_opt_eq_minus)) {
+      CmdArgs.push_back(
+          Args.MakeArgString("-Wl,--mllvm=" + StringRef(Arg->getValue())));
+    }
   }
 
   if (Args.hasArg(OPT_embed_bitcode))



More information about the cfe-commits mailing list