[llvm-branch-commits] [llvm] RuntimeLibcalls: Use a single LibcallImpl for long double functions (PR #233872)
Matt Arsenault via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Tue Oct 20 08:02:11 PDT 2026
https://github.com/arsenm created https://github.com/llvm/llvm-project/pull/233872
Replace the per-format <func>l_{f80|f128|ppcf128} implementations with
a single <func>l implementaton. The concrete type is now derived from
the module/triple's LongDoubleFormat, so this is no longer a static
property.
On targets where long double is double, the l-suffixed functions do
not provide a libcall. This could be fixed in principle, but nothing
would use it in the compiler.
Co-authored-by: Claude Opus 5.5 <noreply at anthropic.com>
>From 319e9a6bc4b2d1bd4c386b16b32ca0b12be1ae4e Mon Sep 17 00:00:00 2001
From: Matt Arsenault <Matthew.Arsenault at amd.com>
Date: Tue, 20 Oct 2026 13:51:34 +0200
Subject: [PATCH] RuntimeLibcalls: Use a single LibcallImpl for long double
functions
Replace the per-format <func>l_{f80|f128|ppcf128} implementations with
a single <func>l implementaton. The concrete type is now derived from
the module/triple's LongDoubleFormat, so this is no longer a static
property.
On targets where long double is double, the l-suffixed functions do
not provide a libcall. This could be fixed in principle, but nothing
would use it in the compiler.
Co-authored-by: Claude Opus 5.5 <noreply at anthropic.com>
---
llvm/include/llvm/IR/RuntimeLibcalls.h | 10 +-
llvm/include/llvm/IR/RuntimeLibcalls.td | 116 ++++++------------
llvm/include/llvm/IR/RuntimeLibcallsImpl.td | 12 ++
llvm/lib/Analysis/LibcallLoweringInfo.cpp | 5 +-
llvm/lib/IR/RuntimeLibcalls.cpp | 20 +++
.../Target/AArch64/AArch64SMEAttributes.cpp | 2 +-
llvm/lib/Target/Mips/MipsSubtarget.cpp | 4 +-
.../WebAssemblyRuntimeLibcallSignatures.cpp | 4 +-
.../RuntimeLibcallEmitter-multiple-impls.td | 4 +-
llvm/test/TableGen/RuntimeLibcallEmitter.td | 6 +-
llvm/unittests/IR/RuntimeLibcallsTest.cpp | 14 +--
llvm/utils/TableGen/Basic/RuntimeLibcalls.h | 18 ++-
.../TableGen/Basic/RuntimeLibcallsEmitter.cpp | 42 +++++--
13 files changed, 143 insertions(+), 114 deletions(-)
diff --git a/llvm/include/llvm/IR/RuntimeLibcalls.h b/llvm/include/llvm/IR/RuntimeLibcalls.h
index 4df5d865ab6cba..6a02329b68fc88 100644
--- a/llvm/include/llvm/IR/RuntimeLibcalls.h
+++ b/llvm/include/llvm/IR/RuntimeLibcalls.h
@@ -128,9 +128,7 @@ struct RuntimeLibcallsInfo {
}
/// Return the libcall provided by \p Impl
- static RTLIB::Libcall getLibcallFromImpl(RTLIB::LibcallImpl Impl) {
- return ImplToLibcall[Impl];
- }
+ LLVM_ABI RTLIB::Libcall getLibcallFromImpl(RTLIB::LibcallImpl Impl) const;
/// Return the runtime libcall that the floating-point math intrinsic \p ID
/// may be lowered to, or RTLIB::UNKNOWN_LIBCALL if there is no such mapping.
@@ -212,7 +210,7 @@ struct RuntimeLibcallsInfo {
/// Returns true if the function has a vector mask argument, which is assumed
/// to be the last argument.
static bool hasVectorMaskArgument(RTLIB::LibcallImpl Impl) {
- return getUnmaskedVectorLibcall(getLibcallFromImpl(Impl)) !=
+ return getUnmaskedVectorLibcall(ImplToLibcall[Impl]) !=
RTLIB::UNKNOWN_LIBCALL;
}
@@ -246,6 +244,10 @@ struct RuntimeLibcallsInfo {
/// Map from a concrete LibcallImpl implementation to its RTLIB::Libcall kind.
LLVM_ABI static const RTLIB::Libcall ImplToLibcall[RTLIB::NumLibcallImpls];
+ RTLIB::Libcall selectLongDoubleLibcall(RTLIB::Libcall F80,
+ RTLIB::Libcall F128,
+ RTLIB::Libcall PPCF128) const;
+
/// Utility function for tablegenerated lookup function. Return a range of
/// enum values that apply for the function name at \p NameOffsetEntry with
/// the value \p StrOffset.
diff --git a/llvm/include/llvm/IR/RuntimeLibcalls.td b/llvm/include/llvm/IR/RuntimeLibcalls.td
index 52b3ce23b2916b..7ca9fa82fde47d 100644
--- a/llvm/include/llvm/IR/RuntimeLibcalls.td
+++ b/llvm/include/llvm/IR/RuntimeLibcalls.td
@@ -130,6 +130,8 @@ def isAArch64 : RuntimeLibcallAvailability<(all_of IsAArch64)>;
def isLongDoubleX87 : RuntimeLibcallAvailability<(all_of IsLongDoubleX87)>;
def isLongDoubleF128 : RuntimeLibcallAvailability<(all_of IsLongDoubleF128)>;
def isLongDoublePPCF128 : RuntimeLibcallAvailability<(all_of IsLongDoublePPCF128)>;
+def isLongDoubleWide : RuntimeLibcallAvailability<
+ (any_of IsLongDoubleX87, IsLongDoubleF128, IsLongDoublePPCF128)>;
// The l-suffixed sincos exists only when hasSinCos and the long double type
// matches the width.
@@ -137,6 +139,9 @@ def isLongDoubleX87AndHasSinCos : RuntimeLibcallAvailability<
(all_of IsLongDoubleX87, (any_of IsGNUEnv, IsOSFuchsia, IsAndroid))>;
def isLongDoubleF128AndHasSinCos : RuntimeLibcallAvailability<
(all_of IsLongDoubleF128, (any_of IsGNUEnv, IsOSFuchsia, IsAndroid))>;
+def isLongDoubleWideAndHasSinCos : RuntimeLibcallAvailability<
+ (all_of (any_of IsLongDoubleX87, IsLongDoubleF128, IsLongDoublePPCF128),
+ (any_of IsGNUEnv, IsOSFuchsia, IsAndroid))>;
def isOSWindows : RuntimeLibcallAvailability<(all_of IsOSWindows)>;
def isNotOSWindows : RuntimeLibcallAvailability<(not IsOSWindows)>;
@@ -196,11 +201,6 @@ def hasSinCos
def hasSinCos_f32_f64
: RuntimeLibcallAvailability<(any_of IsGNUEnv, IsOSFuchsia, IsAndroid, IsPS)>;
-// The ppcf128 l-suffixed sincos exists only when hasSinCos and long double is
-// ppcf128.
-def isLongDoublePPCF128AndHasSinCos : RuntimeLibcallAvailability<
- (all_of IsLongDoublePPCF128, (any_of IsGNUEnv, IsOSFuchsia, IsAndroid))>;
-
def IsExceptionModelNone
: LibcallPredicate<[{ExceptionModel == ExceptionHandling::None}]>;
def IsExceptionModelSjLj
@@ -758,15 +758,9 @@ multiclass LibmLibcallImpls<string libcall_basename = !toupper(NAME),
def NAME#""
: RuntimeLibcallImpl<!cast<RuntimeLibcall>(libcall_basename#"_F64"),
!subst("<typesuffix>", "", rtbasename)>;
- def NAME#"l_f128"
- : RuntimeLibcallImpl<!cast<RuntimeLibcall>(libcall_basename#"_F128"),
- !subst("<typesuffix>", "l", rtbasename)>;
- def NAME#"l_ppcf128"
- : RuntimeLibcallImpl<!cast<RuntimeLibcall>(libcall_basename#"_PPCF128"),
- !subst("<typesuffix>", "l", rtbasename)>;
- def NAME#"l_f80"
- : RuntimeLibcallImpl<!cast<RuntimeLibcall>(libcall_basename#"_F80"),
- !subst("<typesuffix>", "l", rtbasename)>;
+ def NAME#"l"
+ : LongDoubleLibcallImpl<libcall_basename,
+ !subst("<typesuffix>", "l", rtbasename)>;
}
// AArch64 calls
@@ -2080,7 +2074,7 @@ def WindowsCRTLibcAArch64 : LibcallLibrary<"libc",
def WindowsCRTLibcARM : LibcallLibrary<"libc", (add __chkstk), isWindowsARM>;
defvar LibmHasSincoslF128 =
- LibcallImpls<(add sincosl_f128), isLongDoubleF128AndHasSinCos>;
+ LibcallImpls<(add sincosl), isLongDoubleF128AndHasSinCos>;
defvar LibmHasExp10F32 = LibcallImpls<(add exp10f), hasExp10>;
defvar LibmHasExp10F64 = LibcallImpls<(add exp10), hasExp10>;
@@ -2088,9 +2082,6 @@ defvar LibmHasExp10F64 = LibcallImpls<(add exp10), hasExp10>;
defvar LibmHasFrexpF32 = LibcallImpls<(add frexpf), isNotOSWindowsOrIsCygwinMinGW>;
defvar LibmHasLdexpF32 = LibcallImpls<(add ldexpf), isNotOSWindowsOrIsCygwinMinGW>;
-defvar LibmHasFrexpF128 = LibcallImpls<(add frexpl_f128), isNotOSWindowsOrIsCygwinMinGW>;
-defvar LibmHasLdexpF128 = LibcallImpls<(add ldexpl_f128), isNotOSWindowsOrIsCygwinMinGW>;
-
defvar has__stack_chk_fail = LibcallImpls<(add __stack_chk_fail), hasStackChkFail>;
defvar has__stack_chk_guard =
LibcallImpls<(add __stack_chk_guard), hasStackChkFail>;
@@ -2120,60 +2111,39 @@ def SafeStackRuntime : LibcallLibrary<"compiler-rt",
// libm provider library
//===----------------------------------------------------------------------===//
-// Width-specific slices of the libm body. The core holds the f32 and f64
+// The long double slice of the libm body. The core holds the f32 and f64
// functions, as well as the complex and fenv entries.
-defvar LibmCoreImpls_f80 =
- !filter(entry, LibmCoreImpls, !match(!cast<string>(entry.Provides), "F80"));
-defvar LibmCoreImpls_ppcf128 =
- !filter(entry, LibmCoreImpls,
- !match(!cast<string>(entry.Provides), "PPCF128"));
-defvar LibmCoreImpls_f128 =
- !filter(entry, LibmCoreImpls, !match(!cast<string>(entry.Provides), "_F128"));
-defvar LibmCoreImpls_core =
- !listremove(
- !listremove(
- !listremove(LibmCoreImpls, LibmCoreImpls_f80),
- LibmCoreImpls_ppcf128),
- LibmCoreImpls_f128);
+defvar LibmCoreImpls_ldbl =
+ !filter(entry, LibmCoreImpls, !isa<LongDoubleLibcallImpl>(entry));
+defvar LibmCoreImpls_core = !listremove(LibmCoreImpls, LibmCoreImpls_ldbl);
// The Windows math runtime lacks frexp/ldexp except for f64, so the other widths
// are pulled out of the slices and re-added under a Windows guard.
defvar LibmFrexpLdexpF32 = [frexpf, ldexpf];
-defvar LibmFrexpLdexpF80 = [frexpl_f80, ldexpl_f80];
-defvar LibmFrexpLdexpF128 = [frexpl_f128, ldexpl_f128];
-defvar LibmFrexpLdexpPPCF128 = [frexpl_ppcf128, ldexpl_ppcf128];
+defvar LibmFrexpLdexpLDbl = [frexpl, ldexpl];
// exp10 is absent from the Darwin math runtime, which uses __exp10 instead.
defvar LibmExp10F32F64 = [exp10f, exp10];
-defvar LibmExp10F80 = [exp10l_f80];
-defvar LibmExp10F128 = [exp10l_f128];
-defvar LibmExp10PPCF128 = [exp10l_ppcf128];
+defvar LibmExp10LDbl = [exp10l];
defvar LibmCoreImpls_core_noFrexpLdexp =
!listremove(!listremove(LibmCoreImpls_core, LibmFrexpLdexpF32),
LibmExp10F32F64);
-defvar LibmCoreImpls_f80_noFrexpLdexp =
- !listremove(!listremove(LibmCoreImpls_f80, LibmFrexpLdexpF80), LibmExp10F80);
-defvar LibmCoreImpls_f128_noFrexpLdexp =
- !listremove(!listremove(LibmCoreImpls_f128, LibmFrexpLdexpF128),
- LibmExp10F128);
-defvar LibmCoreImpls_ppcf128_noFrexpLdexp =
- !listremove(!listremove(LibmCoreImpls_ppcf128, LibmFrexpLdexpPPCF128),
- LibmExp10PPCF128);
-
-def isLongDoubleX87NotWinMath : RuntimeLibcallAvailability<
- (all_of IsLongDoubleX87, (any_of (not IsOSWindows), IsOSCygMing))>;
+defvar LibmCoreImpls_ldbl_noFrexpLdexp =
+ !listremove(!listremove(LibmCoreImpls_ldbl, LibmFrexpLdexpLDbl),
+ LibmExp10LDbl);
+
+def isLongDoubleWideNotWinMath : RuntimeLibcallAvailability<
+ (all_of (any_of IsLongDoubleX87, IsLongDoubleF128, IsLongDoublePPCF128),
+ (any_of (not IsOSWindows), IsOSCygMing))>;
def isLongDoubleF128NotWinMath : RuntimeLibcallAvailability<
(all_of IsLongDoubleF128, (any_of (not IsOSWindows), IsOSCygMing))>;
-def isLongDoublePPCF128NotWinMath : RuntimeLibcallAvailability<
- (all_of IsLongDoublePPCF128, (any_of (not IsOSWindows), IsOSCygMing))>;
-def isLongDoubleX87NotDarwin : RuntimeLibcallAvailability<
- (all_of IsLongDoubleX87, (not IsOSDarwin))>;
+def isLongDoubleWideNotDarwin : RuntimeLibcallAvailability<
+ (all_of (any_of IsLongDoubleX87, IsLongDoubleF128, IsLongDoublePPCF128),
+ (not IsOSDarwin))>;
def isLongDoubleF128NotDarwin : RuntimeLibcallAvailability<
(all_of IsLongDoubleF128, (not IsOSDarwin))>;
-def isLongDoublePPCF128NotDarwin : RuntimeLibcallAvailability<
- (all_of IsLongDoublePPCF128, (not IsOSDarwin))>;
// The libm body shared by every libm variant. The `l`-suffixed functions are
// selected by the module's long double format.
@@ -2181,19 +2151,11 @@ defvar LibmImpls =
(add LibmCoreImpls_core_noFrexpLdexp,
LibcallImpls<(add LibmFrexpLdexpF32), isNotOSWindowsOrIsCygwinMinGW>,
LibcallImpls<(add LibmExp10F32F64), hasExp10>,
- LibcallImpls<(add LibmCoreImpls_f80_noFrexpLdexp), isLongDoubleX87>,
- LibcallImpls<(add LibmFrexpLdexpF80), isLongDoubleX87NotWinMath>,
- LibcallImpls<(add LibmExp10F80), isLongDoubleX87NotDarwin>,
- LibcallImpls<(add LibmCoreImpls_f128_noFrexpLdexp), isLongDoubleF128>,
- LibcallImpls<(add LibmFrexpLdexpF128), isLongDoubleF128NotWinMath>,
- LibcallImpls<(add LibmExp10F128), isLongDoubleF128NotDarwin>,
- LibcallImpls<(add LibmCoreImpls_ppcf128_noFrexpLdexp), isLongDoublePPCF128>,
- LibcallImpls<(add LibmFrexpLdexpPPCF128), isLongDoublePPCF128NotWinMath>,
- LibcallImpls<(add LibmExp10PPCF128), isLongDoublePPCF128NotDarwin>,
+ LibcallImpls<(add LibmCoreImpls_ldbl_noFrexpLdexp), isLongDoubleWide>,
+ LibcallImpls<(add LibmFrexpLdexpLDbl), isLongDoubleWideNotWinMath>,
+ LibcallImpls<(add LibmExp10LDbl), isLongDoubleWideNotDarwin>,
LibcallImpls<(add sincosf, sincos), hasSinCos>,
- LibcallImpls<(add sincosl_f80), isLongDoubleX87AndHasSinCos>,
- LibcallImpls<(add sincosl_f128), isLongDoubleF128AndHasSinCos>,
- LibcallImpls<(add sincosl_ppcf128), isLongDoublePPCF128AndHasSinCos>);
+ LibcallImpls<(add sincosl), isLongDoubleWideAndHasSinCos>);
def Libm : LibcallLibrary<"libm", LibmImpls>;
@@ -2336,18 +2298,17 @@ def isWindowsArm64EC : RuntimeLibcallAvailability<(all_of IsWindowsArm64EC)>;
// frexpl/ldexpl/exp10l are added separately based on the Target Triple.
defvar AArch64LongDoubleF128Body =
- !listremove(LibmCoreImpls_f128,
- [frexpl_f128, ldexpl_f128, exp10l_f128]);
+ !listremove(LibmCoreImpls_ldbl, [frexpl, ldexpl, exp10l]);
// AArch64 libm extras.
def AArch64Libm : LibcallLibrary<"libm",
(add LibmHasFrexpF32, LibmHasLdexpF32, LibmHasSincoslF128,
// The l-suffixed libm functions are fp128 only when long double is.
- LibcallImpls<(add frexpl_f128, ldexpl_f128), isLongDoubleF128NotWinMath>,
+ LibcallImpls<(add frexpl, ldexpl), isLongDoubleF128NotWinMath>,
LibcallImpls<(add AArch64LongDoubleF128Body), isLongDoubleF128>,
LibmHasExp10F32, LibmHasExp10F64,
// exp10l is fp128 only when long double is.
- LibcallImpls<(add exp10l_f128), isLongDoubleF128NotDarwin>),
+ LibcallImpls<(add exp10l), isLongDoubleF128NotDarwin>),
isAArch64_ExceptArm64EC>;
// AArch64 outline atomics and streaming-mode mem* helpers.
@@ -2910,8 +2871,7 @@ def ARMCompilerRt : LibcallLibrary<"compiler-rt",
// The l-suffixed libm functions are fp128 only when long double is.
def ARMLibm : LibcallLibrary<"libm",
- (add LibcallImpls<(add frexpl_f128, ldexpl_f128, sincosl_f128, exp10l_f128),
- isLongDoubleF128>),
+ (add LibcallImpls<(add frexpl, ldexpl, sincosl, exp10l), isLongDoubleF128>),
isARMOrThumb>;
def ARMSystemLibrary
@@ -3419,7 +3379,7 @@ def PPCLibc : LibcallLibrary<"libc",
// PPC's f128 and ppcf128 math.
def PPCLibm : LibcallLibrary<"libm",
- (add LibmF128Libcalls, LibmCoreImpls_ppcf128), isPPC>;
+ (add LibmF128Libcalls, LibmCoreImpls_ldbl), isPPC>;
// PPC's stack protector, which uses __ssp_canary_word on AIX.
def PPCStackProtectorLibc : LibcallLibrary<"libc",
@@ -3629,8 +3589,8 @@ def X86Libm : LibcallLibrary<"libm",
(add X86_F128_Libcalls,
LibcallImpls<(add sincosf, sincos), hasSinCos_f32_f64>,
// frexpl/ldexpl are available on Windows too.
- LibcallImpls<(add frexpl_f80, ldexpl_f80), isLongDoubleX87>,
- LibcallImpls<(add frexpl_f128, ldexpl_f128), isLongDoubleF128>), isX86>;
+ LibcallImpls<(add frexpl, ldexpl), isLongDoubleWide>,
+ LibcallImpls<(add sincosl), isLongDoubleX87AndHasSinCos>), isX86>;
def X86SystemLibrary
: SystemRuntimeLibrary<isX86,
@@ -3638,7 +3598,7 @@ def X86SystemLibrary
!listconcat(WindowsDivRemMulLibcallOverrides,
[__powitf2_f128])>,
// x86 has no fp128 sincosl, only the x87 one.
- LibraryRef<Libm, [sincosl_f128]>,
+ LibraryRef<Libm, [sincosl]>,
LibraryRef<Libc, !listconcat(MemChkLibcalls, [bzero])>,
ExceptionRuntime, SafeStackRuntime)>;
@@ -3816,7 +3776,7 @@ def WasmExceptionRuntime : LibcallLibrary<"unwind",
def WasmSystemLibrary
: SystemRuntimeLibrary<isWasm,
- (add CompilerRtLibgcc, LibraryRef<Libm, [sincos, sincosf, sincosl_f128]>,
+ (add CompilerRtLibgcc, LibraryRef<Libm, [sincos, sincosf, sincosl]>,
Libc, WasmLibc, WasmCompilerRt,
ExceptionRuntime, WasmExceptionRuntime)>;
diff --git a/llvm/include/llvm/IR/RuntimeLibcallsImpl.td b/llvm/include/llvm/IR/RuntimeLibcallsImpl.td
index 4ccb472995795c..81b652176c1c67 100644
--- a/llvm/include/llvm/IR/RuntimeLibcallsImpl.td
+++ b/llvm/include/llvm/IR/RuntimeLibcallsImpl.td
@@ -158,6 +158,18 @@ class RuntimeLibcallImpl<RuntimeLibcall P, string Name = NAME> {
list<FuncArgType> ArgumentTypes = P.ArgumentTypes;
}
+// Implementation of a long double function, which provides the libcall
+// matching the module's long double format.
+class LongDoubleLibcallImpl<string libcall_basename, string Name = NAME>
+ : RuntimeLibcallImpl<!cast<RuntimeLibcall>(libcall_basename#"_F128"),
+ Name> {
+ let Provides = ?;
+ RuntimeLibcall ProvidesF80 = !cast<RuntimeLibcall>(libcall_basename#"_F80");
+ RuntimeLibcall ProvidesF128 = !cast<RuntimeLibcall>(libcall_basename#"_F128");
+ RuntimeLibcall ProvidesPPCF128 =
+ !cast<RuntimeLibcall>(libcall_basename#"_PPCF128");
+}
+
/// A family of runtime libcalls implementing one floating-point operation, used
/// to generate both the backend selector RTLIB::get<base>(EVT) and the IR-level
/// getLibcallForIntrinsic() mapping. The libcall for a type is `<base>_<suffix>`
diff --git a/llvm/lib/Analysis/LibcallLoweringInfo.cpp b/llvm/lib/Analysis/LibcallLoweringInfo.cpp
index 95b3b0fce6a8df..c6095ff75370b4 100644
--- a/llvm/lib/Analysis/LibcallLoweringInfo.cpp
+++ b/llvm/lib/Analysis/LibcallLoweringInfo.cpp
@@ -19,9 +19,10 @@ LibcallLoweringInfo::LibcallLoweringInfo(
// call is available.
for (RTLIB::LibcallImpl Impl : RTLIB::libcall_impls()) {
if (RTLCI.isAvailable(Impl)) {
- RTLIB::Libcall LC = RTLIB::RuntimeLibcallsInfo::getLibcallFromImpl(Impl);
+ RTLIB::Libcall LC = RTLCI.getLibcallFromImpl(Impl);
// FIXME: Hack, assume the first available libcall wins.
- if (LibcallImpls[LC] == RTLIB::Unsupported)
+ if (LC != RTLIB::UNKNOWN_LIBCALL &&
+ LibcallImpls[LC] == RTLIB::Unsupported)
LibcallImpls[LC] = Impl;
}
}
diff --git a/llvm/lib/IR/RuntimeLibcalls.cpp b/llvm/lib/IR/RuntimeLibcalls.cpp
index 4fc7ea7d0a6c90..62b0ff91f78ddd 100644
--- a/llvm/lib/IR/RuntimeLibcalls.cpp
+++ b/llvm/lib/IR/RuntimeLibcalls.cpp
@@ -79,6 +79,26 @@ RuntimeLibcallsInfo::RuntimeLibcallsInfo(const Module &M, StringRef ABIName,
M.getFloatABI(), M.getLongDoubleFormat(), ABIName,
VecLib) {}
+RTLIB::Libcall RuntimeLibcallsInfo::selectLongDoubleLibcall(
+ RTLIB::Libcall F80, RTLIB::Libcall F128, RTLIB::Libcall PPCF128) const {
+ switch (LongDoubleFmt) {
+ case LongDoubleFormat::X87DoubleExtended:
+ return F80;
+ case LongDoubleFormat::IEEEquad:
+ return F128;
+ case LongDoubleFormat::PPCDoubleDouble:
+ return PPCF128;
+ case LongDoubleFormat::IEEEsingle:
+ case LongDoubleFormat::IEEEdouble:
+ // These long double formats aren't properly handled, but we also don't emit
+ // calls for them. TODO: We could fix the avr_sin/avr_cos hack if we handled
+ // the float case.
+ return RTLIB::UNKNOWN_LIBCALL;
+ }
+
+ llvm_unreachable("unhandled long double format");
+}
+
bool RuntimeLibcallsInfo::isLibraryAvailable(RuntimeLibrary Library) const {
// TODO: Drive this from module-level state (e.g. the linked runtime). For now
// every named library is reported as available.
diff --git a/llvm/lib/Target/AArch64/AArch64SMEAttributes.cpp b/llvm/lib/Target/AArch64/AArch64SMEAttributes.cpp
index 0a5d475c211a7b..fa4732bf3e8b5f 100644
--- a/llvm/lib/Target/AArch64/AArch64SMEAttributes.cpp
+++ b/llvm/lib/Target/AArch64/AArch64SMEAttributes.cpp
@@ -79,7 +79,7 @@ void SMEAttrs::addKnownFunctionAttrs(StringRef FuncName,
if (Impl == RTLIB::Unsupported)
return;
unsigned KnownAttrs = SMEAttrs::Normal;
- RTLIB::Libcall LC = RTLIB::RuntimeLibcallsInfo::getLibcallFromImpl(Impl);
+ RTLIB::Libcall LC = RTLCI.getLibcallFromImpl(Impl);
switch (LC) {
case RTLIB::SMEABI_SME_STATE:
case RTLIB::SMEABI_TPIDR2_SAVE:
diff --git a/llvm/lib/Target/Mips/MipsSubtarget.cpp b/llvm/lib/Target/Mips/MipsSubtarget.cpp
index f75a8c2c0e30ad..95f032c0f77500 100644
--- a/llvm/lib/Target/Mips/MipsSubtarget.cpp
+++ b/llvm/lib/Target/Mips/MipsSubtarget.cpp
@@ -305,8 +305,8 @@ void MipsSubtarget::initLibcallLoweringInfo(LibcallLoweringInfo &Info) const {
for (unsigned I = 0; I != std::size(HardFloatLibCalls); ++I) {
assert((I == 0 || HardFloatLibCalls[I - 1] < HardFloatLibCalls[I]) &&
"Array not sorted!");
- RTLIB::Libcall LC =
- RTLIB::RuntimeLibcallsInfo::getLibcallFromImpl(HardFloatLibCalls[I]);
+ RTLIB::Libcall LC = Info.getRuntimeLibcallsInfo().getLibcallFromImpl(
+ HardFloatLibCalls[I]);
Info.setLibcallImpl(LC, HardFloatLibCalls[I]);
}
}
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyRuntimeLibcallSignatures.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyRuntimeLibcallSignatures.cpp
index 698b8084909cea..36bba46126c291 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyRuntimeLibcallSignatures.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyRuntimeLibcallSignatures.cpp
@@ -562,8 +562,8 @@ struct StaticLibcallNameMap {
for (RTLIB::LibcallImpl Impl : RTLIB::libcall_impls()) {
if (!RTCI.isAvailable(Impl))
continue;
- RTLIB::Libcall LC = RTLIB::RuntimeLibcallsInfo::getLibcallFromImpl(Impl);
- if (Table[LC] != unsupported) {
+ RTLIB::Libcall LC = RTCI.getLibcallFromImpl(Impl);
+ if (LC != RTLIB::UNKNOWN_LIBCALL && Table[LC] != unsupported) {
StringRef NameLibcall =
RTLIB::RuntimeLibcallsInfo::getLibcallImplName(Impl);
// FIXME: Map should be to LibcallImpl
diff --git a/llvm/test/TableGen/RuntimeLibcallEmitter-multiple-impls.td b/llvm/test/TableGen/RuntimeLibcallEmitter-multiple-impls.td
index 815ebea4ec28af..c5232683a5b8c9 100644
--- a/llvm/test/TableGen/RuntimeLibcallEmitter-multiple-impls.td
+++ b/llvm/test/TableGen/RuntimeLibcallEmitter-multiple-impls.td
@@ -40,9 +40,9 @@ def TheSystemLibraryA : SystemRuntimeLibrary<isTargetArchA, (add LibA)>;
// CHECK: void llvm::RTLIB::RuntimeLibcallsInfo::setAvailableLibFuncs_libb(
// CHECK: static const RTLIB::LibcallImpl LibraryCalls[] = {
-// CHECK-NEXT: RTLIB::impl_other_func, // other_func
// CHECK-NEXT: RTLIB::impl_func_a, // func_a
// CHECK-NEXT: RTLIB::impl_func_b, // func_b
+// CHECK-NEXT: RTLIB::impl_other_func, // other_func
// CHECK-NEXT: };
def LibB : LibcallLibrary<"libb", (add func_a, other_func, func_b)>;
@@ -52,10 +52,10 @@ def TheSystemLibraryB : SystemRuntimeLibrary<isTargetArchB, (add LibB)>;
// CHECK: static const RTLIB::LibcallImpl LibraryCalls[] = {
// CHECK-NEXT: RTLIB::impl_dup0, // dup0
// CHECK-NEXT: RTLIB::impl_dup1, // dup1
-// CHECK-NEXT: RTLIB::impl_other_func, // other_func
// CHECK-NEXT: RTLIB::impl_func_a, // func_a
// CHECK-NEXT: RTLIB::impl_func_b, // func_b
// CHECK-NEXT: RTLIB::impl_func_c, // func_c
+// CHECK-NEXT: RTLIB::impl_other_func, // other_func
// CHECK-NEXT: };
def LibC : LibcallLibrary<"libc",
diff --git a/llvm/test/TableGen/RuntimeLibcallEmitter.td b/llvm/test/TableGen/RuntimeLibcallEmitter.td
index fa4a50ef029355..3150806a731797 100644
--- a/llvm/test/TableGen/RuntimeLibcallEmitter.td
+++ b/llvm/test/TableGen/RuntimeLibcallEmitter.td
@@ -347,8 +347,8 @@ def BlahLibrary : SystemRuntimeLibrary<isBlahArch, (add BlahLibc)>;
// CHECK-NEXT: if (TT.getArch() == Triple::buzz) {
// CHECK-NEXT: static const RTLIB::LibcallImpl LibraryCalls[] = {
// CHECK-NEXT: RTLIB::impl___ashlsi3, // __ashlsi3
-// CHECK-NEXT: RTLIB::impl_sqrtl_f80, // sqrtl
// CHECK-NEXT: RTLIB::impl___lshrdi3, // __lshrdi3
+// CHECK-NEXT: RTLIB::impl_sqrtl_f80, // sqrtl
// CHECK-NEXT: };
// CHECK-EMPTY:
// CHECK-NEXT: for (const RTLIB::LibcallImpl Impl : LibraryCalls) {
@@ -380,10 +380,10 @@ def BlahLibrary : SystemRuntimeLibrary<isBlahArch, (add BlahLibc)>;
// CHECK-NEXT: }
// CHECK-NEXT: if (TT.getArch() == Triple::simple) {
// CHECK-NEXT: static const RTLIB::LibcallImpl LibraryCalls[] = {
-// CHECK-NEXT: RTLIB::impl_calloc, // calloc
// CHECK-NEXT: RTLIB::impl___ashlsi3, // __ashlsi3
-// CHECK-NEXT: RTLIB::impl_sqrtl_f80, // sqrtl
// CHECK-NEXT: RTLIB::impl___lshrdi3, // __lshrdi3
+// CHECK-NEXT: RTLIB::impl_calloc, // calloc
+// CHECK-NEXT: RTLIB::impl_sqrtl_f80, // sqrtl
// CHECK-NEXT: };
// CHECK-EMPTY:
// CHECK-NEXT: for (const RTLIB::LibcallImpl Impl : LibraryCalls) {
diff --git a/llvm/unittests/IR/RuntimeLibcallsTest.cpp b/llvm/unittests/IR/RuntimeLibcallsTest.cpp
index 22cff2ddfa610f..ae72fa75abfdb1 100644
--- a/llvm/unittests/IR/RuntimeLibcallsTest.cpp
+++ b/llvm/unittests/IR/RuntimeLibcallsTest.cpp
@@ -46,21 +46,15 @@ TEST(RuntimeLibcallsTest, LibcallImplByName) {
{
auto SquirtleSquad =
RTLIB::RuntimeLibcallsInfo::lookupLibcallImplName("sqrtl");
- ASSERT_EQ(size(SquirtleSquad), 3);
- auto I = SquirtleSquad.begin();
- EXPECT_EQ(*I++, RTLIB::impl_sqrtl_f128);
- EXPECT_EQ(*I++, RTLIB::impl_sqrtl_f80);
- EXPECT_EQ(*I++, RTLIB::impl_sqrtl_ppcf128);
+ ASSERT_EQ(size(SquirtleSquad), 1);
+ EXPECT_EQ(*SquirtleSquad.begin(), RTLIB::impl_sqrtl);
}
// Last libcall
{
auto Truncs = RTLIB::RuntimeLibcallsInfo::lookupLibcallImplName("truncl");
- ASSERT_EQ(size(Truncs), 3);
- auto I = Truncs.begin();
- EXPECT_EQ(*I++, RTLIB::impl_truncl_f128);
- EXPECT_EQ(*I++, RTLIB::impl_truncl_f80);
- EXPECT_EQ(*I++, RTLIB::impl_truncl_ppcf128);
+ ASSERT_EQ(size(Truncs), 1);
+ EXPECT_EQ(*Truncs.begin(), RTLIB::impl_truncl);
}
}
diff --git a/llvm/utils/TableGen/Basic/RuntimeLibcalls.h b/llvm/utils/TableGen/Basic/RuntimeLibcalls.h
index 5225a34eb71207..c5b783a3444806 100644
--- a/llvm/utils/TableGen/Basic/RuntimeLibcalls.h
+++ b/llvm/utils/TableGen/Basic/RuntimeLibcalls.h
@@ -101,6 +101,9 @@ class RuntimeLibcall {
class RuntimeLibcallImpl {
const Record *TheDef;
const RuntimeLibcall *Provides = nullptr;
+ const RuntimeLibcall *ProvidesF80 = nullptr;
+ const RuntimeLibcall *ProvidesF128 = nullptr;
+ const RuntimeLibcall *ProvidesPPCF128 = nullptr;
const size_t EnumVal;
public:
@@ -109,8 +112,15 @@ class RuntimeLibcallImpl {
const DenseMap<const Record *, const RuntimeLibcall *> &ProvideMap,
size_t EnumVal)
: TheDef(Def), EnumVal(EnumVal) {
- if (const Record *ProvidesDef = Def->getValueAsDef("Provides"))
+ if (const Record *ProvidesDef = Def->getValueAsOptionalDef("Provides"))
Provides = ProvideMap.lookup(ProvidesDef);
+
+ if (Def->isSubClassOf("LongDoubleLibcallImpl")) {
+ ProvidesF80 = ProvideMap.lookup(Def->getValueAsDef("ProvidesF80"));
+ ProvidesF128 = ProvideMap.lookup(Def->getValueAsDef("ProvidesF128"));
+ ProvidesPPCF128 =
+ ProvideMap.lookup(Def->getValueAsDef("ProvidesPPCF128"));
+ }
}
~RuntimeLibcallImpl() = default;
@@ -123,6 +133,12 @@ class RuntimeLibcallImpl {
const RuntimeLibcall *getProvides() const { return Provides; }
+ bool isLongDouble() const { return ProvidesF80 != nullptr; }
+
+ const RuntimeLibcall *getProvidesF80() const { return ProvidesF80; }
+ const RuntimeLibcall *getProvidesF128() const { return ProvidesF128; }
+ const RuntimeLibcall *getProvidesPPCF128() const { return ProvidesPPCF128; }
+
StringRef getLibcallFuncName() const {
return TheDef->getValueAsString("LibCallFuncName");
}
diff --git a/llvm/utils/TableGen/Basic/RuntimeLibcallsEmitter.cpp b/llvm/utils/TableGen/Basic/RuntimeLibcallsEmitter.cpp
index fc7db67120317a..acc06ac12606cf 100644
--- a/llvm/utils/TableGen/Basic/RuntimeLibcallsEmitter.cpp
+++ b/llvm/utils/TableGen/Basic/RuntimeLibcallsEmitter.cpp
@@ -459,15 +459,41 @@ const uint8_t RTLIB::RuntimeLibcallsInfo::RuntimeLibcallNameSizeTable[] = {
for (const RuntimeLibcallImpl &LibCallImpl :
Libcalls.getRuntimeLibcallImplDefList()) {
- const RuntimeLibcall *Provides = LibCallImpl.getProvides();
OS << " ";
- Provides->emitEnumEntry(OS);
+ if (const RuntimeLibcall *Provides = LibCallImpl.getProvides())
+ Provides->emitEnumEntry(OS);
+ else
+ OS << "RTLIB::UNKNOWN_LIBCALL";
OS << ", // ";
LibCallImpl.emitEnumEntry(OS);
OS << '\n';
}
OS << "};\n\n";
+
+ OS << "RTLIB::Libcall llvm::RTLIB::RuntimeLibcallsInfo::getLibcallFromImpl("
+ "RTLIB::LibcallImpl Impl) const {\n"
+ " switch (Impl) {\n";
+ for (const RuntimeLibcallImpl &LibCallImpl :
+ Libcalls.getRuntimeLibcallImplDefList()) {
+ if (!LibCallImpl.isLongDouble())
+ continue;
+
+ OS << " case ";
+ LibCallImpl.emitEnumEntry(OS);
+ OS << ":\n return selectLongDoubleLibcall(";
+ LibCallImpl.getProvidesF80()->emitEnumEntry(OS);
+ OS << ", ";
+ LibCallImpl.getProvidesF128()->emitEnumEntry(OS);
+ OS << ", ";
+ LibCallImpl.getProvidesPPCF128()->emitEnumEntry(OS);
+ OS << ");\n";
+ }
+
+ OS << " default:\n"
+ " return ImplToLibcall[Impl];\n"
+ " }\n"
+ "}\n\n";
}
emitNameMatchHashTable(OS, Table);
@@ -614,13 +640,11 @@ void RuntimeLibcallEmitter::emitPredicateGroups(
// Records which impls are available, not which is selected, so a libcall
// may have more than one. Order is irrelevant (each entry is a setAvailable
- // call); sort by the provided libcall, breaking ties on the impl enum for a
- // deterministic total order.
- llvm::sort(Funcs, [](const RuntimeLibcallImpl *A,
- const RuntimeLibcallImpl *B) {
- return std::make_pair(A->getProvides()->getEnumVal(), A->getEnumVal()) <
- std::make_pair(B->getProvides()->getEnumVal(), B->getEnumVal());
- });
+ // call); sort by the impl enum for a deterministic order.
+ llvm::sort(Funcs,
+ [](const RuntimeLibcallImpl *A, const RuntimeLibcallImpl *B) {
+ return A->getEnumVal() < B->getEnumVal();
+ });
OS << indent(IndentDepth + 2)
<< "static const RTLIB::LibcallImpl LibraryCalls";
More information about the llvm-branch-commits
mailing list