[llvm] RuntimeLibcalls: Fix wrongly typed x87/fp128 long double libcalls on x86 (PR #216979)
Matt Arsenault via llvm-commits
llvm-commits at lists.llvm.org
Tue Aug 18 08:47:32 PDT 2026
https://github.com/arsenm updated https://github.com/llvm/llvm-project/pull/216979
>From f0c96e77115e583bf9137495261fa0e94be50113 Mon Sep 17 00:00:00 2001
From: Matt Arsenault <Matthew.Arsenault at amd.com>
Date: Fri, 14 Aug 2026 17:51:57 +0200
Subject: [PATCH 1/3] RuntimeLibcalls: Fix wrongly typed x87/fp128 long double
libcalls on x86
The x86 and default libcall sets gated the l-suffixed long double libm
functions on OS conditions rather than the long double format. This
incorrectly provided the f80 libcalls on targets whose long double is not x87
(Windows-MSVC, UEFI, x86_64 Android), double-provided frexpl/ldexpl on musl,
and provided the fp128 sincosl on targets using double as long double (m68k).
Gate the l-suffixed libm math on the long double format, mirroring the earlier
AArch64 fix: x87 targets get the _f80 calls, fp128 targets the _f128 calls, and
double targets neither. The compiler-rt f80 helpers (__extendxftf2, __fixxfti,
__powixf2, ...) are keyed to the x86_fp80 IR type, not the long double format,
so they stay unconditional on x86.
Co-authored-by: Claude (Opus 4.8) <noreply at anthropic.com>
---
llvm/include/llvm/IR/RuntimeLibcalls.td | 61 ++-
.../CodeGen/Generic/fp128-exp10-libcall.ll | 7 +-
llvm/test/CodeGen/X86/finite-libcalls.ll | 359 -----------------
.../CodeGen/X86/fp128-libcalls-longdouble.ll | 9 +
llvm/test/CodeGen/X86/fp80-conv-libcalls.ll | 146 +++++++
llvm/test/CodeGen/X86/fp80-math-libcalls.ll | 374 ++++++++++++++++++
.../CodeGen/X86/fp80-math-no-libcall-error.ll | 92 +++++
llvm/test/CodeGen/X86/ldexp-avx512.ll | 17 +-
8 files changed, 681 insertions(+), 384 deletions(-)
create mode 100644 llvm/test/CodeGen/X86/fp80-conv-libcalls.ll
create mode 100644 llvm/test/CodeGen/X86/fp80-math-libcalls.ll
create mode 100644 llvm/test/CodeGen/X86/fp80-math-no-libcall-error.ll
diff --git a/llvm/include/llvm/IR/RuntimeLibcalls.td b/llvm/include/llvm/IR/RuntimeLibcalls.td
index 1176b9b5d1a5a..8cbb3231571ac 100644
--- a/llvm/include/llvm/IR/RuntimeLibcalls.td
+++ b/llvm/include/llvm/IR/RuntimeLibcalls.td
@@ -60,6 +60,7 @@ def IsEABI4 : LibcallPredicate<[{EABIVersion == EABI::EABI4}]>;
def IsEABI5 : LibcallPredicate<[{EABIVersion == EABI::EABI5}]>;
def IsLongDoubleF128 : LibcallPredicate<[{LongDoubleFormat == LongDoubleFormat::IEEEquad}]>;
+def IsLongDoubleX87 : LibcallPredicate<[{LongDoubleFormat == LongDoubleFormat::X87DoubleExtended}]>;
def IsAMDGPU : LibcallPredicate<[{TT.isAMDGPU()}]>;
def IsARM : LibcallPredicate<[{TT.isARM()}]>;
@@ -114,6 +115,21 @@ def isNotOSOpenBSD : RuntimeLibcallAvailability<(not IsOSOpenBSD)>;
// True when the C `long double` type is IEEE fp128.
def isLongDoubleF128 : RuntimeLibcallAvailability<(all_of IsLongDoubleF128)>;
+// True when the C `long double` type is the x87 80-bit extended format.
+def isLongDoubleX87 : RuntimeLibcallAvailability<(all_of IsLongDoubleX87)>;
+
+// x87 long double variants of sincosl/exp10l, which additionally depend on
+// the libc providing the sincos/exp10 extensions.
+def isLongDoubleX87AndHasSinCos : RuntimeLibcallAvailability<
+ (all_of IsLongDoubleX87, (any_of IsGNUEnv, IsOSFuchsia, IsAndroid))>;
+def isLongDoubleX87AndHasExp10 : RuntimeLibcallAvailability<
+ (all_of IsLongDoubleX87, (not IsOSDarwin))>;
+
+// fp128 long double sincosl, which additionally depends on the libc
+// providing the sincos extension.
+def isLongDoubleF128AndHasSinCos : RuntimeLibcallAvailability<
+ (all_of IsLongDoubleF128, (any_of IsGNUEnv, IsOSFuchsia, IsAndroid))>;
+
def isOSWindows : RuntimeLibcallAvailability<(all_of IsOSWindows)>;
def isNotOSWindows : RuntimeLibcallAvailability<(not IsOSWindows)>;
def isNotOSLinux : RuntimeLibcallAvailability<(not IsOSLinux)>;
@@ -1986,6 +2002,17 @@ defvar DefaultRuntimeLibcallImpls_f80 =
!filter(entry, AllDefaultRuntimeLibcallImpls,
!match(!cast<string>(entry.Provides), "F80"));
+// The l-suffixed libm math functions, only correct when long double is x87.
+defvar DefaultRuntimeLibcallImpls_longdouble_f80 =
+ !filter(entry, AllDefaultRuntimeLibcallImpls,
+ !match(!cast<string>(entry), "l_f80"));
+
+// The compiler-rt helpers, keyed to the x86_fp80 IR type and available on all
+// x86 regardless of the long double format.
+defvar DefaultRuntimeLibcallImpls_f80_helpers =
+ !listremove(DefaultRuntimeLibcallImpls_f80,
+ DefaultRuntimeLibcallImpls_longdouble_f80);
+
defvar DefaultRuntimeLibcallImpls_ppcf128 =
!filter(entry, AllDefaultRuntimeLibcallImpls,
!match(!cast<string>(entry.Provides), "PPCF128"));
@@ -2046,13 +2073,11 @@ defvar SecurityCheckCookieIfWinMSVC =
defvar LibmHasSinCosF32 = LibcallImpls<(add sincosf), hasSinCos>;
defvar LibmHasSinCosF64 = LibcallImpls<(add sincos), hasSinCos>;
-defvar LibmHasSinCosF80 = LibcallImpls<(add sincosl_f80), hasSinCos>;
defvar LibmHasSinCosF128 = LibcallImpls<(add sincosl_f128), hasSinCos>;
defvar LibmHasSinCosPPCF128 = LibcallImpls<(add sincosl_ppcf128), hasSinCos>;
defvar LibmHasExp10F32 = LibcallImpls<(add exp10f), hasExp10>;
defvar LibmHasExp10F64 = LibcallImpls<(add exp10), hasExp10>;
-defvar LibmHasExp10F80 = LibcallImpls<(add exp10l_f80), hasExp10>;
defvar LibmHasExp10F128 = LibcallImpls<(add exp10l_f128), hasExp10>;
defvar LibmHasExp10PPCF128 = LibcallImpls<(add exp10l_ppcf128), hasExp10>;
@@ -2081,9 +2106,6 @@ defvar WinDefaultLibcallImpls = (add WinDefaultLibcallImplsBaseList,
defvar LibmHasFrexpF32 = LibcallImpls<(add frexpf), isNotOSWindowsOrIsCygwinMinGW>;
defvar LibmHasLdexpF32 = LibcallImpls<(add ldexpf), isNotOSWindowsOrIsCygwinMinGW>;
-defvar LibmHasFrexpF80 = LibcallImpls<(add frexpl_f80), isNotOSWindowsOrIsCygwinMinGW>;
-defvar LibmHasLdexpF80 = LibcallImpls<(add ldexpl_f80), isNotOSWindowsOrIsCygwinMinGW>;
-
defvar LibmHasFrexpF128 = LibcallImpls<(add frexpl_f128), isNotOSWindowsOrIsCygwinMinGW>;
defvar LibmHasLdexpF128 = LibcallImpls<(add ldexpl_f128), isNotOSWindowsOrIsCygwinMinGW>;
@@ -3410,9 +3432,11 @@ def isWin64NotCygMing : RuntimeLibcallAvailability<
def darwinHas__bzero : RuntimeLibcallAvailability<
(all_of IsMacOSX, MacOSXVersionAtLeast<10, 6>)>;
-// FIXME: This is has ldexpl/frexpl plus use f128 for long double.
-def hasExpFrexplLdexplF128 : RuntimeLibcallAvailability<
- (all_of (any_of (not IsOSWindows), IsOSCygMing), (not IsGNUEnv))>;
+// frexpl_f80/ldexpl_f80/exp10l_f80 are added separately with their own
+// libc-availability guards, so drop them from the bulk x87 body.
+defvar X86LongDoubleF80Body =
+ !listremove(DefaultRuntimeLibcallImpls_longdouble_f80,
+ [frexpl_f80, ldexpl_f80, exp10l_f80]);
// Use the f128 variants of math functions on x86
defvar X86_F128_Libcalls = LibcallImpls<(add LibmF128Libcalls, LibmF128FiniteLibcalls), isGNUEnvironment>;
@@ -3430,18 +3454,19 @@ defvar X86CommonLibcalls =
(add (sub WinDefaultLibcallImpls, WindowsDivRemMulLibcallOverrides, MemChkLibcalls),
DarwinSinCosStret, DarwinExp10, DarwinMemsetPattern, MacOSUnlockedIO,
X86_F128_Libcalls,
- LibmHasSinCosF80, // FIXME: Depends on long double
+ LibcallImpls<(add sincosl_f80), isLongDoubleX87AndHasSinCos>,
SinCosF32F64Libcalls,
LibcallImpls<(add __bzero), darwinHas__bzero>,
LibmHasFrexpF32, LibmHasLdexpF32,
- LibmHasFrexpF80, LibmHasLdexpF80,
- LibcallImpls<(add frexpl_f128, ldexpl_f128, exp10l_f128), hasExpFrexplLdexplF128>,
- // The l-suffixed long double math is fp128 only when long double is fp128
- // (e.g. x86_64 Android/OHOS). frexpl/ldexpl/exp10l are added above.
+ LibcallImpls<(add frexpl_f80, ldexpl_f80), isLongDoubleX87>,
+ LibcallImpls<(add X86LongDoubleF80Body), isLongDoubleX87>,
+ // The x86_fp80 compiler-rt helpers are format-independent.
+ DefaultRuntimeLibcallImpls_f80_helpers,
+ LibcallImpls<(add frexpl_f128, ldexpl_f128, exp10l_f128), isLongDoubleF128>,
LibcallImpls<(add X86LongDoubleF128Body), isLongDoubleF128>,
- DefaultRuntimeLibcallImpls_f80,
- LibmHasExp10F32, LibmHasExp10F64, LibmHasExp10F80,
- LibcallImpls<(add MostPowI), isNotOSMSVCRT>,
+ LibmHasExp10F32, LibmHasExp10F64,
+ LibcallImpls<(add exp10l_f80), isLongDoubleX87AndHasExp10>,
+ LibcallImpls<(add __powisf2, __powidf2), isNotOSMSVCRT>,
SecurityCheckCookieIfWinMSVC,
// FIXME: MSVCRT doesn't have powi. The f128 case is added as a
// hack for one test relying on it.
@@ -3630,7 +3655,9 @@ def isArch64Bit : RuntimeLibcallAvailability<(all_of IsArch64Bit)>;
def LegacyDefaultSystemLibrary
: SystemRuntimeLibrary<isDefaultLibcallArch,
(add DefaultRuntimeLibcallImpls,
- LibmHasSinCosF32, LibmHasSinCosF64, LibmHasSinCosF128,
+ LibmHasSinCosF32, LibmHasSinCosF64,
+ // sincosl is fp128 only when long double is fp128.
+ LibcallImpls<(add sincosl_f128), isLongDoubleF128AndHasSinCos>,
exp10f, exp10, exp10l_f128,
__powisf2, __powidf2, __powitf2_f128,
LibcallImpls<(add Int128RTLibcalls), isArch64Bit>,
diff --git a/llvm/test/CodeGen/Generic/fp128-exp10-libcall.ll b/llvm/test/CodeGen/Generic/fp128-exp10-libcall.ll
index 54ac792da1374..934dc230370b8 100644
--- a/llvm/test/CodeGen/Generic/fp128-exp10-libcall.ll
+++ b/llvm/test/CodeGen/Generic/fp128-exp10-libcall.ll
@@ -10,14 +10,17 @@
; RUN: %if riscv-registered-target %{ llc < %s -mtriple=riscv32-unknown-linux-gnu | FileCheck %s --check-prefixes=CHECK-ALL,CHECK-USELD %}
; RUN: %if systemz-registered-target %{ llc < %s -mtriple=s390x-unknown-linux-gnu | FileCheck %s --check-prefixes=CHECK-ALL,CHECK-S390X %}
; RUN: %if x86-registered-target %{ llc < %s -mtriple=i686-unknown-linux-gnu | FileCheck %s --check-prefixes=CHECK-ALL,CHECK-F128 %}
-; RUN: %if x86-registered-target %{ llc < %s -mtriple=i686-unknown-linux-musl | FileCheck %s --check-prefixes=CHECK-ALL,CHECK-USELD %}
+; RUN: %if x86-registered-target %{ not llc -mtriple=i686-unknown-linux-musl -filetype=null %s 2>&1 | FileCheck --check-prefix=ERR %s %}
; RUN: %if x86-registered-target %{ llc < %s -mtriple=x86_64-unknown-linux-gnu | FileCheck %s --check-prefixes=CHECK-ALL,CHECK-F128 %}
-; RUN: %if x86-registered-target %{ llc < %s -mtriple=x86_64-unknown-linux-musl | FileCheck %s --check-prefixes=CHECK-ALL,CHECK-USELD %}
+; RUN: %if x86-registered-target %{ not llc -mtriple=x86_64-unknown-linux-musl -filetype=null %s 2>&1 | FileCheck --check-prefix=ERR %s %}
; FIXME(#144006): Windows-MSVC should also be run but has a ldexp selection failure.
; %if x86-registered-target %{ llc < %s -mtriple=x86_64-pc-windows-msvc | FileCheck %s --check-prefixes=CHECK-ALL,CHECK-F128 %}
; %if aarch64-registered-target %{ llc < %s -mtriple=arm64ec-pc-windows-msvc | FileCheck %s --check-prefixes=CHECK-ALL,CHECK-F128 %}
+; x86 musl has x87 long double, so it provides neither exp10l_f128 (fp128 long
+; double) nor exp10f128 (a glibc _Float128 function), and must diagnose instead.
+
; ERR: error: no libcall available for fexp10
define fp128 @test_exp10(fp128 %a) {
; CHECK-ALL-LABEL: test_exp10:
diff --git a/llvm/test/CodeGen/X86/finite-libcalls.ll b/llvm/test/CodeGen/X86/finite-libcalls.ll
index acc7ddeb9a886..a28d87cf5ba96 100644
--- a/llvm/test/CodeGen/X86/finite-libcalls.ll
+++ b/llvm/test/CodeGen/X86/finite-libcalls.ll
@@ -75,63 +75,6 @@ define double @exp_f64(double %x) #0 {
ret double %r
}
-define x86_fp80 @exp_f80(x86_fp80 %x) #0 {
-; GNU-LABEL: exp_f80:
-; GNU: # %bb.0:
-; GNU-NEXT: subq $24, %rsp
-; GNU-NEXT: fldt {{[0-9]+}}(%rsp)
-; GNU-NEXT: fstpt (%rsp)
-; GNU-NEXT: callq expl at PLT
-; GNU-NEXT: addq $24, %rsp
-; GNU-NEXT: retq
-;
-; WIN-LABEL: exp_f80:
-; WIN: # %bb.0:
-; WIN-NEXT: pushq %rsi
-; WIN-NEXT: subq $64, %rsp
-; WIN-NEXT: movq %rcx, %rsi
-; WIN-NEXT: fldt (%rdx)
-; WIN-NEXT: fstpt {{[0-9]+}}(%rsp)
-; WIN-NEXT: leaq {{[0-9]+}}(%rsp), %rcx
-; WIN-NEXT: leaq {{[0-9]+}}(%rsp), %rdx
-; WIN-NEXT: callq expl
-; WIN-NEXT: fldt {{[0-9]+}}(%rsp)
-; WIN-NEXT: fstpt (%rsi)
-; WIN-NEXT: movq %rsi, %rax
-; WIN-NEXT: addq $64, %rsp
-; WIN-NEXT: popq %rsi
-; WIN-NEXT: retq
-;
-; MAC-LABEL: exp_f80:
-; MAC: ## %bb.0:
-; MAC-NEXT: subq $24, %rsp
-; MAC-NEXT: fldt {{[0-9]+}}(%rsp)
-; MAC-NEXT: fstpt (%rsp)
-; MAC-NEXT: callq _expl
-; MAC-NEXT: addq $24, %rsp
-; MAC-NEXT: retq
-;
-; GISEL-X86-LABEL: exp_f80:
-; GISEL-X86: # %bb.0:
-; GISEL-X86-NEXT: subl $12, %esp
-; GISEL-X86-NEXT: fldt {{[0-9]+}}(%esp)
-; GISEL-X86-NEXT: fstpt (%esp)
-; GISEL-X86-NEXT: calll expl
-; GISEL-X86-NEXT: addl $12, %esp
-; GISEL-X86-NEXT: retl
-;
-; GISEL-X64-LABEL: exp_f80:
-; GISEL-X64: # %bb.0:
-; GISEL-X64-NEXT: subq $24, %rsp
-; GISEL-X64-NEXT: fldt {{[0-9]+}}(%rsp)
-; GISEL-X64-NEXT: fstpt (%rsp)
-; GISEL-X64-NEXT: callq expl
-; GISEL-X64-NEXT: addq $24, %rsp
-; GISEL-X64-NEXT: retq
- %r = tail call nnan ninf x86_fp80 @llvm.exp.f80(x86_fp80 %x)
- ret x86_fp80 %r
-}
-
define float @exp2_f32(float %x) #0 {
; GNU-LABEL: exp2_f32:
; GNU: # %bb.0:
@@ -199,63 +142,6 @@ define double @exp2_f64(double %x) #0 {
ret double %r
}
-define x86_fp80 @exp2_f80(x86_fp80 %x) #0 {
-; GNU-LABEL: exp2_f80:
-; GNU: # %bb.0:
-; GNU-NEXT: subq $24, %rsp
-; GNU-NEXT: fldt {{[0-9]+}}(%rsp)
-; GNU-NEXT: fstpt (%rsp)
-; GNU-NEXT: callq exp2l at PLT
-; GNU-NEXT: addq $24, %rsp
-; GNU-NEXT: retq
-;
-; WIN-LABEL: exp2_f80:
-; WIN: # %bb.0:
-; WIN-NEXT: pushq %rsi
-; WIN-NEXT: subq $64, %rsp
-; WIN-NEXT: movq %rcx, %rsi
-; WIN-NEXT: fldt (%rdx)
-; WIN-NEXT: fstpt {{[0-9]+}}(%rsp)
-; WIN-NEXT: leaq {{[0-9]+}}(%rsp), %rcx
-; WIN-NEXT: leaq {{[0-9]+}}(%rsp), %rdx
-; WIN-NEXT: callq exp2l
-; WIN-NEXT: fldt {{[0-9]+}}(%rsp)
-; WIN-NEXT: fstpt (%rsi)
-; WIN-NEXT: movq %rsi, %rax
-; WIN-NEXT: addq $64, %rsp
-; WIN-NEXT: popq %rsi
-; WIN-NEXT: retq
-;
-; MAC-LABEL: exp2_f80:
-; MAC: ## %bb.0:
-; MAC-NEXT: subq $24, %rsp
-; MAC-NEXT: fldt {{[0-9]+}}(%rsp)
-; MAC-NEXT: fstpt (%rsp)
-; MAC-NEXT: callq _exp2l
-; MAC-NEXT: addq $24, %rsp
-; MAC-NEXT: retq
-;
-; GISEL-X86-LABEL: exp2_f80:
-; GISEL-X86: # %bb.0:
-; GISEL-X86-NEXT: subl $12, %esp
-; GISEL-X86-NEXT: fldt {{[0-9]+}}(%esp)
-; GISEL-X86-NEXT: fstpt (%esp)
-; GISEL-X86-NEXT: calll exp2l
-; GISEL-X86-NEXT: addl $12, %esp
-; GISEL-X86-NEXT: retl
-;
-; GISEL-X64-LABEL: exp2_f80:
-; GISEL-X64: # %bb.0:
-; GISEL-X64-NEXT: subq $24, %rsp
-; GISEL-X64-NEXT: fldt {{[0-9]+}}(%rsp)
-; GISEL-X64-NEXT: fstpt (%rsp)
-; GISEL-X64-NEXT: callq exp2l
-; GISEL-X64-NEXT: addq $24, %rsp
-; GISEL-X64-NEXT: retq
- %r = tail call nnan ninf x86_fp80 @llvm.exp2.f80(x86_fp80 %x)
- ret x86_fp80 %r
-}
-
define float @log_f32(float %x) #0 {
; GNU-LABEL: log_f32:
; GNU: # %bb.0:
@@ -323,63 +209,6 @@ define double @log_f64(double %x) #0 {
ret double %r
}
-define x86_fp80 @log_f80(x86_fp80 %x) #0 {
-; GNU-LABEL: log_f80:
-; GNU: # %bb.0:
-; GNU-NEXT: subq $24, %rsp
-; GNU-NEXT: fldt {{[0-9]+}}(%rsp)
-; GNU-NEXT: fstpt (%rsp)
-; GNU-NEXT: callq logl at PLT
-; GNU-NEXT: addq $24, %rsp
-; GNU-NEXT: retq
-;
-; WIN-LABEL: log_f80:
-; WIN: # %bb.0:
-; WIN-NEXT: pushq %rsi
-; WIN-NEXT: subq $64, %rsp
-; WIN-NEXT: movq %rcx, %rsi
-; WIN-NEXT: fldt (%rdx)
-; WIN-NEXT: fstpt {{[0-9]+}}(%rsp)
-; WIN-NEXT: leaq {{[0-9]+}}(%rsp), %rcx
-; WIN-NEXT: leaq {{[0-9]+}}(%rsp), %rdx
-; WIN-NEXT: callq logl
-; WIN-NEXT: fldt {{[0-9]+}}(%rsp)
-; WIN-NEXT: fstpt (%rsi)
-; WIN-NEXT: movq %rsi, %rax
-; WIN-NEXT: addq $64, %rsp
-; WIN-NEXT: popq %rsi
-; WIN-NEXT: retq
-;
-; MAC-LABEL: log_f80:
-; MAC: ## %bb.0:
-; MAC-NEXT: subq $24, %rsp
-; MAC-NEXT: fldt {{[0-9]+}}(%rsp)
-; MAC-NEXT: fstpt (%rsp)
-; MAC-NEXT: callq _logl
-; MAC-NEXT: addq $24, %rsp
-; MAC-NEXT: retq
-;
-; GISEL-X86-LABEL: log_f80:
-; GISEL-X86: # %bb.0:
-; GISEL-X86-NEXT: subl $12, %esp
-; GISEL-X86-NEXT: fldt {{[0-9]+}}(%esp)
-; GISEL-X86-NEXT: fstpt (%esp)
-; GISEL-X86-NEXT: calll logl
-; GISEL-X86-NEXT: addl $12, %esp
-; GISEL-X86-NEXT: retl
-;
-; GISEL-X64-LABEL: log_f80:
-; GISEL-X64: # %bb.0:
-; GISEL-X64-NEXT: subq $24, %rsp
-; GISEL-X64-NEXT: fldt {{[0-9]+}}(%rsp)
-; GISEL-X64-NEXT: fstpt (%rsp)
-; GISEL-X64-NEXT: callq logl
-; GISEL-X64-NEXT: addq $24, %rsp
-; GISEL-X64-NEXT: retq
- %r = tail call nnan ninf x86_fp80 @llvm.log.f80(x86_fp80 %x)
- ret x86_fp80 %r
-}
-
define float @log2_f32(float %x) #0 {
; GNU-LABEL: log2_f32:
; GNU: # %bb.0:
@@ -447,63 +276,6 @@ define double @log2_f64(double %x) #0 {
ret double %r
}
-define x86_fp80 @log2_f80(x86_fp80 %x) #0 {
-; GNU-LABEL: log2_f80:
-; GNU: # %bb.0:
-; GNU-NEXT: subq $24, %rsp
-; GNU-NEXT: fldt {{[0-9]+}}(%rsp)
-; GNU-NEXT: fstpt (%rsp)
-; GNU-NEXT: callq log2l at PLT
-; GNU-NEXT: addq $24, %rsp
-; GNU-NEXT: retq
-;
-; WIN-LABEL: log2_f80:
-; WIN: # %bb.0:
-; WIN-NEXT: pushq %rsi
-; WIN-NEXT: subq $64, %rsp
-; WIN-NEXT: movq %rcx, %rsi
-; WIN-NEXT: fldt (%rdx)
-; WIN-NEXT: fstpt {{[0-9]+}}(%rsp)
-; WIN-NEXT: leaq {{[0-9]+}}(%rsp), %rcx
-; WIN-NEXT: leaq {{[0-9]+}}(%rsp), %rdx
-; WIN-NEXT: callq log2l
-; WIN-NEXT: fldt {{[0-9]+}}(%rsp)
-; WIN-NEXT: fstpt (%rsi)
-; WIN-NEXT: movq %rsi, %rax
-; WIN-NEXT: addq $64, %rsp
-; WIN-NEXT: popq %rsi
-; WIN-NEXT: retq
-;
-; MAC-LABEL: log2_f80:
-; MAC: ## %bb.0:
-; MAC-NEXT: subq $24, %rsp
-; MAC-NEXT: fldt {{[0-9]+}}(%rsp)
-; MAC-NEXT: fstpt (%rsp)
-; MAC-NEXT: callq _log2l
-; MAC-NEXT: addq $24, %rsp
-; MAC-NEXT: retq
-;
-; GISEL-X86-LABEL: log2_f80:
-; GISEL-X86: # %bb.0:
-; GISEL-X86-NEXT: subl $12, %esp
-; GISEL-X86-NEXT: fldt {{[0-9]+}}(%esp)
-; GISEL-X86-NEXT: fstpt (%esp)
-; GISEL-X86-NEXT: calll log2l
-; GISEL-X86-NEXT: addl $12, %esp
-; GISEL-X86-NEXT: retl
-;
-; GISEL-X64-LABEL: log2_f80:
-; GISEL-X64: # %bb.0:
-; GISEL-X64-NEXT: subq $24, %rsp
-; GISEL-X64-NEXT: fldt {{[0-9]+}}(%rsp)
-; GISEL-X64-NEXT: fstpt (%rsp)
-; GISEL-X64-NEXT: callq log2l
-; GISEL-X64-NEXT: addq $24, %rsp
-; GISEL-X64-NEXT: retq
- %r = tail call nnan ninf x86_fp80 @llvm.log2.f80(x86_fp80 %x)
- ret x86_fp80 %r
-}
-
define float @log10_f32(float %x) #0 {
; GNU-LABEL: log10_f32:
; GNU: # %bb.0:
@@ -571,63 +343,6 @@ define double @log10_f64(double %x) #0 {
ret double %r
}
-define x86_fp80 @log10_f80(x86_fp80 %x) #0 {
-; GNU-LABEL: log10_f80:
-; GNU: # %bb.0:
-; GNU-NEXT: subq $24, %rsp
-; GNU-NEXT: fldt {{[0-9]+}}(%rsp)
-; GNU-NEXT: fstpt (%rsp)
-; GNU-NEXT: callq log10l at PLT
-; GNU-NEXT: addq $24, %rsp
-; GNU-NEXT: retq
-;
-; WIN-LABEL: log10_f80:
-; WIN: # %bb.0:
-; WIN-NEXT: pushq %rsi
-; WIN-NEXT: subq $64, %rsp
-; WIN-NEXT: movq %rcx, %rsi
-; WIN-NEXT: fldt (%rdx)
-; WIN-NEXT: fstpt {{[0-9]+}}(%rsp)
-; WIN-NEXT: leaq {{[0-9]+}}(%rsp), %rcx
-; WIN-NEXT: leaq {{[0-9]+}}(%rsp), %rdx
-; WIN-NEXT: callq log10l
-; WIN-NEXT: fldt {{[0-9]+}}(%rsp)
-; WIN-NEXT: fstpt (%rsi)
-; WIN-NEXT: movq %rsi, %rax
-; WIN-NEXT: addq $64, %rsp
-; WIN-NEXT: popq %rsi
-; WIN-NEXT: retq
-;
-; MAC-LABEL: log10_f80:
-; MAC: ## %bb.0:
-; MAC-NEXT: subq $24, %rsp
-; MAC-NEXT: fldt {{[0-9]+}}(%rsp)
-; MAC-NEXT: fstpt (%rsp)
-; MAC-NEXT: callq _log10l
-; MAC-NEXT: addq $24, %rsp
-; MAC-NEXT: retq
-;
-; GISEL-X86-LABEL: log10_f80:
-; GISEL-X86: # %bb.0:
-; GISEL-X86-NEXT: subl $12, %esp
-; GISEL-X86-NEXT: fldt {{[0-9]+}}(%esp)
-; GISEL-X86-NEXT: fstpt (%esp)
-; GISEL-X86-NEXT: calll log10l
-; GISEL-X86-NEXT: addl $12, %esp
-; GISEL-X86-NEXT: retl
-;
-; GISEL-X64-LABEL: log10_f80:
-; GISEL-X64: # %bb.0:
-; GISEL-X64-NEXT: subq $24, %rsp
-; GISEL-X64-NEXT: fldt {{[0-9]+}}(%rsp)
-; GISEL-X64-NEXT: fstpt (%rsp)
-; GISEL-X64-NEXT: callq log10l
-; GISEL-X64-NEXT: addq $24, %rsp
-; GISEL-X64-NEXT: retq
- %r = tail call nnan ninf x86_fp80 @llvm.log10.f80(x86_fp80 %x)
- ret x86_fp80 %r
-}
-
define float @pow_f32(float %x) #0 {
; GNU-LABEL: pow_f32:
; GNU: # %bb.0:
@@ -708,97 +423,23 @@ define double @pow_f64(double %x) #0 {
ret double %r
}
-define x86_fp80 @pow_f80(x86_fp80 %x) #0 {
-; GNU-LABEL: pow_f80:
-; GNU: # %bb.0:
-; GNU-NEXT: subq $40, %rsp
-; GNU-NEXT: fldt {{[0-9]+}}(%rsp)
-; GNU-NEXT: fld %st(0)
-; GNU-NEXT: fstpt {{[0-9]+}}(%rsp)
-; GNU-NEXT: fstpt (%rsp)
-; GNU-NEXT: callq powl at PLT
-; GNU-NEXT: addq $40, %rsp
-; GNU-NEXT: retq
-;
-; WIN-LABEL: pow_f80:
-; WIN: # %bb.0:
-; WIN-NEXT: pushq %rsi
-; WIN-NEXT: subq $80, %rsp
-; WIN-NEXT: movq %rcx, %rsi
-; WIN-NEXT: fldt (%rdx)
-; WIN-NEXT: fld %st(0)
-; WIN-NEXT: fstpt {{[0-9]+}}(%rsp)
-; WIN-NEXT: fstpt {{[0-9]+}}(%rsp)
-; WIN-NEXT: leaq {{[0-9]+}}(%rsp), %rcx
-; WIN-NEXT: leaq {{[0-9]+}}(%rsp), %rdx
-; WIN-NEXT: leaq {{[0-9]+}}(%rsp), %r8
-; WIN-NEXT: callq powl
-; WIN-NEXT: fldt {{[0-9]+}}(%rsp)
-; WIN-NEXT: fstpt (%rsi)
-; WIN-NEXT: movq %rsi, %rax
-; WIN-NEXT: addq $80, %rsp
-; WIN-NEXT: popq %rsi
-; WIN-NEXT: retq
-;
-; MAC-LABEL: pow_f80:
-; MAC: ## %bb.0:
-; MAC-NEXT: subq $40, %rsp
-; MAC-NEXT: fldt {{[0-9]+}}(%rsp)
-; MAC-NEXT: fld %st(0)
-; MAC-NEXT: fstpt {{[0-9]+}}(%rsp)
-; MAC-NEXT: fstpt (%rsp)
-; MAC-NEXT: callq _powl
-; MAC-NEXT: addq $40, %rsp
-; MAC-NEXT: retq
-;
-; GISEL-X86-LABEL: pow_f80:
-; GISEL-X86: # %bb.0:
-; GISEL-X86-NEXT: subl $28, %esp
-; GISEL-X86-NEXT: fldt {{[0-9]+}}(%esp)
-; GISEL-X86-NEXT: fld %st(0)
-; GISEL-X86-NEXT: fstpt (%esp)
-; GISEL-X86-NEXT: fstpt {{[0-9]+}}(%esp)
-; GISEL-X86-NEXT: calll powl
-; GISEL-X86-NEXT: addl $28, %esp
-; GISEL-X86-NEXT: retl
-;
-; GISEL-X64-LABEL: pow_f80:
-; GISEL-X64: # %bb.0:
-; GISEL-X64-NEXT: subq $40, %rsp
-; GISEL-X64-NEXT: fldt {{[0-9]+}}(%rsp)
-; GISEL-X64-NEXT: fld %st(0)
-; GISEL-X64-NEXT: fstpt (%rsp)
-; GISEL-X64-NEXT: fstpt {{[0-9]+}}(%rsp)
-; GISEL-X64-NEXT: callq powl
-; GISEL-X64-NEXT: addq $40, %rsp
-; GISEL-X64-NEXT: retq
- %r = tail call nnan ninf x86_fp80 @llvm.pow.f80(x86_fp80 %x, x86_fp80 %x)
- ret x86_fp80 %r
-}
-
declare float @llvm.exp.f32(float) #1
declare double @llvm.exp.f64(double) #1
-declare x86_fp80 @llvm.exp.f80(x86_fp80) #1
declare float @llvm.exp2.f32(float) #1
declare double @llvm.exp2.f64(double) #1
-declare x86_fp80 @llvm.exp2.f80(x86_fp80) #1
declare float @llvm.log.f32(float) #1
declare double @llvm.log.f64(double) #1
-declare x86_fp80 @llvm.log.f80(x86_fp80) #1
declare float @llvm.log2.f32(float) #1
declare double @llvm.log2.f64(double) #1
-declare x86_fp80 @llvm.log2.f80(x86_fp80) #1
declare float @llvm.log10.f32(float) #1
declare double @llvm.log10.f64(double) #1
-declare x86_fp80 @llvm.log10.f80(x86_fp80) #1
declare float @llvm.pow.f32(float, float) #1
declare double @llvm.pow.f64(double, double) #1
-declare x86_fp80 @llvm.pow.f80(x86_fp80, x86_fp80) #1
attributes #0 = { nounwind "no-infs-fp-math"="true" "no-nans-fp-math"="true" }
attributes #1 = { nounwind readnone speculatable }
diff --git a/llvm/test/CodeGen/X86/fp128-libcalls-longdouble.ll b/llvm/test/CodeGen/X86/fp128-libcalls-longdouble.ll
index d3020bcbcd961..767da1ee190f1 100644
--- a/llvm/test/CodeGen/X86/fp128-libcalls-longdouble.ll
+++ b/llvm/test/CodeGen/X86/fp128-libcalls-longdouble.ll
@@ -90,9 +90,18 @@ define dso_local void @Test128Rint(fp128 %d1) nounwind {
ret void
}
+define fp128 @Test128Ldexp(fp128 %x, i32 %exp) nounwind {
+; ANDROID-LABEL: Test128Ldexp:
+; ANDROID: # %bb.0:
+; ANDROID-NEXT: jmp ldexpl at PLT # TAILCALL
+ %r = tail call fp128 @llvm.ldexp.f128.i32(fp128 %x, i32 %exp)
+ ret fp128 %r
+}
+
declare fp128 @llvm.maxnum.f128(fp128, fp128)
declare fp128 @llvm.minnum.f128(fp128, fp128)
declare fp128 @llvm.sqrt.f128(fp128)
declare fp128 @llvm.sin.f128(fp128)
declare fp128 @llvm.pow.f128(fp128, fp128)
declare fp128 @llvm.rint.f128(fp128)
+declare fp128 @llvm.ldexp.f128.i32(fp128, i32)
diff --git a/llvm/test/CodeGen/X86/fp80-conv-libcalls.ll b/llvm/test/CodeGen/X86/fp80-conv-libcalls.ll
new file mode 100644
index 0000000000000..9a41d25feb030
--- /dev/null
+++ b/llvm/test/CodeGen/X86/fp80-conv-libcalls.ll
@@ -0,0 +1,146 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
+; RUN: llc -mtriple=x86_64-linux-gnu -mattr=+sse < %s | FileCheck %s --check-prefix=GNU
+; RUN: llc -mtriple=x86_64-linux-android -mattr=+sse < %s | FileCheck %s --check-prefix=ANDROID
+; RUN: llc -mtriple=x86_64-pc-windows-msvc < %s | FileCheck %s --check-prefix=MSVC
+
+; The x86_fp80 compiler-rt helpers are keyed to the IR type, which is legal on
+; all x86 regardless of the long double format, so they are available even when
+; long double is not x87 (IEEE double on windows-msvc, IEEE quad on Android).
+
+define fp128 @test_extend(x86_fp80 %x) nounwind {
+; GNU-LABEL: test_extend:
+; GNU: # %bb.0:
+; GNU-NEXT: jmp __extendxftf2 at PLT # TAILCALL
+;
+; ANDROID-LABEL: test_extend:
+; ANDROID: # %bb.0:
+; ANDROID-NEXT: jmp __extendxftf2 at PLT # TAILCALL
+;
+; MSVC-LABEL: test_extend:
+; MSVC: # %bb.0:
+; MSVC-NEXT: pushq %rsi
+; MSVC-NEXT: subq $64, %rsp
+; MSVC-NEXT: movq %rcx, %rsi
+; MSVC-NEXT: fldt (%rdx)
+; MSVC-NEXT: fstpt {{[0-9]+}}(%rsp)
+; MSVC-NEXT: leaq {{[0-9]+}}(%rsp), %rcx
+; MSVC-NEXT: leaq {{[0-9]+}}(%rsp), %rdx
+; MSVC-NEXT: callq __extendxftf2
+; MSVC-NEXT: movaps {{[0-9]+}}(%rsp), %xmm0
+; MSVC-NEXT: movaps %xmm0, (%rsi)
+; MSVC-NEXT: movq %rsi, %rax
+; MSVC-NEXT: addq $64, %rsp
+; MSVC-NEXT: popq %rsi
+; MSVC-NEXT: retq
+ %r = fpext x86_fp80 %x to fp128
+ ret fp128 %r
+}
+
+define x86_fp80 @test_trunc(fp128 %x) nounwind {
+; GNU-LABEL: test_trunc:
+; GNU: # %bb.0:
+; GNU-NEXT: pushq %rax
+; GNU-NEXT: callq __trunctfxf2 at PLT
+; GNU-NEXT: popq %rax
+; GNU-NEXT: retq
+;
+; ANDROID-LABEL: test_trunc:
+; ANDROID: # %bb.0:
+; ANDROID-NEXT: pushq %rax
+; ANDROID-NEXT: callq __trunctfxf2 at PLT
+; ANDROID-NEXT: popq %rax
+; ANDROID-NEXT: retq
+;
+; MSVC-LABEL: test_trunc:
+; MSVC: # %bb.0:
+; MSVC-NEXT: pushq %rsi
+; MSVC-NEXT: subq $64, %rsp
+; MSVC-NEXT: movq %rcx, %rsi
+; MSVC-NEXT: movaps (%rdx), %xmm0
+; MSVC-NEXT: movaps %xmm0, {{[0-9]+}}(%rsp)
+; MSVC-NEXT: leaq {{[0-9]+}}(%rsp), %rcx
+; MSVC-NEXT: leaq {{[0-9]+}}(%rsp), %rdx
+; MSVC-NEXT: callq __trunctfxf2
+; MSVC-NEXT: fldt {{[0-9]+}}(%rsp)
+; MSVC-NEXT: fstpt (%rsi)
+; MSVC-NEXT: movq %rsi, %rax
+; MSVC-NEXT: addq $64, %rsp
+; MSVC-NEXT: popq %rsi
+; MSVC-NEXT: retq
+ %r = fptrunc fp128 %x to x86_fp80
+ ret x86_fp80 %r
+}
+
+define i128 @test_fptosi(x86_fp80 %x) nounwind {
+; GNU-LABEL: test_fptosi:
+; GNU: # %bb.0:
+; GNU-NEXT: subq $24, %rsp
+; GNU-NEXT: fldt {{[0-9]+}}(%rsp)
+; GNU-NEXT: fstpt (%rsp)
+; GNU-NEXT: callq __fixxfti at PLT
+; GNU-NEXT: addq $24, %rsp
+; GNU-NEXT: retq
+;
+; ANDROID-LABEL: test_fptosi:
+; ANDROID: # %bb.0:
+; ANDROID-NEXT: subq $24, %rsp
+; ANDROID-NEXT: fldt {{[0-9]+}}(%rsp)
+; ANDROID-NEXT: fstpt (%rsp)
+; ANDROID-NEXT: callq __fixxfti at PLT
+; ANDROID-NEXT: addq $24, %rsp
+; ANDROID-NEXT: retq
+;
+; MSVC-LABEL: test_fptosi:
+; MSVC: # %bb.0:
+; MSVC-NEXT: subq $56, %rsp
+; MSVC-NEXT: fldt (%rcx)
+; MSVC-NEXT: fstpt {{[0-9]+}}(%rsp)
+; MSVC-NEXT: leaq {{[0-9]+}}(%rsp), %rcx
+; MSVC-NEXT: callq __fixxfti
+; MSVC-NEXT: movq %xmm0, %rax
+; MSVC-NEXT: pshufd {{.*#+}} xmm0 = xmm0[2,3,2,3]
+; MSVC-NEXT: movq %xmm0, %rdx
+; MSVC-NEXT: addq $56, %rsp
+; MSVC-NEXT: retq
+ %r = fptosi x86_fp80 %x to i128
+ ret i128 %r
+}
+
+define x86_fp80 @test_powi(x86_fp80 %x, i32 %n) nounwind {
+; GNU-LABEL: test_powi:
+; GNU: # %bb.0:
+; GNU-NEXT: subq $24, %rsp
+; GNU-NEXT: fldt {{[0-9]+}}(%rsp)
+; GNU-NEXT: fstpt (%rsp)
+; GNU-NEXT: callq __powixf2 at PLT
+; GNU-NEXT: addq $24, %rsp
+; GNU-NEXT: retq
+;
+; ANDROID-LABEL: test_powi:
+; ANDROID: # %bb.0:
+; ANDROID-NEXT: subq $24, %rsp
+; ANDROID-NEXT: fldt {{[0-9]+}}(%rsp)
+; ANDROID-NEXT: fstpt (%rsp)
+; ANDROID-NEXT: callq __powixf2 at PLT
+; ANDROID-NEXT: addq $24, %rsp
+; ANDROID-NEXT: retq
+;
+; MSVC-LABEL: test_powi:
+; MSVC: # %bb.0:
+; MSVC-NEXT: pushq %rsi
+; MSVC-NEXT: subq $64, %rsp
+; MSVC-NEXT: movq %rcx, %rsi
+; MSVC-NEXT: fldt (%rdx)
+; MSVC-NEXT: fstpt {{[0-9]+}}(%rsp)
+; MSVC-NEXT: leaq {{[0-9]+}}(%rsp), %rcx
+; MSVC-NEXT: leaq {{[0-9]+}}(%rsp), %rdx
+; MSVC-NEXT: callq __powixf2
+; MSVC-NEXT: fldt {{[0-9]+}}(%rsp)
+; MSVC-NEXT: fstpt (%rsi)
+; MSVC-NEXT: movq %rsi, %rax
+; MSVC-NEXT: addq $64, %rsp
+; MSVC-NEXT: popq %rsi
+; MSVC-NEXT: retq
+ %r = call x86_fp80 @llvm.powi.f80.i32(x86_fp80 %x, i32 %n)
+ ret x86_fp80 %r
+}
diff --git a/llvm/test/CodeGen/X86/fp80-math-libcalls.ll b/llvm/test/CodeGen/X86/fp80-math-libcalls.ll
new file mode 100644
index 0000000000000..463b1cf77b01a
--- /dev/null
+++ b/llvm/test/CodeGen/X86/fp80-math-libcalls.ll
@@ -0,0 +1,374 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
+; RUN: llc -mtriple=x86_64-linux-gnu < %s | FileCheck %s --check-prefix=X64
+; RUN: llc -mtriple=i686-linux-gnu < %s | FileCheck %s --check-prefix=X86
+
+; On x87-long-double targets, x86_fp80 math intrinsics lower to the l-suffixed
+; libm long double libcalls. On targets whose long double is not x87 (IEEE
+; double on windows-msvc, IEEE quad on Android) these libm calls are not
+; available for x86_fp80 and are diagnosed instead (see
+; fp80-math-no-libcall-error.ll). The nnan ninf variants confirm the finite-math
+; flags still use the plain l-suffixed libcall (there is no x86_fp80 __*_finite).
+
+define x86_fp80 @test_acos(x86_fp80 %x) nounwind {
+; X64-LABEL: test_acos:
+; X64: # %bb.0:
+; X64-NEXT: subq $24, %rsp
+; X64-NEXT: fldt {{[0-9]+}}(%rsp)
+; X64-NEXT: fstpt (%rsp)
+; X64-NEXT: callq acosl at PLT
+; X64-NEXT: addq $24, %rsp
+; X64-NEXT: retq
+;
+; X86-LABEL: test_acos:
+; X86: # %bb.0:
+; X86-NEXT: subl $12, %esp
+; X86-NEXT: fldt {{[0-9]+}}(%esp)
+; X86-NEXT: fstpt (%esp)
+; X86-NEXT: calll acosl
+; X86-NEXT: addl $12, %esp
+; X86-NEXT: retl
+ %r = call x86_fp80 @llvm.acos.f80(x86_fp80 %x)
+ ret x86_fp80 %r
+}
+
+define x86_fp80 @test_sin(x86_fp80 %x) nounwind {
+; X64-LABEL: test_sin:
+; X64: # %bb.0:
+; X64-NEXT: subq $24, %rsp
+; X64-NEXT: fldt {{[0-9]+}}(%rsp)
+; X64-NEXT: fstpt (%rsp)
+; X64-NEXT: callq sinl at PLT
+; X64-NEXT: addq $24, %rsp
+; X64-NEXT: retq
+;
+; X86-LABEL: test_sin:
+; X86: # %bb.0:
+; X86-NEXT: subl $12, %esp
+; X86-NEXT: fldt {{[0-9]+}}(%esp)
+; X86-NEXT: fstpt (%esp)
+; X86-NEXT: calll sinl
+; X86-NEXT: addl $12, %esp
+; X86-NEXT: retl
+ %r = call x86_fp80 @llvm.sin.f80(x86_fp80 %x)
+ ret x86_fp80 %r
+}
+
+define x86_fp80 @test_pow(x86_fp80 %x, x86_fp80 %y) nounwind {
+; X64-LABEL: test_pow:
+; X64: # %bb.0:
+; X64-NEXT: subq $40, %rsp
+; X64-NEXT: fldt {{[0-9]+}}(%rsp)
+; X64-NEXT: fldt {{[0-9]+}}(%rsp)
+; X64-NEXT: fstpt {{[0-9]+}}(%rsp)
+; X64-NEXT: fstpt (%rsp)
+; X64-NEXT: callq powl at PLT
+; X64-NEXT: addq $40, %rsp
+; X64-NEXT: retq
+;
+; X86-LABEL: test_pow:
+; X86: # %bb.0:
+; X86-NEXT: subl $28, %esp
+; X86-NEXT: fldt {{[0-9]+}}(%esp)
+; X86-NEXT: fldt {{[0-9]+}}(%esp)
+; X86-NEXT: fstpt {{[0-9]+}}(%esp)
+; X86-NEXT: fstpt (%esp)
+; X86-NEXT: calll powl
+; X86-NEXT: addl $28, %esp
+; X86-NEXT: retl
+ %r = call x86_fp80 @llvm.pow.f80(x86_fp80 %x, x86_fp80 %y)
+ ret x86_fp80 %r
+}
+
+define x86_fp80 @test_pow_finite(x86_fp80 %x, x86_fp80 %y) nounwind {
+; X64-LABEL: test_pow_finite:
+; X64: # %bb.0:
+; X64-NEXT: subq $40, %rsp
+; X64-NEXT: fldt {{[0-9]+}}(%rsp)
+; X64-NEXT: fldt {{[0-9]+}}(%rsp)
+; X64-NEXT: fstpt {{[0-9]+}}(%rsp)
+; X64-NEXT: fstpt (%rsp)
+; X64-NEXT: callq powl at PLT
+; X64-NEXT: addq $40, %rsp
+; X64-NEXT: retq
+;
+; X86-LABEL: test_pow_finite:
+; X86: # %bb.0:
+; X86-NEXT: subl $28, %esp
+; X86-NEXT: fldt {{[0-9]+}}(%esp)
+; X86-NEXT: fldt {{[0-9]+}}(%esp)
+; X86-NEXT: fstpt {{[0-9]+}}(%esp)
+; X86-NEXT: fstpt (%esp)
+; X86-NEXT: calll powl
+; X86-NEXT: addl $28, %esp
+; X86-NEXT: retl
+ %r = call nnan ninf x86_fp80 @llvm.pow.f80(x86_fp80 %x, x86_fp80 %y)
+ ret x86_fp80 %r
+}
+
+define x86_fp80 @test_rint(x86_fp80 %x) nounwind {
+; X64-LABEL: test_rint:
+; X64: # %bb.0:
+; X64-NEXT: subq $24, %rsp
+; X64-NEXT: fldt {{[0-9]+}}(%rsp)
+; X64-NEXT: fstpt (%rsp)
+; X64-NEXT: callq rintl at PLT
+; X64-NEXT: addq $24, %rsp
+; X64-NEXT: retq
+;
+; X86-LABEL: test_rint:
+; X86: # %bb.0:
+; X86-NEXT: subl $12, %esp
+; X86-NEXT: fldt {{[0-9]+}}(%esp)
+; X86-NEXT: fstpt (%esp)
+; X86-NEXT: calll rintl
+; X86-NEXT: addl $12, %esp
+; X86-NEXT: retl
+ %r = call x86_fp80 @llvm.rint.f80(x86_fp80 %x)
+ ret x86_fp80 %r
+}
+
+define x86_fp80 @test_maxnum(x86_fp80 %x, x86_fp80 %y) nounwind {
+; X64-LABEL: test_maxnum:
+; X64: # %bb.0:
+; X64-NEXT: subq $40, %rsp
+; X64-NEXT: fldt {{[0-9]+}}(%rsp)
+; X64-NEXT: fldt {{[0-9]+}}(%rsp)
+; X64-NEXT: fstpt {{[0-9]+}}(%rsp)
+; X64-NEXT: fstpt (%rsp)
+; X64-NEXT: callq fmaxl at PLT
+; X64-NEXT: addq $40, %rsp
+; X64-NEXT: retq
+;
+; X86-LABEL: test_maxnum:
+; X86: # %bb.0:
+; X86-NEXT: subl $28, %esp
+; X86-NEXT: fldt {{[0-9]+}}(%esp)
+; X86-NEXT: fldt {{[0-9]+}}(%esp)
+; X86-NEXT: fstpt {{[0-9]+}}(%esp)
+; X86-NEXT: fstpt (%esp)
+; X86-NEXT: calll fmaxl
+; X86-NEXT: addl $28, %esp
+; X86-NEXT: retl
+ %r = call x86_fp80 @llvm.maxnum.f80(x86_fp80 %x, x86_fp80 %y)
+ ret x86_fp80 %r
+}
+
+define x86_fp80 @test_exp(x86_fp80 %x) nounwind {
+; X64-LABEL: test_exp:
+; X64: # %bb.0:
+; X64-NEXT: subq $24, %rsp
+; X64-NEXT: fldt {{[0-9]+}}(%rsp)
+; X64-NEXT: fstpt (%rsp)
+; X64-NEXT: callq expl at PLT
+; X64-NEXT: addq $24, %rsp
+; X64-NEXT: retq
+;
+; X86-LABEL: test_exp:
+; X86: # %bb.0:
+; X86-NEXT: subl $12, %esp
+; X86-NEXT: fldt {{[0-9]+}}(%esp)
+; X86-NEXT: fstpt (%esp)
+; X86-NEXT: calll expl
+; X86-NEXT: addl $12, %esp
+; X86-NEXT: retl
+ %r = call x86_fp80 @llvm.exp.f80(x86_fp80 %x)
+ ret x86_fp80 %r
+}
+
+define x86_fp80 @test_exp_finite(x86_fp80 %x) nounwind {
+; X64-LABEL: test_exp_finite:
+; X64: # %bb.0:
+; X64-NEXT: subq $24, %rsp
+; X64-NEXT: fldt {{[0-9]+}}(%rsp)
+; X64-NEXT: fstpt (%rsp)
+; X64-NEXT: callq expl at PLT
+; X64-NEXT: addq $24, %rsp
+; X64-NEXT: retq
+;
+; X86-LABEL: test_exp_finite:
+; X86: # %bb.0:
+; X86-NEXT: subl $12, %esp
+; X86-NEXT: fldt {{[0-9]+}}(%esp)
+; X86-NEXT: fstpt (%esp)
+; X86-NEXT: calll expl
+; X86-NEXT: addl $12, %esp
+; X86-NEXT: retl
+ %r = call nnan ninf x86_fp80 @llvm.exp.f80(x86_fp80 %x)
+ ret x86_fp80 %r
+}
+
+define x86_fp80 @test_exp2(x86_fp80 %x) nounwind {
+; X64-LABEL: test_exp2:
+; X64: # %bb.0:
+; X64-NEXT: subq $24, %rsp
+; X64-NEXT: fldt {{[0-9]+}}(%rsp)
+; X64-NEXT: fstpt (%rsp)
+; X64-NEXT: callq exp2l at PLT
+; X64-NEXT: addq $24, %rsp
+; X64-NEXT: retq
+;
+; X86-LABEL: test_exp2:
+; X86: # %bb.0:
+; X86-NEXT: subl $12, %esp
+; X86-NEXT: fldt {{[0-9]+}}(%esp)
+; X86-NEXT: fstpt (%esp)
+; X86-NEXT: calll exp2l
+; X86-NEXT: addl $12, %esp
+; X86-NEXT: retl
+ %r = call x86_fp80 @llvm.exp2.f80(x86_fp80 %x)
+ ret x86_fp80 %r
+}
+
+define x86_fp80 @test_exp2_finite(x86_fp80 %x) nounwind {
+; X64-LABEL: test_exp2_finite:
+; X64: # %bb.0:
+; X64-NEXT: subq $24, %rsp
+; X64-NEXT: fldt {{[0-9]+}}(%rsp)
+; X64-NEXT: fstpt (%rsp)
+; X64-NEXT: callq exp2l at PLT
+; X64-NEXT: addq $24, %rsp
+; X64-NEXT: retq
+;
+; X86-LABEL: test_exp2_finite:
+; X86: # %bb.0:
+; X86-NEXT: subl $12, %esp
+; X86-NEXT: fldt {{[0-9]+}}(%esp)
+; X86-NEXT: fstpt (%esp)
+; X86-NEXT: calll exp2l
+; X86-NEXT: addl $12, %esp
+; X86-NEXT: retl
+ %r = call nnan ninf x86_fp80 @llvm.exp2.f80(x86_fp80 %x)
+ ret x86_fp80 %r
+}
+
+define x86_fp80 @test_log(x86_fp80 %x) nounwind {
+; X64-LABEL: test_log:
+; X64: # %bb.0:
+; X64-NEXT: subq $24, %rsp
+; X64-NEXT: fldt {{[0-9]+}}(%rsp)
+; X64-NEXT: fstpt (%rsp)
+; X64-NEXT: callq logl at PLT
+; X64-NEXT: addq $24, %rsp
+; X64-NEXT: retq
+;
+; X86-LABEL: test_log:
+; X86: # %bb.0:
+; X86-NEXT: subl $12, %esp
+; X86-NEXT: fldt {{[0-9]+}}(%esp)
+; X86-NEXT: fstpt (%esp)
+; X86-NEXT: calll logl
+; X86-NEXT: addl $12, %esp
+; X86-NEXT: retl
+ %r = call x86_fp80 @llvm.log.f80(x86_fp80 %x)
+ ret x86_fp80 %r
+}
+
+define x86_fp80 @test_log_finite(x86_fp80 %x) nounwind {
+; X64-LABEL: test_log_finite:
+; X64: # %bb.0:
+; X64-NEXT: subq $24, %rsp
+; X64-NEXT: fldt {{[0-9]+}}(%rsp)
+; X64-NEXT: fstpt (%rsp)
+; X64-NEXT: callq logl at PLT
+; X64-NEXT: addq $24, %rsp
+; X64-NEXT: retq
+;
+; X86-LABEL: test_log_finite:
+; X86: # %bb.0:
+; X86-NEXT: subl $12, %esp
+; X86-NEXT: fldt {{[0-9]+}}(%esp)
+; X86-NEXT: fstpt (%esp)
+; X86-NEXT: calll logl
+; X86-NEXT: addl $12, %esp
+; X86-NEXT: retl
+ %r = call nnan ninf x86_fp80 @llvm.log.f80(x86_fp80 %x)
+ ret x86_fp80 %r
+}
+
+define x86_fp80 @test_log2(x86_fp80 %x) nounwind {
+; X64-LABEL: test_log2:
+; X64: # %bb.0:
+; X64-NEXT: subq $24, %rsp
+; X64-NEXT: fldt {{[0-9]+}}(%rsp)
+; X64-NEXT: fstpt (%rsp)
+; X64-NEXT: callq log2l at PLT
+; X64-NEXT: addq $24, %rsp
+; X64-NEXT: retq
+;
+; X86-LABEL: test_log2:
+; X86: # %bb.0:
+; X86-NEXT: subl $12, %esp
+; X86-NEXT: fldt {{[0-9]+}}(%esp)
+; X86-NEXT: fstpt (%esp)
+; X86-NEXT: calll log2l
+; X86-NEXT: addl $12, %esp
+; X86-NEXT: retl
+ %r = call x86_fp80 @llvm.log2.f80(x86_fp80 %x)
+ ret x86_fp80 %r
+}
+
+define x86_fp80 @test_log2_finite(x86_fp80 %x) nounwind {
+; X64-LABEL: test_log2_finite:
+; X64: # %bb.0:
+; X64-NEXT: subq $24, %rsp
+; X64-NEXT: fldt {{[0-9]+}}(%rsp)
+; X64-NEXT: fstpt (%rsp)
+; X64-NEXT: callq log2l at PLT
+; X64-NEXT: addq $24, %rsp
+; X64-NEXT: retq
+;
+; X86-LABEL: test_log2_finite:
+; X86: # %bb.0:
+; X86-NEXT: subl $12, %esp
+; X86-NEXT: fldt {{[0-9]+}}(%esp)
+; X86-NEXT: fstpt (%esp)
+; X86-NEXT: calll log2l
+; X86-NEXT: addl $12, %esp
+; X86-NEXT: retl
+ %r = call nnan ninf x86_fp80 @llvm.log2.f80(x86_fp80 %x)
+ ret x86_fp80 %r
+}
+
+define x86_fp80 @test_log10(x86_fp80 %x) nounwind {
+; X64-LABEL: test_log10:
+; X64: # %bb.0:
+; X64-NEXT: subq $24, %rsp
+; X64-NEXT: fldt {{[0-9]+}}(%rsp)
+; X64-NEXT: fstpt (%rsp)
+; X64-NEXT: callq log10l at PLT
+; X64-NEXT: addq $24, %rsp
+; X64-NEXT: retq
+;
+; X86-LABEL: test_log10:
+; X86: # %bb.0:
+; X86-NEXT: subl $12, %esp
+; X86-NEXT: fldt {{[0-9]+}}(%esp)
+; X86-NEXT: fstpt (%esp)
+; X86-NEXT: calll log10l
+; X86-NEXT: addl $12, %esp
+; X86-NEXT: retl
+ %r = call x86_fp80 @llvm.log10.f80(x86_fp80 %x)
+ ret x86_fp80 %r
+}
+
+define x86_fp80 @test_log10_finite(x86_fp80 %x) nounwind {
+; X64-LABEL: test_log10_finite:
+; X64: # %bb.0:
+; X64-NEXT: subq $24, %rsp
+; X64-NEXT: fldt {{[0-9]+}}(%rsp)
+; X64-NEXT: fstpt (%rsp)
+; X64-NEXT: callq log10l at PLT
+; X64-NEXT: addq $24, %rsp
+; X64-NEXT: retq
+;
+; X86-LABEL: test_log10_finite:
+; X86: # %bb.0:
+; X86-NEXT: subl $12, %esp
+; X86-NEXT: fldt {{[0-9]+}}(%esp)
+; X86-NEXT: fstpt (%esp)
+; X86-NEXT: calll log10l
+; X86-NEXT: addl $12, %esp
+; X86-NEXT: retl
+ %r = call nnan ninf x86_fp80 @llvm.log10.f80(x86_fp80 %x)
+ ret x86_fp80 %r
+}
diff --git a/llvm/test/CodeGen/X86/fp80-math-no-libcall-error.ll b/llvm/test/CodeGen/X86/fp80-math-no-libcall-error.ll
new file mode 100644
index 0000000000000..a2d69cfe20b87
--- /dev/null
+++ b/llvm/test/CodeGen/X86/fp80-math-no-libcall-error.ll
@@ -0,0 +1,92 @@
+; RUN: not llc -mtriple=x86_64-pc-windows-msvc -filetype=null %s 2>&1 | FileCheck %s
+; RUN: not llc -mtriple=x86_64-linux-android -filetype=null %s 2>&1 | FileCheck %s
+
+; The l-suffixed long double math libcalls only exist when long double is x87.
+; On windows-msvc (IEEE double) and Android (fp128) an x86_fp80 math intrinsic
+; must diagnose a missing libcall rather than emit a wrongly-typed call. The
+; nnan ninf variants confirm the finite-math flags do not route to a different
+; (still missing) libcall.
+
+; CHECK: error: no libcall available for facos
+define x86_fp80 @test_acos(x86_fp80 %x) nounwind {
+ %r = call x86_fp80 @llvm.acos.f80(x86_fp80 %x)
+ ret x86_fp80 %r
+}
+
+; CHECK: error: no libcall available for fsin
+define x86_fp80 @test_sin(x86_fp80 %x) nounwind {
+ %r = call x86_fp80 @llvm.sin.f80(x86_fp80 %x)
+ ret x86_fp80 %r
+}
+
+; CHECK: error: no libcall available for fpow
+define x86_fp80 @test_pow(x86_fp80 %x, x86_fp80 %y) nounwind {
+ %r = call x86_fp80 @llvm.pow.f80(x86_fp80 %x, x86_fp80 %y)
+ ret x86_fp80 %r
+}
+
+; CHECK: error: no libcall available for fpow
+define x86_fp80 @test_pow_finite(x86_fp80 %x, x86_fp80 %y) nounwind {
+ %r = call nnan ninf x86_fp80 @llvm.pow.f80(x86_fp80 %x, x86_fp80 %y)
+ ret x86_fp80 %r
+}
+
+; CHECK: error: no libcall available for fexp
+define x86_fp80 @test_exp(x86_fp80 %x) nounwind {
+ %r = call x86_fp80 @llvm.exp.f80(x86_fp80 %x)
+ ret x86_fp80 %r
+}
+
+; CHECK: error: no libcall available for fexp
+define x86_fp80 @test_exp_finite(x86_fp80 %x) nounwind {
+ %r = call nnan ninf x86_fp80 @llvm.exp.f80(x86_fp80 %x)
+ ret x86_fp80 %r
+}
+
+; CHECK: error: no libcall available for fexp2
+define x86_fp80 @test_exp2(x86_fp80 %x) nounwind {
+ %r = call x86_fp80 @llvm.exp2.f80(x86_fp80 %x)
+ ret x86_fp80 %r
+}
+
+; CHECK: error: no libcall available for fexp2
+define x86_fp80 @test_exp2_finite(x86_fp80 %x) nounwind {
+ %r = call nnan ninf x86_fp80 @llvm.exp2.f80(x86_fp80 %x)
+ ret x86_fp80 %r
+}
+
+; CHECK: error: no libcall available for flog
+define x86_fp80 @test_log(x86_fp80 %x) nounwind {
+ %r = call x86_fp80 @llvm.log.f80(x86_fp80 %x)
+ ret x86_fp80 %r
+}
+
+; CHECK: error: no libcall available for flog
+define x86_fp80 @test_log_finite(x86_fp80 %x) nounwind {
+ %r = call nnan ninf x86_fp80 @llvm.log.f80(x86_fp80 %x)
+ ret x86_fp80 %r
+}
+
+; CHECK: error: no libcall available for flog2
+define x86_fp80 @test_log2(x86_fp80 %x) nounwind {
+ %r = call x86_fp80 @llvm.log2.f80(x86_fp80 %x)
+ ret x86_fp80 %r
+}
+
+; CHECK: error: no libcall available for flog2
+define x86_fp80 @test_log2_finite(x86_fp80 %x) nounwind {
+ %r = call nnan ninf x86_fp80 @llvm.log2.f80(x86_fp80 %x)
+ ret x86_fp80 %r
+}
+
+; CHECK: error: no libcall available for flog10
+define x86_fp80 @test_log10(x86_fp80 %x) nounwind {
+ %r = call x86_fp80 @llvm.log10.f80(x86_fp80 %x)
+ ret x86_fp80 %r
+}
+
+; CHECK: error: no libcall available for flog10
+define x86_fp80 @test_log10_finite(x86_fp80 %x) nounwind {
+ %r = call nnan ninf x86_fp80 @llvm.log10.f80(x86_fp80 %x)
+ ret x86_fp80 %r
+}
diff --git a/llvm/test/CodeGen/X86/ldexp-avx512.ll b/llvm/test/CodeGen/X86/ldexp-avx512.ll
index 874596ed3e41d..cce76e969ffff 100644
--- a/llvm/test/CodeGen/X86/ldexp-avx512.ll
+++ b/llvm/test/CodeGen/X86/ldexp-avx512.ll
@@ -62,15 +62,20 @@ entry:
}
declare double @ldexp(double, i32) memory(none)
-define fp128 @testExpl(fp128 %x, i32 %exp) nounwind {
-; CHECK-LABEL: testExpl:
+define x86_fp80 @test_fp80(x86_fp80 %x, i32 %exp) nounwind {
+; CHECK-LABEL: test_fp80:
; CHECK: # %bb.0: # %entry
-; CHECK-NEXT: jmp ldexpl at PLT # TAILCALL
+; CHECK-NEXT: subq $24, %rsp
+; CHECK-NEXT: fldt {{[0-9]+}}(%rsp)
+; CHECK-NEXT: fstpt (%rsp)
+; CHECK-NEXT: callq ldexpl at PLT
+; CHECK-NEXT: addq $24, %rsp
+; CHECK-NEXT: retq
entry:
- %r = tail call fast fp128 @ldexpl(fp128 %x, i32 %exp)
- ret fp128 %r
+ %r = tail call x86_fp80 @llvm.ldexp.f80.i32(x86_fp80 %x, i32 %exp)
+ ret x86_fp80 %r
}
-declare fp128 @ldexpl(fp128, i32) memory(none)
+declare x86_fp80 @llvm.ldexp.f80.i32(x86_fp80, i32) memory(none)
define <8 x half> @test_ldexp_8xhalf(<8 x half> %x, <8 x i16> %exp) nounwind {
; AVX512F-LABEL: test_ldexp_8xhalf:
>From af76f11ad7d73beffae992719dd83f23660980b9 Mon Sep 17 00:00:00 2001
From: Matt Arsenault <Matthew.Arsenault at amd.com>
Date: Tue, 18 Aug 2026 15:10:55 +0200
Subject: [PATCH 2/3] split mips fp128 sincosl test
---
llvm/test/CodeGen/Mips/llvm.sincos.f128.ll | 78 ++++++
llvm/test/CodeGen/Mips/llvm.sincos.ll | 266 ---------------------
2 files changed, 78 insertions(+), 266 deletions(-)
create mode 100644 llvm/test/CodeGen/Mips/llvm.sincos.f128.ll
diff --git a/llvm/test/CodeGen/Mips/llvm.sincos.f128.ll b/llvm/test/CodeGen/Mips/llvm.sincos.f128.ll
new file mode 100644
index 0000000000000..d3388fabc8397
--- /dev/null
+++ b/llvm/test/CodeGen/Mips/llvm.sincos.f128.ll
@@ -0,0 +1,78 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc -mtriple=mips64 < %s | FileCheck %s -check-prefix=SOFT-FLOAT-64
+; RUN: not llc -mtriple=mipsel -filetype=null < %s 2>&1 | FileCheck %s -check-prefix=ERR
+; RUN: not llc -mtriple=mips -filetype=null < %s 2>&1 | FileCheck %s -check-prefix=ERR
+
+; fp128 sincos lowers to the sincosl long double libcall only where long double
+; is IEEE quad (mips64/n64). On 32-bit MIPS long double is IEEE double, so
+; sincosl is the wrong type and no libcall is available; it must diagnose rather
+; than emit a wrongly-typed call.
+
+; ERR: error: do not know how to soften fsincos
+define { fp128, fp128 } @test_sincos_f128(fp128 %a) #0 {
+; SOFT-FLOAT-64-LABEL: test_sincos_f128:
+; SOFT-FLOAT-64: # %bb.0:
+; SOFT-FLOAT-64-NEXT: daddiu $sp, $sp, -48
+; SOFT-FLOAT-64-NEXT: sd $ra, 40($sp) # 8-byte Folded Spill
+; SOFT-FLOAT-64-NEXT: daddiu $6, $sp, 16
+; SOFT-FLOAT-64-NEXT: jal sincosl
+; SOFT-FLOAT-64-NEXT: daddiu $7, $sp, 0
+; SOFT-FLOAT-64-NEXT: ldc1 $f0, 16($sp)
+; SOFT-FLOAT-64-NEXT: ldc1 $f2, 24($sp)
+; SOFT-FLOAT-64-NEXT: ld $2, 0($sp)
+; SOFT-FLOAT-64-NEXT: ld $3, 8($sp)
+; SOFT-FLOAT-64-NEXT: ld $ra, 40($sp) # 8-byte Folded Reload
+; SOFT-FLOAT-64-NEXT: jr $ra
+; SOFT-FLOAT-64-NEXT: daddiu $sp, $sp, 48
+ %result = call { fp128, fp128 } @llvm.sincos.f128(fp128 %a)
+ ret { fp128, fp128 } %result
+}
+
+define { <2 x fp128>, <2 x fp128> } @test_sincos_v2f128(<2 x fp128> %a) #0 {
+; SOFT-FLOAT-64-LABEL: test_sincos_v2f128:
+; SOFT-FLOAT-64: # %bb.0:
+; SOFT-FLOAT-64-NEXT: daddiu $sp, $sp, -96
+; SOFT-FLOAT-64-NEXT: sd $ra, 88($sp) # 8-byte Folded Spill
+; SOFT-FLOAT-64-NEXT: sd $18, 80($sp) # 8-byte Folded Spill
+; SOFT-FLOAT-64-NEXT: sd $17, 72($sp) # 8-byte Folded Spill
+; SOFT-FLOAT-64-NEXT: sd $16, 64($sp) # 8-byte Folded Spill
+; SOFT-FLOAT-64-NEXT: move $16, $6
+; SOFT-FLOAT-64-NEXT: move $17, $5
+; SOFT-FLOAT-64-NEXT: move $18, $4
+; SOFT-FLOAT-64-NEXT: dmtc1 $7, $f12
+; SOFT-FLOAT-64-NEXT: dmtc1 $8, $f13
+; SOFT-FLOAT-64-NEXT: daddiu $6, $sp, 48
+; SOFT-FLOAT-64-NEXT: jal sincosl
+; SOFT-FLOAT-64-NEXT: daddiu $7, $sp, 32
+; SOFT-FLOAT-64-NEXT: dmtc1 $17, $f12
+; SOFT-FLOAT-64-NEXT: dmtc1 $16, $f13
+; SOFT-FLOAT-64-NEXT: daddiu $6, $sp, 16
+; SOFT-FLOAT-64-NEXT: jal sincosl
+; SOFT-FLOAT-64-NEXT: daddiu $7, $sp, 0
+; SOFT-FLOAT-64-NEXT: ld $1, 56($sp)
+; SOFT-FLOAT-64-NEXT: ld $2, 0($sp)
+; SOFT-FLOAT-64-NEXT: ld $3, 8($sp)
+; SOFT-FLOAT-64-NEXT: ld $4, 32($sp)
+; SOFT-FLOAT-64-NEXT: ld $5, 40($sp)
+; SOFT-FLOAT-64-NEXT: sd $5, 56($18)
+; SOFT-FLOAT-64-NEXT: sd $4, 48($18)
+; SOFT-FLOAT-64-NEXT: sd $3, 40($18)
+; SOFT-FLOAT-64-NEXT: sd $2, 32($18)
+; SOFT-FLOAT-64-NEXT: sd $1, 24($18)
+; SOFT-FLOAT-64-NEXT: ld $1, 48($sp)
+; SOFT-FLOAT-64-NEXT: sd $1, 16($18)
+; SOFT-FLOAT-64-NEXT: ld $1, 24($sp)
+; SOFT-FLOAT-64-NEXT: sd $1, 8($18)
+; SOFT-FLOAT-64-NEXT: ld $1, 16($sp)
+; SOFT-FLOAT-64-NEXT: sd $1, 0($18)
+; SOFT-FLOAT-64-NEXT: ld $16, 64($sp) # 8-byte Folded Reload
+; SOFT-FLOAT-64-NEXT: ld $17, 72($sp) # 8-byte Folded Reload
+; SOFT-FLOAT-64-NEXT: ld $18, 80($sp) # 8-byte Folded Reload
+; SOFT-FLOAT-64-NEXT: ld $ra, 88($sp) # 8-byte Folded Reload
+; SOFT-FLOAT-64-NEXT: jr $ra
+; SOFT-FLOAT-64-NEXT: daddiu $sp, $sp, 96
+ %result = call { <2 x fp128>, <2 x fp128> } @llvm.sincos.v2f128(<2 x fp128> %a)
+ ret { <2 x fp128>, <2 x fp128> } %result
+}
+
+attributes #0 = { nounwind }
diff --git a/llvm/test/CodeGen/Mips/llvm.sincos.ll b/llvm/test/CodeGen/Mips/llvm.sincos.ll
index 58eb427d3a69b..014d36aa07dce 100644
--- a/llvm/test/CodeGen/Mips/llvm.sincos.ll
+++ b/llvm/test/CodeGen/Mips/llvm.sincos.ll
@@ -765,270 +765,4 @@ define { <2 x double>, <2 x double> } @test_sincos_v2f64(<2 x double> %a) #0 {
ret { <2 x double>, <2 x double> } %result
}
-define { fp128, fp128 } @test_sincos_f128(fp128 %a) #0 {
-; MIPSEL-LABEL: test_sincos_f128:
-; MIPSEL: # %bb.0:
-; MIPSEL-NEXT: addiu $sp, $sp, -64
-; MIPSEL-NEXT: sw $ra, 60($sp) # 4-byte Folded Spill
-; MIPSEL-NEXT: sw $16, 56($sp) # 4-byte Folded Spill
-; MIPSEL-NEXT: move $1, $7
-; MIPSEL-NEXT: move $16, $4
-; MIPSEL-NEXT: addiu $2, $sp, 24
-; MIPSEL-NEXT: sw $2, 20($sp)
-; MIPSEL-NEXT: addiu $2, $sp, 40
-; MIPSEL-NEXT: sw $2, 16($sp)
-; MIPSEL-NEXT: lw $7, 80($sp)
-; MIPSEL-NEXT: move $4, $5
-; MIPSEL-NEXT: move $5, $6
-; MIPSEL-NEXT: jal sincosl
-; MIPSEL-NEXT: move $6, $1
-; MIPSEL-NEXT: lw $1, 52($sp)
-; MIPSEL-NEXT: lw $2, 24($sp)
-; MIPSEL-NEXT: lw $3, 28($sp)
-; MIPSEL-NEXT: lw $4, 32($sp)
-; MIPSEL-NEXT: lw $5, 36($sp)
-; MIPSEL-NEXT: sw $5, 28($16)
-; MIPSEL-NEXT: sw $4, 24($16)
-; MIPSEL-NEXT: sw $3, 20($16)
-; MIPSEL-NEXT: sw $2, 16($16)
-; MIPSEL-NEXT: sw $1, 12($16)
-; MIPSEL-NEXT: lw $1, 48($sp)
-; MIPSEL-NEXT: sw $1, 8($16)
-; MIPSEL-NEXT: lw $1, 44($sp)
-; MIPSEL-NEXT: sw $1, 4($16)
-; MIPSEL-NEXT: lw $1, 40($sp)
-; MIPSEL-NEXT: sw $1, 0($16)
-; MIPSEL-NEXT: lw $16, 56($sp) # 4-byte Folded Reload
-; MIPSEL-NEXT: lw $ra, 60($sp) # 4-byte Folded Reload
-; MIPSEL-NEXT: jr $ra
-; MIPSEL-NEXT: addiu $sp, $sp, 64
-;
-; SOFT-FLOAT-32-LABEL: test_sincos_f128:
-; SOFT-FLOAT-32: # %bb.0:
-; SOFT-FLOAT-32-NEXT: addiu $sp, $sp, -64
-; SOFT-FLOAT-32-NEXT: sw $ra, 60($sp) # 4-byte Folded Spill
-; SOFT-FLOAT-32-NEXT: sw $16, 56($sp) # 4-byte Folded Spill
-; SOFT-FLOAT-32-NEXT: move $1, $7
-; SOFT-FLOAT-32-NEXT: move $16, $4
-; SOFT-FLOAT-32-NEXT: addiu $2, $sp, 24
-; SOFT-FLOAT-32-NEXT: sw $2, 20($sp)
-; SOFT-FLOAT-32-NEXT: addiu $2, $sp, 40
-; SOFT-FLOAT-32-NEXT: sw $2, 16($sp)
-; SOFT-FLOAT-32-NEXT: lw $7, 80($sp)
-; SOFT-FLOAT-32-NEXT: move $4, $5
-; SOFT-FLOAT-32-NEXT: move $5, $6
-; SOFT-FLOAT-32-NEXT: jal sincosl
-; SOFT-FLOAT-32-NEXT: move $6, $1
-; SOFT-FLOAT-32-NEXT: lw $1, 52($sp)
-; SOFT-FLOAT-32-NEXT: lw $2, 24($sp)
-; SOFT-FLOAT-32-NEXT: lw $3, 28($sp)
-; SOFT-FLOAT-32-NEXT: lw $4, 32($sp)
-; SOFT-FLOAT-32-NEXT: lw $5, 36($sp)
-; SOFT-FLOAT-32-NEXT: sw $5, 28($16)
-; SOFT-FLOAT-32-NEXT: sw $4, 24($16)
-; SOFT-FLOAT-32-NEXT: sw $3, 20($16)
-; SOFT-FLOAT-32-NEXT: sw $2, 16($16)
-; SOFT-FLOAT-32-NEXT: sw $1, 12($16)
-; SOFT-FLOAT-32-NEXT: lw $1, 48($sp)
-; SOFT-FLOAT-32-NEXT: sw $1, 8($16)
-; SOFT-FLOAT-32-NEXT: lw $1, 44($sp)
-; SOFT-FLOAT-32-NEXT: sw $1, 4($16)
-; SOFT-FLOAT-32-NEXT: lw $1, 40($sp)
-; SOFT-FLOAT-32-NEXT: sw $1, 0($16)
-; SOFT-FLOAT-32-NEXT: lw $16, 56($sp) # 4-byte Folded Reload
-; SOFT-FLOAT-32-NEXT: lw $ra, 60($sp) # 4-byte Folded Reload
-; SOFT-FLOAT-32-NEXT: jr $ra
-; SOFT-FLOAT-32-NEXT: addiu $sp, $sp, 64
-;
-; SOFT-FLOAT-64-LABEL: test_sincos_f128:
-; SOFT-FLOAT-64: # %bb.0:
-; SOFT-FLOAT-64-NEXT: daddiu $sp, $sp, -48
-; SOFT-FLOAT-64-NEXT: sd $ra, 40($sp) # 8-byte Folded Spill
-; SOFT-FLOAT-64-NEXT: daddiu $6, $sp, 16
-; SOFT-FLOAT-64-NEXT: jal sincosl
-; SOFT-FLOAT-64-NEXT: daddiu $7, $sp, 0
-; SOFT-FLOAT-64-NEXT: ldc1 $f0, 16($sp)
-; SOFT-FLOAT-64-NEXT: ldc1 $f2, 24($sp)
-; SOFT-FLOAT-64-NEXT: ld $2, 0($sp)
-; SOFT-FLOAT-64-NEXT: ld $3, 8($sp)
-; SOFT-FLOAT-64-NEXT: ld $ra, 40($sp) # 8-byte Folded Reload
-; SOFT-FLOAT-64-NEXT: jr $ra
-; SOFT-FLOAT-64-NEXT: daddiu $sp, $sp, 48
- %result = call { fp128, fp128 } @llvm.sincos.f128(fp128 %a)
- ret { fp128, fp128 } %result
-}
-
-define { <2 x fp128>, <2 x fp128> } @test_sincos_v2f128(<2 x fp128> %a) #0 {
-; MIPSEL-LABEL: test_sincos_v2f128:
-; MIPSEL: # %bb.0:
-; MIPSEL-NEXT: addiu $sp, $sp, -96
-; MIPSEL-NEXT: sw $ra, 92($sp) # 4-byte Folded Spill
-; MIPSEL-NEXT: sw $16, 88($sp) # 4-byte Folded Spill
-; MIPSEL-NEXT: move $5, $7
-; MIPSEL-NEXT: move $1, $6
-; MIPSEL-NEXT: move $16, $4
-; MIPSEL-NEXT: addiu $2, $sp, 24
-; MIPSEL-NEXT: sw $2, 20($sp)
-; MIPSEL-NEXT: addiu $2, $sp, 40
-; MIPSEL-NEXT: sw $2, 16($sp)
-; MIPSEL-NEXT: lw $6, 112($sp)
-; MIPSEL-NEXT: lw $7, 116($sp)
-; MIPSEL-NEXT: jal sincosl
-; MIPSEL-NEXT: move $4, $1
-; MIPSEL-NEXT: addiu $1, $sp, 56
-; MIPSEL-NEXT: sw $1, 20($sp)
-; MIPSEL-NEXT: addiu $1, $sp, 72
-; MIPSEL-NEXT: sw $1, 16($sp)
-; MIPSEL-NEXT: lw $4, 120($sp)
-; MIPSEL-NEXT: lw $5, 124($sp)
-; MIPSEL-NEXT: lw $6, 128($sp)
-; MIPSEL-NEXT: lw $7, 132($sp)
-; MIPSEL-NEXT: jal sincosl
-; MIPSEL-NEXT: nop
-; MIPSEL-NEXT: lw $1, 36($sp)
-; MIPSEL-NEXT: lw $2, 56($sp)
-; MIPSEL-NEXT: lw $3, 60($sp)
-; MIPSEL-NEXT: lw $4, 64($sp)
-; MIPSEL-NEXT: lw $5, 52($sp)
-; MIPSEL-NEXT: lw $6, 72($sp)
-; MIPSEL-NEXT: lw $7, 76($sp)
-; MIPSEL-NEXT: lw $8, 80($sp)
-; MIPSEL-NEXT: lw $9, 84($sp)
-; MIPSEL-NEXT: lw $10, 24($sp)
-; MIPSEL-NEXT: lw $11, 28($sp)
-; MIPSEL-NEXT: lw $12, 32($sp)
-; MIPSEL-NEXT: lw $13, 68($sp)
-; MIPSEL-NEXT: sw $13, 60($16)
-; MIPSEL-NEXT: sw $4, 56($16)
-; MIPSEL-NEXT: sw $3, 52($16)
-; MIPSEL-NEXT: sw $2, 48($16)
-; MIPSEL-NEXT: sw $1, 44($16)
-; MIPSEL-NEXT: sw $12, 40($16)
-; MIPSEL-NEXT: sw $11, 36($16)
-; MIPSEL-NEXT: sw $10, 32($16)
-; MIPSEL-NEXT: sw $9, 28($16)
-; MIPSEL-NEXT: sw $8, 24($16)
-; MIPSEL-NEXT: sw $7, 20($16)
-; MIPSEL-NEXT: sw $6, 16($16)
-; MIPSEL-NEXT: sw $5, 12($16)
-; MIPSEL-NEXT: lw $1, 48($sp)
-; MIPSEL-NEXT: sw $1, 8($16)
-; MIPSEL-NEXT: lw $1, 44($sp)
-; MIPSEL-NEXT: sw $1, 4($16)
-; MIPSEL-NEXT: lw $1, 40($sp)
-; MIPSEL-NEXT: sw $1, 0($16)
-; MIPSEL-NEXT: lw $16, 88($sp) # 4-byte Folded Reload
-; MIPSEL-NEXT: lw $ra, 92($sp) # 4-byte Folded Reload
-; MIPSEL-NEXT: jr $ra
-; MIPSEL-NEXT: addiu $sp, $sp, 96
-;
-; SOFT-FLOAT-32-LABEL: test_sincos_v2f128:
-; SOFT-FLOAT-32: # %bb.0:
-; SOFT-FLOAT-32-NEXT: addiu $sp, $sp, -96
-; SOFT-FLOAT-32-NEXT: sw $ra, 92($sp) # 4-byte Folded Spill
-; SOFT-FLOAT-32-NEXT: sw $16, 88($sp) # 4-byte Folded Spill
-; SOFT-FLOAT-32-NEXT: move $5, $7
-; SOFT-FLOAT-32-NEXT: move $1, $6
-; SOFT-FLOAT-32-NEXT: move $16, $4
-; SOFT-FLOAT-32-NEXT: addiu $2, $sp, 24
-; SOFT-FLOAT-32-NEXT: sw $2, 20($sp)
-; SOFT-FLOAT-32-NEXT: addiu $2, $sp, 40
-; SOFT-FLOAT-32-NEXT: sw $2, 16($sp)
-; SOFT-FLOAT-32-NEXT: lw $6, 112($sp)
-; SOFT-FLOAT-32-NEXT: lw $7, 116($sp)
-; SOFT-FLOAT-32-NEXT: jal sincosl
-; SOFT-FLOAT-32-NEXT: move $4, $1
-; SOFT-FLOAT-32-NEXT: addiu $1, $sp, 56
-; SOFT-FLOAT-32-NEXT: sw $1, 20($sp)
-; SOFT-FLOAT-32-NEXT: addiu $1, $sp, 72
-; SOFT-FLOAT-32-NEXT: sw $1, 16($sp)
-; SOFT-FLOAT-32-NEXT: lw $4, 120($sp)
-; SOFT-FLOAT-32-NEXT: lw $5, 124($sp)
-; SOFT-FLOAT-32-NEXT: lw $6, 128($sp)
-; SOFT-FLOAT-32-NEXT: lw $7, 132($sp)
-; SOFT-FLOAT-32-NEXT: jal sincosl
-; SOFT-FLOAT-32-NEXT: nop
-; SOFT-FLOAT-32-NEXT: lw $1, 36($sp)
-; SOFT-FLOAT-32-NEXT: lw $2, 56($sp)
-; SOFT-FLOAT-32-NEXT: lw $3, 60($sp)
-; SOFT-FLOAT-32-NEXT: lw $4, 64($sp)
-; SOFT-FLOAT-32-NEXT: lw $5, 52($sp)
-; SOFT-FLOAT-32-NEXT: lw $6, 72($sp)
-; SOFT-FLOAT-32-NEXT: lw $7, 76($sp)
-; SOFT-FLOAT-32-NEXT: lw $8, 80($sp)
-; SOFT-FLOAT-32-NEXT: lw $9, 84($sp)
-; SOFT-FLOAT-32-NEXT: lw $10, 24($sp)
-; SOFT-FLOAT-32-NEXT: lw $11, 28($sp)
-; SOFT-FLOAT-32-NEXT: lw $12, 32($sp)
-; SOFT-FLOAT-32-NEXT: lw $13, 68($sp)
-; SOFT-FLOAT-32-NEXT: sw $13, 60($16)
-; SOFT-FLOAT-32-NEXT: sw $4, 56($16)
-; SOFT-FLOAT-32-NEXT: sw $3, 52($16)
-; SOFT-FLOAT-32-NEXT: sw $2, 48($16)
-; SOFT-FLOAT-32-NEXT: sw $1, 44($16)
-; SOFT-FLOAT-32-NEXT: sw $12, 40($16)
-; SOFT-FLOAT-32-NEXT: sw $11, 36($16)
-; SOFT-FLOAT-32-NEXT: sw $10, 32($16)
-; SOFT-FLOAT-32-NEXT: sw $9, 28($16)
-; SOFT-FLOAT-32-NEXT: sw $8, 24($16)
-; SOFT-FLOAT-32-NEXT: sw $7, 20($16)
-; SOFT-FLOAT-32-NEXT: sw $6, 16($16)
-; SOFT-FLOAT-32-NEXT: sw $5, 12($16)
-; SOFT-FLOAT-32-NEXT: lw $1, 48($sp)
-; SOFT-FLOAT-32-NEXT: sw $1, 8($16)
-; SOFT-FLOAT-32-NEXT: lw $1, 44($sp)
-; SOFT-FLOAT-32-NEXT: sw $1, 4($16)
-; SOFT-FLOAT-32-NEXT: lw $1, 40($sp)
-; SOFT-FLOAT-32-NEXT: sw $1, 0($16)
-; SOFT-FLOAT-32-NEXT: lw $16, 88($sp) # 4-byte Folded Reload
-; SOFT-FLOAT-32-NEXT: lw $ra, 92($sp) # 4-byte Folded Reload
-; SOFT-FLOAT-32-NEXT: jr $ra
-; SOFT-FLOAT-32-NEXT: addiu $sp, $sp, 96
-;
-; SOFT-FLOAT-64-LABEL: test_sincos_v2f128:
-; SOFT-FLOAT-64: # %bb.0:
-; SOFT-FLOAT-64-NEXT: daddiu $sp, $sp, -96
-; SOFT-FLOAT-64-NEXT: sd $ra, 88($sp) # 8-byte Folded Spill
-; SOFT-FLOAT-64-NEXT: sd $18, 80($sp) # 8-byte Folded Spill
-; SOFT-FLOAT-64-NEXT: sd $17, 72($sp) # 8-byte Folded Spill
-; SOFT-FLOAT-64-NEXT: sd $16, 64($sp) # 8-byte Folded Spill
-; SOFT-FLOAT-64-NEXT: move $16, $6
-; SOFT-FLOAT-64-NEXT: move $17, $5
-; SOFT-FLOAT-64-NEXT: move $18, $4
-; SOFT-FLOAT-64-NEXT: dmtc1 $7, $f12
-; SOFT-FLOAT-64-NEXT: dmtc1 $8, $f13
-; SOFT-FLOAT-64-NEXT: daddiu $6, $sp, 48
-; SOFT-FLOAT-64-NEXT: jal sincosl
-; SOFT-FLOAT-64-NEXT: daddiu $7, $sp, 32
-; SOFT-FLOAT-64-NEXT: dmtc1 $17, $f12
-; SOFT-FLOAT-64-NEXT: dmtc1 $16, $f13
-; SOFT-FLOAT-64-NEXT: daddiu $6, $sp, 16
-; SOFT-FLOAT-64-NEXT: jal sincosl
-; SOFT-FLOAT-64-NEXT: daddiu $7, $sp, 0
-; SOFT-FLOAT-64-NEXT: ld $1, 56($sp)
-; SOFT-FLOAT-64-NEXT: ld $2, 0($sp)
-; SOFT-FLOAT-64-NEXT: ld $3, 8($sp)
-; SOFT-FLOAT-64-NEXT: ld $4, 32($sp)
-; SOFT-FLOAT-64-NEXT: ld $5, 40($sp)
-; SOFT-FLOAT-64-NEXT: sd $5, 56($18)
-; SOFT-FLOAT-64-NEXT: sd $4, 48($18)
-; SOFT-FLOAT-64-NEXT: sd $3, 40($18)
-; SOFT-FLOAT-64-NEXT: sd $2, 32($18)
-; SOFT-FLOAT-64-NEXT: sd $1, 24($18)
-; SOFT-FLOAT-64-NEXT: ld $1, 48($sp)
-; SOFT-FLOAT-64-NEXT: sd $1, 16($18)
-; SOFT-FLOAT-64-NEXT: ld $1, 24($sp)
-; SOFT-FLOAT-64-NEXT: sd $1, 8($18)
-; SOFT-FLOAT-64-NEXT: ld $1, 16($sp)
-; SOFT-FLOAT-64-NEXT: sd $1, 0($18)
-; SOFT-FLOAT-64-NEXT: ld $16, 64($sp) # 8-byte Folded Reload
-; SOFT-FLOAT-64-NEXT: ld $17, 72($sp) # 8-byte Folded Reload
-; SOFT-FLOAT-64-NEXT: ld $18, 80($sp) # 8-byte Folded Reload
-; SOFT-FLOAT-64-NEXT: ld $ra, 88($sp) # 8-byte Folded Reload
-; SOFT-FLOAT-64-NEXT: jr $ra
-; SOFT-FLOAT-64-NEXT: daddiu $sp, $sp, 96
- %result = call { <2 x fp128>, <2 x fp128> } @llvm.sincos.v2f128(<2 x fp128> %a)
- ret { <2 x fp128>, <2 x fp128> } %result
-}
-
attributes #0 = { nounwind }
>From 87ff8f315077ffbc0f756ed56238e24e57001d45 Mon Sep 17 00:00:00 2001
From: Matt Arsenault <Matthew.Arsenault at amd.com>
Date: Tue, 18 Aug 2026 17:31:26 +0200
Subject: [PATCH 3/3] Add x86_fp80 ldexp/frexp no-libcall error coverage
---
llvm/test/CodeGen/X86/fp80-math-no-libcall-error.ll | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/llvm/test/CodeGen/X86/fp80-math-no-libcall-error.ll b/llvm/test/CodeGen/X86/fp80-math-no-libcall-error.ll
index a2d69cfe20b87..38991855dcb5b 100644
--- a/llvm/test/CodeGen/X86/fp80-math-no-libcall-error.ll
+++ b/llvm/test/CodeGen/X86/fp80-math-no-libcall-error.ll
@@ -90,3 +90,15 @@ define x86_fp80 @test_log10_finite(x86_fp80 %x) nounwind {
%r = call nnan ninf x86_fp80 @llvm.log10.f80(x86_fp80 %x)
ret x86_fp80 %r
}
+
+; CHECK: error: no libcall available for fldexp
+define x86_fp80 @test_ldexp(x86_fp80 %x, i32 %exp) nounwind {
+ %r = call x86_fp80 @llvm.ldexp.f80.i32(x86_fp80 %x, i32 %exp)
+ ret x86_fp80 %r
+}
+
+; CHECK: error: no libcall available for ffrexp
+define { x86_fp80, i32 } @test_frexp(x86_fp80 %x) nounwind {
+ %r = call { x86_fp80, i32 } @llvm.frexp.f80.i32(x86_fp80 %x)
+ ret { x86_fp80, i32 } %r
+}
More information about the llvm-commits
mailing list