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

>From 119a0fb1642c3d294d055bbe62163ed1e9464541 Mon Sep 17 00:00:00 2001
From: Matt Arsenault <[email protected]>
Date: Mon, 20 Jul 2026 12:48:49 +0200
Subject: [PATCH] PowerPC: Rename "float-abi" module flag to "long-double-type"

PPC was emitting a "float-abi" module flag for indicating the type of long
double. The "float ABI" naming is already widely taken by soft vs. hard
float controls (e.g., the clang flag is called -mfloat-abi), so this shouldn't
have taken it. This should also not be PPC specific; x86 has the same problem.
Rename the flag to the more specific long-double-type, and add appropriate
verification and documentation (which was also missing). Also changes the value
names to match the IR type names.

Co-authored-by: Claude (Claude-Opus-4.8) <[email protected]>
---
 clang/lib/CodeGen/Targets/PPC.cpp             | 14 +++---
 ...i-attr.c => ppc64-long-double-type-attr.c} |  8 ++--
 llvm/docs/LangRef.md                          | 30 +++++++++++++
 llvm/lib/IR/AutoUpgrade.cpp                   | 20 +++++++++
 llvm/lib/IR/Verifier.cpp                      | 11 +++++
 llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp     | 16 +++----
 .../module-flags-long-double-type.ll          | 19 ++++++++
 llvm/test/Bitcode/upgrade-ppc-float-abi.ll    | 45 +++++++++++++++++++
 llvm/test/CodeGen/PowerPC/gnu-attribute.ll    | 31 ++++++++++---
 .../Linker/module-flags-long-double-type.ll   | 31 +++++++++++++
 .../Verifier/module-flags-long-double-type.ll | 37 +++++++++++++++
 11 files changed, 237 insertions(+), 25 deletions(-)
 rename clang/test/CodeGen/{ppc64-float-abi-attr.c => 
ppc64-long-double-type-attr.c} (71%)
 create mode 100644 llvm/test/Assembler/module-flags-long-double-type.ll
 create mode 100644 llvm/test/Bitcode/upgrade-ppc-float-abi.ll
 create mode 100644 llvm/test/Linker/module-flags-long-double-type.ll
 create mode 100644 llvm/test/Verifier/module-flags-long-double-type.ll

diff --git a/clang/lib/CodeGen/Targets/PPC.cpp 
b/clang/lib/CodeGen/Targets/PPC.cpp
index ab069bfbd1b51..92d14261ae81f 100644
--- a/clang/lib/CodeGen/Targets/PPC.cpp
+++ b/clang/lib/CodeGen/Targets/PPC.cpp
@@ -1046,15 +1046,17 @@ void PPC64_SVR4_TargetCodeGenInfo::emitTargetMetadata(
   if (CGM.getTypes().isLongDoubleReferenced()) {
     llvm::LLVMContext &Ctx = CGM.getLLVMContext();
     const auto *flt = &CGM.getTarget().getLongDoubleFormat();
+    StringRef Type;
     if (flt == &llvm::APFloat::PPCDoubleDouble())
-      CGM.getModule().addModuleFlag(llvm::Module::Error, "float-abi",
-                                    llvm::MDString::get(Ctx, "doubledouble"));
+      Type = "ppc_fp128";
     else if (flt == &llvm::APFloat::IEEEquad())
-      CGM.getModule().addModuleFlag(llvm::Module::Error, "float-abi",
-                                    llvm::MDString::get(Ctx, "ieeequad"));
+      Type = "fp128";
     else if (flt == &llvm::APFloat::IEEEdouble())
-      CGM.getModule().addModuleFlag(llvm::Module::Error, "float-abi",
-                                    llvm::MDString::get(Ctx, "ieeedouble"));
+      Type = "double";
+
+    if (!Type.empty())
+      CGM.getModule().addModuleFlag(llvm::Module::Error, "long-double-type",
+                                    llvm::MDString::get(Ctx, Type));
   }
 }
 
diff --git a/clang/test/CodeGen/ppc64-float-abi-attr.c 
b/clang/test/CodeGen/ppc64-long-double-type-attr.c
similarity index 71%
rename from clang/test/CodeGen/ppc64-float-abi-attr.c
rename to clang/test/CodeGen/ppc64-long-double-type-attr.c
index 8e0eca17b9b6c..b6f3baab28f7d 100644
--- a/clang/test/CodeGen/ppc64-float-abi-attr.c
+++ b/clang/test/CodeGen/ppc64-long-double-type-attr.c
@@ -11,7 +11,7 @@ long double foo(long double a, long double b) {
 
 int bar() { return 1; }
 
-// CHECK: ![[#]] = !{i32 1, !"float-abi", !"doubledouble"}
-// IEEE: ![[#]] = !{i32 1, !"float-abi", !"ieeequad"}
-// LDBL64: ![[#]] = !{i32 1, !"float-abi", !"ieeedouble"}
-// NOLDBL-NOT: ![[#]] = !{i32 1, !"float-abi"
+// CHECK: ![[#]] = !{i32 1, !"long-double-type", !"ppc_fp128"}
+// IEEE: ![[#]] = !{i32 1, !"long-double-type", !"fp128"}
+// LDBL64: ![[#]] = !{i32 1, !"long-double-type", !"double"}
+// NOLDBL-NOT: ![[#]] = !{i32 1, !"long-double-type"
diff --git a/llvm/docs/LangRef.md b/llvm/docs/LangRef.md
index 361333a7801c0..8b6b847d4e41a 100644
--- a/llvm/docs/LangRef.md
+++ b/llvm/docs/LangRef.md
@@ -9355,6 +9355,36 @@ enum is the smallest type which can represent all of its 
values:
 !1 = !{i32 1, !"short_enum", i32 0}
 ```
 
+### Long Double Type Module Flags Metadata
+
+Describe the floating-point format used by libm for `long double`. The
+value is an `MDString` naming the corresponding IR floating-point
+type, and must be one of:
+
+```{list-table}
+:header-rows: 1
+:widths: 30 70
+* - Value
+  - Meaning
+
+* - `"double"`
+  - IEEE 754 double precision (64-bit).
+
+* - `"fp128"`
+  - IEEE 754 quadruple precision (128-bit).
+
+* - `"ppc_fp128"`
+  - IBM `double-double` (a pair of IEEE doubles).
+
+```
+
+The flag must use the `error` merge behavior, so that linking modules with
+conflicting long double types is rejected. For example:
+```
+!llvm.module.flags = !{!0}
+!0 = !{i32 1, !"long-double-type", !"fp128"}
+```
+
 ### Stack Alignment Metadata
 
 Changes the default stack alignment from the target ABI's implicit default
diff --git a/llvm/lib/IR/AutoUpgrade.cpp b/llvm/lib/IR/AutoUpgrade.cpp
index 926e18924956f..db69d03d61ffc 100644
--- a/llvm/lib/IR/AutoUpgrade.cpp
+++ b/llvm/lib/IR/AutoUpgrade.cpp
@@ -6606,6 +6606,26 @@ bool llvm::UpgradeModuleFlags(Module &M) {
       ModFlags->setOperand(I, MDNode::get(M.getContext(), Ops));
       Changed = true;
     }
+
+    // clang/PowerPC used to use "float-abi" to describe the long double 
format;
+    // it has been renamed to "long-double-type", with its values changed to 
the
+    // corresponding IR floating-point type names. Map any unrecognized value
+    // (which was never valid) to the PowerPC default ppc_fp128 rather than
+    // erasing the flag.
+    if (M.getTargetTriple().isPPC() && ID->getString() == "float-abi") {
+      StringRef Format;
+      if (auto *S = dyn_cast_or_null<MDString>(Op->getOperand(2)))
+        Format = S->getString();
+      StringRef NewType = StringSwitch<StringRef>(Format)
+                              .Case("ieeequad", "fp128")
+                              .Case("ieeedouble", "double")
+                              .Default("ppc_fp128");
+      Metadata *Ops[3] = {Op->getOperand(0),
+                          MDString::get(M.getContext(), "long-double-type"),
+                          MDString::get(M.getContext(), NewType)};
+      ModFlags->setOperand(I, MDNode::get(M.getContext(), Ops));
+      Changed = true;
+    }
   }
 
   // "Objective-C Class Properties" is recently added for Objective-C. We
diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp
index f6b7d30cf42c3..3324752fd5baa 100644
--- a/llvm/lib/IR/Verifier.cpp
+++ b/llvm/lib/IR/Verifier.cpp
@@ -2000,6 +2000,17 @@ Verifier::visitModuleFlag(const MDNode *Op,
     Check(Value, "wchar_size metadata requires constant integer argument");
   }
 
+  if (ID->getString() == "long-double-type") {
+    Check(MFB == Module::Error,
+          "long-double-type module flag must use 'error' merge behavior", Op);
+    const MDString *Value = dyn_cast_or_null<MDString>(Op->getOperand(2));
+    Check(Value, "long-double-type metadata requires a string argument");
+    if (Value)
+      Check(Value->getString() == "ppc_fp128" ||
+                Value->getString() == "fp128" || Value->getString() == 
"double",
+            "invalid long-double-type metadata value", Op);
+  }
+
   if (ID->getString() == "Linker Options") {
     // If the llvm.linker.options named metadata exists, we assume that the
     // bitcode reader has upgraded the module flag. Otherwise the flag might
diff --git a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp 
b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
index 51f2ff4a68be7..4ccb578bbe263 100644
--- a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
+++ b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
@@ -1768,22 +1768,22 @@ PPCAsmPrinter::getAdjustedFasterLocalExpr(const 
MachineOperand &MO,
 }
 
 void PPCLinuxAsmPrinter::emitGNUAttributes(Module &M) {
-  // Emit float ABI into GNU attribute
-  Metadata *MD = M.getModuleFlag("float-abi");
-  MDString *FloatABI = dyn_cast_or_null<MDString>(MD);
-  if (!FloatABI)
+  // Emit long double format into GNU attribute
+  Metadata *MD = M.getModuleFlag("long-double-type");
+  MDString *LongDoubleType = dyn_cast_or_null<MDString>(MD);
+  if (!LongDoubleType)
     return;
-  StringRef flt = FloatABI->getString();
+  StringRef flt = LongDoubleType->getString();
   // TODO: Support emitting soft-fp and hard double/single attributes.
-  if (flt == "doubledouble")
+  if (flt == "ppc_fp128")
     OutStreamer->emitGNUAttribute(Tag_GNU_Power_ABI_FP,
                                   Val_GNU_Power_ABI_HardFloat_DP |
                                       Val_GNU_Power_ABI_LDBL_IBM128);
-  else if (flt == "ieeequad")
+  else if (flt == "fp128")
     OutStreamer->emitGNUAttribute(Tag_GNU_Power_ABI_FP,
                                   Val_GNU_Power_ABI_HardFloat_DP |
                                       Val_GNU_Power_ABI_LDBL_IEEE128);
-  else if (flt == "ieeedouble")
+  else if (flt == "double")
     OutStreamer->emitGNUAttribute(Tag_GNU_Power_ABI_FP,
                                   Val_GNU_Power_ABI_HardFloat_DP |
                                       Val_GNU_Power_ABI_LDBL_64);
diff --git a/llvm/test/Assembler/module-flags-long-double-type.ll 
b/llvm/test/Assembler/module-flags-long-double-type.ll
new file mode 100644
index 0000000000000..636758d810695
--- /dev/null
+++ b/llvm/test/Assembler/module-flags-long-double-type.ll
@@ -0,0 +1,19 @@
+; RUN: split-file %s %t
+; RUN: llvm-as < %t/ppc_fp128.ll | llvm-dis | FileCheck %s 
--check-prefix=PPCFP128
+; RUN: llvm-as < %t/fp128.ll | llvm-dis | FileCheck %s --check-prefix=FP128
+; RUN: llvm-as < %t/double.ll | llvm-dis | FileCheck %s --check-prefix=DOUBLE
+
+;--- ppc_fp128.ll
+!llvm.module.flags = !{!0}
+!0 = !{i32 1, !"long-double-type", !"ppc_fp128"}
+; PPCFP128: !0 = !{i32 1, !"long-double-type", !"ppc_fp128"}
+
+;--- fp128.ll
+!llvm.module.flags = !{!0}
+!0 = !{i32 1, !"long-double-type", !"fp128"}
+; FP128: !0 = !{i32 1, !"long-double-type", !"fp128"}
+
+;--- double.ll
+!llvm.module.flags = !{!0}
+!0 = !{i32 1, !"long-double-type", !"double"}
+; DOUBLE: !0 = !{i32 1, !"long-double-type", !"double"}
diff --git a/llvm/test/Bitcode/upgrade-ppc-float-abi.ll 
b/llvm/test/Bitcode/upgrade-ppc-float-abi.ll
new file mode 100644
index 0000000000000..31df56d973723
--- /dev/null
+++ b/llvm/test/Bitcode/upgrade-ppc-float-abi.ll
@@ -0,0 +1,45 @@
+;; The PowerPC "float-abi" module flag (describing the long double
+;; format) was renamed to "long-double-type", with its values changed
+;; to the corresponding IR floating-point type names.
+
+; RUN: split-file %s %t
+; RUN: llvm-as < %t/doubledouble.ll | llvm-dis | FileCheck %s 
--check-prefix=DOUBLEDOUBLE
+; RUN: llvm-as < %t/ieeequad.ll | llvm-dis | FileCheck %s 
--check-prefix=IEEEQUAD
+; RUN: llvm-as < %t/ieeedouble.ll | llvm-dis | FileCheck %s 
--check-prefix=IEEEDOUBLE
+; RUN: llvm-as < %t/unrecognized.ll | llvm-dis | FileCheck %s 
--check-prefix=UNRECOGNIZED
+; RUN: llvm-as < %t/arm.ll | llvm-dis | FileCheck %s --check-prefix=ARM
+
+;; All the old PowerPC long double format spellings are upgraded to the new key
+;; and IR type-name values.
+;--- doubledouble.ll
+target triple = "powerpc64le-unknown-linux-gnu"
+!llvm.module.flags = !{!0}
+!0 = !{i32 1, !"float-abi", !"doubledouble"}
+; DOUBLEDOUBLE: !0 = !{i32 1, !"long-double-type", !"ppc_fp128"}
+
+;--- ieeequad.ll
+target triple = "powerpc64le-unknown-linux-gnu"
+!llvm.module.flags = !{!0}
+!0 = !{i32 1, !"float-abi", !"ieeequad"}
+; IEEEQUAD: !0 = !{i32 1, !"long-double-type", !"fp128"}
+
+;--- ieeedouble.ll
+target triple = "powerpc64le-unknown-linux-gnu"
+!llvm.module.flags = !{!0}
+!0 = !{i32 1, !"float-abi", !"ieeedouble"}
+; IEEEDOUBLE: !0 = !{i32 1, !"long-double-type", !"double"}
+
+;--- unrecognized.ll
+;; An unrecognized value was never valid; upgrade it to the PowerPC default
+;; ppc_fp128 rather than leaving a stale "float-abi" flag.
+target triple = "powerpc64le-unknown-linux-gnu"
+!llvm.module.flags = !{!0}
+!0 = !{i32 1, !"float-abi", !"bogus"}
+; UNRECOGNIZED: !0 = !{i32 1, !"long-double-type", !"ppc_fp128"}
+
+;--- arm.ll
+;; A non-PowerPC module is never touched.
+target triple = "armv7-unknown-linux-gnueabihf"
+!llvm.module.flags = !{!0}
+!0 = !{i32 1, !"float-abi", !"hard"}
+; ARM: !0 = !{i32 1, !"float-abi", !"hard"}
diff --git a/llvm/test/CodeGen/PowerPC/gnu-attribute.ll 
b/llvm/test/CodeGen/PowerPC/gnu-attribute.ll
index 31747146d2345..f33cb8cc7b398 100644
--- a/llvm/test/CodeGen/PowerPC/gnu-attribute.ll
+++ b/llvm/test/CodeGen/PowerPC/gnu-attribute.ll
@@ -1,15 +1,32 @@
-; RUN: sed -e 's/FLTABI/ieeequad/' %s | llc -mtriple=powerpc64le | FileCheck 
%s --check-prefix=IEEE
-; RUN: sed -e 's/FLTABI/doubledouble/' %s | llc -mtriple=powerpc64le | 
FileCheck %s --check-prefix=IBM
-; RUN: sed -e 's/FLTABI/ieeedouble/' %s | llc -mtriple=powerpc64le | FileCheck 
%s --check-prefix=DBL
-; RUN: sed -e 's/FLTABI//' %s | llc -mtriple=powerpc64le | FileCheck %s 
--check-prefix=NONE
+; RUN: split-file %s %t
+; RUN: llc -mtriple=powerpc64le < %t/fp128.ll | FileCheck %s 
--check-prefix=IEEE
+; RUN: llc -mtriple=powerpc64le < %t/ppc_fp128.ll | FileCheck %s 
--check-prefix=IBM
+; RUN: llc -mtriple=powerpc64le < %t/double.ll | FileCheck %s 
--check-prefix=DBL
+; RUN: llc -mtriple=powerpc64le < %t/none.ll | FileCheck %s --check-prefix=NONE
 
+;--- fp128.ll
+!llvm.module.flags = !{!0, !1, !2}
+!0 = !{i32 1, !"wchar_size", i32 4}
+!1 = !{i32 7, !"uwtable", i32 1}
+!2 = !{i32 1, !"long-double-type", !"fp128"}
 ; IEEE: .gnu_attribute 4, 13
+
+;--- ppc_fp128.ll
+!llvm.module.flags = !{!0, !1, !2}
+!0 = !{i32 1, !"wchar_size", i32 4}
+!1 = !{i32 7, !"uwtable", i32 1}
+!2 = !{i32 1, !"long-double-type", !"ppc_fp128"}
 ; IBM: .gnu_attribute 4, 5
-; DBL: .gnu_attribute 4, 9
-; NONE-NOT: .gnu_attribute 4,
 
+;--- double.ll
 !llvm.module.flags = !{!0, !1, !2}
+!0 = !{i32 1, !"wchar_size", i32 4}
+!1 = !{i32 7, !"uwtable", i32 1}
+!2 = !{i32 1, !"long-double-type", !"double"}
+; DBL: .gnu_attribute 4, 9
 
+;--- none.ll
+!llvm.module.flags = !{!0, !1}
 !0 = !{i32 1, !"wchar_size", i32 4}
 !1 = !{i32 7, !"uwtable", i32 1}
-!2 = !{i32 1, !"float-abi", !"FLTABI"}
+; NONE-NOT: .gnu_attribute 4,
diff --git a/llvm/test/Linker/module-flags-long-double-type.ll 
b/llvm/test/Linker/module-flags-long-double-type.ll
new file mode 100644
index 0000000000000..30a85a24273c0
--- /dev/null
+++ b/llvm/test/Linker/module-flags-long-double-type.ll
@@ -0,0 +1,31 @@
+; RUN: split-file %s %t
+
+;; A module with an explicit "long-double-type" flag links cleanly with a 
module
+;; that has no flag, and the explicit value is preserved (both link orders).
+; RUN: llvm-link %t/fp128.ll %t/none.ll -S -o - | FileCheck %s 
--check-prefix=FP128
+; RUN: llvm-link %t/none.ll %t/fp128.ll -S -o - | FileCheck %s 
--check-prefix=FP128
+
+;; Two modules that agree link cleanly.
+; RUN: llvm-link %t/fp128.ll %t/fp128.ll -S -o - | FileCheck %s 
--check-prefix=FP128
+
+;; Two modules that disagree are rejected by the 'error' merge behavior.
+; RUN: not llvm-link %t/fp128.ll %t/ppc_fp128.ll -S -o /dev/null 2>&1 | 
FileCheck %s --check-prefix=CONFLICT
+
+; FP128: !{i32 1, !"long-double-type", !"fp128"}
+; CONFLICT: linking module flags 'long-double-type': IDs have conflicting 
values
+
+;--- none.ll
+target triple = "powerpc64le-unknown-linux-gnu"
+define void @g() {
+  ret void
+}
+
+;--- fp128.ll
+target triple = "powerpc64le-unknown-linux-gnu"
+!llvm.module.flags = !{!0}
+!0 = !{i32 1, !"long-double-type", !"fp128"}
+
+;--- ppc_fp128.ll
+target triple = "powerpc64le-unknown-linux-gnu"
+!llvm.module.flags = !{!0}
+!0 = !{i32 1, !"long-double-type", !"ppc_fp128"}
diff --git a/llvm/test/Verifier/module-flags-long-double-type.ll 
b/llvm/test/Verifier/module-flags-long-double-type.ll
new file mode 100644
index 0000000000000..5aabbd0768508
--- /dev/null
+++ b/llvm/test/Verifier/module-flags-long-double-type.ll
@@ -0,0 +1,37 @@
+; RUN: split-file %s %t
+; RUN: not llvm-as < %t/not-string.ll -disable-output 2>&1 | FileCheck %s 
--check-prefix=NOTSTRING
+; RUN: not llvm-as < %t/bad-value.ll -disable-output 2>&1 | FileCheck %s 
--check-prefix=BADVALUE
+; RUN: not llvm-as < %t/empty-value.ll -disable-output 2>&1 | FileCheck %s 
--check-prefix=EMPTY
+; RUN: not llvm-as < %t/too-few.ll -disable-output 2>&1 | FileCheck %s 
--check-prefix=TOOFEW
+; RUN: not llvm-as < %t/too-many.ll -disable-output 2>&1 | FileCheck %s 
--check-prefix=TOOMANY
+; RUN: not llvm-as < %t/bad-behavior.ll -disable-output 2>&1 | FileCheck %s 
--check-prefix=BEHAVIOR
+
+;--- not-string.ll
+!llvm.module.flags = !{!0}
+!0 = !{i32 1, !"long-double-type", i32 1}
+; NOTSTRING: long-double-type metadata requires a string argument
+
+;--- bad-value.ll
+!llvm.module.flags = !{!0}
+!0 = !{i32 1, !"long-double-type", !"bogus"}
+; BADVALUE: invalid long-double-type metadata value
+
+;--- empty-value.ll
+!llvm.module.flags = !{!0}
+!0 = !{i32 1, !"long-double-type", !""}
+; EMPTY: invalid long-double-type metadata value
+
+;--- too-few.ll
+!llvm.module.flags = !{!0}
+!0 = !{i32 1, !"long-double-type"}
+; TOOFEW: incorrect number of operands in module flag
+
+;--- too-many.ll
+!llvm.module.flags = !{!0}
+!0 = !{i32 1, !"long-double-type", !"fp128", !"extra"}
+; TOOMANY: incorrect number of operands in module flag
+
+;--- bad-behavior.ll
+!llvm.module.flags = !{!0}
+!0 = !{i32 2, !"long-double-type", !"fp128"}
+; BEHAVIOR: long-double-type module flag must use 'error' merge behavior

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

Reply via email to