[llvm-branch-commits] [llvm] RuntimeLibcalls: Fix AArch64 wrongly typed long-double libcalls (PR #215993)

Matt Arsenault via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Thu Aug 13 02:12:27 PDT 2026


https://github.com/arsenm created https://github.com/llvm/llvm-project/pull/215993

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>

>From 42fb82794f91a347763e2eb1549435143adcfabe 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 ffbe89a6d1b8c..eb908b1cef0d2 100644
--- a/llvm/include/llvm/IR/RuntimeLibcalls.td
+++ b/llvm/include/llvm/IR/RuntimeLibcalls.td
@@ -2202,12 +2202,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>,
@@ -2215,7 +2223,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..901e838105088
--- /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=GNU %s
+
+; fp128 exp10 lowers to exp10l where long double is fp128, and diagnoses a
+; missing libcall (instead of crashing) 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
+; RUN: not llc -mtriple=aarch64-linux-android -filetype=null %s 2>&1 | FileCheck -check-prefix=ERR %s
+
+; ERR: error: no libcall available for fexp10
+
+define fp128 @test_exp10_f128(fp128 %x) {
+; GNU-LABEL: test_exp10_f128:
+; GNU:       // %bb.0:
+; GNU-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..3eef6e7dda0ef
--- /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=GNU %s
+
+; fp128 frexp lowers to frexpl where long double is fp128, 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
+; RUN: not llc -mtriple=aarch64-linux-android -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 {
+; GNU-LABEL: test_frexp_f128_i32:
+; GNU:       // %bb.0:
+; GNU-NEXT:    str x30, [sp, #-16]! // 8-byte Folded Spill
+; GNU-NEXT:    add x0, sp, #12
+; GNU-NEXT:    bl frexpl
+; GNU-NEXT:    ldr w0, [sp, #12]
+; GNU-NEXT:    ldr x30, [sp], #16 // 8-byte Folded Reload
+; GNU-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..9b715591fa710
--- /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=GNU %s
+
+; fp128 ldexp lowers to ldexpl where long double is fp128, 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
+; RUN: not llc -mtriple=aarch64-linux-android -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) {
+; GNU-LABEL: test_ldexp_f128_i32:
+; GNU:       // %bb.0:
+; GNU-NEXT:    b ldexpl
+  %call = tail call fp128 @llvm.ldexp.f128.i32(fp128 %val, i32 %a)
+  ret fp128 %call
+}



More information about the llvm-branch-commits mailing list