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

>From baeb153d00cefd92e629693401a1d74def1f2595 Mon Sep 17 00:00:00 2001
From: Fangrui Song <[email protected]>
Date: Wed, 14 Oct 2026 19:39:01 -0700
Subject: [PATCH 1/6] [Option] Make OptionsStruct per-context by default

Make perContext the default, and opt out the ported libraries that still
read Global with perContext = false. X86Options, X86MCOptions, and
RISCVOptions become per-context.

A TargetMachine and the MC layer have no LLVMContext. Add
MCTargetOptions::LibraryOptions, which llc, opt, and clang set to the
compiled module's LLVMContext. X86TargetMachine, RISCVTargetMachine, and
X86's MCAsmInfo, MCAsmBackend, and MCTargetAsmParser read their options
through LibraryOptionsContext::get, which returns the global values when
it is unset, as in llvm-mc and clang -cc1as.

Aided by Opus 5.5
---
 clang/lib/CodeGen/BackendUtil.cpp             |  2 +
 llvm/include/llvm/CodeGen/CommandFlags.h      |  3 +-
 llvm/include/llvm/MC/MCTargetOptions.h        |  8 ++
 llvm/include/llvm/Option/LibraryOptions.td    |  2 +-
 .../llvm/Support/LibraryOptionsContext.h      |  5 ++
 llvm/lib/CGData/CGDataOptions.td              |  2 +-
 llvm/lib/CodeGen/CodeGenOptions.td            |  2 +-
 llvm/lib/CodeGen/CommandFlags.cpp             | 11 +--
 llvm/lib/MC/MCCLOptions.td                    |  2 +-
 llvm/lib/Passes/PassesOptions.td              |  2 +-
 llvm/lib/Target/AArch64/AArch64Options.td     |  2 +-
 .../AArch64/MCTargetDesc/AArch64MCOptions.td  |  2 +-
 .../Target/Mips/MCTargetDesc/MipsMCOptions.td |  2 +-
 llvm/lib/Target/Mips/MipsOptions.td           |  2 +-
 .../RISCV/MCTargetDesc/RISCVMCOptions.td      |  2 +-
 llvm/lib/Target/RISCV/RISCVTargetMachine.cpp  |  4 +-
 llvm/lib/Target/Sparc/SparcOptions.td         |  2 +-
 .../lib/Target/X86/AsmParser/X86AsmParser.cpp |  4 +-
 .../Target/X86/MCTargetDesc/X86AsmBackend.cpp | 78 ++++++++++---------
 .../Target/X86/MCTargetDesc/X86MCAsmInfo.cpp  | 14 ++--
 llvm/lib/Target/X86/X86TargetMachine.cpp      |  5 +-
 .../InstCombine/InstCombineCLOptions.td       |  2 +-
 .../Instrumentation/InstrumentationOptions.td |  2 +-
 llvm/lib/Transforms/Scalar/ScalarOptions.td   |  2 +-
 .../Transforms/Vectorize/VectorizeOptions.td  |  2 +-
 llvm/tools/llc/lib/llcdriver.cpp              |  1 +
 llvm/tools/opt/optdriver.cpp                  |  4 +-
 llvm/unittests/Option/LibraryOpts.td          |  2 +-
 28 files changed, 102 insertions(+), 69 deletions(-)

diff --git a/clang/lib/CodeGen/BackendUtil.cpp 
b/clang/lib/CodeGen/BackendUtil.cpp
index f07e4ee84b9b65..5a9ff964380023 100644
--- a/clang/lib/CodeGen/BackendUtil.cpp
+++ b/clang/lib/CodeGen/BackendUtil.cpp
@@ -597,6 +597,8 @@ void EmitAssemblyHelper::CreateTargetMachine(bool 
MustCreateTM) {
   llvm::TargetOptions Options;
   if (!initTargetOptions(CI, Diags, Options))
     return;
+  Options.MCOptions.LibraryOptions =
+      &TheModule->getContext().getLibraryOptions();
   TM.reset(TheTarget->createTargetMachine(Triple, TargetOpts.CPU, FeaturesStr,
                                           Options, RM, CM, OptLevel));
   if (TM)
diff --git a/llvm/include/llvm/CodeGen/CommandFlags.h 
b/llvm/include/llvm/CodeGen/CommandFlags.h
index 4e09a2c720c170..8959d7995fb9b7 100644
--- a/llvm/include/llvm/CodeGen/CommandFlags.h
+++ b/llvm/include/llvm/CodeGen/CommandFlags.h
@@ -194,7 +194,8 @@ LLVM_ABI void setFunctionAttributes(Module &M, StringRef 
CPU,
 /// the TargetOptions.
 LLVM_ABI Expected<std::unique_ptr<TargetMachine>> createTargetMachineForTriple(
     const Triple &TargetTriple,
-    CodeGenOptLevel OptLevel = CodeGenOptLevel::Default);
+    CodeGenOptLevel OptLevel = CodeGenOptLevel::Default,
+    const cl::LibraryOptionsContext *LibraryOptions = nullptr);
 
 /// Conditionally enables the collection of LLVM statistics during the tool 
run,
 /// based on the value of the flag. Must be called before the tool run to
diff --git a/llvm/include/llvm/MC/MCTargetOptions.h 
b/llvm/include/llvm/MC/MCTargetOptions.h
index 6bda34904a5c56..8414723cf6e0c8 100644
--- a/llvm/include/llvm/MC/MCTargetOptions.h
+++ b/llvm/include/llvm/MC/MCTargetOptions.h
@@ -35,6 +35,9 @@ enum class RelocSectionSymType {
 };
 
 class StringRef;
+namespace cl {
+class LibraryOptionsContext;
+} // namespace cl
 
 class MCTargetOptions {
 public:
@@ -133,6 +136,11 @@ class MCTargetOptions {
   // (personality/LSDA/TType already default to sdata8).
   bool LargeEHEncoding = false;
 
+  // The library options of the compilation, usually its LLVMContext's.
+  // TODO: Make it non-null once every tool sets it. Null means the global
+  // values.
+  const cl::LibraryOptionsContext *LibraryOptions = nullptr;
+
   LLVM_ABI MCTargetOptions();
 
   /// Parse a binutils version string ("major[.minor]" or "none") into a
diff --git a/llvm/include/llvm/Option/LibraryOptions.td 
b/llvm/include/llvm/Option/LibraryOptions.td
index ab027c056831ea..9cd18a5a0de1d9 100644
--- a/llvm/include/llvm/Option/LibraryOptions.td
+++ b/llvm/include/llvm/Option/LibraryOptions.td
@@ -18,7 +18,7 @@ include "llvm/Option/OptParser.td"
 
 // A row whose spelling starts with prefix names its member without it.
 // perContext makes Global private; read through 
cl::LibraryOptionsContext::get.
-class OptionsStruct<string namespace = "llvm", string prefix = "", bit 
perContext = false> {
+class OptionsStruct<string namespace = "llvm", string prefix = "", bit 
perContext = true> {
   string Namespace = namespace;
   string MemberPrefix = prefix;
   bit PerContext = perContext;
diff --git a/llvm/include/llvm/Support/LibraryOptionsContext.h 
b/llvm/include/llvm/Support/LibraryOptionsContext.h
index 16312dc4ba32b1..4fad737637db78 100644
--- a/llvm/include/llvm/Support/LibraryOptionsContext.h
+++ b/llvm/include/llvm/Support/LibraryOptionsContext.h
@@ -50,6 +50,11 @@ class LLVM_ABI LibraryOptionsContext {
     return T::Global;
   }
 
+  // C's values of T, or T::Global if C is null.
+  template <typename T> static const T &get(const LibraryOptionsContext *C) {
+    return C ? C->get<T>() : T::Global;
+  }
+
 private:
   DenseMap<const void *, void *> Values;
   SmallVector<const char *, 0> SavedArgs;
diff --git a/llvm/lib/CGData/CGDataOptions.td b/llvm/lib/CGData/CGDataOptions.td
index 025e91f5bca236..0e4cbdcc005bac 100644
--- a/llvm/lib/CGData/CGDataOptions.td
+++ b/llvm/lib/CGData/CGDataOptions.td
@@ -8,7 +8,7 @@
 
 include "llvm/Option/LibraryOptions.td"
 
-def CGDataOptions : OptionsStruct;
+def CGDataOptions : OptionsStruct<perContext = false>;
 
 defm : BoolField<"codegen-data-generate", "false",
   "Emit CodeGen Data into custom sections">;
diff --git a/llvm/lib/CodeGen/CodeGenOptions.td 
b/llvm/lib/CodeGen/CodeGenOptions.td
index 21ba8450ca3947..0b644d0b96e96c 100644
--- a/llvm/lib/CodeGen/CodeGenOptions.td
+++ b/llvm/lib/CodeGen/CodeGenOptions.td
@@ -8,7 +8,7 @@
 
 include "llvm/Option/LibraryOptions.td"
 
-def CodeGenOptions : OptionsStruct;
+def CodeGenOptions : OptionsStruct<perContext = false>;
 
 // CodeGenPrepare.cpp
 defm : BoolField<"bbsections-guided-section-prefix", "true",
diff --git a/llvm/lib/CodeGen/CommandFlags.cpp 
b/llvm/lib/CodeGen/CommandFlags.cpp
index 46a294f3524b94..ea1b0a089f5f3a 100644
--- a/llvm/lib/CodeGen/CommandFlags.cpp
+++ b/llvm/lib/CodeGen/CommandFlags.cpp
@@ -752,9 +752,9 @@ void codegen::setFunctionAttributes(Module &M, StringRef 
CPU,
     setFunctionAttributes(F, CPU, Features, TuneCPU);
 }
 
-Expected<std::unique_ptr<TargetMachine>>
-codegen::createTargetMachineForTriple(const Triple &TargetTriple,
-                                      CodeGenOptLevel OptLevel) {
+Expected<std::unique_ptr<TargetMachine>> codegen::createTargetMachineForTriple(
+    const Triple &TargetTriple, CodeGenOptLevel OptLevel,
+    const cl::LibraryOptionsContext *LibraryOptions) {
   // lookupTarget may mutate the triple, so we need a copy.
   Triple TheTriple(TargetTriple);
   std::string Error;
@@ -762,9 +762,10 @@ codegen::createTargetMachineForTriple(const Triple 
&TargetTriple,
       TargetRegistry::lookupTarget(codegen::getMArch(), TheTriple, Error);
   if (!TheTarget)
     return createStringError(inconvertibleErrorCode(), Error);
+  TargetOptions Options = 
codegen::InitTargetOptionsFromCodeGenFlags(TheTriple);
+  Options.MCOptions.LibraryOptions = LibraryOptions;
   auto *Target = TheTarget->createTargetMachine(
-      TheTriple, codegen::getCPUStr(), codegen::getFeaturesStr(),
-      codegen::InitTargetOptionsFromCodeGenFlags(TheTriple),
+      TheTriple, codegen::getCPUStr(), codegen::getFeaturesStr(), Options,
       codegen::getExplicitRelocModel(), codegen::getExplicitCodeModel(),
       OptLevel);
   if (!Target)
diff --git a/llvm/lib/MC/MCCLOptions.td b/llvm/lib/MC/MCCLOptions.td
index 37bb5ac6a3125a..fea3e378450a4b 100644
--- a/llvm/lib/MC/MCCLOptions.td
+++ b/llvm/lib/MC/MCCLOptions.td
@@ -8,7 +8,7 @@
 
 include "llvm/Option/LibraryOptions.td"
 
-def MCCLOptions : OptionsStruct;
+def MCCLOptions : OptionsStruct<perContext = false>;
 
 defm : DefaultOnOffField<"dwarf-extended-loc",
   "Disable emission of the extended flags in .loc directives">;
diff --git a/llvm/lib/Passes/PassesOptions.td b/llvm/lib/Passes/PassesOptions.td
index 4398d5c06bff2b..8789b2a243dd8c 100644
--- a/llvm/lib/Passes/PassesOptions.td
+++ b/llvm/lib/Passes/PassesOptions.td
@@ -8,7 +8,7 @@
 
 include "llvm/Option/LibraryOptions.td"
 
-def PassesOptions : OptionsStruct;
+def PassesOptions : OptionsStruct<perContext = false>;
 
 // PassBuilder.cpp
 defm : FlagOrEnumField<"print-pipeline-passes",
diff --git a/llvm/lib/Target/AArch64/AArch64Options.td 
b/llvm/lib/Target/AArch64/AArch64Options.td
index 57cd2553c7aeb4..ed6f6e3888d8d8 100644
--- a/llvm/lib/Target/AArch64/AArch64Options.td
+++ b/llvm/lib/Target/AArch64/AArch64Options.td
@@ -8,7 +8,7 @@
 
 include "llvm/Option/LibraryOptions.td"
 
-def AArch64Options : OptionsStruct<prefix = "aarch64-">;
+def AArch64Options : OptionsStruct<prefix = "aarch64-", perContext = false>;
 
 // AArch64A57FPLoadBalancing.cpp
 // Enforce the algorithm to use the scavenged register even when the original
diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCOptions.td 
b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCOptions.td
index c8805db89fa46a..e73d73daebfa98 100644
--- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCOptions.td
+++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCOptions.td
@@ -8,7 +8,7 @@
 
 include "llvm/Option/LibraryOptions.td"
 
-def AArch64MCOptions : OptionsStruct<prefix = "aarch64-">;
+def AArch64MCOptions : OptionsStruct<prefix = "aarch64-", perContext = false>;
 
 // AArch64MCAsmInfo.cpp
 defm : EnumField<"aarch64-neon-syntax", 
"std::optional<AArch64::AsmWriterVariantTy>", "std::nullopt",
diff --git a/llvm/lib/Target/Mips/MCTargetDesc/MipsMCOptions.td 
b/llvm/lib/Target/Mips/MCTargetDesc/MipsMCOptions.td
index da7bc248b46116..ce5403d97cbed6 100644
--- a/llvm/lib/Target/Mips/MCTargetDesc/MipsMCOptions.td
+++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsMCOptions.td
@@ -8,7 +8,7 @@
 
 include "llvm/Option/LibraryOptions.td"
 
-def MipsMCOptions : OptionsStruct<prefix = "mips-">;
+def MipsMCOptions : OptionsStruct<prefix = "mips-", perContext = false>;
 
 // MCTargetDesc/MipsABIInfo.cpp
 defm : BoolField<"mips-jalr-reloc", "true",
diff --git a/llvm/lib/Target/Mips/MipsOptions.td 
b/llvm/lib/Target/Mips/MipsOptions.td
index 22e0c8e652b538..7e239ebd3ca003 100644
--- a/llvm/lib/Target/Mips/MipsOptions.td
+++ b/llvm/lib/Target/Mips/MipsOptions.td
@@ -8,7 +8,7 @@
 
 include "llvm/Option/LibraryOptions.td"
 
-def MipsOptions : OptionsStruct<prefix = "mips-">;
+def MipsOptions : OptionsStruct<prefix = "mips-", perContext = false>;
 
 // Mips16ISelLowering.cpp
 defm : BoolField<"mips16-dont-expand-cond-pseudo", "false",
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCOptions.td 
b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCOptions.td
index 491914a1a9b465..daf443dd9ebcf8 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCOptions.td
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCOptions.td
@@ -8,7 +8,7 @@
 
 include "llvm/Option/LibraryOptions.td"
 
-def RISCVMCOptions : OptionsStruct<prefix = "riscv-">;
+def RISCVMCOptions : OptionsStruct<prefix = "riscv-", perContext = false>;
 
 // AsmParser/RISCVAsmParser.cpp
 defm : BoolField<"riscv-add-build-attributes", "false", "">;
diff --git a/llvm/lib/Target/RISCV/RISCVTargetMachine.cpp 
b/llvm/lib/Target/RISCV/RISCVTargetMachine.cpp
index 5b717bbe02b538..1100e6ebfa304c 100644
--- a/llvm/lib/Target/RISCV/RISCVTargetMachine.cpp
+++ b/llvm/lib/Target/RISCV/RISCVTargetMachine.cpp
@@ -107,7 +107,9 @@ RISCVTargetMachine::RISCVTargetMachine(const Target &T, 
const Triple &TT,
     : CodeGenTargetMachineImpl(T, TT, CPU, FS, Options,
                                getEffectiveRelocModel(TT, RM),
                                getEffectiveCodeModel(CM, CodeModel::Small), 
OL),
-      CLOpts(RISCVOptions::Global), TLOF(createTLOF(TT)) {
+      CLOpts(cl::LibraryOptionsContext::get<RISCVOptions>(
+          Options.MCOptions.LibraryOptions)),
+      TLOF(createTLOF(TT)) {
   initAsmInfo();
 
   // RISC-V supports the MachineOutliner.
diff --git a/llvm/lib/Target/Sparc/SparcOptions.td 
b/llvm/lib/Target/Sparc/SparcOptions.td
index 8d02271270e8e4..d76ad8c275325d 100644
--- a/llvm/lib/Target/Sparc/SparcOptions.td
+++ b/llvm/lib/Target/Sparc/SparcOptions.td
@@ -8,7 +8,7 @@
 
 include "llvm/Option/LibraryOptions.td"
 
-def SparcOptions : OptionsStruct<prefix = "sparc-">;
+def SparcOptions : OptionsStruct<prefix = "sparc-", perContext = false>;
 
 defm : BoolField<"disable-sparc-delay-filler", "false",
   "Disable the Sparc delay slot filler">;
diff --git a/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp 
b/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp
index 4fefb1a6f6597f..47ce4689c622e0 100644
--- a/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp
+++ b/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp
@@ -1401,7 +1401,9 @@ class X86AsmParser : public MCTargetAsmParser {
 
   X86AsmParser(const MCSubtargetInfo &sti, MCAsmParser &Parser,
                const MCInstrInfo &mii)
-      : MCTargetAsmParser(sti, mii), CLOpts(X86MCOptions::Global),
+      : MCTargetAsmParser(sti, mii),
+        CLOpts(cl::LibraryOptionsContext::get<X86MCOptions>(
+            Parser.getContext().getTargetOptions().LibraryOptions)),
         InstInfo(nullptr), Code16GCC(false) {
 
     Parser.addAliasForDirective(".word", ".2byte");
diff --git a/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp 
b/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp
index 1368d9f91c450b..2aa611d6d6f192 100644
--- a/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp
+++ b/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp
@@ -97,9 +97,10 @@ class X86AsmBackend : public MCAsmBackend {
   void emitInstructionEndBundle(MCObjectStreamer &OS);
 
 public:
-  X86AsmBackend(const Target &T, const MCSubtargetInfo &STI)
-      : MCAsmBackend(llvm::endianness::little), CLOpts(X86MCOptions::Global),
-        STI(STI), MCII(T.createMCInstrInfo()) {
+  X86AsmBackend(const X86MCOptions &CLOpts, const Target &T,
+                const MCSubtargetInfo &STI)
+      : MCAsmBackend(llvm::endianness::little), CLOpts(CLOpts), STI(STI),
+        MCII(T.createMCInstrInfo()) {
     if (CLOpts.branches_within_32B_boundaries) {
       // At the moment, this defaults to aligning fused branches, unconditional
       // jumps, and (unfused) conditional jumps with nops.  Both the
@@ -125,6 +126,8 @@ class X86AsmBackend : public MCAsmBackend {
     AllowBundling = true;
   }
 
+  const X86MCOptions &getCLOpts() const { return CLOpts; }
+
   // The streamer frees the fragments these point into.
   void reset() override {
     PrevInst = MCInst();
@@ -424,8 +427,9 @@ bool X86AsmBackend::needAlign(const MCInst &Inst) const {
 
 void X86_MC::emitInstruction(MCObjectStreamer &S, const MCInst &Inst,
                              const MCSubtargetInfo &STI) {
+  auto &Backend = static_cast<X86AsmBackend &>(S.getAssembler().getBackend());
   bool AutoPadding = S.getAllowAutoPadding();
-  if (LLVM_LIKELY(!AutoPadding && !X86MCOptions::Global.pad_for_align)) {
+  if (LLVM_LIKELY(!AutoPadding && !Backend.getCLOpts().pad_for_align)) {
     S.MCObjectStreamer::emitInstruction(Inst, STI);
     return;
   }
@@ -436,7 +440,6 @@ void X86_MC::emitInstruction(MCObjectStreamer &S, const 
MCInst &Inst,
   if (S.getLFIRewriter() && S.getLFIRewriter()->rewriteInst(Inst, S, STI))
     return;
 
-  auto &Backend = static_cast<X86AsmBackend &>(S.getAssembler().getBackend());
   Backend.emitInstructionBegin(S, Inst, STI);
   S.MCObjectStreamer::emitInstruction(Inst, STI);
   Backend.emitInstructionEnd(S, Inst);
@@ -1186,15 +1189,16 @@ namespace {
 class ELFX86AsmBackend : public X86AsmBackend {
 public:
   uint8_t OSABI;
-  ELFX86AsmBackend(const Target &T, uint8_t OSABI, const MCSubtargetInfo &STI)
-      : X86AsmBackend(T, STI), OSABI(OSABI) {}
+  ELFX86AsmBackend(const X86MCOptions &CLOpts, const Target &T, uint8_t OSABI,
+                   const MCSubtargetInfo &STI)
+      : X86AsmBackend(CLOpts, T, STI), OSABI(OSABI) {}
 };
 
 class ELFX86_32AsmBackend : public ELFX86AsmBackend {
 public:
-  ELFX86_32AsmBackend(const Target &T, uint8_t OSABI,
-                      const MCSubtargetInfo &STI)
-    : ELFX86AsmBackend(T, OSABI, STI) {}
+  ELFX86_32AsmBackend(const X86MCOptions &CLOpts, const Target &T,
+                      uint8_t OSABI, const MCSubtargetInfo &STI)
+      : ELFX86AsmBackend(CLOpts, T, OSABI, STI) {}
 
   std::unique_ptr<MCObjectTargetWriter>
   createObjectTargetWriter() const override {
@@ -1204,9 +1208,9 @@ class ELFX86_32AsmBackend : public ELFX86AsmBackend {
 
 class ELFX86_X32AsmBackend : public ELFX86AsmBackend {
 public:
-  ELFX86_X32AsmBackend(const Target &T, uint8_t OSABI,
-                       const MCSubtargetInfo &STI)
-      : ELFX86AsmBackend(T, OSABI, STI) {}
+  ELFX86_X32AsmBackend(const X86MCOptions &CLOpts, const Target &T,
+                       uint8_t OSABI, const MCSubtargetInfo &STI)
+      : ELFX86AsmBackend(CLOpts, T, OSABI, STI) {}
 
   std::unique_ptr<MCObjectTargetWriter>
   createObjectTargetWriter() const override {
@@ -1217,9 +1221,9 @@ class ELFX86_X32AsmBackend : public ELFX86AsmBackend {
 
 class ELFX86_IAMCUAsmBackend : public ELFX86AsmBackend {
 public:
-  ELFX86_IAMCUAsmBackend(const Target &T, uint8_t OSABI,
-                         const MCSubtargetInfo &STI)
-      : ELFX86AsmBackend(T, OSABI, STI) {}
+  ELFX86_IAMCUAsmBackend(const X86MCOptions &CLOpts, const Target &T,
+                         uint8_t OSABI, const MCSubtargetInfo &STI)
+      : ELFX86AsmBackend(CLOpts, T, OSABI, STI) {}
 
   std::unique_ptr<MCObjectTargetWriter>
   createObjectTargetWriter() const override {
@@ -1230,9 +1234,9 @@ class ELFX86_IAMCUAsmBackend : public ELFX86AsmBackend {
 
 class ELFX86_64AsmBackend : public ELFX86AsmBackend {
 public:
-  ELFX86_64AsmBackend(const Target &T, uint8_t OSABI,
-                      const MCSubtargetInfo &STI)
-    : ELFX86AsmBackend(T, OSABI, STI) {}
+  ELFX86_64AsmBackend(const X86MCOptions &CLOpts, const Target &T,
+                      uint8_t OSABI, const MCSubtargetInfo &STI)
+      : ELFX86AsmBackend(CLOpts, T, OSABI, STI) {}
 
   std::unique_ptr<MCObjectTargetWriter>
   createObjectTargetWriter() const override {
@@ -1244,11 +1248,9 @@ class WindowsX86AsmBackend : public X86AsmBackend {
   bool Is64Bit;
 
 public:
-  WindowsX86AsmBackend(const Target &T, bool is64Bit,
-                       const MCSubtargetInfo &STI)
-    : X86AsmBackend(T, STI)
-    , Is64Bit(is64Bit) {
-  }
+  WindowsX86AsmBackend(const X86MCOptions &CLOpts, const Target &T,
+                       bool is64Bit, const MCSubtargetInfo &STI)
+      : X86AsmBackend(CLOpts, T, STI), Is64Bit(is64Bit) {}
 
   std::optional<MCFixupKind> getFixupKind(StringRef Name) const override {
     return StringSwitch<std::optional<MCFixupKind>>(Name)
@@ -1438,9 +1440,9 @@ class DarwinX86AsmBackend : public X86AsmBackend {
   }
 
 public:
-  DarwinX86AsmBackend(const Target &T, const MCRegisterInfo &MRI,
-                      const MCSubtargetInfo &STI)
-      : X86AsmBackend(T, STI), MRI(MRI), TT(STI.getTargetTriple()),
+  DarwinX86AsmBackend(const X86MCOptions &CLOpts, const Target &T,
+                      const MCRegisterInfo &MRI, const MCSubtargetInfo &STI)
+      : X86AsmBackend(CLOpts, T, STI), MRI(MRI), TT(STI.getTargetTriple()),
         Is64Bit(TT.isX86_64()) {
     memset(SavedRegs, 0, sizeof(SavedRegs));
     OffsetSize = Is64Bit ? 8 : 4;
@@ -1632,18 +1634,20 @@ MCAsmBackend *llvm::createX86_32AsmBackend(const Target 
&T,
                                            const MCRegisterInfo &MRI,
                                            const MCTargetOptions &Options) {
   const Triple &TheTriple = STI.getTargetTriple();
+  const X86MCOptions &CLOpts =
+      cl::LibraryOptionsContext::get<X86MCOptions>(Options.LibraryOptions);
   if (TheTriple.isOSBinFormatMachO())
-    return new DarwinX86AsmBackend(T, MRI, STI);
+    return new DarwinX86AsmBackend(CLOpts, T, MRI, STI);
 
   if (TheTriple.isOSWindows() && TheTriple.isOSBinFormatCOFF())
-    return new WindowsX86AsmBackend(T, false, STI);
+    return new WindowsX86AsmBackend(CLOpts, T, false, STI);
 
   uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(TheTriple.getOS());
 
   if (TheTriple.isOSIAMCU())
-    return new ELFX86_IAMCUAsmBackend(T, OSABI, STI);
+    return new ELFX86_IAMCUAsmBackend(CLOpts, T, OSABI, STI);
 
-  return new ELFX86_32AsmBackend(T, OSABI, STI);
+  return new ELFX86_32AsmBackend(CLOpts, T, OSABI, STI);
 }
 
 MCAsmBackend *llvm::createX86_64AsmBackend(const Target &T,
@@ -1651,23 +1655,25 @@ MCAsmBackend *llvm::createX86_64AsmBackend(const Target 
&T,
                                            const MCRegisterInfo &MRI,
                                            const MCTargetOptions &Options) {
   const Triple &TheTriple = STI.getTargetTriple();
+  const X86MCOptions &CLOpts =
+      cl::LibraryOptionsContext::get<X86MCOptions>(Options.LibraryOptions);
   if (TheTriple.isOSBinFormatMachO())
-    return new DarwinX86AsmBackend(T, MRI, STI);
+    return new DarwinX86AsmBackend(CLOpts, T, MRI, STI);
 
   if (TheTriple.isOSWindows() && TheTriple.isOSBinFormatCOFF())
-    return new WindowsX86AsmBackend(T, true, STI);
+    return new WindowsX86AsmBackend(CLOpts, T, true, STI);
 
   if (TheTriple.isUEFI()) {
     assert(TheTriple.isOSBinFormatCOFF() &&
          "Only COFF format is supported in UEFI environment.");
-    return new WindowsX86AsmBackend(T, true, STI);
+    return new WindowsX86AsmBackend(CLOpts, T, true, STI);
   }
 
   uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(TheTriple.getOS());
 
   if (TheTriple.isX32())
-    return new ELFX86_X32AsmBackend(T, OSABI, STI);
-  return new ELFX86_64AsmBackend(T, OSABI, STI);
+    return new ELFX86_X32AsmBackend(CLOpts, T, OSABI, STI);
+  return new ELFX86_64AsmBackend(CLOpts, T, OSABI, STI);
 }
 
 namespace {
diff --git a/llvm/lib/Target/X86/MCTargetDesc/X86MCAsmInfo.cpp 
b/llvm/lib/Target/X86/MCTargetDesc/X86MCAsmInfo.cpp
index af96b318270069..4ea19bac46dc04 100644
--- a/llvm/lib/Target/X86/MCTargetDesc/X86MCAsmInfo.cpp
+++ b/llvm/lib/Target/X86/MCTargetDesc/X86MCAsmInfo.cpp
@@ -50,6 +50,10 @@ constexpr EnumStringDef<MCAsmInfo::AtSpecifierKind> 
AtSpecifierDefs[] = {
 };
 constexpr auto atSpecifiers = BUILD_ENUM_STRINGS(AtSpecifierDefs);
 
+static const X86MCOptions &getCLOpts(const MCTargetOptions &Options) {
+  return cl::LibraryOptionsContext::get<X86MCOptions>(Options.LibraryOptions);
+}
+
 void X86MCAsmInfoDarwin::anchor() { }
 
 X86MCAsmInfoDarwin::X86MCAsmInfoDarwin(const Triple &T,
@@ -59,7 +63,7 @@ X86MCAsmInfoDarwin::X86MCAsmInfoDarwin(const Triple &T,
   if (is64Bit)
     CodePointerSize = CalleeSaveStackSlotSize = 8;
 
-  AssemblerDialect = X86MCOptions::Global.asm_syntax;
+  AssemblerDialect = getCLOpts(Options).asm_syntax;
 
   if (!is64Bit)
     Data64bitsDirective = nullptr;       // we can't emit a 64-bit unit
@@ -72,7 +76,7 @@ X86MCAsmInfoDarwin::X86MCAsmInfoDarwin(const Triple &T,
   CommentString = "##";
 
   SupportsDebugInformation = true;
-  UseDataRegionDirectives = X86MCOptions::Global.mark_data_regions;
+  UseDataRegionDirectives = getCLOpts(Options).mark_data_regions;
 
   // Exceptions handling
   ExceptionsType = ExceptionHandling::DwarfCFI;
@@ -111,7 +115,7 @@ X86ELFMCAsmInfo::X86ELFMCAsmInfo(const Triple &T,
   // OTOH, stack slot size is always 8 for x86-64, even with the x32 ABI.
   CalleeSaveStackSlotSize = is64Bit ? 8 : 4;
 
-  AssemblerDialect = X86MCOptions::Global.asm_syntax;
+  AssemblerDialect = getCLOpts(Options).asm_syntax;
 
   // Debug Information
   SupportsDebugInformation = true;
@@ -150,7 +154,7 @@ X86MCAsmInfoMicrosoft::X86MCAsmInfoMicrosoft(const Triple 
&Triple,
 
   ExceptionsType = ExceptionHandling::WinEH;
 
-  AssemblerDialect = X86MCOptions::Global.asm_syntax;
+  AssemblerDialect = getCLOpts(Options).asm_syntax;
 
   AllowAtInName = true;
 
@@ -187,7 +191,7 @@ X86MCAsmInfoGNUCOFF::X86MCAsmInfoGNUCOFF(const Triple 
&Triple,
     ExceptionsType = ExceptionHandling::DwarfCFI;
   }
 
-  AssemblerDialect = X86MCOptions::Global.asm_syntax;
+  AssemblerDialect = getCLOpts(Options).asm_syntax;
 
   AllowAtInName = true;
 
diff --git a/llvm/lib/Target/X86/X86TargetMachine.cpp 
b/llvm/lib/Target/X86/X86TargetMachine.cpp
index c7b836610a1167..ad498dd498d0c2 100644
--- a/llvm/lib/Target/X86/X86TargetMachine.cpp
+++ b/llvm/lib/Target/X86/X86TargetMachine.cpp
@@ -184,8 +184,9 @@ X86TargetMachine::X86TargetMachine(const Target &T, const 
Triple &TT,
     : CodeGenTargetMachineImpl(T, TT, CPU, FS, Options,
                                getEffectiveRelocModel(TT, JIT, RM),
                                getEffectiveX86CodeModel(TT, CM, JIT), OL),
-      CLOpts(X86Options::Global), TLOF(createTLOF(getTargetTriple())),
-      IsJIT(JIT) {
+      CLOpts(cl::LibraryOptionsContext::get<X86Options>(
+          Options.MCOptions.LibraryOptions)),
+      TLOF(createTLOF(getTargetTriple())), IsJIT(JIT) {
   // On PS4/PS5, the "return address" of a 'noreturn' call must still be within
   // the calling function. Note that this also includes __stack_chk_fail,
   // so there was some target-specific logic in the instruction selectors
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCLOptions.td 
b/llvm/lib/Transforms/InstCombine/InstCombineCLOptions.td
index 868852632fe158..290977ac2f2628 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCLOptions.td
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCLOptions.td
@@ -8,7 +8,7 @@
 
 include "llvm/Option/LibraryOptions.td"
 
-def InstCombineCLOptions : OptionsStruct<prefix = "instcombine-", perContext = 
true>;
+def InstCombineCLOptions : OptionsStruct<prefix = "instcombine-">;
 
 defm : BoolField<"instcombine-code-sinking", "true",
   "Enable code sinking">;
diff --git a/llvm/lib/Transforms/Instrumentation/InstrumentationOptions.td 
b/llvm/lib/Transforms/Instrumentation/InstrumentationOptions.td
index 44a2c46ed3ec43..a430c79f325758 100644
--- a/llvm/lib/Transforms/Instrumentation/InstrumentationOptions.td
+++ b/llvm/lib/Transforms/Instrumentation/InstrumentationOptions.td
@@ -8,7 +8,7 @@
 
 include "llvm/Option/LibraryOptions.td"
 
-def InstrumentationOptions : OptionsStruct;
+def InstrumentationOptions : OptionsStruct<perContext = false>;
 
 // AddressSanitizer.cpp
 defm : BoolField<"asan-always-slow-path", "false",
diff --git a/llvm/lib/Transforms/Scalar/ScalarOptions.td 
b/llvm/lib/Transforms/Scalar/ScalarOptions.td
index 0f7cba53e38509..8ca44f7009eaff 100644
--- a/llvm/lib/Transforms/Scalar/ScalarOptions.td
+++ b/llvm/lib/Transforms/Scalar/ScalarOptions.td
@@ -8,7 +8,7 @@
 
 include "llvm/Option/LibraryOptions.td"
 
-def ScalarOptions : OptionsStruct;
+def ScalarOptions : OptionsStruct<perContext = false>;
 
 // ADCE.cpp
 // This is a temporary option until we change the interface to this pass based
diff --git a/llvm/lib/Transforms/Vectorize/VectorizeOptions.td 
b/llvm/lib/Transforms/Vectorize/VectorizeOptions.td
index 9a43436ee057a3..e3bb555306f387 100644
--- a/llvm/lib/Transforms/Vectorize/VectorizeOptions.td
+++ b/llvm/lib/Transforms/Vectorize/VectorizeOptions.td
@@ -8,7 +8,7 @@
 
 include "llvm/Option/LibraryOptions.td"
 
-def VectorizeOptions : OptionsStruct<perContext = true>;
+def VectorizeOptions : OptionsStruct;
 
 // LoopIdiomVectorize.cpp
 defm : BoolField<"disable-loop-idiom-vectorize-all", "false",
diff --git a/llvm/tools/llc/lib/llcdriver.cpp b/llvm/tools/llc/lib/llcdriver.cpp
index 241c5148bd4ab6..fa27cda8b515e8 100644
--- a/llvm/tools/llc/lib/llcdriver.cpp
+++ b/llvm/tools/llc/lib/llcdriver.cpp
@@ -571,6 +571,7 @@ static int compileModule(char **argv, 
SmallVectorImpl<PassPlugin> &PluginList,
     Options.MCOptions.IASSearchPaths = IncludeDirs;
     Options.MCOptions.InstPrinterOptions = InstPrinterOptions;
     Options.MCOptions.SplitDwarfFile = SplitDwarfFile;
+    Options.MCOptions.LibraryOptions = &Context.getLibraryOptions();
     if (DwarfDirectory.getPosition()) {
       Options.MCOptions.MCUseDwarfDirectory =
           DwarfDirectory ? MCTargetOptions::EnableDwarfDirectory
diff --git a/llvm/tools/opt/optdriver.cpp b/llvm/tools/opt/optdriver.cpp
index da87ef049c7d4e..28b01bfc6c95c0 100644
--- a/llvm/tools/opt/optdriver.cpp
+++ b/llvm/tools/opt/optdriver.cpp
@@ -698,8 +698,8 @@ optMain(int argc, char **argv,
     TuneCPUStr = codegen::getTuneCPUStr();
     FeaturesStr = codegen::getFeaturesStr();
     Expected<std::unique_ptr<TargetMachine>> ExpectedTM =
-        codegen::createTargetMachineForTriple(ModuleTriple,
-                                              GetCodeGenOptLevel());
+        codegen::createTargetMachineForTriple(
+            ModuleTriple, GetCodeGenOptLevel(), &Context.getLibraryOptions());
     if (auto E = ExpectedTM.takeError()) {
       errs() << argv[0] << ": WARNING: failed to create target machine for '"
              << ModuleTriple.str() << "': " << toString(std::move(E)) << "\n";
diff --git a/llvm/unittests/Option/LibraryOpts.td 
b/llvm/unittests/Option/LibraryOpts.td
index 6e4d48bc8d37ac..ce51590056bc57 100644
--- a/llvm/unittests/Option/LibraryOpts.td
+++ b/llvm/unittests/Option/LibraryOpts.td
@@ -8,7 +8,7 @@
 
 include "llvm/Option/LibraryOptions.td"
 
-def TestLibraryOptions : OptionsStruct<"test", prefix = "lib-">;
+def TestLibraryOptions : OptionsStruct<"test", prefix = "lib-", perContext = 
false>;
 
 defm : BoolField<"lib-enable", "false", "A bool">;
 def InBuild : BuildCondition<"__cplusplus">;

>From 4143e457bcd76f7460988ad6dfe6de41c86cbe3e Mon Sep 17 00:00:00 2001
From: Fangrui Song <[email protected]>
Date: Wed, 14 Oct 2026 20:44:28 -0700
Subject: [PATCH 2/6] simplify

---
 .../lib/Target/X86/AsmParser/X86AsmParser.cpp |  3 +--
 .../Target/X86/MCTargetDesc/X86AsmBackend.cpp | 22 +++++--------------
 .../Target/X86/MCTargetDesc/X86MCAsmInfo.cpp  | 14 +++++-------
 .../Target/X86/MCTargetDesc/X86MCOptions.h    |  7 ++++++
 llvm/tools/llc/lib/llcdriver.cpp              |  1 -
 5 files changed, 19 insertions(+), 28 deletions(-)

diff --git a/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp 
b/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp
index 47ce4689c622e0..7038fe6ef229f6 100644
--- a/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp
+++ b/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp
@@ -1402,8 +1402,7 @@ class X86AsmParser : public MCTargetAsmParser {
   X86AsmParser(const MCSubtargetInfo &sti, MCAsmParser &Parser,
                const MCInstrInfo &mii)
       : MCTargetAsmParser(sti, mii),
-        CLOpts(cl::LibraryOptionsContext::get<X86MCOptions>(
-            Parser.getContext().getTargetOptions().LibraryOptions)),
+        CLOpts(X86_MC::getCLOpts(Parser.getContext().getTargetOptions())),
         InstInfo(nullptr), Code16GCC(false) {
 
     Parser.addAliasForDirective(".word", ".2byte");
diff --git a/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp 
b/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp
index 2aa611d6d6f192..2904221ee71136 100644
--- a/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp
+++ b/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp
@@ -1196,9 +1196,7 @@ class ELFX86AsmBackend : public X86AsmBackend {
 
 class ELFX86_32AsmBackend : public ELFX86AsmBackend {
 public:
-  ELFX86_32AsmBackend(const X86MCOptions &CLOpts, const Target &T,
-                      uint8_t OSABI, const MCSubtargetInfo &STI)
-      : ELFX86AsmBackend(CLOpts, T, OSABI, STI) {}
+  using ELFX86AsmBackend::ELFX86AsmBackend;
 
   std::unique_ptr<MCObjectTargetWriter>
   createObjectTargetWriter() const override {
@@ -1208,9 +1206,7 @@ class ELFX86_32AsmBackend : public ELFX86AsmBackend {
 
 class ELFX86_X32AsmBackend : public ELFX86AsmBackend {
 public:
-  ELFX86_X32AsmBackend(const X86MCOptions &CLOpts, const Target &T,
-                       uint8_t OSABI, const MCSubtargetInfo &STI)
-      : ELFX86AsmBackend(CLOpts, T, OSABI, STI) {}
+  using ELFX86AsmBackend::ELFX86AsmBackend;
 
   std::unique_ptr<MCObjectTargetWriter>
   createObjectTargetWriter() const override {
@@ -1221,9 +1217,7 @@ class ELFX86_X32AsmBackend : public ELFX86AsmBackend {
 
 class ELFX86_IAMCUAsmBackend : public ELFX86AsmBackend {
 public:
-  ELFX86_IAMCUAsmBackend(const X86MCOptions &CLOpts, const Target &T,
-                         uint8_t OSABI, const MCSubtargetInfo &STI)
-      : ELFX86AsmBackend(CLOpts, T, OSABI, STI) {}
+  using ELFX86AsmBackend::ELFX86AsmBackend;
 
   std::unique_ptr<MCObjectTargetWriter>
   createObjectTargetWriter() const override {
@@ -1234,9 +1228,7 @@ class ELFX86_IAMCUAsmBackend : public ELFX86AsmBackend {
 
 class ELFX86_64AsmBackend : public ELFX86AsmBackend {
 public:
-  ELFX86_64AsmBackend(const X86MCOptions &CLOpts, const Target &T,
-                      uint8_t OSABI, const MCSubtargetInfo &STI)
-      : ELFX86AsmBackend(CLOpts, T, OSABI, STI) {}
+  using ELFX86AsmBackend::ELFX86AsmBackend;
 
   std::unique_ptr<MCObjectTargetWriter>
   createObjectTargetWriter() const override {
@@ -1634,8 +1626,7 @@ MCAsmBackend *llvm::createX86_32AsmBackend(const Target 
&T,
                                            const MCRegisterInfo &MRI,
                                            const MCTargetOptions &Options) {
   const Triple &TheTriple = STI.getTargetTriple();
-  const X86MCOptions &CLOpts =
-      cl::LibraryOptionsContext::get<X86MCOptions>(Options.LibraryOptions);
+  const X86MCOptions &CLOpts = X86_MC::getCLOpts(Options);
   if (TheTriple.isOSBinFormatMachO())
     return new DarwinX86AsmBackend(CLOpts, T, MRI, STI);
 
@@ -1655,8 +1646,7 @@ MCAsmBackend *llvm::createX86_64AsmBackend(const Target 
&T,
                                            const MCRegisterInfo &MRI,
                                            const MCTargetOptions &Options) {
   const Triple &TheTriple = STI.getTargetTriple();
-  const X86MCOptions &CLOpts =
-      cl::LibraryOptionsContext::get<X86MCOptions>(Options.LibraryOptions);
+  const X86MCOptions &CLOpts = X86_MC::getCLOpts(Options);
   if (TheTriple.isOSBinFormatMachO())
     return new DarwinX86AsmBackend(CLOpts, T, MRI, STI);
 
diff --git a/llvm/lib/Target/X86/MCTargetDesc/X86MCAsmInfo.cpp 
b/llvm/lib/Target/X86/MCTargetDesc/X86MCAsmInfo.cpp
index 4ea19bac46dc04..ace32354153178 100644
--- a/llvm/lib/Target/X86/MCTargetDesc/X86MCAsmInfo.cpp
+++ b/llvm/lib/Target/X86/MCTargetDesc/X86MCAsmInfo.cpp
@@ -50,10 +50,6 @@ constexpr EnumStringDef<MCAsmInfo::AtSpecifierKind> 
AtSpecifierDefs[] = {
 };
 constexpr auto atSpecifiers = BUILD_ENUM_STRINGS(AtSpecifierDefs);
 
-static const X86MCOptions &getCLOpts(const MCTargetOptions &Options) {
-  return cl::LibraryOptionsContext::get<X86MCOptions>(Options.LibraryOptions);
-}
-
 void X86MCAsmInfoDarwin::anchor() { }
 
 X86MCAsmInfoDarwin::X86MCAsmInfoDarwin(const Triple &T,
@@ -63,7 +59,7 @@ X86MCAsmInfoDarwin::X86MCAsmInfoDarwin(const Triple &T,
   if (is64Bit)
     CodePointerSize = CalleeSaveStackSlotSize = 8;
 
-  AssemblerDialect = getCLOpts(Options).asm_syntax;
+  AssemblerDialect = X86_MC::getCLOpts(Options).asm_syntax;
 
   if (!is64Bit)
     Data64bitsDirective = nullptr;       // we can't emit a 64-bit unit
@@ -76,7 +72,7 @@ X86MCAsmInfoDarwin::X86MCAsmInfoDarwin(const Triple &T,
   CommentString = "##";
 
   SupportsDebugInformation = true;
-  UseDataRegionDirectives = getCLOpts(Options).mark_data_regions;
+  UseDataRegionDirectives = X86_MC::getCLOpts(Options).mark_data_regions;
 
   // Exceptions handling
   ExceptionsType = ExceptionHandling::DwarfCFI;
@@ -115,7 +111,7 @@ X86ELFMCAsmInfo::X86ELFMCAsmInfo(const Triple &T,
   // OTOH, stack slot size is always 8 for x86-64, even with the x32 ABI.
   CalleeSaveStackSlotSize = is64Bit ? 8 : 4;
 
-  AssemblerDialect = getCLOpts(Options).asm_syntax;
+  AssemblerDialect = X86_MC::getCLOpts(Options).asm_syntax;
 
   // Debug Information
   SupportsDebugInformation = true;
@@ -154,7 +150,7 @@ X86MCAsmInfoMicrosoft::X86MCAsmInfoMicrosoft(const Triple 
&Triple,
 
   ExceptionsType = ExceptionHandling::WinEH;
 
-  AssemblerDialect = getCLOpts(Options).asm_syntax;
+  AssemblerDialect = X86_MC::getCLOpts(Options).asm_syntax;
 
   AllowAtInName = true;
 
@@ -191,7 +187,7 @@ X86MCAsmInfoGNUCOFF::X86MCAsmInfoGNUCOFF(const Triple 
&Triple,
     ExceptionsType = ExceptionHandling::DwarfCFI;
   }
 
-  AssemblerDialect = getCLOpts(Options).asm_syntax;
+  AssemblerDialect = X86_MC::getCLOpts(Options).asm_syntax;
 
   AllowAtInName = true;
 
diff --git a/llvm/lib/Target/X86/MCTargetDesc/X86MCOptions.h 
b/llvm/lib/Target/X86/MCTargetDesc/X86MCOptions.h
index 4b6583f73ca374..676a06cd0e586a 100644
--- a/llvm/lib/Target/X86/MCTargetDesc/X86MCOptions.h
+++ b/llvm/lib/Target/X86/MCTargetDesc/X86MCOptions.h
@@ -9,6 +9,7 @@
 #ifndef LLVM_LIB_TARGET_X86_MCTARGETDESC_X86MCOPTIONS_H
 #define LLVM_LIB_TARGET_X86_MCTARGETDESC_X86MCOPTIONS_H
 
+#include "llvm/MC/MCTargetOptions.h"
 #include <optional>
 
 namespace llvm::X86 {
@@ -20,4 +21,10 @@ enum AsmWriterFlavorTy { ATT = 0, Intel = 1 };
 #define OPTIONS_STRUCT_DECL
 #include "X86MCOptions.inc"
 
+namespace llvm::X86_MC {
+inline const X86MCOptions &getCLOpts(const MCTargetOptions &Options) {
+  return cl::LibraryOptionsContext::get<X86MCOptions>(Options.LibraryOptions);
+}
+} // namespace llvm::X86_MC
+
 #endif // LLVM_LIB_TARGET_X86_MCTARGETDESC_X86MCOPTIONS_H
diff --git a/llvm/tools/llc/lib/llcdriver.cpp b/llvm/tools/llc/lib/llcdriver.cpp
index fa27cda8b515e8..241c5148bd4ab6 100644
--- a/llvm/tools/llc/lib/llcdriver.cpp
+++ b/llvm/tools/llc/lib/llcdriver.cpp
@@ -571,7 +571,6 @@ static int compileModule(char **argv, 
SmallVectorImpl<PassPlugin> &PluginList,
     Options.MCOptions.IASSearchPaths = IncludeDirs;
     Options.MCOptions.InstPrinterOptions = InstPrinterOptions;
     Options.MCOptions.SplitDwarfFile = SplitDwarfFile;
-    Options.MCOptions.LibraryOptions = &Context.getLibraryOptions();
     if (DwarfDirectory.getPosition()) {
       Options.MCOptions.MCUseDwarfDirectory =
           DwarfDirectory ? MCTargetOptions::EnableDwarfDirectory

>From 84d618a6f887640ebc71417c0c240a0ec84ee765 Mon Sep 17 00:00:00 2001
From: Fangrui Song <[email protected]>
Date: Wed, 14 Oct 2026 20:59:12 -0700
Subject: [PATCH 3/6] add clang -fthinlto-index= and ld.lld -mllvm tests to
 ensure integrated and distributed LTO modes accept -mllvm

---
 clang/test/CodeGen/thinlto-loop-vectorize-pm.c | 6 ++++++
 lld/test/ELF/lto/mllvm.ll                      | 6 ++++++
 llvm/lib/LTO/LTOBackend.cpp                    | 1 +
 3 files changed, 13 insertions(+)

diff --git a/clang/test/CodeGen/thinlto-loop-vectorize-pm.c 
b/clang/test/CodeGen/thinlto-loop-vectorize-pm.c
index 18fcf7595cd20c..9e56093f893f29 100644
--- a/clang/test/CodeGen/thinlto-loop-vectorize-pm.c
+++ b/clang/test/CodeGen/thinlto-loop-vectorize-pm.c
@@ -31,6 +31,12 @@
 // O2-NoInterLeave: = !{!"llvm.loop.isvectorized", i32 1}
 // O0-InterLeave-NOT: = !{!"llvm.loop.isvectorized", i32 1}
 
+// Test that -mllvm options of per-context libraries reach the ThinLTO 
backend's
+// TargetMachine.
+//
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -O2 -mllvm 
-x86-asm-syntax=intel -S -o - -x ir %t.o -fthinlto-index=%t.thinlto.bc 2>&1 | 
FileCheck %s --check-prefix=INTEL
+// INTEL: .intel_syntax
+
 void foo(double *a) {
   for (int i = 0; i < 1000; i++)
     a[i] = 10;
diff --git a/lld/test/ELF/lto/mllvm.ll b/lld/test/ELF/lto/mllvm.ll
index d09dcd0bf7b95d..69489ee4e5153b 100644
--- a/lld/test/ELF/lto/mllvm.ll
+++ b/lld/test/ELF/lto/mllvm.ll
@@ -7,11 +7,17 @@
 ;; most -plugin-opt=- prefixed options are passed through to 
cl::ParseCommandLineOptions.
 ; RUN: ld.lld %t.o -o %t -plugin-opt=-debug-pass=Structure 
-plugin-opt=-print-after-all 2>&1 | FileCheck %s
 
+;; -mllvm reaches per-context library options.
+; RUN: ld.lld %t.o -o %t2 --lto-emit-asm -mllvm -x86-asm-syntax=intel
+; RUN: FileCheck %s --check-prefix=INTEL < %t2.lto.s
+
 ; CHECK: Pass Arguments:
 ; CHECK: # *** IR Dump
 
 ; DISASM: nopw
 
+; INTEL: .intel_syntax
+
 target triple = "x86_64-unknown-linux-gnu"
 target datalayout = 
"e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
 
diff --git a/llvm/lib/LTO/LTOBackend.cpp b/llvm/lib/LTO/LTOBackend.cpp
index 13b5e6e93335dc..9e906e00342ac2 100644
--- a/llvm/lib/LTO/LTOBackend.cpp
+++ b/llvm/lib/LTO/LTOBackend.cpp
@@ -243,6 +243,7 @@ createTargetMachine(const Config &Conf, const Target 
*TheTarget, Module &M) {
   if (TargetOpts.MCOptions.ABIName.empty()) {
     TargetOpts.MCOptions.ABIName = M.getTargetABIFromMD();
   }
+  TargetOpts.MCOptions.LibraryOptions = &M.getContext().getLibraryOptions();
 
   std::unique_ptr<TargetMachine> TM(TheTarget->createTargetMachine(
       TheTriple, Conf.CPU, Features.getString(), TargetOpts, RelocModel,

>From a158a6832a689c5c95afa15534f5fb9e73867c54 Mon Sep 17 00:00:00 2001
From: Fangrui Song <[email protected]>
Date: Wed, 14 Oct 2026 21:41:57 -0700
Subject: [PATCH 4/6] use x86-asm-syntax=intel in CIR/CodeGen test

---
 clang/test/CIR/CodeGen/mllvm-library-options.c | 17 +++--------------
 1 file changed, 3 insertions(+), 14 deletions(-)

diff --git a/clang/test/CIR/CodeGen/mllvm-library-options.c 
b/clang/test/CIR/CodeGen/mllvm-library-options.c
index 4f584b4058a81c..10c99349184801 100644
--- a/clang/test/CIR/CodeGen/mllvm-library-options.c
+++ b/clang/test/CIR/CodeGen/mllvm-library-options.c
@@ -1,17 +1,6 @@
 // -mllvm options of per-context libraries reach the LLVMContext that CIR is
 // lowered into.
-// RUN: %clang_cc1 -triple x86_64 -O1 -fclangir -emit-llvm %s -o - | FileCheck 
%s --check-prefixes=CHECK,SINK
-// RUN: %clang_cc1 -triple x86_64 -O1 -fclangir -emit-llvm -mllvm 
-instcombine-code-sinking=0 %s -o - | FileCheck %s --check-prefixes=CHECK,NOSINK
+// RUN: %clang_cc1 -triple x86_64 -fclangir -S -mllvm -x86-asm-syntax=intel %s 
-o - | FileCheck %s
 
-void use(int);
-
-// CHECK-LABEL: define {{.*}} @f(
-// SINK-NOT:      sdiv
-// NOSINK:        sdiv
-// CHECK:         br i1
-// SINK:          sdiv
-void f(int c, int a, int b) {
-  int d = a / b;
-  if (c)
-    use(d);
-}
+// CHECK: .intel_syntax
+void f(void) {}

>From b5ff55e0a85ba44f21e19ddea27dd5255da11aa6 Mon Sep 17 00:00:00 2001
From: Fangrui Song <[email protected]>
Date: Wed, 14 Oct 2026 23:44:35 -0700
Subject: [PATCH 5/6] createTargetMachineForTriple take const
 LibraryOptionsContext& to force users to pass in an object

---
 llvm/include/llvm/CodeGen/CommandFlags.h         | 5 ++---
 llvm/lib/CodeGen/CommandFlags.cpp                | 6 +++---
 llvm/tools/llvm-ir2vec/llvm-ir2vec.cpp           | 3 ++-
 llvm/tools/llvm-isel-fuzzer/llvm-isel-fuzzer.cpp | 5 ++++-
 llvm/tools/llvm-opt-fuzzer/llvm-opt-fuzzer.cpp   | 4 +++-
 llvm/tools/llvm-reduce/ReducerWorkItem.cpp       | 3 ++-
 llvm/tools/opt/optdriver.cpp                     | 2 +-
 7 files changed, 17 insertions(+), 11 deletions(-)

diff --git a/llvm/include/llvm/CodeGen/CommandFlags.h 
b/llvm/include/llvm/CodeGen/CommandFlags.h
index 8959d7995fb9b7..cbaffbba98eaef 100644
--- a/llvm/include/llvm/CodeGen/CommandFlags.h
+++ b/llvm/include/llvm/CodeGen/CommandFlags.h
@@ -193,9 +193,8 @@ LLVM_ABI void setFunctionAttributes(Module &M, StringRef 
CPU,
 /// line. This can be used for tools that do not need further customization of
 /// the TargetOptions.
 LLVM_ABI Expected<std::unique_ptr<TargetMachine>> createTargetMachineForTriple(
-    const Triple &TargetTriple,
-    CodeGenOptLevel OptLevel = CodeGenOptLevel::Default,
-    const cl::LibraryOptionsContext *LibraryOptions = nullptr);
+    const cl::LibraryOptionsContext &LibraryOptions, const Triple 
&TargetTriple,
+    CodeGenOptLevel OptLevel = CodeGenOptLevel::Default);
 
 /// Conditionally enables the collection of LLVM statistics during the tool 
run,
 /// based on the value of the flag. Must be called before the tool run to
diff --git a/llvm/lib/CodeGen/CommandFlags.cpp 
b/llvm/lib/CodeGen/CommandFlags.cpp
index ea1b0a089f5f3a..3c4652405cb6a6 100644
--- a/llvm/lib/CodeGen/CommandFlags.cpp
+++ b/llvm/lib/CodeGen/CommandFlags.cpp
@@ -753,8 +753,8 @@ void codegen::setFunctionAttributes(Module &M, StringRef 
CPU,
 }
 
 Expected<std::unique_ptr<TargetMachine>> codegen::createTargetMachineForTriple(
-    const Triple &TargetTriple, CodeGenOptLevel OptLevel,
-    const cl::LibraryOptionsContext *LibraryOptions) {
+    const cl::LibraryOptionsContext &LibraryOptions, const Triple 
&TargetTriple,
+    CodeGenOptLevel OptLevel) {
   // lookupTarget may mutate the triple, so we need a copy.
   Triple TheTriple(TargetTriple);
   std::string Error;
@@ -763,7 +763,7 @@ Expected<std::unique_ptr<TargetMachine>> 
codegen::createTargetMachineForTriple(
   if (!TheTarget)
     return createStringError(inconvertibleErrorCode(), Error);
   TargetOptions Options = 
codegen::InitTargetOptionsFromCodeGenFlags(TheTriple);
-  Options.MCOptions.LibraryOptions = LibraryOptions;
+  Options.MCOptions.LibraryOptions = &LibraryOptions;
   auto *Target = TheTarget->createTargetMachine(
       TheTriple, codegen::getCPUStr(), codegen::getFeaturesStr(), Options,
       codegen::getExplicitRelocModel(), codegen::getExplicitCodeModel(),
diff --git a/llvm/tools/llvm-ir2vec/llvm-ir2vec.cpp 
b/llvm/tools/llvm-ir2vec/llvm-ir2vec.cpp
index 861cd849501623..db08962357a30c 100644
--- a/llvm/tools/llvm-ir2vec/llvm-ir2vec.cpp
+++ b/llvm/tools/llvm-ir2vec/llvm-ir2vec.cpp
@@ -208,7 +208,8 @@ static Error setupMIRContext(const std::string &InputFile, 
MIRContext &Ctx) {
     if (TheTriple.getTriple().empty())
       TheTriple.setTriple(sys::getDefaultTargetTriple());
 
-    auto TMOrErr = codegen::createTargetMachineForTriple(TheTriple);
+    auto TMOrErr = codegen::createTargetMachineForTriple(
+        Ctx.Context.getLibraryOptions(), TheTriple);
     if (!TMOrErr) {
       Err.print(ToolName, errs());
       exit(1); // Match original behavior
diff --git a/llvm/tools/llvm-isel-fuzzer/llvm-isel-fuzzer.cpp 
b/llvm/tools/llvm-isel-fuzzer/llvm-isel-fuzzer.cpp
index adac7a7bd8db01..0b605f78355546 100644
--- a/llvm/tools/llvm-isel-fuzzer/llvm-isel-fuzzer.cpp
+++ b/llvm/tools/llvm-isel-fuzzer/llvm-isel-fuzzer.cpp
@@ -28,6 +28,7 @@
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/DataTypes.h"
 #include "llvm/Support/Debug.h"
+#include "llvm/Support/LibraryOptionsContext.h"
 #include "llvm/Support/SourceMgr.h"
 #include "llvm/Support/TargetSelect.h"
 #include "llvm/Target/TargetMachine.h"
@@ -47,6 +48,7 @@ static cl::opt<char>
 static cl::opt<std::string>
     TargetTriple("mtriple", cl::desc("Override target triple for module"));
 
+static cl::LibraryOptionsContext LibraryOptions;
 static std::unique_ptr<TargetMachine> TM;
 static std::unique_ptr<IRMutator> Mutator;
 
@@ -143,7 +145,8 @@ extern "C" LLVM_ATTRIBUTE_USED int LLVMFuzzerInitialize(int 
*argc,
 
   Triple TT(Triple::normalize(TargetTriple));
 
-  TM = ExitOnErr(codegen::createTargetMachineForTriple(TT, OLvl));
+  TM = ExitOnErr(
+      codegen::createTargetMachineForTriple(LibraryOptions, TT, OLvl));
   assert(TM && "Could not allocate target machine!");
 
   // Make sure we print the summary and the current unit when LLVM errors out.
diff --git a/llvm/tools/llvm-opt-fuzzer/llvm-opt-fuzzer.cpp 
b/llvm/tools/llvm-opt-fuzzer/llvm-opt-fuzzer.cpp
index f40d5fdc08483c..7035c8ccd78719 100644
--- a/llvm/tools/llvm-opt-fuzzer/llvm-opt-fuzzer.cpp
+++ b/llvm/tools/llvm-opt-fuzzer/llvm-opt-fuzzer.cpp
@@ -19,6 +19,7 @@
 #include "llvm/MC/TargetRegistry.h"
 #include "llvm/Passes/PassBuilder.h"
 #include "llvm/Support/CommandLine.h"
+#include "llvm/Support/LibraryOptionsContext.h"
 #include "llvm/Support/SourceMgr.h"
 #include "llvm/Support/TargetSelect.h"
 #include "llvm/Target/TargetMachine.h"
@@ -36,6 +37,7 @@ static cl::opt<std::string> PassPipeline(
     cl::desc("A textual description of the pass pipeline for testing"));
 
 static std::unique_ptr<IRMutator> Mutator;
+static cl::LibraryOptionsContext LibraryOptions;
 static std::unique_ptr<TargetMachine> TM;
 
 std::unique_ptr<IRMutator> createOptMutator() {
@@ -201,7 +203,7 @@ extern "C" LLVM_ATTRIBUTE_USED int LLVMFuzzerInitialize(int 
*argc,
   ExitOnError ExitOnErr(std::string(ExecName) + ": error:");
 
   Triple TT(Triple::normalize(TargetTripleStr));
-  TM = ExitOnErr(codegen::createTargetMachineForTriple(TT));
+  TM = ExitOnErr(codegen::createTargetMachineForTriple(LibraryOptions, TT));
 
   // Check that pass pipeline is specified and correct
   //
diff --git a/llvm/tools/llvm-reduce/ReducerWorkItem.cpp 
b/llvm/tools/llvm-reduce/ReducerWorkItem.cpp
index 6b202aec3e8f85..c675b2b9e28166 100644
--- a/llvm/tools/llvm-reduce/ReducerWorkItem.cpp
+++ b/llvm/tools/llvm-reduce/ReducerWorkItem.cpp
@@ -856,7 +856,8 @@ llvm::parseReducerWorkItem(StringRef ToolName, StringRef 
Filename,
       if (TheTriple.getTriple().empty())
         TheTriple.setTriple(sys::getDefaultTargetTriple());
       ExitOnError ExitOnErr(std::string(ToolName) + ": error: ");
-      TM = ExitOnErr(codegen::createTargetMachineForTriple(TheTriple));
+      TM = ExitOnErr(codegen::createTargetMachineForTriple(
+          Ctxt.getLibraryOptions(), TheTriple));
 
       return TheTriple.computeDataLayout();
     };
diff --git a/llvm/tools/opt/optdriver.cpp b/llvm/tools/opt/optdriver.cpp
index 28b01bfc6c95c0..816a7b0cc16ea1 100644
--- a/llvm/tools/opt/optdriver.cpp
+++ b/llvm/tools/opt/optdriver.cpp
@@ -699,7 +699,7 @@ optMain(int argc, char **argv,
     FeaturesStr = codegen::getFeaturesStr();
     Expected<std::unique_ptr<TargetMachine>> ExpectedTM =
         codegen::createTargetMachineForTriple(
-            ModuleTriple, GetCodeGenOptLevel(), &Context.getLibraryOptions());
+            Context.getLibraryOptions(), ModuleTriple, GetCodeGenOptLevel());
     if (auto E = ExpectedTM.takeError()) {
       errs() << argv[0] << ": WARNING: failed to create target machine for '"
              << ModuleTriple.str() << "': " << toString(std::move(E)) << "\n";

>From 804ac7b1023ba6385610744df0c210c26ba6b186 Mon Sep 17 00:00:00 2001
From: Fangrui Song <[email protected]>
Date: Wed, 14 Oct 2026 23:53:14 -0700
Subject: [PATCH 6/6] add REQUIRES: x86-registered-target to CIR test

---
 clang/test/CIR/CodeGen/mllvm-library-options.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/clang/test/CIR/CodeGen/mllvm-library-options.c 
b/clang/test/CIR/CodeGen/mllvm-library-options.c
index 10c99349184801..1fc4471d9765d5 100644
--- a/clang/test/CIR/CodeGen/mllvm-library-options.c
+++ b/clang/test/CIR/CodeGen/mllvm-library-options.c
@@ -1,3 +1,4 @@
+// REQUIRES: x86-registered-target
 // -mllvm options of per-context libraries reach the LLVMContext that CIR is
 // lowered into.
 // RUN: %clang_cc1 -triple x86_64 -fclangir -S -mllvm -x86-asm-syntax=intel %s 
-o - | FileCheck %s

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

Reply via email to