PowerPC: Rename "float-abi" module flag to "long-double-type" (#210817)
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) <noreply@anthropic.com>
This commit is contained in:
parent
6d59a24272
commit
9d4eb0a855
11 changed files with 241 additions and 29 deletions
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
@ -9407,6 +9407,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
|
||||
|
|
|
|||
|
|
@ -6626,6 +6626,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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
19
llvm/test/Assembler/module-flags-long-double-type.ll
Normal file
19
llvm/test/Assembler/module-flags-long-double-type.ll
Normal file
|
|
@ -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"}
|
||||
45
llvm/test/Bitcode/upgrade-ppc-float-abi.ll
Normal file
45
llvm/test/Bitcode/upgrade-ppc-float-abi.ll
Normal file
|
|
@ -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"}
|
||||
|
|
@ -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
|
||||
|
||||
; IEEE: .gnu_attribute 4, 13
|
||||
; IBM: .gnu_attribute 4, 5
|
||||
; DBL: .gnu_attribute 4, 9
|
||||
; NONE-NOT: .gnu_attribute 4,
|
||||
; 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, !"float-abi", !"FLTABI"}
|
||||
!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
|
||||
|
||||
;--- 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}
|
||||
; NONE-NOT: .gnu_attribute 4,
|
||||
|
|
|
|||
31
llvm/test/Linker/module-flags-long-double-type.ll
Normal file
31
llvm/test/Linker/module-flags-long-double-type.ll
Normal file
|
|
@ -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"}
|
||||
37
llvm/test/Verifier/module-flags-long-double-type.ll
Normal file
37
llvm/test/Verifier/module-flags-long-double-type.ll
Normal file
|
|
@ -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
|
||||
Loading…
Reference in a new issue