https://github.com/MaskRay updated 
https://github.com/llvm/llvm-project/pull/237615

>From d8f86cee73312aabfe7cded264b005a95e4547f7 Mon Sep 17 00:00:00 2001
From: Fangrui Song <[email protected]>
Date: Sat, 31 Oct 2026 12:20:12 -0700
Subject: [PATCH 1/2] [Passes] Make PipelineTuningOptions take a
 LibraryOptionsContext reference

Delete the default ctor, which reads the global values of library
options. Make the constructor and the getters it calls take a reference.

lto::Config::PTO becomes std::optional. If unset, the LTO backend reads
the tuning options from the module's LLVMContext. LLVMPassBuilderOptions
reads cl::getCAPILibraryOptions(), which LLVMParseCommandLineOptions
sets along with the global values.

LLM-aided
---
 clang/lib/CodeGen/BackendUtil.cpp              | 18 +++++++++---------
 .../ClangNVLinkWrapper.cpp                     |  2 +-
 flang/lib/Frontend/FrontendActions.cpp         |  2 +-
 lld/COFF/LTO.cpp                               |  6 +++---
 lld/ELF/LTO.cpp                                |  6 +++---
 lld/MachO/LTO.cpp                              |  6 +++---
 lld/wasm/LTO.cpp                               |  2 +-
 llvm/include/llvm/Analysis/CallGraphSCCPass.h  |  2 +-
 llvm/include/llvm/LTO/Config.h                 |  5 +++--
 llvm/include/llvm/Passes/PassBuilder.h         | 11 +++--------
 llvm/include/llvm/Transforms/Scalar/LICM.h     | 10 ++++------
 .../llvm/Transforms/Scalar/LoopUnrollPass.h    |  5 ++---
 llvm/lib/Analysis/CallGraphSCCPass.cpp         |  5 ++---
 llvm/lib/DTLTO/DTLTO.cpp                       |  2 +-
 llvm/lib/LTO/LTOCodeGenerator.cpp              |  6 +++---
 llvm/lib/LTO/ThinLTOCodeGenerator.cpp          |  2 +-
 llvm/lib/Passes/PassBuilder.cpp                |  2 +-
 llvm/lib/Passes/PassBuilderBindings.cpp        |  4 +++-
 llvm/lib/Passes/PassBuilderPipelines.cpp       |  5 ++---
 llvm/lib/Passes/RunCodeGen.cpp                 |  2 +-
 llvm/lib/Transforms/Scalar/LICM.cpp            | 10 ++++------
 llvm/lib/Transforms/Scalar/LoopUnrollPass.cpp  |  5 ++---
 llvm/tools/gold/gold-plugin.cpp                | 10 +++++-----
 llvm/tools/llvm-lto2/llvm-lto2.cpp             |  6 +++---
 llvm/tools/opt/NewPMDriver.cpp                 |  2 +-
 mlir/lib/ExecutionEngine/OptUtils.cpp          |  2 +-
 26 files changed, 64 insertions(+), 74 deletions(-)

diff --git a/clang/lib/CodeGen/BackendUtil.cpp 
b/clang/lib/CodeGen/BackendUtil.cpp
index fe1454026f569d..d56185146f63df 100644
--- a/clang/lib/CodeGen/BackendUtil.cpp
+++ b/clang/lib/CodeGen/BackendUtil.cpp
@@ -903,7 +903,7 @@ void EmitAssemblyHelper::RunOptimizationPipeline(
   if (TM)
     TM->setPGOOption(PGOOpt);
 
-  PipelineTuningOptions PTO(&LibraryOptions);
+  PipelineTuningOptions PTO(LibraryOptions);
   PTO.LoopUnrolling = CodeGenOpts.UnrollLoops;
   PTO.LoopInterchange = CodeGenOpts.InterchangeLoops;
   PTO.LoopFusion = CodeGenOpts.FuseLoops;
@@ -1380,18 +1380,18 @@ runThinLTOBackend(CompilerInstance &CI, 
ModuleSummaryIndex *CombinedIndex,
   Conf.SampleProfile = std::move(SampleProfile);
   const cl::LibraryOptionsContext &LibraryOptions =
       M->getContext().getLibraryOptions();
-  Conf.PTO = PipelineTuningOptions(&LibraryOptions);
-  Conf.PTO.LoopUnrolling = CGOpts.UnrollLoops;
-  Conf.PTO.LoopInterchange = CGOpts.InterchangeLoops;
-  Conf.PTO.LoopFusion = CGOpts.FuseLoops;
+  Conf.PTO.emplace(LibraryOptions);
+  Conf.PTO->LoopUnrolling = CGOpts.UnrollLoops;
+  Conf.PTO->LoopInterchange = CGOpts.InterchangeLoops;
+  Conf.PTO->LoopFusion = CGOpts.FuseLoops;
   // For historical reasons, loop interleaving is set to mirror setting for 
loop
   // unrolling.
-  Conf.PTO.LoopInterleaving = CGOpts.UnrollLoops;
-  Conf.PTO.LoopVectorization = CGOpts.VectorizeLoop;
-  Conf.PTO.SLPVectorization = CGOpts.VectorizeSLP;
+  Conf.PTO->LoopInterleaving = CGOpts.UnrollLoops;
+  Conf.PTO->LoopVectorization = CGOpts.VectorizeLoop;
+  Conf.PTO->SLPVectorization = CGOpts.VectorizeSLP;
   // Only enable CGProfilePass when using integrated assembler, since
   // non-integrated assemblers don't recognize .cgprofile section.
-  Conf.PTO.CallGraphProfile = !CGOpts.DisableIntegratedAS;
+  Conf.PTO->CallGraphProfile = !CGOpts.DisableIntegratedAS;
 
   // Context sensitive profile.
   if (CGOpts.hasProfileCSIRInstr()) {
diff --git a/clang/tools/clang-nvlink-wrapper/ClangNVLinkWrapper.cpp 
b/clang/tools/clang-nvlink-wrapper/ClangNVLinkWrapper.cpp
index 6550902a6a6551..e0803212092a0b 100644
--- a/clang/tools/clang-nvlink-wrapper/ClangNVLinkWrapper.cpp
+++ b/clang/tools/clang-nvlink-wrapper/ClangNVLinkWrapper.cpp
@@ -376,7 +376,7 @@ createLTO(const cl::LibraryOptionsContext &LibraryOptions,
   const llvm::Triple Triple("nvptx64-nvidia-cuda");
   lto::Config Conf;
   Conf.LibraryOptions = &LibraryOptions;
-  Conf.PTO = PipelineTuningOptions(&LibraryOptions);
+  Conf.PTO.emplace(LibraryOptions);
   lto::ThinBackend Backend;
   unsigned Jobs = 0;
   if (auto *Arg = Args.getLastArg(OPT_jobs))
diff --git a/flang/lib/Frontend/FrontendActions.cpp 
b/flang/lib/Frontend/FrontendActions.cpp
index 823b437d6e83fc..d497d4d6278ddd 100644
--- a/flang/lib/Frontend/FrontendActions.cpp
+++ b/flang/lib/Frontend/FrontendActions.cpp
@@ -966,7 +966,7 @@ void 
CodeGenAction::runOptimizationPipeline(llvm::raw_pwrite_stream &os) {
   llvm::PassInstrumentationCallbacks pic;
   const llvm::cl::LibraryOptionsContext &libraryOptions =
       llvmModule->getContext().getLibraryOptions();
-  llvm::PipelineTuningOptions pto(&libraryOptions);
+  llvm::PipelineTuningOptions pto(libraryOptions);
   std::optional<llvm::PGOOptions> pgoOpt;
 
   if (opts.hasProfileIRInstr()) {
diff --git a/lld/COFF/LTO.cpp b/lld/COFF/LTO.cpp
index 20209019a3e6fe..17fda23f63d4b6 100644
--- a/lld/COFF/LTO.cpp
+++ b/lld/COFF/LTO.cpp
@@ -57,7 +57,7 @@ std::string BitcodeCompiler::getThinLTOOutputFile(StringRef 
path) {
 lto::Config BitcodeCompiler::createConfig() {
   lto::Config c;
   c.LibraryOptions = &ctx.config.libraryOptions;
-  c.PTO = PipelineTuningOptions(c.LibraryOptions);
+  c.PTO.emplace(*c.LibraryOptions);
   c.Options = initTargetOptionsFromCodeGenFlags();
   c.Options.EmitAddrsig = true;
   for (StringRef C : ctx.config.mllvmOpts)
@@ -120,8 +120,8 @@ lto::Config BitcodeCompiler::createConfig() {
                               /*UseInputModulePath*/ true,
                               ctx.config.saveTempsArgs));
 
-  c.PTO.LoopVectorization = c.OptLevel > 1;
-  c.PTO.SLPVectorization = c.OptLevel > 1;
+  c.PTO->LoopVectorization = c.OptLevel > 1;
+  c.PTO->SLPVectorization = c.OptLevel > 1;
 
   return c;
 }
diff --git a/lld/ELF/LTO.cpp b/lld/ELF/LTO.cpp
index 0fa5673ed0f25b..96d14a65d57cea 100644
--- a/lld/ELF/LTO.cpp
+++ b/lld/ELF/LTO.cpp
@@ -56,7 +56,7 @@ static std::string getThinLTOOutputFile(Ctx &ctx, StringRef 
modulePath) {
 static lto::Config createConfig(Ctx &ctx) {
   lto::Config c;
   c.LibraryOptions = &ctx.arg.libraryOptions;
-  c.PTO = PipelineTuningOptions(c.LibraryOptions);
+  c.PTO.emplace(*c.LibraryOptions);
 
   // LLD supports the new relocations and address-significance tables.
   c.Options = initTargetOptionsFromCodeGenFlags();
@@ -117,8 +117,8 @@ static lto::Config createConfig(Ctx &ctx) {
   c.MAttrs = getMAttrs();
   c.CGOptLevel = ctx.arg.ltoCgo;
 
-  c.PTO.LoopVectorization = c.OptLevel > 1;
-  c.PTO.SLPVectorization = c.OptLevel > 1;
+  c.PTO->LoopVectorization = c.OptLevel > 1;
+  c.PTO->SLPVectorization = c.OptLevel > 1;
 
   // Set up a custom pipeline if we've been asked to.
   c.OptPipeline = std::string(ctx.arg.ltoNewPmPasses);
diff --git a/lld/MachO/LTO.cpp b/lld/MachO/LTO.cpp
index 8eb008c990fe6c..7c5187b2a5f960 100644
--- a/lld/MachO/LTO.cpp
+++ b/lld/MachO/LTO.cpp
@@ -39,7 +39,7 @@ static std::string getThinLTOOutputFile(StringRef modulePath) 
{
 static lto::Config createConfig() {
   lto::Config c;
   c.LibraryOptions = &config->libraryOptions;
-  c.PTO = PipelineTuningOptions(c.LibraryOptions);
+  c.PTO.emplace(*c.LibraryOptions);
   c.Options = initTargetOptionsFromCodeGenFlags();
   c.Options.EmitAddrsig = config->icfLevel == ICFLevel::safe ||
                           config->icfLevel == ICFLevel::safe_thunks;
@@ -65,8 +65,8 @@ static lto::Config createConfig() {
   c.OptLevel = config->ltoo;
   c.CGOptLevel = config->ltoCgo;
 
-  c.PTO.LoopVectorization = c.OptLevel > 1;
-  c.PTO.SLPVectorization = c.OptLevel > 1;
+  c.PTO->LoopVectorization = c.OptLevel > 1;
+  c.PTO->SLPVectorization = c.OptLevel > 1;
 
   if (config->saveTemps)
     checkError(c.addSaveTemps(config->outputFile.str() + ".",
diff --git a/lld/wasm/LTO.cpp b/lld/wasm/LTO.cpp
index 8bafd95a258688..0c158058e93725 100644
--- a/lld/wasm/LTO.cpp
+++ b/lld/wasm/LTO.cpp
@@ -43,7 +43,7 @@ static std::string getThinLTOOutputFile(StringRef modulePath) 
{
 static lto::Config createConfig() {
   lto::Config c;
   c.LibraryOptions = &ctx.arg.libraryOptions;
-  c.PTO = PipelineTuningOptions(c.LibraryOptions);
+  c.PTO.emplace(*c.LibraryOptions);
   c.Options = initTargetOptionsFromCodeGenFlags();
 
   // Always emit a section per function/data with LTO.
diff --git a/llvm/include/llvm/Analysis/CallGraphSCCPass.h 
b/llvm/include/llvm/Analysis/CallGraphSCCPass.h
index a9042a43fec700..68c0277e9fb63d 100644
--- a/llvm/include/llvm/Analysis/CallGraphSCCPass.h
+++ b/llvm/include/llvm/Analysis/CallGraphSCCPass.h
@@ -35,7 +35,7 @@ namespace cl {
 class LibraryOptionsContext;
 } // namespace cl
 
-LLVM_ABI unsigned getMaxDevirtIterations(const cl::LibraryOptionsContext *);
+LLVM_ABI unsigned getMaxDevirtIterations(const cl::LibraryOptionsContext &);
 
 class LLVM_ABI CallGraphSCCPass : public Pass {
 public:
diff --git a/llvm/include/llvm/LTO/Config.h b/llvm/include/llvm/LTO/Config.h
index 60cb2a08c0381b..916875068d8e5e 100644
--- a/llvm/include/llvm/LTO/Config.h
+++ b/llvm/include/llvm/LTO/Config.h
@@ -211,8 +211,9 @@ struct Config {
   /// with llvm-lto2.
   std::unique_ptr<raw_ostream> ResolutionFile;
 
-  /// Tunable parameters for passes in the default pipelines.
-  PipelineTuningOptions PTO;
+  /// Tunable parameters for passes in the default pipelines. If unset, the
+  /// backend reads them from the module's LLVMContext.
+  std::optional<PipelineTuningOptions> PTO;
 
   /// The following callbacks deal with tasks, which normally represent the
   /// entire optimization and code generation pipeline for what will become a
diff --git a/llvm/include/llvm/Passes/PassBuilder.h 
b/llvm/include/llvm/Passes/PassBuilder.h
index 3512c9c9a9ca29..c5fbb5a064d0be 100644
--- a/llvm/include/llvm/Passes/PassBuilder.h
+++ b/llvm/include/llvm/Passes/PassBuilder.h
@@ -45,15 +45,10 @@ class LibraryOptionsContext;
 /// Tunable parameters for passes in the default pipelines.
 class PipelineTuningOptions {
 public:
-  /// Constructor sets pipeline tuning defaults based on the global values of
-  /// the library options. Each option can be set in the PassBuilder when using
-  /// a LLVM as a library.
-  PipelineTuningOptions() : PipelineTuningOptions(nullptr) {}
-
-  /// Reads the defaults from \p LibraryOptions, or their global values if
-  /// null.
+  /// Reads the defaults from \p LibraryOptions. Each option can be set in the
+  /// PassBuilder when using LLVM as a library.
   LLVM_ABI explicit PipelineTuningOptions(
-      const cl::LibraryOptionsContext *LibraryOptions);
+      const cl::LibraryOptionsContext &LibraryOptions);
 
   /// Tuning option to set loop interleaving on/off, set based on opt level.
   bool LoopInterleaving;
diff --git a/llvm/include/llvm/Transforms/Scalar/LICM.h 
b/llvm/include/llvm/Transforms/Scalar/LICM.h
index 7eb460e7b33599..379dbd2152a308 100644
--- a/llvm/include/llvm/Transforms/Scalar/LICM.h
+++ b/llvm/include/llvm/Transforms/Scalar/LICM.h
@@ -45,14 +45,12 @@ namespace cl {
 class LibraryOptionsContext;
 } // namespace cl
 
-/// Returns -licm-mssa-optimization-cap of LibraryOptions, or its global value
-/// if null.
+/// Return -licm-mssa-optimization-cap.
 LLVM_ABI unsigned
-getLicmMssaOptCap(const cl::LibraryOptionsContext *LibraryOptions);
-/// Returns -licm-mssa-max-acc-promotion of LibraryOptions, or its global value
-/// if null.
+getLicmMssaOptCap(const cl::LibraryOptionsContext &LibraryOptions);
+/// Return -licm-mssa-max-acc-promotion.
 LLVM_ABI unsigned getLicmMssaNoAccForPromotionCap(
-    const cl::LibraryOptionsContext *LibraryOptions);
+    const cl::LibraryOptionsContext &LibraryOptions);
 
 struct LICMOptions {
   // Unset means the -licm-mssa-* value of the loop's LLVMContext.
diff --git a/llvm/include/llvm/Transforms/Scalar/LoopUnrollPass.h 
b/llvm/include/llvm/Transforms/Scalar/LoopUnrollPass.h
index 7955d8f79dc5c0..f2e50353b9b42e 100644
--- a/llvm/include/llvm/Transforms/Scalar/LoopUnrollPass.h
+++ b/llvm/include/llvm/Transforms/Scalar/LoopUnrollPass.h
@@ -19,10 +19,9 @@ namespace cl {
 class LibraryOptionsContext;
 } // namespace cl
 
-/// Returns -forget-scev-loop-unroll of LibraryOptions, or its global value if
-/// null.
+/// Return -forget-scev-loop-unroll.
 LLVM_ABI bool
-getForgetSCEVInLoopUnroll(const cl::LibraryOptionsContext *LibraryOptions);
+getForgetSCEVInLoopUnroll(const cl::LibraryOptionsContext &LibraryOptions);
 
 class Function;
 class Loop;
diff --git a/llvm/lib/Analysis/CallGraphSCCPass.cpp 
b/llvm/lib/Analysis/CallGraphSCCPass.cpp
index ba120b245275df..bff6aee0cad972 100644
--- a/llvm/lib/Analysis/CallGraphSCCPass.cpp
+++ b/llvm/lib/Analysis/CallGraphSCCPass.cpp
@@ -44,9 +44,8 @@ using namespace llvm;
 #define DEBUG_TYPE "cgscc-passmgr"
 
 unsigned
-llvm::getMaxDevirtIterations(const cl::LibraryOptionsContext *LibraryOptions) {
-  return cl::LibraryOptionsContext::get<AnalysisOptions>(LibraryOptions)
-      .max_devirt_iterations;
+llvm::getMaxDevirtIterations(const cl::LibraryOptionsContext &LibraryOptions) {
+  return LibraryOptions.get<AnalysisOptions>().max_devirt_iterations;
 }
 
 STATISTIC(MaxSCCIterations, "Maximum CGSCCPassMgr iterations on one SCC");
diff --git a/llvm/lib/DTLTO/DTLTO.cpp b/llvm/lib/DTLTO/DTLTO.cpp
index 669ba75c80d4b6..dc103d3d461cc8 100644
--- a/llvm/lib/DTLTO/DTLTO.cpp
+++ b/llvm/lib/DTLTO/DTLTO.cpp
@@ -226,7 +226,7 @@ void lto::DTLTO::buildCommonRemoteCompilerOptions() {
     Ops.push_back("-ffunction-sections");
   if (C.Options.DataSections)
     Ops.push_back("-fdata-sections");
-  if (C.PTO.LoopInterchange)
+  if (C.PTO && C.PTO->LoopInterchange)
     Ops.push_back("-floop-interchange");
 
   if (C.RelocModel == Reloc::PIC_)
diff --git a/llvm/lib/LTO/LTOCodeGenerator.cpp 
b/llvm/lib/LTO/LTOCodeGenerator.cpp
index ad58b4fc3cf239..fe34c24975dc1e 100644
--- a/llvm/lib/LTO/LTOCodeGenerator.cpp
+++ b/llvm/lib/LTO/LTOCodeGenerator.cpp
@@ -564,9 +564,9 @@ bool LTOCodeGenerator::optimize() {
   Config.RunCSIRInstr = LTORunCSIRInstr;
   Config.CSIRProfile = LTOCSIRProfile;
   Config.SampleProfile = SampleProfileFile;
-  Config.PTO = PipelineTuningOptions(Config.LibraryOptions);
-  Config.PTO.LoopVectorization = Config.OptLevel > 1;
-  Config.PTO.SLPVectorization = Config.OptLevel > 1;
+  Config.PTO.emplace(*Config.LibraryOptions);
+  Config.PTO->LoopVectorization = Config.OptLevel > 1;
+  Config.PTO->SLPVectorization = Config.OptLevel > 1;
 
   auto DiagFileOrErr = lto::setupLLVMOptimizationRemarks(
       Context, RemarksFilename, RemarksPasses, RemarksFormat,
diff --git a/llvm/lib/LTO/ThinLTOCodeGenerator.cpp 
b/llvm/lib/LTO/ThinLTOCodeGenerator.cpp
index 13e4c7bb5fc6f6..0709b8b0724f7c 100644
--- a/llvm/lib/LTO/ThinLTOCodeGenerator.cpp
+++ b/llvm/lib/LTO/ThinLTOCodeGenerator.cpp
@@ -261,7 +261,7 @@ static void optimizeModule(Module &TheModule, TargetMachine 
&TM,
   PassInstrumentationCallbacks PIC;
   StandardInstrumentations SI(TheModule.getContext(), DebugPassManager);
   SI.registerCallbacks(PIC, &MAM);
-  PipelineTuningOptions PTO(&TheModule.getContext().getLibraryOptions());
+  PipelineTuningOptions PTO(TheModule.getContext().getLibraryOptions());
   PTO.LoopVectorization = true;
   PTO.SLPVectorization = true;
   PassBuilder PB(TheModule.getContext(), &TM, PTO, PGOOpt, &PIC);
diff --git a/llvm/lib/Passes/PassBuilder.cpp b/llvm/lib/Passes/PassBuilder.cpp
index 4e9a38be994505..db933577e3d35f 100644
--- a/llvm/lib/Passes/PassBuilder.cpp
+++ b/llvm/lib/Passes/PassBuilder.cpp
@@ -573,7 +573,7 @@ PassBuilder::PassBuilder(LLVMContext &Context, 
TargetMachine *TM,
                          PassInstrumentationCallbacks *PIC,
                          IntrusiveRefCntPtr<vfs::FileSystem> FS)
     : Context(Context), Opts(getPassesOptions(Context)), TM(TM),
-      PTO(PTO ? *PTO : PipelineTuningOptions(&Context.getLibraryOptions())),
+      PTO(PTO ? *PTO : PipelineTuningOptions(Context.getLibraryOptions())),
       PGOOpt(PGOOpt), PIC(PIC), FS(std::move(FS)) {
   if (TM)
     TM->registerPassBuilderCallbacks(*this);
diff --git a/llvm/lib/Passes/PassBuilderBindings.cpp 
b/llvm/lib/Passes/PassBuilderBindings.cpp
index d9f2f887c6467d..1fe73932ed0f5f 100644
--- a/llvm/lib/Passes/PassBuilderBindings.cpp
+++ b/llvm/lib/Passes/PassBuilderBindings.cpp
@@ -18,6 +18,7 @@
 #include "llvm/Passes/PassBuilder.h"
 #include "llvm/Passes/StandardInstrumentations.h"
 #include "llvm/Support/CBindingWrapping.h"
+#include "llvm/Support/CommandLine.h"
 
 using namespace llvm;
 
@@ -30,7 +31,8 @@ class LLVMPassBuilderOptions {
   explicit LLVMPassBuilderOptions(
       bool DebugLogging = false, bool VerifyEach = false,
       const char *AAPipeline = nullptr,
-      PipelineTuningOptions PTO = PipelineTuningOptions())
+      PipelineTuningOptions PTO =
+          PipelineTuningOptions(cl::getCAPILibraryOptions()))
       : DebugLogging(DebugLogging), VerifyEach(VerifyEach),
         AAPipeline(AAPipeline), PTO(PTO) {}
 
diff --git a/llvm/lib/Passes/PassBuilderPipelines.cpp 
b/llvm/lib/Passes/PassBuilderPipelines.cpp
index 1987ceb6b06c02..c8235d14e22099 100644
--- a/llvm/lib/Passes/PassBuilderPipelines.cpp
+++ b/llvm/lib/Passes/PassBuilderPipelines.cpp
@@ -171,9 +171,8 @@ extern cl::opt<bool> EnableProfcheckInPipeline;
 } // namespace llvm
 
 PipelineTuningOptions::PipelineTuningOptions(
-    const cl::LibraryOptionsContext *LibraryOptions) {
-  const PassesOptions &Opts =
-      cl::LibraryOptionsContext::get<PassesOptions>(LibraryOptions);
+    const cl::LibraryOptionsContext &LibraryOptions) {
+  const PassesOptions &Opts = LibraryOptions.get<PassesOptions>();
   LoopInterleaving = true;
   LoopVectorization = true;
   SLPVectorization = false;
diff --git a/llvm/lib/Passes/RunCodeGen.cpp b/llvm/lib/Passes/RunCodeGen.cpp
index 67aecdb6f5494c..c64f387ab61654 100644
--- a/llvm/lib/Passes/RunCodeGen.cpp
+++ b/llvm/lib/Passes/RunCodeGen.cpp
@@ -66,7 +66,7 @@ static Error runCodeGenPipelineNewPM(TargetMachine &TM, 
Module &M,
   MachineModuleInfo MMI(&TM);
   PassInstrumentationCallbacks PIC;
   const auto &LibraryOptions = M.getContext().getLibraryOptions();
-  PipelineTuningOptions PTOptions(&LibraryOptions);
+  PipelineTuningOptions PTOptions(LibraryOptions);
   PassBuilder PB(M.getContext(), &TM, PTOptions, std::nullopt, &PIC, VFS);
   PB.registerModuleAnalyses(MAM);
   PB.registerCGSCCAnalyses(CGAM);
diff --git a/llvm/lib/Transforms/Scalar/LICM.cpp 
b/llvm/lib/Transforms/Scalar/LICM.cpp
index df0f7eda307d31..beacb150e56287 100644
--- a/llvm/lib/Transforms/Scalar/LICM.cpp
+++ b/llvm/lib/Transforms/Scalar/LICM.cpp
@@ -117,15 +117,13 @@ STATISTIC(NumBOAssociationsHoisted, "Number of invariant 
BinaryOp expressions "
                                     "reassociated and hoisted out of the 
loop");
 
 unsigned
-llvm::getLicmMssaOptCap(const cl::LibraryOptionsContext *LibraryOptions) {
-  return cl::LibraryOptionsContext::get<ScalarOptions>(LibraryOptions)
-      .licm_mssa_optimization_cap;
+llvm::getLicmMssaOptCap(const cl::LibraryOptionsContext &LibraryOptions) {
+  return LibraryOptions.get<ScalarOptions>().licm_mssa_optimization_cap;
 }
 
 unsigned llvm::getLicmMssaNoAccForPromotionCap(
-    const cl::LibraryOptionsContext *LibraryOptions) {
-  return cl::LibraryOptionsContext::get<ScalarOptions>(LibraryOptions)
-      .licm_mssa_max_acc_promotion;
+    const cl::LibraryOptionsContext &LibraryOptions) {
+  return LibraryOptions.get<ScalarOptions>().licm_mssa_max_acc_promotion;
 }
 
 static bool inSubLoop(BasicBlock *BB, Loop *CurLoop, LoopInfo *LI);
diff --git a/llvm/lib/Transforms/Scalar/LoopUnrollPass.cpp 
b/llvm/lib/Transforms/Scalar/LoopUnrollPass.cpp
index d21de774096345..a68cd506eecfe3 100644
--- a/llvm/lib/Transforms/Scalar/LoopUnrollPass.cpp
+++ b/llvm/lib/Transforms/Scalar/LoopUnrollPass.cpp
@@ -75,9 +75,8 @@ using namespace llvm;
 #define DEBUG_TYPE "loop-unroll"
 
 bool llvm::getForgetSCEVInLoopUnroll(
-    const cl::LibraryOptionsContext *LibraryOptions) {
-  return cl::LibraryOptionsContext::get<ScalarOptions>(LibraryOptions)
-      .forget_scev_loop_unroll;
+    const cl::LibraryOptionsContext &LibraryOptions) {
+  return LibraryOptions.get<ScalarOptions>().forget_scev_loop_unroll;
 }
 
 /// A magic value for use with the Threshold parameter to indicate
diff --git a/llvm/tools/gold/gold-plugin.cpp b/llvm/tools/gold/gold-plugin.cpp
index 17bdac650512cf..f95f4ef05f5687 100644
--- a/llvm/tools/gold/gold-plugin.cpp
+++ b/llvm/tools/gold/gold-plugin.cpp
@@ -902,11 +902,11 @@ createLTO(const cl::LibraryOptionsContext &LibraryOptions,
   Conf.CGOptLevel = *CGOptLevelOrNone;
   Conf.DisableVerify = options::DisableVerify;
   Conf.OptLevel = options::OptLevel;
-  Conf.PTO = PipelineTuningOptions(&LibraryOptions);
-  Conf.PTO.LoopVectorization = options::OptLevel > 1;
-  Conf.PTO.SLPVectorization = options::OptLevel > 1;
-  Conf.PTO.MergeFunctions = options::merge_functions;
-  Conf.PTO.UnifiedLTO = options::unifiedlto;
+  Conf.PTO.emplace(LibraryOptions);
+  Conf.PTO->LoopVectorization = options::OptLevel > 1;
+  Conf.PTO->SLPVectorization = options::OptLevel > 1;
+  Conf.PTO->MergeFunctions = options::merge_functions;
+  Conf.PTO->UnifiedLTO = options::unifiedlto;
   Conf.AlwaysEmitRegularLTOObj = !options::obj_path.empty();
 
   if (options::thinlto_index_only) {
diff --git a/llvm/tools/llvm-lto2/llvm-lto2.cpp 
b/llvm/tools/llvm-lto2/llvm-lto2.cpp
index 8cf21ef909b740..b4cf1dbf7f7783 100644
--- a/llvm/tools/llvm-lto2/llvm-lto2.cpp
+++ b/llvm/tools/llvm-lto2/llvm-lto2.cpp
@@ -346,7 +346,7 @@ static int run(int argc, char **argv) {
 
   Config Conf;
   Conf.LibraryOptions = &LibraryOptions;
-  Conf.PTO = PipelineTuningOptions(&LibraryOptions);
+  Conf.PTO.emplace(LibraryOptions);
   if (TimeTrace) {
     Conf.TimeTraceEnabled = TimeTrace;
     Conf.TimeTraceGranularity = TimeTraceGranularity;
@@ -408,8 +408,8 @@ static int run(int argc, char **argv) {
   Conf.OverrideTriple = OverrideTriple;
   Conf.DefaultTriple = DefaultTriple;
   Conf.StatsFile = StatsFile;
-  Conf.PTO.LoopVectorization = Conf.OptLevel > 1;
-  Conf.PTO.SLPVectorization = Conf.OptLevel > 1;
+  Conf.PTO->LoopVectorization = Conf.OptLevel > 1;
+  Conf.PTO->SLPVectorization = Conf.OptLevel > 1;
 
   if (WholeProgramVisibilityEnabledInLTO.getNumOccurrences() > 0)
     Conf.HasWholeProgramVisibility = WholeProgramVisibilityEnabledInLTO;
diff --git a/llvm/tools/opt/NewPMDriver.cpp b/llvm/tools/opt/NewPMDriver.cpp
index 22899f4eb8ccbb..667cbf8c3c0538 100644
--- a/llvm/tools/opt/NewPMDriver.cpp
+++ b/llvm/tools/opt/NewPMDriver.cpp
@@ -473,7 +473,7 @@ bool llvm::runPassPipeline(
     Debugify.registerCallbacks(PIC, MAM);
   }
 
-  PipelineTuningOptions PTO(&M.getContext().getLibraryOptions());
+  PipelineTuningOptions PTO(M.getContext().getLibraryOptions());
   // LoopUnrolling defaults on to true and DisableLoopUnrolling is initialized
   // to false above so we shouldn't necessarily need to check whether or not 
the
   // option has been enabled.
diff --git a/mlir/lib/ExecutionEngine/OptUtils.cpp 
b/mlir/lib/ExecutionEngine/OptUtils.cpp
index 2e2f36a35c1afc..003d5af6764cbd 100644
--- a/mlir/lib/ExecutionEngine/OptUtils.cpp
+++ b/mlir/lib/ExecutionEngine/OptUtils.cpp
@@ -60,7 +60,7 @@ mlir::makeOptimizingTransformer(unsigned optLevel, unsigned 
sizeLevel,
     CGSCCAnalysisManager cgam;
     ModuleAnalysisManager mam;
 
-    PipelineTuningOptions tuningOptions(&m->getContext().getLibraryOptions());
+    PipelineTuningOptions tuningOptions(m->getContext().getLibraryOptions());
     tuningOptions.LoopUnrolling = true;
     tuningOptions.LoopInterleaving = true;
     tuningOptions.LoopVectorization = true;

>From d9e78875d44d532fe19d3e8e563e96528b3b7630 Mon Sep 17 00:00:00 2001
From: Fangrui Song <[email protected]>
Date: Sat, 31 Oct 2026 12:26:55 -0700
Subject: [PATCH 2/2] simplify

---
 clang/lib/CodeGen/BackendUtil.cpp                | 16 ++++++++--------
 .../clang-nvlink-wrapper/ClangNVLinkWrapper.cpp  |  1 -
 lld/wasm/LTO.cpp                                 |  1 -
 llvm/lib/DTLTO/DTLTO.cpp                         |  8 +++++++-
 llvm/tools/gold/gold-plugin.cpp                  | 10 +++++-----
 5 files changed, 20 insertions(+), 16 deletions(-)

diff --git a/clang/lib/CodeGen/BackendUtil.cpp 
b/clang/lib/CodeGen/BackendUtil.cpp
index d56185146f63df..249755e937f2f9 100644
--- a/clang/lib/CodeGen/BackendUtil.cpp
+++ b/clang/lib/CodeGen/BackendUtil.cpp
@@ -1380,18 +1380,18 @@ runThinLTOBackend(CompilerInstance &CI, 
ModuleSummaryIndex *CombinedIndex,
   Conf.SampleProfile = std::move(SampleProfile);
   const cl::LibraryOptionsContext &LibraryOptions =
       M->getContext().getLibraryOptions();
-  Conf.PTO.emplace(LibraryOptions);
-  Conf.PTO->LoopUnrolling = CGOpts.UnrollLoops;
-  Conf.PTO->LoopInterchange = CGOpts.InterchangeLoops;
-  Conf.PTO->LoopFusion = CGOpts.FuseLoops;
+  PipelineTuningOptions &PTO = Conf.PTO.emplace(LibraryOptions);
+  PTO.LoopUnrolling = CGOpts.UnrollLoops;
+  PTO.LoopInterchange = CGOpts.InterchangeLoops;
+  PTO.LoopFusion = CGOpts.FuseLoops;
   // For historical reasons, loop interleaving is set to mirror setting for 
loop
   // unrolling.
-  Conf.PTO->LoopInterleaving = CGOpts.UnrollLoops;
-  Conf.PTO->LoopVectorization = CGOpts.VectorizeLoop;
-  Conf.PTO->SLPVectorization = CGOpts.VectorizeSLP;
+  PTO.LoopInterleaving = CGOpts.UnrollLoops;
+  PTO.LoopVectorization = CGOpts.VectorizeLoop;
+  PTO.SLPVectorization = CGOpts.VectorizeSLP;
   // Only enable CGProfilePass when using integrated assembler, since
   // non-integrated assemblers don't recognize .cgprofile section.
-  Conf.PTO->CallGraphProfile = !CGOpts.DisableIntegratedAS;
+  PTO.CallGraphProfile = !CGOpts.DisableIntegratedAS;
 
   // Context sensitive profile.
   if (CGOpts.hasProfileCSIRInstr()) {
diff --git a/clang/tools/clang-nvlink-wrapper/ClangNVLinkWrapper.cpp 
b/clang/tools/clang-nvlink-wrapper/ClangNVLinkWrapper.cpp
index e0803212092a0b..7bd9b007c74087 100644
--- a/clang/tools/clang-nvlink-wrapper/ClangNVLinkWrapper.cpp
+++ b/clang/tools/clang-nvlink-wrapper/ClangNVLinkWrapper.cpp
@@ -376,7 +376,6 @@ createLTO(const cl::LibraryOptionsContext &LibraryOptions,
   const llvm::Triple Triple("nvptx64-nvidia-cuda");
   lto::Config Conf;
   Conf.LibraryOptions = &LibraryOptions;
-  Conf.PTO.emplace(LibraryOptions);
   lto::ThinBackend Backend;
   unsigned Jobs = 0;
   if (auto *Arg = Args.getLastArg(OPT_jobs))
diff --git a/lld/wasm/LTO.cpp b/lld/wasm/LTO.cpp
index 0c158058e93725..774908babc84de 100644
--- a/lld/wasm/LTO.cpp
+++ b/lld/wasm/LTO.cpp
@@ -43,7 +43,6 @@ static std::string getThinLTOOutputFile(StringRef modulePath) 
{
 static lto::Config createConfig() {
   lto::Config c;
   c.LibraryOptions = &ctx.arg.libraryOptions;
-  c.PTO.emplace(*c.LibraryOptions);
   c.Options = initTargetOptionsFromCodeGenFlags();
 
   // Always emit a section per function/data with LTO.
diff --git a/llvm/lib/DTLTO/DTLTO.cpp b/llvm/lib/DTLTO/DTLTO.cpp
index dc103d3d461cc8..e92758523ef237 100644
--- a/llvm/lib/DTLTO/DTLTO.cpp
+++ b/llvm/lib/DTLTO/DTLTO.cpp
@@ -226,7 +226,13 @@ void lto::DTLTO::buildCommonRemoteCompilerOptions() {
     Ops.push_back("-ffunction-sections");
   if (C.Options.DataSections)
     Ops.push_back("-fdata-sections");
-  if (C.PTO && C.PTO->LoopInterchange)
+  // An unset PTO means the defaults of the backend's LLVMContext, which copies
+  // C.LibraryOptions.
+  cl::LibraryOptionsContext NoLibraryOptions;
+  if (C.PTO ? C.PTO->LoopInterchange
+            : PipelineTuningOptions(C.LibraryOptions ? *C.LibraryOptions
+                                                     : NoLibraryOptions)
+                  .LoopInterchange)
     Ops.push_back("-floop-interchange");
 
   if (C.RelocModel == Reloc::PIC_)
diff --git a/llvm/tools/gold/gold-plugin.cpp b/llvm/tools/gold/gold-plugin.cpp
index f95f4ef05f5687..5d23292f77c2d1 100644
--- a/llvm/tools/gold/gold-plugin.cpp
+++ b/llvm/tools/gold/gold-plugin.cpp
@@ -902,11 +902,11 @@ createLTO(const cl::LibraryOptionsContext &LibraryOptions,
   Conf.CGOptLevel = *CGOptLevelOrNone;
   Conf.DisableVerify = options::DisableVerify;
   Conf.OptLevel = options::OptLevel;
-  Conf.PTO.emplace(LibraryOptions);
-  Conf.PTO->LoopVectorization = options::OptLevel > 1;
-  Conf.PTO->SLPVectorization = options::OptLevel > 1;
-  Conf.PTO->MergeFunctions = options::merge_functions;
-  Conf.PTO->UnifiedLTO = options::unifiedlto;
+  PipelineTuningOptions &PTO = Conf.PTO.emplace(LibraryOptions);
+  PTO.LoopVectorization = options::OptLevel > 1;
+  PTO.SLPVectorization = options::OptLevel > 1;
+  PTO.MergeFunctions = options::merge_functions;
+  PTO.UnifiedLTO = options::unifiedlto;
   Conf.AlwaysEmitRegularLTOObj = !options::obj_path.empty();
 
   if (options::thinlto_index_only) {

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

Reply via email to