[llvm-branch-commits] [llvm] Triple: Add query for the default long double format (PR #211239)
Matt Arsenault via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Wed Jul 22 04:44:28 PDT 2026
https://github.com/arsenm created https://github.com/llvm/llvm-project/pull/211239
The long double format changes the library call info, which needs
to be computed independently of codegen. Implement this based on the
clang target code.
>From 590b8787ec9149add0edc8c9045b4a39f1ab4230 Mon Sep 17 00:00:00 2001
From: Matt Arsenault <Matthew.Arsenault at amd.com>
Date: Wed, 22 Jul 2026 10:39:33 +0200
Subject: [PATCH] Triple: Add query for the default long double format
The long double format changes the library call info, which needs
to be computed independently of codegen. Implement this based on the
clang target code.
---
llvm/include/llvm/Support/CodeGen.h | 9 ++
llvm/include/llvm/TargetParser/Triple.h | 4 +
llvm/lib/TargetParser/Triple.cpp | 58 ++++++++
llvm/unittests/TargetParser/TripleTest.cpp | 161 +++++++++++++++++++++
4 files changed, 232 insertions(+)
diff --git a/llvm/include/llvm/Support/CodeGen.h b/llvm/include/llvm/Support/CodeGen.h
index 62be46ffb8bd3..d29b24101c723 100644
--- a/llvm/include/llvm/Support/CodeGen.h
+++ b/llvm/include/llvm/Support/CodeGen.h
@@ -70,6 +70,15 @@ namespace llvm {
};
}
+ /// The floating-point format used for the target's "long double" type.
+ enum class LongDoubleFormat {
+ IEEEsingle,
+ IEEEdouble,
+ X87DoubleExtended,
+ IEEEquad,
+ PPCDoubleDouble,
+ };
+
enum class EABI {
Unknown,
Default, // Default means not specified
diff --git a/llvm/include/llvm/TargetParser/Triple.h b/llvm/include/llvm/TargetParser/Triple.h
index 141926473c9eb..18634a8bbe6ff 100644
--- a/llvm/include/llvm/TargetParser/Triple.h
+++ b/llvm/include/llvm/TargetParser/Triple.h
@@ -1257,6 +1257,10 @@ class Triple {
/// Tests if the target's default floating-point ABI is hard float.
bool isHardFloatABI() const { return getDefaultFloatABI() == FloatABI::Hard; }
+ /// Returns the default floating-point format for the "long double" type. A
+ /// particular module may override this default.
+ LLVM_ABI LongDoubleFormat getDefaultLongDoubleFormat() const;
+
/// Tests whether the target supports comdat
bool supportsCOMDAT() const {
return !(isOSBinFormatMachO() || isOSBinFormatXCOFF() ||
diff --git a/llvm/lib/TargetParser/Triple.cpp b/llvm/lib/TargetParser/Triple.cpp
index 333cd0d6d68aa..4710d1df40811 100644
--- a/llvm/lib/TargetParser/Triple.cpp
+++ b/llvm/lib/TargetParser/Triple.cpp
@@ -2581,6 +2581,64 @@ FloatABI::ABIType Triple::getDefaultFloatABI() const {
return FloatABI::Hard;
}
+LongDoubleFormat Triple::getDefaultLongDoubleFormat() const {
+ switch (getArch()) {
+ case loongarch64:
+ case riscv32:
+ case riscv64:
+ case riscv32be:
+ case riscv64be:
+ case sparc:
+ case sparcel:
+ case sparcv9:
+ case systemz:
+ case ve:
+ case wasm32:
+ case wasm64:
+ return LongDoubleFormat::IEEEquad;
+ case ppc:
+ case ppcle:
+ case ppc64:
+ case ppc64le:
+ // PowerPC uses IBM double-double, except on a handful of OSes that use
+ // plain IEEE double. NetBSD only switches to IEEE double on 32-bit PowerPC.
+ if (isOSAIX() || isOSFreeBSD() || isOSOpenBSD() || isMusl() ||
+ (isOSNetBSD() && isPPC32()))
+ return LongDoubleFormat::IEEEdouble;
+ return LongDoubleFormat::PPCDoubleDouble;
+ case x86:
+ case x86_64:
+ // Android and OHOS use IEEE double on 32-bit and IEEE quad on 64-bit.
+ if (isAndroid() || isOHOSFamily())
+ return isX86_64() ? LongDoubleFormat::IEEEquad
+ : LongDoubleFormat::IEEEdouble;
+ // Windows-MSVC and UEFI use IEEE double. MinGW and Cygwin keep x87.
+ if (isWindowsMSVCEnvironment() || isUEFI())
+ return LongDoubleFormat::IEEEdouble;
+ return LongDoubleFormat::X87DoubleExtended;
+ case aarch64:
+ case aarch64_be:
+ case aarch64_32:
+ // AArch64 uses IEEE quad, except on Windows, Darwin, and Android.
+ if (isOSWindows() || isOSDarwin() || isAndroid())
+ return LongDoubleFormat::IEEEdouble;
+ return LongDoubleFormat::IEEEquad;
+ case mips64:
+ case mips64el:
+ return LongDoubleFormat::IEEEquad;
+ case avr:
+ case tce:
+ case tcele:
+ // AVR and 32-bit OpenASIP use IEEE single precision.
+ return LongDoubleFormat::IEEEsingle;
+ case tcele64:
+ // 64-bit OpenASIP uses IEEE double, unlike its 32-bit variants.
+ return LongDoubleFormat::IEEEdouble;
+ default:
+ return LongDoubleFormat::IEEEdouble;
+ }
+}
+
// HLSL triple environment orders are relied on in the front end
static_assert(Triple::Vertex - Triple::Pixel == 1,
"incorrect HLSL stage order");
diff --git a/llvm/unittests/TargetParser/TripleTest.cpp b/llvm/unittests/TargetParser/TripleTest.cpp
index 28d541a703417..219e3ce9c0baf 100644
--- a/llvm/unittests/TargetParser/TripleTest.cpp
+++ b/llvm/unittests/TargetParser/TripleTest.cpp
@@ -1687,6 +1687,167 @@ TEST(TripleTest, DefaultFloatABI) {
EXPECT_EQ(FloatABI::Hard, Triple("amdgpu-amd-amdhsa").getDefaultFloatABI());
}
+TEST(TripleTest, DefaultLongDoubleFormat) {
+ // PowerPC defaults to IBM double-double, independent of the environment.
+ EXPECT_EQ(
+ LongDoubleFormat::PPCDoubleDouble,
+ Triple("powerpc64le-unknown-linux-gnu").getDefaultLongDoubleFormat());
+ EXPECT_EQ(LongDoubleFormat::PPCDoubleDouble,
+ Triple("powerpc64le-unknown-linux").getDefaultLongDoubleFormat());
+ EXPECT_EQ(LongDoubleFormat::PPCDoubleDouble,
+ Triple("powerpc64-unknown-linux-gnu").getDefaultLongDoubleFormat());
+ EXPECT_EQ(LongDoubleFormat::PPCDoubleDouble,
+ Triple("powerpc64-unknown-linux").getDefaultLongDoubleFormat());
+ EXPECT_EQ(LongDoubleFormat::PPCDoubleDouble,
+ Triple("powerpc-unknown-linux-gnu").getDefaultLongDoubleFormat());
+ EXPECT_EQ(LongDoubleFormat::PPCDoubleDouble,
+ Triple("powerpc-unknown-linux").getDefaultLongDoubleFormat());
+ EXPECT_EQ(LongDoubleFormat::PPCDoubleDouble,
+ Triple("powerpcle-unknown-linux-gnu").getDefaultLongDoubleFormat());
+ EXPECT_EQ(LongDoubleFormat::PPCDoubleDouble,
+ Triple("powerpcle-unknown-linux").getDefaultLongDoubleFormat());
+ // ... except on AIX, FreeBSD, OpenBSD, and Musl, which use IEEE double.
+ EXPECT_EQ(LongDoubleFormat::IEEEdouble,
+ Triple("powerpc-ibm-aix").getDefaultLongDoubleFormat());
+ EXPECT_EQ(LongDoubleFormat::IEEEdouble,
+ Triple("powerpc64-ibm-aix").getDefaultLongDoubleFormat());
+ EXPECT_EQ(LongDoubleFormat::IEEEdouble,
+ Triple("powerpc64-unknown-freebsd").getDefaultLongDoubleFormat());
+ EXPECT_EQ(LongDoubleFormat::IEEEdouble,
+ Triple("powerpc64-unknown-openbsd").getDefaultLongDoubleFormat());
+ EXPECT_EQ(
+ LongDoubleFormat::IEEEdouble,
+ Triple("powerpc64-unknown-linux-musl").getDefaultLongDoubleFormat());
+ // NetBSD only switches to IEEE double on 32-bit PowerPC.
+ EXPECT_EQ(LongDoubleFormat::IEEEdouble,
+ Triple("powerpc-unknown-netbsd").getDefaultLongDoubleFormat());
+ EXPECT_EQ(LongDoubleFormat::PPCDoubleDouble,
+ Triple("powerpc64-unknown-netbsd").getDefaultLongDoubleFormat());
+
+ // X86 defaults to x87 80-bit extended precision, independent of environment.
+ EXPECT_EQ(LongDoubleFormat::X87DoubleExtended,
+ Triple("x86_64-unknown-linux-gnu").getDefaultLongDoubleFormat());
+ EXPECT_EQ(LongDoubleFormat::X87DoubleExtended,
+ Triple("x86_64-unknown-linux").getDefaultLongDoubleFormat());
+ EXPECT_EQ(LongDoubleFormat::X87DoubleExtended,
+ Triple("i686-unknown-linux-gnu").getDefaultLongDoubleFormat());
+ EXPECT_EQ(LongDoubleFormat::X87DoubleExtended,
+ Triple("i686-unknown-linux").getDefaultLongDoubleFormat());
+ EXPECT_EQ(LongDoubleFormat::X87DoubleExtended,
+ Triple("x86_64-apple-macosx").getDefaultLongDoubleFormat());
+ // MinGW and Cygwin keep x87 extended precision.
+ EXPECT_EQ(LongDoubleFormat::X87DoubleExtended,
+ Triple("x86_64-pc-windows-gnu").getDefaultLongDoubleFormat());
+ EXPECT_EQ(LongDoubleFormat::X87DoubleExtended,
+ Triple("x86_64-pc-cygwin").getDefaultLongDoubleFormat());
+ // Windows-MSVC and UEFI use IEEE double.
+ EXPECT_EQ(LongDoubleFormat::IEEEdouble,
+ Triple("x86_64-pc-windows-msvc").getDefaultLongDoubleFormat());
+ EXPECT_EQ(LongDoubleFormat::IEEEdouble,
+ Triple("i686-pc-windows-msvc").getDefaultLongDoubleFormat());
+ EXPECT_EQ(LongDoubleFormat::IEEEdouble,
+ Triple("x86_64-unknown-uefi").getDefaultLongDoubleFormat());
+ // Android and OHOS use IEEE double on 32-bit and IEEE quad on 64-bit.
+ EXPECT_EQ(LongDoubleFormat::IEEEdouble,
+ Triple("i686-unknown-linux-android").getDefaultLongDoubleFormat());
+ EXPECT_EQ(
+ LongDoubleFormat::IEEEquad,
+ Triple("x86_64-unknown-linux-android").getDefaultLongDoubleFormat());
+ EXPECT_EQ(LongDoubleFormat::IEEEdouble,
+ Triple("i686-unknown-linux-ohos").getDefaultLongDoubleFormat());
+ EXPECT_EQ(LongDoubleFormat::IEEEquad,
+ Triple("x86_64-unknown-linux-ohos").getDefaultLongDoubleFormat());
+
+ // AArch64 defaults to IEEE quad, for all AArch64 arch variants, independent
+ // of the environment.
+ EXPECT_EQ(LongDoubleFormat::IEEEquad,
+ Triple("aarch64-unknown-linux-gnu").getDefaultLongDoubleFormat());
+ EXPECT_EQ(LongDoubleFormat::IEEEquad,
+ Triple("aarch64-unknown-linux").getDefaultLongDoubleFormat());
+ EXPECT_EQ(
+ LongDoubleFormat::IEEEquad,
+ Triple("aarch64_be-unknown-linux-gnu").getDefaultLongDoubleFormat());
+ EXPECT_EQ(
+ LongDoubleFormat::IEEEquad,
+ Triple("aarch64_32-unknown-linux-gnu").getDefaultLongDoubleFormat());
+ // ... except on Windows, Darwin, and Android, which use IEEE double.
+ EXPECT_EQ(LongDoubleFormat::IEEEdouble,
+ Triple("aarch64-pc-windows-msvc").getDefaultLongDoubleFormat());
+ EXPECT_EQ(LongDoubleFormat::IEEEdouble,
+ Triple("arm64-apple-macosx").getDefaultLongDoubleFormat());
+ EXPECT_EQ(
+ LongDoubleFormat::IEEEdouble,
+ Triple("aarch64-unknown-linux-android").getDefaultLongDoubleFormat());
+
+ // ARM/Thumb use IEEE double.
+ EXPECT_EQ(
+ LongDoubleFormat::IEEEdouble,
+ Triple("armv7-unknown-linux-gnueabihf").getDefaultLongDoubleFormat());
+ EXPECT_EQ(
+ 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());
+ 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("sparcv9-unknown-linux-gnu").getDefaultLongDoubleFormat());
+ EXPECT_EQ(LongDoubleFormat::IEEEquad,
+ Triple("riscv32-unknown-linux-gnu").getDefaultLongDoubleFormat());
+ EXPECT_EQ(LongDoubleFormat::IEEEquad,
+ Triple("riscv64-unknown-linux-gnu").getDefaultLongDoubleFormat());
+ EXPECT_EQ(LongDoubleFormat::IEEEquad,
+ Triple("riscv32be-unknown-linux-gnu").getDefaultLongDoubleFormat());
+ EXPECT_EQ(LongDoubleFormat::IEEEquad,
+ Triple("riscv64be-unknown-linux-gnu").getDefaultLongDoubleFormat());
+ EXPECT_EQ(
+ LongDoubleFormat::IEEEquad,
+ Triple("loongarch64-unknown-linux-gnu").getDefaultLongDoubleFormat());
+ EXPECT_EQ(LongDoubleFormat::IEEEquad,
+ Triple("ve-unknown-linux-gnu").getDefaultLongDoubleFormat());
+ EXPECT_EQ(LongDoubleFormat::IEEEquad,
+ Triple("wasm32-unknown-unknown").getDefaultLongDoubleFormat());
+ EXPECT_EQ(LongDoubleFormat::IEEEquad,
+ Triple("wasm64-unknown-unknown").getDefaultLongDoubleFormat());
+
+ // 64-bit MIPS uses IEEE quad; 32-bit MIPS uses IEEE double. Both are
+ // independent of the environment.
+ EXPECT_EQ(LongDoubleFormat::IEEEquad,
+ Triple("mips64-unknown-linux-gnu").getDefaultLongDoubleFormat());
+ EXPECT_EQ(LongDoubleFormat::IEEEquad,
+ Triple("mips64-unknown-linux").getDefaultLongDoubleFormat());
+ EXPECT_EQ(LongDoubleFormat::IEEEquad,
+ Triple("mips64el-unknown-linux-gnu").getDefaultLongDoubleFormat());
+ EXPECT_EQ(LongDoubleFormat::IEEEdouble,
+ Triple("mips-unknown-linux-gnu").getDefaultLongDoubleFormat());
+ EXPECT_EQ(LongDoubleFormat::IEEEdouble,
+ Triple("mips-unknown-linux").getDefaultLongDoubleFormat());
+
+ // AVR and 32-bit OpenASIP use IEEE single; the 64-bit tcele64 uses double.
+ EXPECT_EQ(LongDoubleFormat::IEEEsingle,
+ Triple("avr-unknown-unknown").getDefaultLongDoubleFormat());
+ EXPECT_EQ(LongDoubleFormat::IEEEsingle,
+ Triple("tce-unknown-unknown").getDefaultLongDoubleFormat());
+ EXPECT_EQ(LongDoubleFormat::IEEEsingle,
+ Triple("tcele-unknown-unknown").getDefaultLongDoubleFormat());
+ EXPECT_EQ(LongDoubleFormat::IEEEdouble,
+ Triple("tcele64-unknown-unknown").getDefaultLongDoubleFormat());
+
+ // Targets without a special case fall back to IEEE double.
+ EXPECT_EQ(LongDoubleFormat::IEEEdouble,
+ Triple("msp430-unknown-unknown").getDefaultLongDoubleFormat());
+ EXPECT_EQ(LongDoubleFormat::IEEEdouble,
+ Triple("amdgpu-unknown-unknown").getDefaultLongDoubleFormat());
+ EXPECT_EQ(LongDoubleFormat::IEEEdouble,
+ Triple("nvptx64-unknown-unknown").getDefaultLongDoubleFormat());
+}
+
TEST(TripleTest, Normalization) {
EXPECT_EQ("unknown", Triple::normalize(""));
More information about the llvm-branch-commits
mailing list