https://github.com/citymarina updated 
https://github.com/llvm/llvm-project/pull/178005

>From 6609e334db5c5a74aef1fb73ac8b751702ba728e Mon Sep 17 00:00:00 2001
From: Marina Taylor <[email protected]>
Date: Tue, 27 Jan 2026 15:20:45 +0000
Subject: [PATCH 1/2] NFC: Rename StackUsageOutput to StackUsageFile

---
 clang/include/clang/Basic/CodeGenOptions.h | 2 +-
 clang/include/clang/Options/Options.td     | 2 +-
 clang/lib/CodeGen/BackendUtil.cpp          | 2 +-
 clang/lib/Frontend/CompilerInvocation.cpp  | 2 +-
 llvm/include/llvm/Target/TargetOptions.h   | 2 +-
 llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp | 2 +-
 6 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/clang/include/clang/Basic/CodeGenOptions.h 
b/clang/include/clang/Basic/CodeGenOptions.h
index c60ca507ff917..8ef0d87faaeaf 100644
--- a/clang/include/clang/Basic/CodeGenOptions.h
+++ b/clang/include/clang/Basic/CodeGenOptions.h
@@ -521,7 +521,7 @@ class CodeGenOptions : public CodeGenOptionsBase {
   /// Name of the stack usage file (i.e., .su file) if user passes
   /// -fstack-usage. If empty, it can be implied that -fstack-usage is not
   /// passed on the command line.
-  std::string StackUsageOutput;
+  std::string StackUsageFile;
 
   /// Executable and command-line used to create a given CompilerInvocation.
   /// Most of the time this will be the full -cc1 command.
diff --git a/clang/include/clang/Options/Options.td 
b/clang/include/clang/Options/Options.td
index 188739e72434a..93038ed324ae8 100644
--- a/clang/include/clang/Options/Options.td
+++ b/clang/include/clang/Options/Options.td
@@ -4652,7 +4652,7 @@ def fstack_usage : Flag<["-"], "fstack-usage">, 
Group<f_Group>,
 def stack_usage_file : Separate<["-"], "stack-usage-file">,
   Visibility<[CC1Option]>,
   HelpText<"Filename (or -) to write stack usage output to">,
-  MarshallingInfoString<CodeGenOpts<"StackUsageOutput">>;
+  MarshallingInfoString<CodeGenOpts<"StackUsageFile">>;
 def fextend_variable_liveness_EQ : Joined<["-"], "fextend-variable-liveness=">,
   Group<f_Group>, Visibility<[ClangOption, CC1Option]>,
   HelpText<"Extend the liveness of user variables through optimizations to "
diff --git a/clang/lib/CodeGen/BackendUtil.cpp 
b/clang/lib/CodeGen/BackendUtil.cpp
index d411ef1bf8763..b286ff359ec40 100644
--- a/clang/lib/CodeGen/BackendUtil.cpp
+++ b/clang/lib/CodeGen/BackendUtil.cpp
@@ -453,7 +453,7 @@ static bool initTargetOptions(const CompilerInstance &CI,
   Options.EmulatedTLS = CodeGenOpts.EmulatedTLS;
   Options.DebuggerTuning = CodeGenOpts.getDebuggerTuning();
   Options.EmitStackSizeSection = CodeGenOpts.StackSizeSection;
-  Options.StackUsageOutput = CodeGenOpts.StackUsageOutput;
+  Options.StackUsageFile = CodeGenOpts.StackUsageFile;
   Options.EmitAddrsig = CodeGenOpts.Addrsig;
   Options.ForceDwarfFrameSection = CodeGenOpts.ForceDwarfFrameSection;
   Options.EmitCallGraphSection = CodeGenOpts.CallGraphSection;
diff --git a/clang/lib/Frontend/CompilerInvocation.cpp 
b/clang/lib/Frontend/CompilerInvocation.cpp
index 5a79634773866..2af4a7f536623 100644
--- a/clang/lib/Frontend/CompilerInvocation.cpp
+++ b/clang/lib/Frontend/CompilerInvocation.cpp
@@ -2244,7 +2244,7 @@ bool CompilerInvocation::ParseCodeGenArgs(CodeGenOptions 
&Opts, ArgList &Args,
   if (UsingSampleProfile)
     NeedLocTracking = true;
 
-  if (!Opts.StackUsageOutput.empty())
+  if (!Opts.StackUsageFile.empty())
     NeedLocTracking = true;
 
   // If the user requested a flag that requires source locations available in
diff --git a/llvm/include/llvm/Target/TargetOptions.h 
b/llvm/include/llvm/Target/TargetOptions.h
index 7af50691ec0e5..a9b86626cf598 100644
--- a/llvm/include/llvm/Target/TargetOptions.h
+++ b/llvm/include/llvm/Target/TargetOptions.h
@@ -368,7 +368,7 @@ class TargetOptions {
   /// Name of the stack usage file (i.e., .su file) if user passes
   /// -fstack-usage. If empty, it can be implied that -fstack-usage is not
   /// passed on the command line.
-  std::string StackUsageOutput;
+  std::string StackUsageFile;
 
   /// If greater than 0, override TargetLoweringBase::PrefLoopAlignment.
   unsigned LoopAlignment = 0;
diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp 
b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
index 3c758ed006bf5..e318f4e8551e1 100644
--- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
@@ -1672,7 +1672,7 @@ void AsmPrinter::emitStackSizeSection(const 
MachineFunction &MF) {
 }
 
 void AsmPrinter::emitStackUsage(const MachineFunction &MF) {
-  const std::string &OutputFilename = MF.getTarget().Options.StackUsageOutput;
+  const std::string &OutputFilename = MF.getTarget().Options.StackUsageFile;
 
   // OutputFilename empty implies -fstack-usage is not passed.
   if (OutputFilename.empty())

>From 96909ceccb08ca47ea061d8f9e671bddd383053d Mon Sep 17 00:00:00 2001
From: Marina Taylor <[email protected]>
Date: Mon, 26 Jan 2026 16:51:46 +0000
Subject: [PATCH 2/2] [LTO] Make stack usage files work with LTO

This change plumbs the stack usage filename from the various CLI
entry points down to `TargetOptions::StackUsageFile`, ultimately
for use by `AsmPrinter::emitStackUsage`.

rdar://143089305
---
 clang/lib/CodeGen/BackendUtil.cpp                |  1 +
 clang/lib/Driver/ToolChains/Darwin.cpp           |  9 +++++++++
 clang/test/Driver/stack-usage.c                  |  6 ++++++
 lld/COFF/Config.h                                |  3 +++
 lld/COFF/Driver.cpp                              |  1 +
 lld/COFF/LTO.cpp                                 |  1 +
 lld/COFF/Options.td                              |  3 +++
 lld/ELF/Config.h                                 |  1 +
 lld/ELF/Driver.cpp                               |  1 +
 lld/ELF/LTO.cpp                                  |  3 +++
 lld/ELF/Options.td                               |  2 ++
 lld/MachO/Config.h                               |  1 +
 lld/MachO/Driver.cpp                             |  1 +
 lld/MachO/LTO.cpp                                |  1 +
 lld/MachO/Options.td                             |  4 ++++
 lld/test/COFF/lto-stack-usage-file.ll            | 15 +++++++++++++++
 lld/test/ELF/lto/stack-usage-file.ll             | 15 +++++++++++++++
 lld/test/MachO/lto-stack-usage-file.ll           | 16 ++++++++++++++++
 lld/test/wasm/lto/stack-usage-file.ll            | 13 +++++++++++++
 lld/wasm/Config.h                                |  1 +
 lld/wasm/Driver.cpp                              |  1 +
 lld/wasm/LTO.cpp                                 |  1 +
 lld/wasm/Options.td                              |  2 ++
 llvm/include/llvm/LTO/Config.h                   |  3 +++
 llvm/lib/LTO/LTOBackend.cpp                      |  3 +++
 llvm/lib/LTO/LTOCodeGenerator.cpp                |  6 ++++++
 llvm/lib/LTO/ThinLTOCodeGenerator.cpp            |  5 +++++
 .../tools/llvm-lto2/X86/stack-usage-output.ll    | 15 +++++++++++++++
 llvm/tools/llvm-lto2/llvm-lto2.cpp               |  5 +++++
 29 files changed, 139 insertions(+)
 create mode 100644 lld/test/COFF/lto-stack-usage-file.ll
 create mode 100644 lld/test/ELF/lto/stack-usage-file.ll
 create mode 100644 lld/test/MachO/lto-stack-usage-file.ll
 create mode 100644 lld/test/wasm/lto/stack-usage-file.ll
 create mode 100644 llvm/test/tools/llvm-lto2/X86/stack-usage-output.ll

diff --git a/clang/lib/CodeGen/BackendUtil.cpp 
b/clang/lib/CodeGen/BackendUtil.cpp
index b286ff359ec40..8c8fee486e59f 100644
--- a/clang/lib/CodeGen/BackendUtil.cpp
+++ b/clang/lib/CodeGen/BackendUtil.cpp
@@ -1383,6 +1383,7 @@ runThinLTOBackend(CompilerInstance &CI, 
ModuleSummaryIndex *CombinedIndex,
   Conf.RemarksFormat = CGOpts.OptRecordFormat;
   Conf.SplitDwarfFile = CGOpts.SplitDwarfFile;
   Conf.SplitDwarfOutput = CGOpts.SplitDwarfOutput;
+  Conf.StackUsageFile = CGOpts.StackUsageFile;
   switch (Action) {
   case Backend_EmitNothing:
     Conf.PreCodeGenModuleHook = [](size_t Task, const llvm::Module &Mod) {
diff --git a/clang/lib/Driver/ToolChains/Darwin.cpp 
b/clang/lib/Driver/ToolChains/Darwin.cpp
index fb75739360328..f091ff478197a 100644
--- a/clang/lib/Driver/ToolChains/Darwin.cpp
+++ b/clang/lib/Driver/ToolChains/Darwin.cpp
@@ -660,6 +660,15 @@ void darwin::Linker::ConstructJob(Compilation &C, const 
JobAction &JA,
     CmdArgs.push_back(Args.MakeArgString("-lto-stats-file=" + 
StatsFile.str()));
   }
 
+  // Set up stack usage output file for LTO.
+  if (Args.hasArg(options::OPT_fstack_usage)) {
+    SmallString<128> StackUsageFile(Output.getFilename());
+    llvm::sys::path::replace_extension(StackUsageFile, "su");
+    CmdArgs.push_back("-mllvm");
+    CmdArgs.push_back(
+        Args.MakeArgString("-lto-stack-usage-file=" + StackUsageFile));
+  }
+
   // It seems that the 'e' option is completely ignored for dynamic executables
   // (the default), and with static executables, the last one wins, as 
expected.
   Args.addAllArgs(CmdArgs, {options::OPT_d_Flag, options::OPT_s, 
options::OPT_t,
diff --git a/clang/test/Driver/stack-usage.c b/clang/test/Driver/stack-usage.c
index 7256707040f9c..d77d63cbf0b32 100644
--- a/clang/test/Driver/stack-usage.c
+++ b/clang/test/Driver/stack-usage.c
@@ -4,4 +4,10 @@
 // RUN: %clang -target aarch64-unknown -fstack-usage %s -### 2>&1 | FileCheck 
%s --check-prefix=CHECK-PRESENT
 // CHECK-PRESENT: "-stack-usage-file"
 
+// RUN: %clang --target=arm64-apple-darwin -fstack-usage -flto %s -### -o foo 
2>&1 | FileCheck %s --check-prefix=DARWIN-LTO
+// DARWIN-LTO: "-mllvm" "-lto-stack-usage-file=foo.su"
+
+// RUN: %clang --target=arm64-apple-darwin -flto %s -### -o foo 2>&1 | 
FileCheck %s --check-prefix=DARWIN-LTO-ABSENT
+// DARWIN-LTO-ABSENT-NOT: "-lto-stack-usage-file"
+
 int foo() { return 42; }
diff --git a/lld/COFF/Config.h b/lld/COFF/Config.h
index 2ee60aca116d6..92d611a381392 100644
--- a/lld/COFF/Config.h
+++ b/lld/COFF/Config.h
@@ -272,6 +272,9 @@ struct Configuration {
   // Used for /lto-obj-path:
   llvm::StringRef ltoObjPath;
 
+  // Used for /lto-stack-usage-file:
+  llvm::StringRef ltoStackUsageFile;
+
   // Used for /lto-cs-profile-generate:
   bool ltoCSProfileGenerate = false;
 
diff --git a/lld/COFF/Driver.cpp b/lld/COFF/Driver.cpp
index b1337ea8157ab..cb5a8c4de6aa2 100644
--- a/lld/COFF/Driver.cpp
+++ b/lld/COFF/Driver.cpp
@@ -2209,6 +2209,7 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> 
argsArr) {
   config->thinLTOObjectSuffixReplace =
       getOldNewOptions(ctx, args, OPT_thinlto_object_suffix_replace);
   config->ltoObjPath = args.getLastArgValue(OPT_lto_obj_path);
+  config->ltoStackUsageFile = args.getLastArgValue(OPT_lto_stack_usage_file);
   config->ltoCSProfileGenerate = args.hasArg(OPT_lto_cs_profile_generate);
   config->ltoCSProfileFile = args.getLastArgValue(OPT_lto_cs_profile_file);
   config->ltoSampleProfileName = args.getLastArgValue(OPT_lto_sample_profile);
diff --git a/lld/COFF/LTO.cpp b/lld/COFF/LTO.cpp
index e621bb263d2c9..03c05d17f0d61 100644
--- a/lld/COFF/LTO.cpp
+++ b/lld/COFF/LTO.cpp
@@ -83,6 +83,7 @@ lto::Config BitcodeCompiler::createConfig() {
   c.RunCSIRInstr = ctx.config.ltoCSProfileGenerate;
   c.PGOWarnMismatch = ctx.config.ltoPGOWarnMismatch;
   c.SampleProfile = ctx.config.ltoSampleProfileName;
+  c.StackUsageFile = std::string(ctx.config.ltoStackUsageFile);
   c.TimeTraceEnabled = ctx.config.timeTraceEnabled;
   c.TimeTraceGranularity = ctx.config.timeTraceGranularity;
 
diff --git a/lld/COFF/Options.td b/lld/COFF/Options.td
index fb762b880c2cb..b21cba85573b1 100644
--- a/lld/COFF/Options.td
+++ b/lld/COFF/Options.td
@@ -308,6 +308,9 @@ defm fat_lto_objects: B<"fat-lto-objects",
 def lto_obj_path : P<
     "lto-obj-path",
     "output native object for merged LTO unit to this path">;
+def lto_stack_usage_file : P<
+    "lto-stack-usage-file",
+    "output stack usage information for LTO">;
 def lto_cs_profile_generate: F<"lto-cs-profile-generate">,
     HelpText<"Perform context sensitive PGO instrumentation">;
 def lto_cs_profile_file : P<"lto-cs-profile-file",
diff --git a/lld/ELF/Config.h b/lld/ELF/Config.h
index 8ec5a2c04e71c..11092d87db667 100644
--- a/lld/ELF/Config.h
+++ b/lld/ELF/Config.h
@@ -234,6 +234,7 @@ struct Config {
   llvm::StringRef ltoNewPmPasses;
   llvm::StringRef ltoObjPath;
   llvm::StringRef ltoSampleProfile;
+  llvm::StringRef ltoStackUsageFile;
   llvm::StringRef mapFile;
   llvm::StringRef outputFile;
   llvm::StringRef optRemarksFilename;
diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp
index 8647752be31fe..ebf1757eb5620 100644
--- a/lld/ELF/Driver.cpp
+++ b/lld/ELF/Driver.cpp
@@ -1469,6 +1469,7 @@ static void readConfigs(Ctx &ctx, opt::InputArgList 
&args) {
   ctx.arg.ltoObjPath = args.getLastArgValue(OPT_lto_obj_path_eq);
   ctx.arg.ltoPartitions = args::getInteger(args, OPT_lto_partitions, 1);
   ctx.arg.ltoSampleProfile = args.getLastArgValue(OPT_lto_sample_profile);
+  ctx.arg.ltoStackUsageFile = args.getLastArgValue(OPT_lto_stack_usage_file);
   ctx.arg.ltoBBAddrMap =
       args.hasFlag(OPT_lto_basic_block_address_map,
                    OPT_no_lto_basic_block_address_map, false);
diff --git a/lld/ELF/LTO.cpp b/lld/ELF/LTO.cpp
index 44a679498ed1d..59aff9eadf9fc 100644
--- a/lld/ELF/LTO.cpp
+++ b/lld/ELF/LTO.cpp
@@ -122,6 +122,9 @@ static lto::Config createConfig(Ctx &ctx) {
   // Set up output file to emit statistics.
   c.StatsFile = std::string(ctx.arg.optStatsFilename);
 
+  // Set up output file for stack usage.
+  c.StackUsageFile = std::string(ctx.arg.ltoStackUsageFile);
+
   c.SampleProfile = std::string(ctx.arg.ltoSampleProfile);
   for (StringRef pluginFn : ctx.arg.passPlugins)
     c.PassPlugins.push_back(std::string(pluginFn));
diff --git a/lld/ELF/Options.td b/lld/ELF/Options.td
index c2111e58c12b9..c7c0615bac19e 100644
--- a/lld/ELF/Options.td
+++ b/lld/ELF/Options.td
@@ -689,6 +689,8 @@ def opt_remarks_with_hotness: 
FF<"opt-remarks-with-hotness">,
   HelpText<"Include hotness information in the optimization remarks file">;
 def opt_remarks_format: Separate<["--"], "opt-remarks-format">,
   HelpText<"The format used for serializing remarks (default: YAML)">;
+def lto_stack_usage_file: JJ<"lto-stack-usage-file=">,
+  HelpText<"Stack usage output file path for LTO">;
 def save_temps: F<"save-temps">, HelpText<"Save intermediate LTO compilation 
results">;
 def save_temps_eq: JJ<"save-temps=">, HelpText<"Save select intermediate LTO 
compilation results">,
   
Values<"resolution,preopt,promote,internalize,import,opt,precodegen,prelink,combinedindex">;
diff --git a/lld/MachO/Config.h b/lld/MachO/Config.h
index 814ba1016849f..cfda2c628549e 100644
--- a/lld/MachO/Config.h
+++ b/lld/MachO/Config.h
@@ -169,6 +169,7 @@ struct Configuration {
   llvm::StringRef mapFile;
   llvm::StringRef ltoNewPmPasses;
   llvm::StringRef ltoObjPath;
+  llvm::StringRef ltoStackUsageFile;
   llvm::StringRef thinLTOJobs;
   llvm::StringRef umbrella;
   uint32_t ltoo = 2;
diff --git a/lld/MachO/Driver.cpp b/lld/MachO/Driver.cpp
index 973b3f5535cb4..7a6fc88c874df 100644
--- a/lld/MachO/Driver.cpp
+++ b/lld/MachO/Driver.cpp
@@ -1929,6 +1929,7 @@ bool link(ArrayRef<const char *> argsArr, 
llvm::raw_ostream &stdoutOS,
     config->umbrella = arg->getValue();
   }
   config->ltoObjPath = args.getLastArgValue(OPT_object_path_lto);
+  config->ltoStackUsageFile = args.getLastArgValue(OPT_lto_stack_usage_file);
   config->ltoNewPmPasses = args.getLastArgValue(OPT_lto_newpm_passes);
   config->thinLTOCacheDir = args.getLastArgValue(OPT_cache_path_lto);
   config->thinLTOCachePolicy = getLTOCachePolicy(args);
diff --git a/lld/MachO/LTO.cpp b/lld/MachO/LTO.cpp
index 2c360374ef3cc..91c3713a33ee4 100644
--- a/lld/MachO/LTO.cpp
+++ b/lld/MachO/LTO.cpp
@@ -61,6 +61,7 @@ static lto::Config createConfig() {
   c.DisableVerify = config->disableVerify;
   c.OptLevel = config->ltoo;
   c.CGOptLevel = config->ltoCgo;
+  c.StackUsageFile = std::string(config->ltoStackUsageFile);
   if (config->saveTemps)
     checkError(c.addSaveTemps(config->outputFile.str() + ".",
                               /*UseInputModulePath=*/true));
diff --git a/lld/MachO/Options.td b/lld/MachO/Options.td
index 5bd220b3c196a..6353afacd7171 100644
--- a/lld/MachO/Options.td
+++ b/lld/MachO/Options.td
@@ -1040,6 +1040,10 @@ def object_path_lto : Separate<["-"], "object_path_lto">,
     MetaVarName<"<path>">,
     HelpText<"Retain any temporary mach-o file in <path> that would otherwise 
be deleted during LTO">,
     Group<grp_rare>;
+def lto_stack_usage_file : Separate<["-"], "lto_stack_usage_file">,
+    MetaVarName<"<path>">,
+    HelpText<"Write stack usage information for LTO to <path>">,
+    Group<grp_rare>;
 def cache_path_lto : Separate<["-"], "cache_path_lto">,
     MetaVarName<"<path>">,
     HelpText<"Use <path> as a directory for the incremental LTO cache">,
diff --git a/lld/test/COFF/lto-stack-usage-file.ll 
b/lld/test/COFF/lto-stack-usage-file.ll
new file mode 100644
index 0000000000000..b9986c5b035c3
--- /dev/null
+++ b/lld/test/COFF/lto-stack-usage-file.ll
@@ -0,0 +1,15 @@
+; REQUIRES: x86
+
+; RUN: llvm-as %s -o %t.obj
+; RUN: lld-link /subsystem:console /entry:f /out:%t.exe 
/lto-stack-usage-file:%t.su %t.obj
+; RUN: FileCheck --input-file=%t.su %s
+
+target datalayout = 
"e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-pc-windows-msvc19.0.24215"
+
+define void @f() {
+  %a = alloca [64 x i8]
+  ret void
+}
+
+; CHECK: f {{[0-9]+}} static
diff --git a/lld/test/ELF/lto/stack-usage-file.ll 
b/lld/test/ELF/lto/stack-usage-file.ll
new file mode 100644
index 0000000000000..ac4e38900caa7
--- /dev/null
+++ b/lld/test/ELF/lto/stack-usage-file.ll
@@ -0,0 +1,15 @@
+; REQUIRES: x86
+
+; RUN: llvm-as -o %t.bc %s
+; RUN: ld.lld --lto-stack-usage-file=%t.su -m elf_x86_64 -r -o %t.o %t.bc
+; RUN: FileCheck --input-file=%t.su %s
+
+target datalayout = 
"e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @f() {
+  %a = alloca [64 x i8]
+  ret void
+}
+
+; CHECK: f {{[0-9]+}} static
diff --git a/lld/test/MachO/lto-stack-usage-file.ll 
b/lld/test/MachO/lto-stack-usage-file.ll
new file mode 100644
index 0000000000000..e3ccc6bf4723c
--- /dev/null
+++ b/lld/test/MachO/lto-stack-usage-file.ll
@@ -0,0 +1,16 @@
+; REQUIRES: x86
+
+; RUN: rm -rf %t; mkdir %t
+; RUN: llvm-as %s -o %t/test.o
+; RUN: %lld %t/test.o -o %t/test -lto_stack_usage_file %t/test.su
+; RUN: FileCheck --input-file=%t/test.su %s
+
+target triple = "x86_64-apple-macosx10.15.0"
+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 @main() {
+  %a = alloca [64 x i8]
+  ret void
+}
+
+; CHECK: main {{[0-9]+}} static
diff --git a/lld/test/wasm/lto/stack-usage-file.ll 
b/lld/test/wasm/lto/stack-usage-file.ll
new file mode 100644
index 0000000000000..4ee85edbc7189
--- /dev/null
+++ b/lld/test/wasm/lto/stack-usage-file.ll
@@ -0,0 +1,13 @@
+; RUN: llvm-as %s -o %t.o
+; RUN: wasm-ld --entry f %t.o -o %t.wasm --lto-stack-usage-file=%t.su
+; RUN: FileCheck --input-file=%t.su %s
+
+target datalayout = 
"e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128-ni:1:10:20"
+target triple = "wasm32-unknown-unknown"
+
+define void @f() {
+  %a = alloca [64 x i8]
+  ret void
+}
+
+; CHECK: f {{[0-9]+}} static
diff --git a/lld/wasm/Config.h b/lld/wasm/Config.h
index 9d903e0c799db..8d69a04e657c2 100644
--- a/lld/wasm/Config.h
+++ b/lld/wasm/Config.h
@@ -110,6 +110,7 @@ struct Config {
 
   llvm::StringRef entry;
   llvm::StringRef ltoObjPath;
+  llvm::StringRef ltoStackUsageFile;
   llvm::StringRef mapFile;
   llvm::StringRef outputFile;
   llvm::StringRef soName;
diff --git a/lld/wasm/Driver.cpp b/lld/wasm/Driver.cpp
index d18126bef766f..5c6cc7a717d8f 100644
--- a/lld/wasm/Driver.cpp
+++ b/lld/wasm/Driver.cpp
@@ -573,6 +573,7 @@ static void readConfigs(opt::InputArgList &args) {
     error("invalid codegen optimization level for LTO: " + Twine(ltoCgo));
   ctx.arg.ltoPartitions = args::getInteger(args, OPT_lto_partitions, 1);
   ctx.arg.ltoObjPath = args.getLastArgValue(OPT_lto_obj_path_eq);
+  ctx.arg.ltoStackUsageFile = 
args.getLastArgValue(OPT_lto_stack_usage_file_eq);
   ctx.arg.ltoDebugPassManager = args.hasArg(OPT_lto_debug_pass_manager);
   ctx.arg.mapFile = args.getLastArgValue(OPT_Map);
   ctx.arg.optimize = args::getInteger(args, OPT_O, 1);
diff --git a/lld/wasm/LTO.cpp b/lld/wasm/LTO.cpp
index 668cdf21ea3ed..5a9b56628e907 100644
--- a/lld/wasm/LTO.cpp
+++ b/lld/wasm/LTO.cpp
@@ -56,6 +56,7 @@ static lto::Config createConfig() {
   c.CGOptLevel = ctx.arg.ltoCgo;
   c.DebugPassManager = ctx.arg.ltoDebugPassManager;
   c.AlwaysEmitRegularLTOObj = !ctx.arg.ltoObjPath.empty();
+  c.StackUsageFile = std::string(ctx.arg.ltoStackUsageFile);
 
   if (auto relocModel = getRelocModelFromCMModel())
     c.RelocModel = *relocModel;
diff --git a/lld/wasm/Options.td b/lld/wasm/Options.td
index 33ecf03176d36..022d629cdfd55 100644
--- a/lld/wasm/Options.td
+++ b/lld/wasm/Options.td
@@ -304,6 +304,8 @@ def lto_CGO: JJ<"lto-CGO">, MetaVarName<"<cgopt-level>">,
 def lto_partitions: JJ<"lto-partitions=">,
   HelpText<"Number of LTO codegen partitions">;
 def lto_obj_path_eq: JJ<"lto-obj-path=">;
+def lto_stack_usage_file_eq: JJ<"lto-stack-usage-file=">,
+  HelpText<"Stack usage output file path for LTO">;
 def disable_verify: F<"disable-verify">;
 def save_temps: F<"save-temps">, HelpText<"Save intermediate LTO compilation 
results">;
 def thinlto_cache_dir: JJ<"thinlto-cache-dir=">,
diff --git a/llvm/include/llvm/LTO/Config.h b/llvm/include/llvm/LTO/Config.h
index 566a87ed1a790..6db504bf3bbbc 100644
--- a/llvm/include/llvm/LTO/Config.h
+++ b/llvm/include/llvm/LTO/Config.h
@@ -179,6 +179,9 @@ struct Config {
   /// Statistics output file path.
   std::string StatsFile;
 
+  /// Stack usage output file path.
+  std::string StackUsageFile;
+
   /// Specific thinLTO modules to compile.
   std::vector<std::string> ThinLTOModulesToCompile;
 
diff --git a/llvm/lib/LTO/LTOBackend.cpp b/llvm/lib/LTO/LTOBackend.cpp
index 43e5c3b398372..59649332238d3 100644
--- a/llvm/lib/LTO/LTOBackend.cpp
+++ b/llvm/lib/LTO/LTOBackend.cpp
@@ -448,6 +448,9 @@ static void codegen(const Config &Conf, TargetMachine *TM,
                          EC.message());
   }
 
+  if (!Conf.StackUsageFile.empty())
+    TM->Options.StackUsageFile = Conf.StackUsageFile;
+
   Expected<std::unique_ptr<CachedFileStream>> StreamOrErr =
       AddStream(Task, Mod.getModuleIdentifier());
   if (Error Err = StreamOrErr.takeError())
diff --git a/llvm/lib/LTO/LTOCodeGenerator.cpp 
b/llvm/lib/LTO/LTOCodeGenerator.cpp
index 46be71da5a092..4313380191349 100644
--- a/llvm/lib/LTO/LTOCodeGenerator.cpp
+++ b/llvm/lib/LTO/LTOCodeGenerator.cpp
@@ -106,6 +106,11 @@ static cl::opt<std::string>
     LTOStatsFile("lto-stats-file",
                  cl::desc("Save statistics to the specified file"), 
cl::Hidden);
 
+cl::opt<std::string>
+    LTOStackUsageFile("lto-stack-usage-file",
+                      cl::desc("Output filename for stack usage information"),
+                      cl::value_desc("filename"), cl::Hidden);
+
 static cl::opt<std::string> AIXSystemAssemblerPath(
     "lto-aix-system-assembler",
     cl::desc("Path to a system assembler, picked up on AIX only"),
@@ -638,6 +643,7 @@ bool LTOCodeGenerator::compileOptimized(AddStreamFn 
AddStream,
   ModuleSummaryIndex CombinedIndex(false);
 
   Config.CodeGenOnly = true;
+  Config.StackUsageFile = LTOStackUsageFile;
   Error Err = backend(Config, AddStream, ParallelismLevel, *MergedModule,
                       CombinedIndex);
   assert(!Err && "unexpected code-generation failure");
diff --git a/llvm/lib/LTO/ThinLTOCodeGenerator.cpp 
b/llvm/lib/LTO/ThinLTOCodeGenerator.cpp
index 961dd0ee43370..07d46303b1a03 100644
--- a/llvm/lib/LTO/ThinLTOCodeGenerator.cpp
+++ b/llvm/lib/LTO/ThinLTOCodeGenerator.cpp
@@ -79,6 +79,7 @@ extern cl::opt<bool> RemarksWithHotness;
 extern cl::opt<std::optional<uint64_t>, false, remarks::HotnessThresholdParser>
     RemarksHotnessThreshold;
 extern cl::opt<std::string> RemarksFormat;
+extern cl::opt<std::string> LTOStackUsageFile;
 }
 
 // Default to using all available threads in the system, but using only one
@@ -960,6 +961,10 @@ void ThinLTOCodeGenerator::run() {
     if (llvm::timeTraceProfilerEnabled())
       llvm::timeTraceProfilerEnd();
   });
+
+  if (!LTOStackUsageFile.empty())
+    TMBuilder.Options.StackUsageFile = LTOStackUsageFile;
+
   // Prepare the resulting object vector
   assert(ProducedBinaries.empty() && "The generator should not be reused");
   if (SavedObjectsDirectoryPath.empty())
diff --git a/llvm/test/tools/llvm-lto2/X86/stack-usage-output.ll 
b/llvm/test/tools/llvm-lto2/X86/stack-usage-output.ll
new file mode 100644
index 0000000000000..d316eee8cb665
--- /dev/null
+++ b/llvm/test/tools/llvm-lto2/X86/stack-usage-output.ll
@@ -0,0 +1,15 @@
+; REQUIRES: x86-registered-target
+
+; RUN: llvm-as < %s > %t1.bc
+; RUN: llvm-lto2 run %t1.bc -o %t.o -r %t1.bc,f,px -lto-stack-usage-file=%t.su
+; RUN: FileCheck --input-file=%t.su %s
+
+target datalayout = 
"e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @f() {
+  %a = alloca [64 x i8]
+  ret void
+}
+
+; CHECK: f {{[0-9]+}} static
diff --git a/llvm/tools/llvm-lto2/llvm-lto2.cpp 
b/llvm/tools/llvm-lto2/llvm-lto2.cpp
index 955c1130e9f4c..d2ca4b12de77a 100644
--- a/llvm/tools/llvm-lto2/llvm-lto2.cpp
+++ b/llvm/tools/llvm-lto2/llvm-lto2.cpp
@@ -202,6 +202,10 @@ static cl::opt<bool>
 static cl::opt<std::string>
     StatsFile("stats-file", cl::desc("Filename to write statistics to"));
 
+static cl::opt<std::string>
+    StackUsageFileFilename("lto-stack-usage-file",
+                           cl::desc("Filename to write stack usage info to"));
+
 static cl::list<std::string>
     PassPlugins("load-pass-plugin",
                 cl::desc("Load passes from plugin library"));
@@ -390,6 +394,7 @@ static int run(int argc, char **argv) {
   Conf.OverrideTriple = OverrideTriple;
   Conf.DefaultTriple = DefaultTriple;
   Conf.StatsFile = StatsFile;
+  Conf.StackUsageFile = StackUsageFileFilename;
   Conf.PTO.LoopVectorization = Conf.OptLevel > 1;
   Conf.PTO.SLPVectorization = Conf.OptLevel > 1;
 

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to