[llvm] TargetMachine: Verify option/module-flag consistency once per module (PR #217597)

Matt Arsenault via llvm-commits llvm-commits at lists.llvm.org
Thu Aug 20 06:19:10 PDT 2026


https://github.com/arsenm updated https://github.com/llvm/llvm-project/pull/217597

>From 140fe2010da0dcff41c4592e2f8198ba9fba06d4 Mon Sep 17 00:00:00 2001
From: Matt Arsenault <Matthew.Arsenault at amd.com>
Date: Thu, 20 Aug 2026 13:15:32 +0200
Subject: [PATCH] TargetMachine: Verify option/module-flag consistency once per
 module

The -target-abi option / "target-abi" module flag conflict was reported from
the per-function getSubtargetImpl in RISCV and LoongArch, so a module with
multiple subtargets would repeatedly diagnose. Introduce a new TargetMachine
method to validate the module for the global options.

I wasn't sure the best place to actually perform this check. This is now
performing it in the earliest pass in codegen, MachineModuleInfo.
MachineModuleInfo is a glorified map from IR to MachineFunction, so I'm not
sure this is the right place. The other alternative I started with was the
AsmPrinter initialization.

Ideally we would eliminate the global options. In particular target-abi is
going to be a bit sticky, because it lives in MCOptions and is thus used by
non-codegen contexts which won't have an IR module to read a flag from.

Co-authored-by: Claude (Claude-Opus-4.8) <noreply at anthropic.com>
---
 llvm/include/llvm/Target/TargetMachine.h      | 11 ++++++---
 llvm/lib/CodeGen/MachineModuleInfo.cpp        |  2 ++
 llvm/lib/Target/TargetMachine.cpp             | 24 +++++++++++--------
 .../RISCV/module-target-abi-conflict.ll       | 24 +++++++++++++++++++
 4 files changed, 48 insertions(+), 13 deletions(-)
 create mode 100644 llvm/test/CodeGen/RISCV/module-target-abi-conflict.ll

diff --git a/llvm/include/llvm/Target/TargetMachine.h b/llvm/include/llvm/Target/TargetMachine.h
index d6067613cf324..a6b73d636dc27 100644
--- a/llvm/include/llvm/Target/TargetMachine.h
+++ b/llvm/include/llvm/Target/TargetMachine.h
@@ -138,11 +138,16 @@ class LLVM_ABI TargetMachine {
   StringRef getTargetFeatureString() const { return TargetFS; }
   void setTargetFeatureString(StringRef FS) { TargetFS = std::string(FS); }
 
-  /// Returns the effective target ABI name. Reads the "target-abi" module flag
-  /// if present, otherwise the -target-abi option. Emits an error if both are
-  /// present and disagree.
+  /// Returns the effective target ABI name: the "target-abi" module flag if
+  /// present, otherwise the -target-abi option. This is a pure query; call
+  /// verifyOptionsConsistency once per module to diagnose a conflict.
   StringRef getTargetABIName(const Module &M) const;
 
+  /// Diagnoses command-line codegen options that conflict with the
+  /// corresponding module flags (e.g. -target-abi vs the "target-abi" module
+  /// flag). Intended to be called once per module.
+  void verifyOptionsConsistency(const Module &M) const;
+
   /// Virtual method implemented by subclasses that returns a reference to that
   /// target's TargetSubtargetInfo-derived member variable.
   virtual const TargetSubtargetInfo *getSubtargetImpl(const Function &) const {
diff --git a/llvm/lib/CodeGen/MachineModuleInfo.cpp b/llvm/lib/CodeGen/MachineModuleInfo.cpp
index e421378bd5b17..dd9defdec276b 100644
--- a/llvm/lib/CodeGen/MachineModuleInfo.cpp
+++ b/llvm/lib/CodeGen/MachineModuleInfo.cpp
@@ -218,6 +218,7 @@ bool MachineModuleInfoWrapperPass::doInitialization(Module &M) {
         Ctx.diagnose(
             DiagnosticInfoSrcMgr(SMD, M.getName(), IsInlineAsm, LocCookie));
       });
+  MMI.getTarget().verifyOptionsConsistency(M);
   return false;
 }
 
@@ -242,5 +243,6 @@ MachineModuleAnalysis::run(Module &M, ModuleAnalysisManager &) {
         Ctx.diagnose(
             DiagnosticInfoSrcMgr(SMD, M.getName(), IsInlineAsm, LocCookie));
       });
+  MMI.getTarget().verifyOptionsConsistency(M);
   return Result(MMI);
 }
diff --git a/llvm/lib/Target/TargetMachine.cpp b/llvm/lib/Target/TargetMachine.cpp
index c26661f365d7b..676c44495e798 100644
--- a/llvm/lib/Target/TargetMachine.cpp
+++ b/llvm/lib/Target/TargetMachine.cpp
@@ -331,18 +331,22 @@ std::pair<int, int> TargetMachine::parseBinutilsVersion(StringRef Version) {
 }
 
 StringRef TargetMachine::getTargetABIName(const Module &M) const {
+  if (const auto *MD = cast_or_null<MDString>(M.getModuleFlag("target-abi")))
+    return MD->getString();
+  return Options.MCOptions.getABIName();
+}
+
+void TargetMachine::verifyOptionsConsistency(const Module &M) const {
+  // The "target-abi" module flag must agree with the -target-abi option.
   StringRef OptionABI = Options.MCOptions.getABIName();
-  const auto *MD = cast_or_null<MDString>(M.getModuleFlag("target-abi"));
-  if (!MD)
-    return OptionABI;
-
-  StringRef ModuleABI = MD->getString();
-  if (!OptionABI.empty() && OptionABI != ModuleABI) {
-    M.getContext().emitError("-target-abi option != target-abi module flag");
-    return "";
+  if (!OptionABI.empty()) {
+    if (const auto *MD =
+            cast_or_null<MDString>(M.getModuleFlag("target-abi"))) {
+      if (OptionABI != MD->getString())
+        M.getContext().emitError(
+            "-target-abi option != target-abi module flag");
+    }
   }
-
-  return ModuleABI;
 }
 
 const MCSubtargetInfo &TargetMachine::getMCSubtargetInfo(StringRef CPU,
diff --git a/llvm/test/CodeGen/RISCV/module-target-abi-conflict.ll b/llvm/test/CodeGen/RISCV/module-target-abi-conflict.ll
new file mode 100644
index 0000000000000..36ed06e895ca3
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/module-target-abi-conflict.ll
@@ -0,0 +1,24 @@
+; A "target-abi" module flag that conflicts with the -target-abi
+; command-line option is an error, which should be diagnosed exactly
+; once
+
+; RUN: not llc -target-abi=lp64d -filetype=null < %s 2>&1 | FileCheck %s -implicit-check-not=error:
+; RUN: not llc -enable-new-pm -target-abi=lp64d -filetype=null < %s 2>&1 | FileCheck %s -implicit-check-not=error:
+
+; CHECK: error: -target-abi option != target-abi module flag
+
+target triple = "riscv64"
+
+define void @f1() #0 {
+  ret void
+}
+
+define void @f2() #1 {
+  ret void
+}
+
+attributes #0 = { "target-cpu"="generic-rv64" }
+attributes #1 = { "target-cpu"="rocket-rv64" }
+
+!llvm.module.flags = !{!0}
+!0 = !{i32 1, !"target-abi", !"lp64"}



More information about the llvm-commits mailing list