[llvm] RuntimeLibcalls: Fix AArch64 wrongly typed long-double libcalls (PR #215993)
Matt Arsenault via llvm-commits
llvm-commits at lists.llvm.org
Fri Aug 14 15:51:37 PDT 2026
https://github.com/arsenm updated https://github.com/llvm/llvm-project/pull/215993
>From 901417e17f402adff8a00756b25c8143e9c6c3d7 Mon Sep 17 00:00:00 2001
From: Matt Arsenault <Matthew.Arsenault at amd.com>
Date: Sat, 8 Aug 2026 17:51:04 +0200
Subject: [PATCH] RuntimeLibcalls: Fix AArch64 wrongly typed long-double
libcalls
Respect the triple's LongDoubleFormat.
AArch64SystemLibrary added the fp128-typed frexpl/ldexpl and exp10l without a
long-double-format guard, so triples where long double is IEEE double
(Darwin, Windows, Android) were emitting l suffixed calls with the wrong
type.
Co-authored-by: Claude (Claude-Opus-4.8) <noreply at anthropic.com>
---
llvm/include/llvm/IR/RuntimeLibcalls.td | 14 ++++++++++++--
llvm/test/CodeGen/AArch64/exp10-f128.ll | 19 +++++++++++++++++++
llvm/test/CodeGen/AArch64/frexp-f128.ll | 24 ++++++++++++++++++++++++
llvm/test/CodeGen/AArch64/ldexp-f128.ll | 19 +++++++++++++++++++
4 files changed, 74 insertions(+), 2 deletions(-)
create mode 100644 llvm/test/CodeGen/AArch64/exp10-f128.ll
create mode 100644 llvm/test/CodeGen/AArch64/frexp-f128.ll
create mode 100644 llvm/test/CodeGen/AArch64/ldexp-f128.ll
diff --git a/llvm/include/llvm/IR/RuntimeLibcalls.td b/llvm/include/llvm/IR/RuntimeLibcalls.td
index 2146ba42a3eb8..79bc7418f4027 100644
--- a/llvm/include/llvm/IR/RuntimeLibcalls.td
+++ b/llvm/include/llvm/IR/RuntimeLibcalls.td
@@ -2201,12 +2201,20 @@ defvar AArch64LongDoubleF128Body =
!listremove(DefaultRuntimeLibcallImpls_longdouble_f128,
[frexpl_f128, ldexpl_f128, exp10l_f128]);
+// fp128 long double, excluding the Windows math runtime (which lacks frexpl/
+// ldexpl) and Darwin (which lacks exp10l).
+def isLongDoubleF128NotWinMath : RuntimeLibcallAvailability<
+ (all_of IsLongDoubleF128, (any_of (not IsOSWindows), IsOSCygMing))>;
+def isLongDoubleF128NotDarwin : RuntimeLibcallAvailability<
+ (all_of IsLongDoubleF128, (not IsOSDarwin))>;
+
def AArch64SystemLibrary : SystemRuntimeLibrary<
isAArch64_ExceptArm64EC,
(add WinDefaultLibcallImpls,
LibcallImpls<(add __powisf2, __powidf2), isNotOSMSVCRT>,
LibmHasFrexpF32, LibmHasLdexpF32,
- LibmHasFrexpF128, LibmHasLdexpF128,
+ // The l-suffixed libm functions are fp128 only when long double is.
+ LibcallImpls<(add frexpl_f128, ldexpl_f128), isLongDoubleF128NotWinMath>,
LibcallImpls<(add AArch64LongDoubleF128Body), isLongDoubleF128>,
AArch64LibcallImpls,
LibcallImpls<(add Int128RTLibcalls), isAArch64_ILP64>,
@@ -2214,7 +2222,9 @@ def AArch64SystemLibrary : SystemRuntimeLibrary<
DarwinExp10, DarwinSinCosStret, DarwinMemsetPattern,
MacOSUnlockedIO,
LibmHasSinCosF32, LibmHasSinCosF64, LibmHasSinCosF128,
- DefaultLibmExp10,
+ LibmHasExp10F32, LibmHasExp10F64,
+ // exp10l is fp128 only when long double is.
+ LibcallImpls<(add exp10l_f128), isLongDoubleF128NotDarwin>,
DefaultStackProtector,
SecurityCheckCookieIfWinMSVC,
LibcallImpls<(add __chkstk), isOSWindows>,
diff --git a/llvm/test/CodeGen/AArch64/exp10-f128.ll b/llvm/test/CodeGen/AArch64/exp10-f128.ll
new file mode 100644
index 0000000000000..e551c52b7def1
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/exp10-f128.ll
@@ -0,0 +1,19 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
+; RUN: llc -mtriple=aarch64-linux-gnu < %s | FileCheck -check-prefix=HAS-FP128 %s
+; RUN: llc -mtriple=aarch64-linux-android < %s | FileCheck -check-prefix=HAS-FP128 %s
+
+; fp128 exp10 lowers to exp10l where long double is fp128 (Linux,
+; including Android), and diagnoses a missing libcall where it is not.
+
+; RUN: not llc -mtriple=aarch64-apple-macosx -filetype=null %s 2>&1 | FileCheck -check-prefix=ERR %s
+; RUN: not llc -mtriple=aarch64-windows-msvc -filetype=null %s 2>&1 | FileCheck -check-prefix=ERR %s
+
+; ERR: error: no libcall available for fexp10
+
+define fp128 @test_exp10_f128(fp128 %x) {
+; HAS-FP128-LABEL: test_exp10_f128:
+; HAS-FP128: // %bb.0:
+; HAS-FP128-NEXT: b exp10l
+ %r = call fp128 @llvm.exp10.f128(fp128 %x)
+ ret fp128 %r
+}
diff --git a/llvm/test/CodeGen/AArch64/frexp-f128.ll b/llvm/test/CodeGen/AArch64/frexp-f128.ll
new file mode 100644
index 0000000000000..5276f501821e8
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/frexp-f128.ll
@@ -0,0 +1,24 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
+; RUN: llc -mtriple=aarch64-linux-gnu < %s | FileCheck -check-prefix=HAS-FP128 %s
+; RUN: llc -mtriple=aarch64-linux-android < %s | FileCheck -check-prefix=HAS-FP128 %s
+
+; fp128 frexp lowers to frexpl where long double is fp128 (Linux, including
+; Android), and diagnoses a missing libcall when it is not.
+
+; RUN: not llc -mtriple=aarch64-apple-macosx -filetype=null %s 2>&1 | FileCheck -check-prefix=ERR %s
+; RUN: not llc -mtriple=aarch64-windows-msvc -filetype=null %s 2>&1 | FileCheck -check-prefix=ERR %s
+
+; ERR: error: no libcall available for ffrexp
+
+define { fp128, i32 } @test_frexp_f128_i32(fp128 %a) nounwind {
+; HAS-FP128-LABEL: test_frexp_f128_i32:
+; HAS-FP128: // %bb.0:
+; HAS-FP128-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill
+; HAS-FP128-NEXT: add x0, sp, #12
+; HAS-FP128-NEXT: bl frexpl
+; HAS-FP128-NEXT: ldr w0, [sp, #12]
+; HAS-FP128-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload
+; HAS-FP128-NEXT: ret
+ %call = call { fp128, i32 } @llvm.frexp.f128.i32(fp128 %a)
+ ret { fp128, i32 } %call
+}
diff --git a/llvm/test/CodeGen/AArch64/ldexp-f128.ll b/llvm/test/CodeGen/AArch64/ldexp-f128.ll
new file mode 100644
index 0000000000000..62b34afb0e179
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/ldexp-f128.ll
@@ -0,0 +1,19 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
+; RUN: llc -mtriple=aarch64-linux-gnu < %s | FileCheck -check-prefix=HAS-FP128 %s
+; RUN: llc -mtriple=aarch64-linux-android < %s | FileCheck -check-prefix=HAS-FP128 %s
+
+; fp128 ldexp lowers to ldexpl where long double is fp128 (Linux, including
+; Android), and diagnoses a missing libcall where it is not.
+
+; RUN: not llc -mtriple=aarch64-apple-macosx -filetype=null %s 2>&1 | FileCheck -check-prefix=ERR %s
+; RUN: not llc -mtriple=aarch64-windows-msvc -filetype=null %s 2>&1 | FileCheck -check-prefix=ERR %s
+
+; ERR: error: no libcall available for fldexp
+
+define fp128 @test_ldexp_f128_i32(fp128 %val, i32 %a) {
+; HAS-FP128-LABEL: test_ldexp_f128_i32:
+; HAS-FP128: // %bb.0:
+; HAS-FP128-NEXT: b ldexpl
+ %call = tail call fp128 @llvm.ldexp.f128.i32(fp128 %val, i32 %a)
+ ret fp128 %call
+}
More information about the llvm-commits
mailing list