https://github.com/doac updated https://github.com/llvm/llvm-project/pull/222304
>From 6d87620fab43b0ab7cf6cc3b46b111316c027010 Mon Sep 17 00:00:00 2001 From: Daniel Cederman <[email protected]> Date: Wed, 1 Jul 2026 07:42:06 +0200 Subject: [PATCH 1/2] [Sparc][clang] Use 64-bit long double on bare-metal targets GCC uses 64-bit long double for bare-metal SPARC V8 targets, including RTEMS. Keep the default 128-bit for other SPARC targets. Use the scalar calling convention for 64-bit long double. Assisted-by: Codex --- clang/lib/Basic/Targets/Sparc.cpp | 3 +- clang/lib/Basic/Targets/Sparc.h | 18 +++++++--- clang/lib/CodeGen/Targets/Sparc.cpp | 6 ++-- .../CodeGen/Sparc/sparc-long-double-abi.c | 17 ++++++++++ clang/test/CodeGen/Sparc/sparc-vaarg.c | 2 +- clang/test/CodeGen/Sparc/sparcv8-abi.c | 2 +- clang/test/CodeGen/Sparc/variadic-aggregate.c | 2 +- clang/test/Preprocessor/init.c | 33 ++++++++++++------- .../Preprocessor/predefined-arch-macros.c | 9 +++++ 9 files changed, 70 insertions(+), 22 deletions(-) create mode 100644 clang/test/CodeGen/Sparc/sparc-long-double-abi.c diff --git a/clang/lib/Basic/Targets/Sparc.cpp b/clang/lib/Basic/Targets/Sparc.cpp index fe1aad6804aa6..46261d4556998 100644 --- a/clang/lib/Basic/Targets/Sparc.cpp +++ b/clang/lib/Basic/Targets/Sparc.cpp @@ -165,7 +165,8 @@ void SparcV8TargetInfo::getTargetDefines(const LangOptions &Opts, Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4"); Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8"); } - Builder.defineMacro("__LONG_DOUBLE_128__"); + if (LongDoubleWidth == 128) + Builder.defineMacro("__LONG_DOUBLE_128__"); } void SparcV9TargetInfo::getTargetDefines(const LangOptions &Opts, diff --git a/clang/lib/Basic/Targets/Sparc.h b/clang/lib/Basic/Targets/Sparc.h index 95b69ff2be4bb..1d0cebaa18496 100644 --- a/clang/lib/Basic/Targets/Sparc.h +++ b/clang/lib/Basic/Targets/Sparc.h @@ -167,11 +167,19 @@ class LLVM_LIBRARY_VISIBILITY SparcV8TargetInfo : public SparcTargetInfo { break; } - // The SPARCv8 System V ABI has long double 128-bits in size, but 64-bit - // aligned. - LongDoubleWidth = 128; - LongDoubleAlign = 64; - LongDoubleFormat = &llvm::APFloat::IEEEquad(); + // Bare-metal and RTEMS targets default to 64-bit long double, matching + // GCC. Other targets use 128-bit per the SPARCv8 System V ABI, with + // 64-bit alignment. + if (getTriple().getOS() == llvm::Triple::UnknownOS || + getTriple().getOS() == llvm::Triple::RTEMS) { + LongDoubleWidth = 64; + LongDoubleAlign = 64; + LongDoubleFormat = &llvm::APFloat::IEEEdouble(); + } else { + LongDoubleWidth = 128; + LongDoubleAlign = 64; + LongDoubleFormat = &llvm::APFloat::IEEEquad(); + } // Up to 32 bits (V8) or 64 bits (V9) are lock-free atomic, but we're // willing to do atomic ops on up to 64 bits. diff --git a/clang/lib/CodeGen/Targets/Sparc.cpp b/clang/lib/CodeGen/Targets/Sparc.cpp index f5a17aa51184a..fd0c18e290655 100644 --- a/clang/lib/CodeGen/Targets/Sparc.cpp +++ b/clang/lib/CodeGen/Targets/Sparc.cpp @@ -72,7 +72,8 @@ ABIArgInfo SparcV8ABIInfo::classifyReturnType(QualType Ty) const { return classifyComplexType(CT, /*IsRet=*/true); if (const auto *BT = Ty->getAs<BuiltinType>(); - BT && BT->getKind() == BuiltinType::LongDouble) + BT && BT->getKind() == BuiltinType::LongDouble && + getContext().getTypeSize(Ty) > 64) return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace(), /*ByVal=*/false); @@ -84,7 +85,8 @@ ABIArgInfo SparcV8ABIInfo::classifyArgumentType(QualType Ty) const { return classifyComplexType(CT, /*IsRet=*/false); const auto *BT = Ty->getAs<BuiltinType>(); - if (BT && BT->getKind() == BuiltinType::LongDouble) + if (BT && BT->getKind() == BuiltinType::LongDouble && + getContext().getTypeSize(Ty) > 64) return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace()); return DefaultABIInfo::classifyArgumentType(Ty); diff --git a/clang/test/CodeGen/Sparc/sparc-long-double-abi.c b/clang/test/CodeGen/Sparc/sparc-long-double-abi.c new file mode 100644 index 0000000000000..e022643e87adc --- /dev/null +++ b/clang/test/CodeGen/Sparc/sparc-long-double-abi.c @@ -0,0 +1,17 @@ +// RUN: %clang_cc1 -triple sparc-unknown-none -O1 -emit-llvm -o - %s | FileCheck %s + +void sink(long double); +void vararg(int, ...); +long double source(void); + +long double test(long double x) { + sink(x); + vararg(0, x); + return source(); +} + +// CHECK-LABEL: define{{.*}} double @test(double noundef %x) +// CHECK: {{.*}}call void @sink(double noundef %x) +// CHECK: {{.*}}call void (i32, ...) @vararg(i32 noundef 0, double noundef %x) +// CHECK: [[RESULT:%.*]] = {{.*}}call double @source() +// CHECK: ret double [[RESULT]] diff --git a/clang/test/CodeGen/Sparc/sparc-vaarg.c b/clang/test/CodeGen/Sparc/sparc-vaarg.c index f322229e20c43..bfe1a0209461e 100644 --- a/clang/test/CodeGen/Sparc/sparc-vaarg.c +++ b/clang/test/CodeGen/Sparc/sparc-vaarg.c @@ -1,5 +1,5 @@ // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 6 -// RUN: %clang_cc1 -triple sparc -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple sparc-unknown-linux -emit-llvm -o - %s | FileCheck %s #include <stdarg.h> // CHECK-LABEL: define dso_local i32 @get_int( diff --git a/clang/test/CodeGen/Sparc/sparcv8-abi.c b/clang/test/CodeGen/Sparc/sparcv8-abi.c index 7beddd20e5e4d..317a5ea1beee5 100644 --- a/clang/test/CodeGen/Sparc/sparcv8-abi.c +++ b/clang/test/CodeGen/Sparc/sparcv8-abi.c @@ -1,5 +1,5 @@ // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --filter "^define |^entry:" --version 6 -// RUN: %clang_cc1 -triple sparc-unknown-unknown -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -triple sparc-unknown-linux -emit-llvm %s -o - | FileCheck %s float __complex__ // CHECK-LABEL: define dso_local { float, float } @p( diff --git a/clang/test/CodeGen/Sparc/variadic-aggregate.c b/clang/test/CodeGen/Sparc/variadic-aggregate.c index be571ecb5fadd..d451056ef434a 100644 --- a/clang/test/CodeGen/Sparc/variadic-aggregate.c +++ b/clang/test/CodeGen/Sparc/variadic-aggregate.c @@ -1,5 +1,5 @@ // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 6 -// RUN: %clang_cc1 -triple sparc -emit-llvm -o - %s \ +// RUN: %clang_cc1 -triple sparc-unknown-linux -emit-llvm -o - %s \ // RUN: | FileCheck %s --check-prefixes=SPARC // // RUN: %clang_cc1 -triple sparcv9-unknown-unknown -emit-llvm -o - %s \ diff --git a/clang/test/Preprocessor/init.c b/clang/test/Preprocessor/init.c index 21d61de8c0aaf..56c782aeb1397 100644 --- a/clang/test/Preprocessor/init.c +++ b/clang/test/Preprocessor/init.c @@ -1122,19 +1122,29 @@ // SPARC:#define __INT_LEAST8_MAX__ 127 // SPARC:#define __INT_LEAST8_TYPE__ signed char // SPARC:#define __INT_MAX__ 2147483647 -// SPARC:#define __LDBL_DENORM_MIN__ 6.47517511943802511092443895822764655e-4966L -// SPARC:#define __LDBL_DIG__ 33 -// SPARC:#define __LDBL_EPSILON__ 1.92592994438723585305597794258492732e-34L +// SPARC-DEFAULT:#define __LDBL_DENORM_MIN__ 4.9406564584124654e-324L +// SPARC-NETOPENBSD:#define __LDBL_DENORM_MIN__ 6.47517511943802511092443895822764655e-4966L +// SPARC-DEFAULT:#define __LDBL_DIG__ 15 +// SPARC-NETOPENBSD:#define __LDBL_DIG__ 33 +// SPARC-DEFAULT:#define __LDBL_EPSILON__ 2.2204460492503131e-16L +// SPARC-NETOPENBSD:#define __LDBL_EPSILON__ 1.92592994438723585305597794258492732e-34L // SPARC:#define __LDBL_HAS_DENORM__ 1 // SPARC:#define __LDBL_HAS_INFINITY__ 1 // SPARC:#define __LDBL_HAS_QUIET_NAN__ 1 -// SPARC:#define __LDBL_MANT_DIG__ 113 -// SPARC:#define __LDBL_MAX_10_EXP__ 4932 -// SPARC:#define __LDBL_MAX_EXP__ 16384 -// SPARC:#define __LDBL_MAX__ 1.18973149535723176508575932662800702e+4932L -// SPARC:#define __LDBL_MIN_10_EXP__ (-4931) -// SPARC:#define __LDBL_MIN_EXP__ (-16381) -// SPARC:#define __LDBL_MIN__ 3.36210314311209350626267781732175260e-4932L +// SPARC-DEFAULT:#define __LDBL_MANT_DIG__ 53 +// SPARC-NETOPENBSD:#define __LDBL_MANT_DIG__ 113 +// SPARC-DEFAULT:#define __LDBL_MAX_10_EXP__ 308 +// SPARC-NETOPENBSD:#define __LDBL_MAX_10_EXP__ 4932 +// SPARC-DEFAULT:#define __LDBL_MAX_EXP__ 1024 +// SPARC-NETOPENBSD:#define __LDBL_MAX_EXP__ 16384 +// SPARC-DEFAULT:#define __LDBL_MAX__ 1.7976931348623157e+308L +// SPARC-NETOPENBSD:#define __LDBL_MAX__ 1.18973149535723176508575932662800702e+4932L +// SPARC-DEFAULT:#define __LDBL_MIN_10_EXP__ (-307) +// SPARC-NETOPENBSD:#define __LDBL_MIN_10_EXP__ (-4931) +// SPARC-DEFAULT:#define __LDBL_MIN_EXP__ (-1021) +// SPARC-NETOPENBSD:#define __LDBL_MIN_EXP__ (-16381) +// SPARC-DEFAULT:#define __LDBL_MIN__ 2.2250738585072014e-308L +// SPARC-NETOPENBSD:#define __LDBL_MIN__ 3.36210314311209350626267781732175260e-4932L // SPARC:#define __LONG_LONG_MAX__ 9223372036854775807LL // SPARC:#define __LONG_MAX__ 2147483647L // SPARC-NOT:#define __LP64__ @@ -1150,7 +1160,8 @@ // SPARC:#define __SIZEOF_DOUBLE__ 8 // SPARC:#define __SIZEOF_FLOAT__ 4 // SPARC:#define __SIZEOF_INT__ 4 -// SPARC:#define __SIZEOF_LONG_DOUBLE__ 16 +// SPARC-DEFAULT:#define __SIZEOF_LONG_DOUBLE__ 8 +// SPARC-NETOPENBSD:#define __SIZEOF_LONG_DOUBLE__ 16 // SPARC:#define __SIZEOF_LONG_LONG__ 8 // SPARC:#define __SIZEOF_LONG__ 4 // SPARC:#define __SIZEOF_POINTER__ 4 diff --git a/clang/test/Preprocessor/predefined-arch-macros.c b/clang/test/Preprocessor/predefined-arch-macros.c index 01a132d84daba..1eb28de306421 100644 --- a/clang/test/Preprocessor/predefined-arch-macros.c +++ b/clang/test/Preprocessor/predefined-arch-macros.c @@ -4792,6 +4792,15 @@ // RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_SPARC_LDBL // CHECK_SPARC_LDBL: #define __LONG_DOUBLE_128__ 1 +// RUN: %clang -E -dM %s -o - 2>&1 \ +// RUN: -target sparc-unknown-none \ +// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_SPARC_LDBL64 +// RUN: %clang -E -dM %s -o - 2>&1 \ +// RUN: -target sparc-unknown-rtems \ +// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_SPARC_LDBL64 +// CHECK_SPARC_LDBL64-NOT: #define __LONG_DOUBLE_128__ 1 +// CHECK_SPARC_LDBL64: #define __SIZEOF_LONG_DOUBLE__ 8 + // RUN: %clang -mcpu=v9 -E -dM %s -o - 2>&1 \ // RUN: -target sparc-unknown-linux \ // RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_SPARC-V9 >From 35017a31fac7420c2fadeb7cf2535fbaba2acd68 Mon Sep 17 00:00:00 2001 From: Daniel Cederman <[email protected]> Date: Mon, 14 Sep 2026 10:43:09 +0200 Subject: [PATCH 2/2] [Sparc][clang] Use 64-bit long double on bare-metal targets v2 Move size decision to Triple::getDefaultLongDoubleFormat(). Added more tests. --- clang/lib/Basic/Targets/Sparc.h | 8 +++----- .../CodeGen/Sparc/sparc-long-double-abi.c | 8 ++++++++ .../Preprocessor/predefined-arch-macros.c | 3 +++ llvm/lib/TargetParser/Triple.cpp | 8 ++++++-- llvm/unittests/TargetParser/TripleTest.cpp | 19 ++++++++++++++----- 5 files changed, 34 insertions(+), 12 deletions(-) diff --git a/clang/lib/Basic/Targets/Sparc.h b/clang/lib/Basic/Targets/Sparc.h index 1d0cebaa18496..dfb34f3cb45ed 100644 --- a/clang/lib/Basic/Targets/Sparc.h +++ b/clang/lib/Basic/Targets/Sparc.h @@ -167,11 +167,9 @@ class LLVM_LIBRARY_VISIBILITY SparcV8TargetInfo : public SparcTargetInfo { break; } - // Bare-metal and RTEMS targets default to 64-bit long double, matching - // GCC. Other targets use 128-bit per the SPARCv8 System V ABI, with - // 64-bit alignment. - if (getTriple().getOS() == llvm::Triple::UnknownOS || - getTriple().getOS() == llvm::Triple::RTEMS) { + // Base long double format on the triple. + if (getTriple().getDefaultLongDoubleFormat() == + llvm::LongDoubleFormat::IEEEdouble) { LongDoubleWidth = 64; LongDoubleAlign = 64; LongDoubleFormat = &llvm::APFloat::IEEEdouble(); diff --git a/clang/test/CodeGen/Sparc/sparc-long-double-abi.c b/clang/test/CodeGen/Sparc/sparc-long-double-abi.c index e022643e87adc..0cc2d666d1642 100644 --- a/clang/test/CodeGen/Sparc/sparc-long-double-abi.c +++ b/clang/test/CodeGen/Sparc/sparc-long-double-abi.c @@ -1,4 +1,5 @@ // RUN: %clang_cc1 -triple sparc-unknown-none -O1 -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple sparc-unknown-linux-gnu -O1 -emit-llvm -o - %s | FileCheck %s --check-prefix=LINUX void sink(long double); void vararg(int, ...); @@ -15,3 +16,10 @@ long double test(long double x) { // CHECK: {{.*}}call void (i32, ...) @vararg(i32 noundef 0, double noundef %x) // CHECK: [[RESULT:%.*]] = {{.*}}call double @source() // CHECK: ret double [[RESULT]] + +// Linux retains the SPARC V8 System V 128-bit long double ABI. +// LINUX-LABEL: define{{.*}} void @test(ptr {{.*}}sret(fp128) align 8{{.*}}, ptr {{.*}}byval(fp128) align 8{{.*}}) +// LINUX: {{.*}}call void @sink(ptr {{.*}}byval(fp128) align 8{{.*}}) +// LINUX: {{.*}}call void (i32, ...) @vararg(i32 noundef 0, ptr {{.*}}byval(fp128) align 8{{.*}}) +// LINUX: {{.*}}call void @source(ptr {{.*}}sret(fp128) align 8{{.*}}) +// LINUX: ret void diff --git a/clang/test/Preprocessor/predefined-arch-macros.c b/clang/test/Preprocessor/predefined-arch-macros.c index 1eb28de306421..c9295a5f2ab3c 100644 --- a/clang/test/Preprocessor/predefined-arch-macros.c +++ b/clang/test/Preprocessor/predefined-arch-macros.c @@ -4790,6 +4790,9 @@ // RUN: %clang -E -dM %s -o - 2>&1 \ // RUN: -target sparc-unknown-linux \ // RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_SPARC_LDBL +// RUN: %clang -E -dM %s -o - 2>&1 \ +// RUN: -target sparc-sun-solaris \ +// RUN: | FileCheck -match-full-lines %s -check-prefix=CHECK_SPARC_LDBL // CHECK_SPARC_LDBL: #define __LONG_DOUBLE_128__ 1 // RUN: %clang -E -dM %s -o - 2>&1 \ diff --git a/llvm/lib/TargetParser/Triple.cpp b/llvm/lib/TargetParser/Triple.cpp index 7d67961256f92..f44bc98852c12 100644 --- a/llvm/lib/TargetParser/Triple.cpp +++ b/llvm/lib/TargetParser/Triple.cpp @@ -2545,14 +2545,18 @@ LongDoubleFormat Triple::getDefaultLongDoubleFormat() const { case riscv64: case riscv32be: case riscv64be: - case sparc: - case sparcel: case sparcv9: case systemz: case ve: case wasm32: case wasm64: return LongDoubleFormat::IEEEquad; + case sparc: + case sparcel: + // GCC uses IEEE double for bare-metal and RTEMS SPARC V8 targets. + if (getOS() == UnknownOS || getOS() == RTEMS) + return LongDoubleFormat::IEEEdouble; + return LongDoubleFormat::IEEEquad; case ppc: case ppcle: case ppc64: diff --git a/llvm/unittests/TargetParser/TripleTest.cpp b/llvm/unittests/TargetParser/TripleTest.cpp index e7a6b056702c3..976765c39eaff 100644 --- a/llvm/unittests/TargetParser/TripleTest.cpp +++ b/llvm/unittests/TargetParser/TripleTest.cpp @@ -1787,17 +1787,26 @@ TEST(TripleTest, DefaultLongDoubleFormat) { LongDoubleFormat::IEEEdouble, Triple("thumbv7-unknown-linux-gnueabi").getDefaultLongDoubleFormat()); - // Targets that use IEEE quad, independent of the environment. - EXPECT_EQ(LongDoubleFormat::IEEEquad, - Triple("s390x-unknown-linux-gnu").getDefaultLongDoubleFormat()); - EXPECT_EQ(LongDoubleFormat::IEEEquad, - Triple("s390x-unknown-linux").getDefaultLongDoubleFormat()); + // SPARC V8 uses IEEE double for bare-metal and RTEMS targets. Linux, + // Solaris, and other targets use IEEE quad. SPARC V9 always uses IEEE quad. + EXPECT_EQ(LongDoubleFormat::IEEEdouble, + Triple("sparc-unknown-unknown").getDefaultLongDoubleFormat()); + EXPECT_EQ(LongDoubleFormat::IEEEdouble, + Triple("sparc-unknown-rtems").getDefaultLongDoubleFormat()); EXPECT_EQ(LongDoubleFormat::IEEEquad, Triple("sparc-unknown-linux-gnu").getDefaultLongDoubleFormat()); EXPECT_EQ(LongDoubleFormat::IEEEquad, Triple("sparcel-unknown-linux-gnu").getDefaultLongDoubleFormat()); + EXPECT_EQ(LongDoubleFormat::IEEEquad, + Triple("sparc-unknown-solaris").getDefaultLongDoubleFormat()); EXPECT_EQ(LongDoubleFormat::IEEEquad, Triple("sparcv9-unknown-linux-gnu").getDefaultLongDoubleFormat()); + + // Targets that use IEEE quad, independent of the environment. + EXPECT_EQ(LongDoubleFormat::IEEEquad, + Triple("s390x-unknown-linux-gnu").getDefaultLongDoubleFormat()); + EXPECT_EQ(LongDoubleFormat::IEEEquad, + Triple("s390x-unknown-linux").getDefaultLongDoubleFormat()); EXPECT_EQ(LongDoubleFormat::IEEEquad, Triple("riscv32-unknown-linux-gnu").getDefaultLongDoubleFormat()); EXPECT_EQ(LongDoubleFormat::IEEEquad, _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
