[clang] [llvm] [WIP] Correct lowering of `fp128` intrinsics (PR #76558)
Trevor Gross via cfe-commits
cfe-commits at lists.llvm.org
Sun Apr 27 00:38:38 PDT 2025
https://github.com/tgross35 updated https://github.com/llvm/llvm-project/pull/76558
>From dafb3a378876db6b3bf505b425b386fd8f79c918 Mon Sep 17 00:00:00 2001
From: Trevor Gross <tmgross at umich.edu>
Date: Fri, 11 Aug 2023 22:16:01 -0400
Subject: [PATCH 1/5] [IR] Add a test for `f128` libcall lowering (NFC)
`f128` intrinsic functions sometimes lower to `long double` library
calls when they instead need to be `f128` versions. Add a test
demonstrating current behavior.
---
.../CodeGen/Generic/f128-math-lowering.ll | 328 ++++++++++++++++++
1 file changed, 328 insertions(+)
create mode 100644 llvm/test/CodeGen/Generic/f128-math-lowering.ll
diff --git a/llvm/test/CodeGen/Generic/f128-math-lowering.ll b/llvm/test/CodeGen/Generic/f128-math-lowering.ll
new file mode 100644
index 0000000000000..dfbd1eaeda109
--- /dev/null
+++ b/llvm/test/CodeGen/Generic/f128-math-lowering.ll
@@ -0,0 +1,328 @@
+; RUN: llc < %s -mtriple=aarch64-unknown-none -verify-machineinstrs | FileCheck %s --check-prefix=CHECK-USELD
+; RUN: llc < %s -mtriple=i686-unknown -verify-machineinstrs | FileCheck %s --check-prefix=CHECK-USELD
+; RUN: llc < %s -mtriple=riscv32 -verify-machineinstrs | FileCheck %s --check-prefix=CHECK-USELD
+; RUN: llc < %s -mtriple=s390x-unknown -verify-machineinstrs | FileCheck %s --check-prefix=CHECK-S390X
+; RUN: llc < %s -mtriple=x86_64-unknown -verify-machineinstrs | FileCheck %s --check-prefix=CHECK-USELD
+; RUN: llc < %s -mtriple=x86_64-unknown-linux-gnu -verify-machineinstrs | FileCheck %s --check-prefix=CHECK-NOTLD
+; RUN: llc < %s -mtriple=x86_64-unknown-linux-musl -verify-machineinstrs | FileCheck %s --check-prefix=CHECK-USELD
+;
+; REQUIRES: aarch64-registered-target
+; REQUIRES: riscv-registered-target
+; REQUIRES: systemz-registered-target
+; REQUIRES: x86-registered-target
+;
+; Verify that fp128 intrinsics only lower to `long double` calls (e.g. `sinl`)
+; on platforms where `f128` and `long double` have the same layout, and
+; otherwise lower to `f128` versions (e.g. `sinf128`).
+;
+; Targets include:
+; * x86, x64 (80-bit long double)
+; * aarch64 (long double == f128)
+; * riscv32 (long double == f64)
+; * s390x (long double == f128, hardware support)
+; * A couple assorted environments for x86
+;
+; FIXME: only targets where long double is `f128` should be using `USELD`, all
+; others need to be NOTLD. PowerPC should be added but it currently emits an
+; interesting blend of both (e.g. `acosl` but `ceilf128`).
+
+define fp128 @test_acosf128(fp128 %a) {
+; CHECK-LABEL: test_acosf128:
+; CHECK-NOTLD: acosf128
+; CHECK-USELD: acosl
+; CHECK-S390X: acosl
+start:
+ %0 = tail call fp128 @llvm.acos.f128(fp128 %a)
+ ret fp128 %0
+}
+
+define fp128 @test_asinf128(fp128 %a) {
+; CHECK-LABEL: test_asinf128:
+; CHECK-NOTLD: asinf128
+; CHECK-USELD: asinl
+; CHECK-S390X: asinl
+start:
+ %0 = tail call fp128 @llvm.asin.f128(fp128 %a)
+ ret fp128 %0
+}
+
+define fp128 @test_atanf128(fp128 %a) {
+; CHECK-LABEL: test_atanf128:
+; CHECK-NOTLD: atanf128
+; CHECK-USELD: atanl
+; CHECK-S390X: atanl
+start:
+ %0 = tail call fp128 @llvm.atan.f128(fp128 %a)
+ ret fp128 %0
+}
+
+define fp128 @test_ceilf128(fp128 %a) {
+; CHECK-LABEL: test_ceilf128:
+; CHECK-NOTLD: ceilf128
+; CHECK-USELD: ceill
+; CHECK-S390X: ceill
+start:
+ %0 = tail call fp128 @llvm.ceil.f128(fp128 %a)
+ ret fp128 %0
+}
+
+define fp128 @test_copysignf128(fp128 %a, fp128 %b) {
+; copysign should always get lowered to assembly
+; CHECK-LABEL: test_copysignf128:
+; CHECK-NOT: copysignl
+; CHECK-NOT: copysignf128
+start:
+ %0 = tail call fp128 @llvm.copysign.f128(fp128 %a, fp128 %b)
+ ret fp128 %0
+}
+
+define fp128 @test_cosf128(fp128 %a) {
+; CHECK-LABEL: test_cosf128:
+; CHECK-NOTLD: cosf128
+; CHECK-USELD: cosl
+; CHECK-S390X: cosl
+start:
+ %0 = tail call fp128 @llvm.cos.f128(fp128 %a)
+ ret fp128 %0
+}
+
+define fp128 @test_exp10f128(fp128 %a) {
+; CHECK-LABEL: test_exp2f128:
+; CHECK-NOTLD: exp10f128
+; CHECK-USELD: exp10l
+; CHECK-S390X: exp10l
+start:
+ %0 = tail call fp128 @llvm.exp10.f128(fp128 %a)
+ ret fp128 %0
+}
+
+define fp128 @test_exp2f128(fp128 %a) {
+; CHECK-LABEL: test_exp2f128:
+; CHECK-NOTLD: exp2f128
+; CHECK-USELD: exp2l
+; CHECK-S390X: exp2l
+start:
+ %0 = tail call fp128 @llvm.exp2.f128(fp128 %a)
+ ret fp128 %0
+}
+
+
+define fp128 @test_expf128(fp128 %a) {
+; CHECK-LABEL: test_expf128:
+; CHECK-NOTLD: expf128
+; CHECK-USELD: expl
+; CHECK-S390X: expl
+start:
+ %0 = tail call fp128 @llvm.exp.f128(fp128 %a)
+ ret fp128 %0
+}
+
+define fp128 @test_fabsf128(fp128 %a) {
+; fabs should always get lowered to assembly
+; CHECK-LABEL: test_fabsf128:
+; CHECK-NOT: fabsl
+; CHECK-NOT: fabsf128
+start:
+ %0 = tail call fp128 @llvm.fabs.f128(fp128 %a)
+ ret fp128 %0
+}
+
+define fp128 @test_floorf128(fp128 %a) {
+; CHECK-LABEL: test_floorf128:
+; CHECK-NOTLD: floorf128
+; CHECK-USELD: floorl
+; CHECK-S390X: floorl
+start:
+ %0 = tail call fp128 @llvm.floor.f128(fp128 %a)
+ ret fp128 %0
+}
+
+define fp128 @test_fmaf128(fp128 %a, fp128 %b, fp128 %c) {
+; CHECK-LABEL: test_fmaf128:
+; CHECK-NOTLD: fmaf128
+; CHECK-USELD: fmal
+; CHECK-S390X: fmal
+start:
+ %0 = tail call fp128 @llvm.fma.f128(fp128 %a, fp128 %b, fp128 %c)
+ ret fp128 %0
+}
+
+define { fp128, i32 } @test_frexpf128(fp128 %a) {
+; CHECK-LABEL: test_frexpf128:
+; CHECK-NOTLD: frexpf128
+; CHECK-USELD: frexpl
+; CHECK-S390X: frexpl
+start:
+ %0 = tail call { fp128, i32 } @llvm.frexp.f128(fp128 %a)
+ ret { fp128, i32 } %0
+}
+
+define fp128 @test_ldexpf128(fp128 %a, i32 %b) {
+; CHECK-LABEL: test_ldexpf128:
+; CHECK-NOTLD: ldexpf128
+; CHECK-USELD: ldexpl
+; CHECK-S390X: ldexpl
+start:
+ %0 = tail call fp128 @llvm.ldexp.f128(fp128 %a, i32 %b)
+ ret fp128 %0
+}
+
+define i64 @test_llrintf128(fp128 %a) {
+; CHECK-LABEL: test_llrintf128:
+; CHECK-NOTLD: llrintf128
+; CHECK-USELD: llrintl
+; CHECK-S390X: llrintl
+start:
+ %0 = tail call i64 @llvm.llrint.f128(fp128 %a)
+ ret i64 %0
+}
+
+define i64 @test_llroundf128(fp128 %a) {
+; CHECK-LABEL: test_llroundf128:
+; CHECK-NOTLD: llroundf128
+; CHECK-USELD: llroundl
+; CHECK-S390X: llroundl
+start:
+ %0 = tail call i64 @llvm.llround.i64.f128(fp128 %a)
+ ret i64 %0
+}
+
+define fp128 @test_log10f128(fp128 %a) {
+; CHECK-LABEL: test_log10f128:
+; CHECK-NOTLD: log10f128
+; CHECK-USELD: log10l
+; CHECK-S390X: log10l
+start:
+ %0 = tail call fp128 @llvm.log10.f128(fp128 %a)
+ ret fp128 %0
+}
+
+define fp128 @test_log2f128(fp128 %a) {
+; CHECK-LABEL: test_log2f128:
+; CHECK-NOTLD: log2f128
+; CHECK-USELD: log2l
+; CHECK-S390X: log2l
+start:
+ %0 = tail call fp128 @llvm.log2.f128(fp128 %a)
+ ret fp128 %0
+}
+
+define fp128 @test_logf128(fp128 %a) {
+; CHECK-LABEL: test_logf128:
+; CHECK-NOTLD: logf128
+; CHECK-USELD: logl
+; CHECK-S390X: logl
+start:
+ %0 = tail call fp128 @llvm.log.f128(fp128 %a)
+ ret fp128 %0
+}
+
+define i64 @test_lrintf128(fp128 %a) {
+; CHECK-LABEL: test_exp2f128:
+; CHECK-NOTLD: lrintf128
+; CHECK-USELD: lrintl
+; CHECK-S390X: lrintl
+start:
+ %0 = tail call i64 @llvm.lrint.f128(fp128 %a)
+ ret i64 %0
+}
+
+define i64 @test_lroundf128(fp128 %a) {
+; CHECK-LABEL: test_lroundf128:
+; CHECK-NOTLD: lroundf128
+; CHECK-USELD: lroundl
+; CHECK-S390X: lroundl
+start:
+ %0 = tail call i64 @llvm.lround.i64.f128(fp128 %a)
+ ret i64 %0
+}
+
+define fp128 @test_nearbyintf128(fp128 %a) {
+; CHECK-LABEL: test_nearbyintf128:
+; CHECK-NOTLD: nearbyintf128
+; CHECK-USELD: nearbyintl
+; CHECK-S390X: nearbyintl
+start:
+ %0 = tail call fp128 @llvm.nearbyint.f128(fp128 %a)
+ ret fp128 %0
+}
+
+define fp128 @test_powf128(fp128 %a, fp128 %b) {
+; CHECK-LABEL: test_powf128:
+; CHECK-NOTLD: powf128
+; CHECK-USELD: powl
+; CHECK-S390X: powl
+start:
+ %0 = tail call fp128 @llvm.pow.f128(fp128 %a, fp128 %b)
+ ret fp128 %0
+}
+
+define fp128 @test_rintf128(fp128 %a) {
+; CHECK-LABEL: test_rintf128:
+; CHECK-NOTLD: rintf128
+; CHECK-USELD: rintl
+; CHECK-S390X: fixbr {{%.*}}, 0, {{%.*}}
+start:
+ %0 = tail call fp128 @llvm.rint.f128(fp128 %a)
+ ret fp128 %0
+}
+
+define fp128 @test_roundevenf128(fp128 %a) {
+; CHECK-LABEL: test_roundevenf128:
+; CHECK-NOTLD: roundevenf128
+; CHECK-USELD: roundevenl
+; CHECK-S390X: roundevenl
+start:
+ %0 = tail call fp128 @llvm.roundeven.f128(fp128 %a)
+ ret fp128 %0
+}
+
+define fp128 @test_roundf128(fp128 %a) {
+; CHECK-LABEL: test_roundf128:
+; CHECK-NOTLD: roundf128
+; CHECK-USELD: roundl
+; CHECK-S390X: roundl
+start:
+ %0 = tail call fp128 @llvm.round.f128(fp128 %a)
+ ret fp128 %0
+}
+
+define fp128 @test_sinf128(fp128 %a) {
+; CHECK-LABEL: test_sinf128:
+; CHECK-NOTLD: sinf128
+; CHECK-USELD: sinl
+; CHECK-S390X: sinl
+start:
+ %0 = tail call fp128 @llvm.sin.f128(fp128 %a)
+ ret fp128 %0
+}
+
+define fp128 @test_sqrtf128(fp128 %a) {
+; CHECK-LABEL: test_sqrtf128:
+; CHECK-NOTLD: sqrtf128
+; CHECK-USELD: sqrtl
+; CHECK-S390X: sqxbr {{%.*}}, {{%.*}}
+start:
+ %0 = tail call fp128 @llvm.sqrt.f128(fp128 %a)
+ ret fp128 %0
+}
+
+define fp128 @test_tanf128(fp128 %a) {
+; CHECK-LABEL: test_tanf128:
+; CHECK-NOTLD: tanf128
+; CHECK-USELD: tanl
+; CHECK-S390X: tanl
+start:
+ %0 = tail call fp128 @llvm.tan.f128(fp128 %a)
+ ret fp128 %0
+}
+
+define fp128 @test_truncf128(fp128 %a) {
+; CHECK-LABEL: test_truncf128:
+; CHECK-NOTLD: truncf128
+; CHECK-USELD: truncl
+; CHECK-S390X: truncl
+start:
+ %0 = tail call fp128 @llvm.trunc.f128(fp128 %a)
+ ret fp128 %0
+}
>From 655f5c8d9afce6796c90508c47e2b8e2d509a3ee Mon Sep 17 00:00:00 2001
From: Trevor Gross <tmgross at umich.edu>
Date: Thu, 28 Dec 2023 04:01:22 -0500
Subject: [PATCH 2/5] [IR] Change `fp128` lowering to use `f128` functions by
default
Switch from emitting long double functions to using `f128`-specific functions.
Fixes https://github.com/llvm/llvm-project/issues/44744.
---
llvm/include/llvm/IR/RuntimeLibcalls.def | 98 +++++++++----------
llvm/lib/IR/RuntimeLibcalls.cpp | 94 +++++++++---------
llvm/lib/Target/PowerPC/PPCISelLowering.cpp | 26 -----
.../CodeGen/Generic/f128-math-lowering.ll | 11 ++-
4 files changed, 103 insertions(+), 126 deletions(-)
diff --git a/llvm/include/llvm/IR/RuntimeLibcalls.def b/llvm/include/llvm/IR/RuntimeLibcalls.def
index cd8e9b598044c..8680dfb59be30 100644
--- a/llvm/include/llvm/IR/RuntimeLibcalls.def
+++ b/llvm/include/llvm/IR/RuntimeLibcalls.def
@@ -113,12 +113,12 @@ HANDLE_LIBCALL(DIV_PPCF128, "__gcc_qdiv")
HANDLE_LIBCALL(REM_F32, "fmodf")
HANDLE_LIBCALL(REM_F64, "fmod")
HANDLE_LIBCALL(REM_F80, "fmodl")
-HANDLE_LIBCALL(REM_F128, "fmodl")
+HANDLE_LIBCALL(REM_F128, "fmodf128")
HANDLE_LIBCALL(REM_PPCF128, "fmodl")
HANDLE_LIBCALL(FMA_F32, "fmaf")
HANDLE_LIBCALL(FMA_F64, "fma")
HANDLE_LIBCALL(FMA_F80, "fmal")
-HANDLE_LIBCALL(FMA_F128, "fmal")
+HANDLE_LIBCALL(FMA_F128, "fmaf128")
HANDLE_LIBCALL(FMA_PPCF128, "fmal")
HANDLE_LIBCALL(POWI_F32, "__powisf2")
HANDLE_LIBCALL(POWI_F64, "__powidf2")
@@ -128,117 +128,117 @@ HANDLE_LIBCALL(POWI_PPCF128, "__powitf2")
HANDLE_LIBCALL(SQRT_F32, "sqrtf")
HANDLE_LIBCALL(SQRT_F64, "sqrt")
HANDLE_LIBCALL(SQRT_F80, "sqrtl")
-HANDLE_LIBCALL(SQRT_F128, "sqrtl")
+HANDLE_LIBCALL(SQRT_F128, "sqrtf128")
HANDLE_LIBCALL(SQRT_PPCF128, "sqrtl")
HANDLE_LIBCALL(CBRT_F32, "cbrtf")
HANDLE_LIBCALL(CBRT_F64, "cbrt")
HANDLE_LIBCALL(CBRT_F80, "cbrtl")
-HANDLE_LIBCALL(CBRT_F128, "cbrtl")
+HANDLE_LIBCALL(CBRT_F128, "cbrtf128")
HANDLE_LIBCALL(CBRT_PPCF128, "cbrtl")
HANDLE_LIBCALL(LOG_F32, "logf")
HANDLE_LIBCALL(LOG_F64, "log")
HANDLE_LIBCALL(LOG_F80, "logl")
-HANDLE_LIBCALL(LOG_F128, "logl")
+HANDLE_LIBCALL(LOG_F128, "logf128")
HANDLE_LIBCALL(LOG_PPCF128, "logl")
HANDLE_LIBCALL(LOG_FINITE_F32, "__logf_finite")
HANDLE_LIBCALL(LOG_FINITE_F64, "__log_finite")
HANDLE_LIBCALL(LOG_FINITE_F80, "__logl_finite")
-HANDLE_LIBCALL(LOG_FINITE_F128, "__logl_finite")
+HANDLE_LIBCALL(LOG_FINITE_F128, "__logf128_finite")
HANDLE_LIBCALL(LOG_FINITE_PPCF128, "__logl_finite")
HANDLE_LIBCALL(LOG2_F32, "log2f")
HANDLE_LIBCALL(LOG2_F64, "log2")
HANDLE_LIBCALL(LOG2_F80, "log2l")
-HANDLE_LIBCALL(LOG2_F128, "log2l")
+HANDLE_LIBCALL(LOG2_F128, "log2f128")
HANDLE_LIBCALL(LOG2_PPCF128, "log2l")
HANDLE_LIBCALL(LOG2_FINITE_F32, "__log2f_finite")
HANDLE_LIBCALL(LOG2_FINITE_F64, "__log2_finite")
HANDLE_LIBCALL(LOG2_FINITE_F80, "__log2l_finite")
-HANDLE_LIBCALL(LOG2_FINITE_F128, "__log2l_finite")
+HANDLE_LIBCALL(LOG2_FINITE_F128, "__log2f128_finite")
HANDLE_LIBCALL(LOG2_FINITE_PPCF128, "__log2l_finite")
HANDLE_LIBCALL(LOG10_F32, "log10f")
HANDLE_LIBCALL(LOG10_F64, "log10")
HANDLE_LIBCALL(LOG10_F80, "log10l")
-HANDLE_LIBCALL(LOG10_F128, "log10l")
+HANDLE_LIBCALL(LOG10_F128, "log10f128")
HANDLE_LIBCALL(LOG10_PPCF128, "log10l")
HANDLE_LIBCALL(LOG10_FINITE_F32, "__log10f_finite")
HANDLE_LIBCALL(LOG10_FINITE_F64, "__log10_finite")
HANDLE_LIBCALL(LOG10_FINITE_F80, "__log10l_finite")
-HANDLE_LIBCALL(LOG10_FINITE_F128, "__log10l_finite")
+HANDLE_LIBCALL(LOG10_FINITE_F128, "__log10f128_finite")
HANDLE_LIBCALL(LOG10_FINITE_PPCF128, "__log10l_finite")
HANDLE_LIBCALL(EXP_F32, "expf")
HANDLE_LIBCALL(EXP_F64, "exp")
HANDLE_LIBCALL(EXP_F80, "expl")
-HANDLE_LIBCALL(EXP_F128, "expl")
+HANDLE_LIBCALL(EXP_F128, "expf128")
HANDLE_LIBCALL(EXP_PPCF128, "expl")
HANDLE_LIBCALL(EXP_FINITE_F32, "__expf_finite")
HANDLE_LIBCALL(EXP_FINITE_F64, "__exp_finite")
HANDLE_LIBCALL(EXP_FINITE_F80, "__expl_finite")
-HANDLE_LIBCALL(EXP_FINITE_F128, "__expl_finite")
+HANDLE_LIBCALL(EXP_FINITE_F128, "__expf128_finite")
HANDLE_LIBCALL(EXP_FINITE_PPCF128, "__expl_finite")
HANDLE_LIBCALL(EXP2_F32, "exp2f")
HANDLE_LIBCALL(EXP2_F64, "exp2")
HANDLE_LIBCALL(EXP2_F80, "exp2l")
-HANDLE_LIBCALL(EXP2_F128, "exp2l")
+HANDLE_LIBCALL(EXP2_F128, "exp2f128")
HANDLE_LIBCALL(EXP2_PPCF128, "exp2l")
HANDLE_LIBCALL(EXP2_FINITE_F32, "__exp2f_finite")
HANDLE_LIBCALL(EXP2_FINITE_F64, "__exp2_finite")
HANDLE_LIBCALL(EXP2_FINITE_F80, "__exp2l_finite")
-HANDLE_LIBCALL(EXP2_FINITE_F128, "__exp2l_finite")
+HANDLE_LIBCALL(EXP2_FINITE_F128, "__exp2f128_finite")
HANDLE_LIBCALL(EXP2_FINITE_PPCF128, "__exp2l_finite")
HANDLE_LIBCALL(EXP10_F32, "exp10f")
HANDLE_LIBCALL(EXP10_F64, "exp10")
HANDLE_LIBCALL(EXP10_F80, "exp10l")
-HANDLE_LIBCALL(EXP10_F128, "exp10l")
+HANDLE_LIBCALL(EXP10_F128, "exp10f128")
HANDLE_LIBCALL(EXP10_PPCF128, "exp10l")
HANDLE_LIBCALL(SIN_F32, "sinf")
HANDLE_LIBCALL(SIN_F64, "sin")
HANDLE_LIBCALL(SIN_F80, "sinl")
-HANDLE_LIBCALL(SIN_F128, "sinl")
+HANDLE_LIBCALL(SIN_F128, "sinf128")
HANDLE_LIBCALL(SIN_PPCF128, "sinl")
HANDLE_LIBCALL(COS_F32, "cosf")
HANDLE_LIBCALL(COS_F64, "cos")
HANDLE_LIBCALL(COS_F80, "cosl")
-HANDLE_LIBCALL(COS_F128, "cosl")
+HANDLE_LIBCALL(COS_F128, "cosf128")
HANDLE_LIBCALL(COS_PPCF128, "cosl")
HANDLE_LIBCALL(TAN_F32, "tanf")
HANDLE_LIBCALL(TAN_F64, "tan")
HANDLE_LIBCALL(TAN_F80, "tanl")
-HANDLE_LIBCALL(TAN_F128,"tanl")
+HANDLE_LIBCALL(TAN_F128,"tanf128")
HANDLE_LIBCALL(TAN_PPCF128, "tanl")
HANDLE_LIBCALL(SINH_F32, "sinhf")
HANDLE_LIBCALL(SINH_F64, "sinh")
HANDLE_LIBCALL(SINH_F80, "sinhl")
-HANDLE_LIBCALL(SINH_F128, "sinhl")
+HANDLE_LIBCALL(SINH_F128, "sinhf128")
HANDLE_LIBCALL(SINH_PPCF128, "sinhl")
HANDLE_LIBCALL(COSH_F32, "coshf")
HANDLE_LIBCALL(COSH_F64, "cosh")
HANDLE_LIBCALL(COSH_F80, "coshl")
-HANDLE_LIBCALL(COSH_F128, "coshl")
+HANDLE_LIBCALL(COSH_F128, "coshf128")
HANDLE_LIBCALL(COSH_PPCF128, "coshl")
HANDLE_LIBCALL(TANH_F32, "tanhf")
HANDLE_LIBCALL(TANH_F64, "tanh")
HANDLE_LIBCALL(TANH_F80, "tanhl")
-HANDLE_LIBCALL(TANH_F128,"tanhl")
+HANDLE_LIBCALL(TANH_F128,"tanhf128")
HANDLE_LIBCALL(TANH_PPCF128, "tanhl")
HANDLE_LIBCALL(ASIN_F32, "asinf")
HANDLE_LIBCALL(ASIN_F64, "asin")
HANDLE_LIBCALL(ASIN_F80, "asinl")
-HANDLE_LIBCALL(ASIN_F128, "asinl")
+HANDLE_LIBCALL(ASIN_F128, "asinf128")
HANDLE_LIBCALL(ASIN_PPCF128, "asinl")
HANDLE_LIBCALL(ACOS_F32, "acosf")
HANDLE_LIBCALL(ACOS_F64, "acos")
HANDLE_LIBCALL(ACOS_F80, "acosl")
-HANDLE_LIBCALL(ACOS_F128, "acosl")
+HANDLE_LIBCALL(ACOS_F128, "acosf128")
HANDLE_LIBCALL(ACOS_PPCF128, "acosl")
HANDLE_LIBCALL(ATAN_F32, "atanf")
HANDLE_LIBCALL(ATAN_F64, "atan")
HANDLE_LIBCALL(ATAN_F80, "atanl")
-HANDLE_LIBCALL(ATAN_F128,"atanl")
+HANDLE_LIBCALL(ATAN_F128,"atanf128")
HANDLE_LIBCALL(ATAN_PPCF128, "atanl")
HANDLE_LIBCALL(ATAN2_F32, "atan2f")
HANDLE_LIBCALL(ATAN2_F64, "atan2")
HANDLE_LIBCALL(ATAN2_F80, "atan2l")
-HANDLE_LIBCALL(ATAN2_F128,"atan2l")
+HANDLE_LIBCALL(ATAN2_F128,"atan2f128")
HANDLE_LIBCALL(ATAN2_PPCF128, "atan2l")
HANDLE_LIBCALL(SINCOS_F32, nullptr)
HANDLE_LIBCALL(SINCOS_F64, nullptr)
@@ -250,122 +250,122 @@ HANDLE_LIBCALL(SINCOS_STRET_F64, nullptr)
HANDLE_LIBCALL(POW_F32, "powf")
HANDLE_LIBCALL(POW_F64, "pow")
HANDLE_LIBCALL(POW_F80, "powl")
-HANDLE_LIBCALL(POW_F128, "powl")
+HANDLE_LIBCALL(POW_F128, "powf128")
HANDLE_LIBCALL(POW_PPCF128, "powl")
HANDLE_LIBCALL(POW_FINITE_F32, "__powf_finite")
HANDLE_LIBCALL(POW_FINITE_F64, "__pow_finite")
HANDLE_LIBCALL(POW_FINITE_F80, "__powl_finite")
-HANDLE_LIBCALL(POW_FINITE_F128, "__powl_finite")
+HANDLE_LIBCALL(POW_FINITE_F128, "__powf128_finite")
HANDLE_LIBCALL(POW_FINITE_PPCF128, "__powl_finite")
HANDLE_LIBCALL(CEIL_F32, "ceilf")
HANDLE_LIBCALL(CEIL_F64, "ceil")
HANDLE_LIBCALL(CEIL_F80, "ceill")
-HANDLE_LIBCALL(CEIL_F128, "ceill")
+HANDLE_LIBCALL(CEIL_F128, "ceilf128")
HANDLE_LIBCALL(CEIL_PPCF128, "ceill")
HANDLE_LIBCALL(TRUNC_F32, "truncf")
HANDLE_LIBCALL(TRUNC_F64, "trunc")
HANDLE_LIBCALL(TRUNC_F80, "truncl")
-HANDLE_LIBCALL(TRUNC_F128, "truncl")
+HANDLE_LIBCALL(TRUNC_F128, "truncf128")
HANDLE_LIBCALL(TRUNC_PPCF128, "truncl")
HANDLE_LIBCALL(RINT_F32, "rintf")
HANDLE_LIBCALL(RINT_F64, "rint")
HANDLE_LIBCALL(RINT_F80, "rintl")
-HANDLE_LIBCALL(RINT_F128, "rintl")
+HANDLE_LIBCALL(RINT_F128, "rintf128")
HANDLE_LIBCALL(RINT_PPCF128, "rintl")
HANDLE_LIBCALL(NEARBYINT_F32, "nearbyintf")
HANDLE_LIBCALL(NEARBYINT_F64, "nearbyint")
HANDLE_LIBCALL(NEARBYINT_F80, "nearbyintl")
-HANDLE_LIBCALL(NEARBYINT_F128, "nearbyintl")
+HANDLE_LIBCALL(NEARBYINT_F128, "nearbyintf128")
HANDLE_LIBCALL(NEARBYINT_PPCF128, "nearbyintl")
HANDLE_LIBCALL(ROUND_F32, "roundf")
HANDLE_LIBCALL(ROUND_F64, "round")
HANDLE_LIBCALL(ROUND_F80, "roundl")
-HANDLE_LIBCALL(ROUND_F128, "roundl")
+HANDLE_LIBCALL(ROUND_F128, "roundf128")
HANDLE_LIBCALL(ROUND_PPCF128, "roundl")
HANDLE_LIBCALL(ROUNDEVEN_F32, "roundevenf")
HANDLE_LIBCALL(ROUNDEVEN_F64, "roundeven")
HANDLE_LIBCALL(ROUNDEVEN_F80, "roundevenl")
-HANDLE_LIBCALL(ROUNDEVEN_F128, "roundevenl")
+HANDLE_LIBCALL(ROUNDEVEN_F128, "roundevenf128")
HANDLE_LIBCALL(ROUNDEVEN_PPCF128, "roundevenl")
HANDLE_LIBCALL(FLOOR_F32, "floorf")
HANDLE_LIBCALL(FLOOR_F64, "floor")
HANDLE_LIBCALL(FLOOR_F80, "floorl")
-HANDLE_LIBCALL(FLOOR_F128, "floorl")
+HANDLE_LIBCALL(FLOOR_F128, "floorf128")
HANDLE_LIBCALL(FLOOR_PPCF128, "floorl")
HANDLE_LIBCALL(COPYSIGN_F32, "copysignf")
HANDLE_LIBCALL(COPYSIGN_F64, "copysign")
HANDLE_LIBCALL(COPYSIGN_F80, "copysignl")
-HANDLE_LIBCALL(COPYSIGN_F128, "copysignl")
+HANDLE_LIBCALL(COPYSIGN_F128, "copysignf128")
HANDLE_LIBCALL(COPYSIGN_PPCF128, "copysignl")
HANDLE_LIBCALL(FMIN_F32, "fminf")
HANDLE_LIBCALL(FMIN_F64, "fmin")
HANDLE_LIBCALL(FMIN_F80, "fminl")
-HANDLE_LIBCALL(FMIN_F128, "fminl")
+HANDLE_LIBCALL(FMIN_F128, "fminf128")
HANDLE_LIBCALL(FMIN_PPCF128, "fminl")
HANDLE_LIBCALL(FMAX_F32, "fmaxf")
HANDLE_LIBCALL(FMAX_F64, "fmax")
HANDLE_LIBCALL(FMAX_F80, "fmaxl")
-HANDLE_LIBCALL(FMAX_F128, "fmaxl")
+HANDLE_LIBCALL(FMAX_F128, "fmaxf128")
HANDLE_LIBCALL(FMAX_PPCF128, "fmaxl")
HANDLE_LIBCALL(FMINIMUM_F32, "fminimumf")
HANDLE_LIBCALL(FMINIMUM_F64, "fminimum")
HANDLE_LIBCALL(FMINIMUM_F80, "fminimuml")
-HANDLE_LIBCALL(FMINIMUM_F128, "fminimuml")
+HANDLE_LIBCALL(FMINIMUM_F128, "fminimumf128")
HANDLE_LIBCALL(FMINIMUM_PPCF128, "fminimuml")
HANDLE_LIBCALL(FMAXIMUM_F32, "fmaximumf")
HANDLE_LIBCALL(FMAXIMUM_F64, "fmaximum")
HANDLE_LIBCALL(FMAXIMUM_F80, "fmaximuml")
-HANDLE_LIBCALL(FMAXIMUM_F128, "fmaximuml")
+HANDLE_LIBCALL(FMAXIMUM_F128, "fmaximumf128")
HANDLE_LIBCALL(FMAXIMUM_PPCF128, "fmaximum_numl")
HANDLE_LIBCALL(FMINIMUMNUM_F32, "fminimum_numf")
HANDLE_LIBCALL(FMINIMUMNUM_F64, "fminimum_num")
HANDLE_LIBCALL(FMINIMUMNUM_F80, "fminimum_numl")
-HANDLE_LIBCALL(FMINIMUMNUM_F128, "fminimum_numl")
+HANDLE_LIBCALL(FMINIMUMNUM_F128, "fminimum_numf128")
HANDLE_LIBCALL(FMINIMUMNUM_PPCF128, "fminimum_numl")
HANDLE_LIBCALL(FMAXIMUMNUM_F32, "fmaximum_numf")
HANDLE_LIBCALL(FMAXIMUMNUM_F64, "fmaximum_num")
HANDLE_LIBCALL(FMAXIMUMNUM_F80, "fmaximum_numl")
-HANDLE_LIBCALL(FMAXIMUMNUM_F128, "fmaximum_numl")
+HANDLE_LIBCALL(FMAXIMUMNUM_F128, "fmaximum_numf128")
HANDLE_LIBCALL(FMAXIMUMNUM_PPCF128, "fmaximum_numl")
HANDLE_LIBCALL(LROUND_F32, "lroundf")
HANDLE_LIBCALL(LROUND_F64, "lround")
HANDLE_LIBCALL(LROUND_F80, "lroundl")
-HANDLE_LIBCALL(LROUND_F128, "lroundl")
+HANDLE_LIBCALL(LROUND_F128, "lroundf128")
HANDLE_LIBCALL(LROUND_PPCF128, "lroundl")
HANDLE_LIBCALL(LLROUND_F32, "llroundf")
HANDLE_LIBCALL(LLROUND_F64, "llround")
HANDLE_LIBCALL(LLROUND_F80, "llroundl")
-HANDLE_LIBCALL(LLROUND_F128, "llroundl")
+HANDLE_LIBCALL(LLROUND_F128, "llroundf128")
HANDLE_LIBCALL(LLROUND_PPCF128, "llroundl")
HANDLE_LIBCALL(LRINT_F32, "lrintf")
HANDLE_LIBCALL(LRINT_F64, "lrint")
HANDLE_LIBCALL(LRINT_F80, "lrintl")
-HANDLE_LIBCALL(LRINT_F128, "lrintl")
+HANDLE_LIBCALL(LRINT_F128, "lrintf128")
HANDLE_LIBCALL(LRINT_PPCF128, "lrintl")
HANDLE_LIBCALL(LLRINT_F32, "llrintf")
HANDLE_LIBCALL(LLRINT_F64, "llrint")
HANDLE_LIBCALL(LLRINT_F80, "llrintl")
-HANDLE_LIBCALL(LLRINT_F128, "llrintl")
+HANDLE_LIBCALL(LLRINT_F128, "llrintf128")
HANDLE_LIBCALL(LLRINT_PPCF128, "llrintl")
HANDLE_LIBCALL(LDEXP_F32, "ldexpf")
HANDLE_LIBCALL(LDEXP_F64, "ldexp")
HANDLE_LIBCALL(LDEXP_F80, "ldexpl")
-HANDLE_LIBCALL(LDEXP_F128, "ldexpl")
+HANDLE_LIBCALL(LDEXP_F128, "ldexpf128")
HANDLE_LIBCALL(LDEXP_PPCF128, "ldexpl")
HANDLE_LIBCALL(FREXP_F32, "frexpf")
HANDLE_LIBCALL(FREXP_F64, "frexp")
HANDLE_LIBCALL(FREXP_F80, "frexpl")
-HANDLE_LIBCALL(FREXP_F128, "frexpl")
+HANDLE_LIBCALL(FREXP_F128, "frexpf128")
HANDLE_LIBCALL(FREXP_PPCF128, "frexpl")
HANDLE_LIBCALL(SINCOSPI_F32, "sincospif")
HANDLE_LIBCALL(SINCOSPI_F64, "sincospi")
HANDLE_LIBCALL(SINCOSPI_F80, "sincospil")
-HANDLE_LIBCALL(SINCOSPI_F128, "sincospil")
+HANDLE_LIBCALL(SINCOSPI_F128, "sincospif128")
HANDLE_LIBCALL(SINCOSPI_PPCF128, "sincospil")
HANDLE_LIBCALL(MODF_F32, "modff")
HANDLE_LIBCALL(MODF_F64, "modf")
HANDLE_LIBCALL(MODF_F80, "modfl")
-HANDLE_LIBCALL(MODF_F128, "modfl")
+HANDLE_LIBCALL(MODF_F128, "modff128")
HANDLE_LIBCALL(MODF_PPCF128, "modfl")
// Floating point environment
diff --git a/llvm/lib/IR/RuntimeLibcalls.cpp b/llvm/lib/IR/RuntimeLibcalls.cpp
index 90c3bf0db0236..22de018d2153d 100644
--- a/llvm/lib/IR/RuntimeLibcalls.cpp
+++ b/llvm/lib/IR/RuntimeLibcalls.cpp
@@ -25,52 +25,53 @@ void RuntimeLibcallsInfo::initLibcalls(const Triple &TT) {
for (int LC = 0; LC < RTLIB::UNKNOWN_LIBCALL; ++LC)
setLibcallCallingConv((RTLIB::Libcall)LC, CallingConv::C);
- // Use the f128 variants of math functions on x86_64
- if (TT.getArch() == Triple::ArchType::x86_64 && TT.isGNUEnvironment()) {
- setLibcallName(RTLIB::REM_F128, "fmodf128");
- setLibcallName(RTLIB::FMA_F128, "fmaf128");
- setLibcallName(RTLIB::SQRT_F128, "sqrtf128");
- setLibcallName(RTLIB::CBRT_F128, "cbrtf128");
- setLibcallName(RTLIB::LOG_F128, "logf128");
- setLibcallName(RTLIB::LOG_FINITE_F128, "__logf128_finite");
- setLibcallName(RTLIB::LOG2_F128, "log2f128");
- setLibcallName(RTLIB::LOG2_FINITE_F128, "__log2f128_finite");
- setLibcallName(RTLIB::LOG10_F128, "log10f128");
- setLibcallName(RTLIB::LOG10_FINITE_F128, "__log10f128_finite");
- setLibcallName(RTLIB::EXP_F128, "expf128");
- setLibcallName(RTLIB::EXP_FINITE_F128, "__expf128_finite");
- setLibcallName(RTLIB::EXP2_F128, "exp2f128");
- setLibcallName(RTLIB::EXP2_FINITE_F128, "__exp2f128_finite");
- setLibcallName(RTLIB::EXP10_F128, "exp10f128");
- setLibcallName(RTLIB::SIN_F128, "sinf128");
- setLibcallName(RTLIB::COS_F128, "cosf128");
- setLibcallName(RTLIB::TAN_F128, "tanf128");
- setLibcallName(RTLIB::SINCOS_F128, "sincosf128");
- setLibcallName(RTLIB::ASIN_F128, "asinf128");
- setLibcallName(RTLIB::ACOS_F128, "acosf128");
- setLibcallName(RTLIB::ATAN_F128, "atanf128");
- setLibcallName(RTLIB::ATAN2_F128, "atan2f128");
- setLibcallName(RTLIB::SINH_F128, "sinhf128");
- setLibcallName(RTLIB::COSH_F128, "coshf128");
- setLibcallName(RTLIB::TANH_F128, "tanhf128");
- setLibcallName(RTLIB::POW_F128, "powf128");
- setLibcallName(RTLIB::POW_FINITE_F128, "__powf128_finite");
- setLibcallName(RTLIB::CEIL_F128, "ceilf128");
- setLibcallName(RTLIB::TRUNC_F128, "truncf128");
- setLibcallName(RTLIB::RINT_F128, "rintf128");
- setLibcallName(RTLIB::NEARBYINT_F128, "nearbyintf128");
- setLibcallName(RTLIB::ROUND_F128, "roundf128");
- setLibcallName(RTLIB::ROUNDEVEN_F128, "roundevenf128");
- setLibcallName(RTLIB::FLOOR_F128, "floorf128");
- setLibcallName(RTLIB::COPYSIGN_F128, "copysignf128");
- setLibcallName(RTLIB::FMIN_F128, "fminf128");
- setLibcallName(RTLIB::FMAX_F128, "fmaxf128");
- setLibcallName(RTLIB::LROUND_F128, "lroundf128");
- setLibcallName(RTLIB::LLROUND_F128, "llroundf128");
- setLibcallName(RTLIB::LRINT_F128, "lrintf128");
- setLibcallName(RTLIB::LLRINT_F128, "llrintf128");
- setLibcallName(RTLIB::LDEXP_F128, "ldexpf128");
- setLibcallName(RTLIB::FREXP_F128, "frexpf128");
+ // The long double version of library functions is more common than the
+ // f128-specific version. Use these if that is the long double type on the
+ // platform, or if the frontend specifies.
+ if (TT.isLongDoubleF128("")) {
+ setLibcallName(RTLIB::ACOS_F128, "acosl");
+ setLibcallName(RTLIB::ASIN_F128, "asinl");
+ setLibcallName(RTLIB::ATAN2_F128,"atan2l");
+ setLibcallName(RTLIB::ATAN_F128,"atanl");
+ setLibcallName(RTLIB::CBRT_F128, "cbrtl");
+ setLibcallName(RTLIB::CEIL_F128, "ceill");
+ setLibcallName(RTLIB::COPYSIGN_F128, "copysignl");
+ setLibcallName(RTLIB::COSH_F128, "coshl");
+ setLibcallName(RTLIB::COS_F128, "cosl");
+ setLibcallName(RTLIB::EXP10_F128, "exp10l");
+ setLibcallName(RTLIB::EXP2_F128, "exp2l");
+ setLibcallName(RTLIB::EXP_F128, "expl");
+ setLibcallName(RTLIB::FLOOR_F128, "floorl");
+ setLibcallName(RTLIB::FMAXIMUMNUM_F128, "fmaximum_numl");
+ setLibcallName(RTLIB::FMAXIMUM_F128, "fmaximuml");
+ setLibcallName(RTLIB::FMAX_F128, "fmaxl");
+ setLibcallName(RTLIB::FMA_F128, "fmal");
+ setLibcallName(RTLIB::FMINIMUMNUM_F128, "fminimum_numl");
+ setLibcallName(RTLIB::FMINIMUM_F128, "fminimuml");
+ setLibcallName(RTLIB::FMIN_F128, "fminl");
+ setLibcallName(RTLIB::FREXP_F128, "frexpl");
+ setLibcallName(RTLIB::LDEXP_F128, "ldexpl");
+ setLibcallName(RTLIB::LLRINT_F128, "llrintl");
+ setLibcallName(RTLIB::LLROUND_F128, "llroundl");
+ setLibcallName(RTLIB::LOG10_F128, "log10l");
+ setLibcallName(RTLIB::LOG2_F128, "log2l");
+ setLibcallName(RTLIB::LOG_F128, "logl");
+ setLibcallName(RTLIB::LRINT_F128, "lrintl");
+ setLibcallName(RTLIB::LROUND_F128, "lroundl");
+ setLibcallName(RTLIB::MODF_F128, "modfl");
+ setLibcallName(RTLIB::NEARBYINT_F128, "nearbyintl");
+ setLibcallName(RTLIB::POW_F128, "powl");
+ setLibcallName(RTLIB::REM_F128, "fmodl");
+ setLibcallName(RTLIB::RINT_F128, "rintl");
+ setLibcallName(RTLIB::ROUNDEVEN_F128, "roundevenl");
+ setLibcallName(RTLIB::ROUND_F128, "roundl");
+ setLibcallName(RTLIB::SINCOSPI_F128, "sincospil");
+ setLibcallName(RTLIB::SINH_F128, "sinhl");
+ setLibcallName(RTLIB::SIN_F128, "sinl");
+ setLibcallName(RTLIB::SQRT_F128, "sqrtl");
+ setLibcallName(RTLIB::TANH_F128,"tanhl");
+ setLibcallName(RTLIB::TAN_F128,"tanl");
+ setLibcallName(RTLIB::TRUNC_F128, "truncl");
}
// For IEEE quad-precision libcall names, PPC uses "kf" instead of "tf".
@@ -178,7 +179,6 @@ void RuntimeLibcallsInfo::initLibcalls(const Triple &TT) {
setLibcallName(RTLIB::SINCOS_F32, "sincosf");
setLibcallName(RTLIB::SINCOS_F64, "sincos");
setLibcallName(RTLIB::SINCOS_F80, "sincosl");
- setLibcallName(RTLIB::SINCOS_F128, "sincosl");
setLibcallName(RTLIB::SINCOS_PPCF128, "sincosl");
}
diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
index 0800ed5dfce2c..221d775b97e50 100644
--- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
+++ b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
@@ -1425,32 +1425,6 @@ PPCTargetLowering::PPCTargetLowering(const PPCTargetMachine &TM,
setTargetDAGCombine({ISD::TRUNCATE, ISD::SETCC, ISD::SELECT_CC});
}
- setLibcallName(RTLIB::LOG_F128, "logf128");
- setLibcallName(RTLIB::LOG2_F128, "log2f128");
- setLibcallName(RTLIB::LOG10_F128, "log10f128");
- setLibcallName(RTLIB::EXP_F128, "expf128");
- setLibcallName(RTLIB::EXP2_F128, "exp2f128");
- setLibcallName(RTLIB::SIN_F128, "sinf128");
- setLibcallName(RTLIB::COS_F128, "cosf128");
- setLibcallName(RTLIB::SINCOS_F128, "sincosf128");
- setLibcallName(RTLIB::POW_F128, "powf128");
- setLibcallName(RTLIB::FMIN_F128, "fminf128");
- setLibcallName(RTLIB::FMAX_F128, "fmaxf128");
- setLibcallName(RTLIB::REM_F128, "fmodf128");
- setLibcallName(RTLIB::SQRT_F128, "sqrtf128");
- setLibcallName(RTLIB::CEIL_F128, "ceilf128");
- setLibcallName(RTLIB::FLOOR_F128, "floorf128");
- setLibcallName(RTLIB::TRUNC_F128, "truncf128");
- setLibcallName(RTLIB::ROUND_F128, "roundf128");
- setLibcallName(RTLIB::LROUND_F128, "lroundf128");
- setLibcallName(RTLIB::LLROUND_F128, "llroundf128");
- setLibcallName(RTLIB::RINT_F128, "rintf128");
- setLibcallName(RTLIB::LRINT_F128, "lrintf128");
- setLibcallName(RTLIB::LLRINT_F128, "llrintf128");
- setLibcallName(RTLIB::NEARBYINT_F128, "nearbyintf128");
- setLibcallName(RTLIB::FMA_F128, "fmaf128");
- setLibcallName(RTLIB::FREXP_F128, "frexpf128");
-
if (Subtarget.isAIXABI()) {
setLibcallName(RTLIB::MEMCPY, isPPC64 ? "___memmove64" : "___memmove");
setLibcallName(RTLIB::MEMMOVE, isPPC64 ? "___memmove64" : "___memmove");
diff --git a/llvm/test/CodeGen/Generic/f128-math-lowering.ll b/llvm/test/CodeGen/Generic/f128-math-lowering.ll
index dfbd1eaeda109..a68cd1c39698e 100644
--- a/llvm/test/CodeGen/Generic/f128-math-lowering.ll
+++ b/llvm/test/CodeGen/Generic/f128-math-lowering.ll
@@ -1,12 +1,15 @@
; RUN: llc < %s -mtriple=aarch64-unknown-none -verify-machineinstrs | FileCheck %s --check-prefix=CHECK-USELD
-; RUN: llc < %s -mtriple=i686-unknown -verify-machineinstrs | FileCheck %s --check-prefix=CHECK-USELD
-; RUN: llc < %s -mtriple=riscv32 -verify-machineinstrs | FileCheck %s --check-prefix=CHECK-USELD
+; RUN: llc < %s -mtriple=i686-unknown -verify-machineinstrs | FileCheck %s --check-prefix=CHECK-NOTLD
+; RUN: llc < %s -mtriple=powerpc-unknown -verify-machineinstrs | FileCheck %s --check-prefix=CHECK-NOTLD
+; RUN: llc < %s -mtriple=powerpc64-unknown -verify-machineinstrs | FileCheck %s --check-prefix=CHECK-NOTLD
+; RUN: llc < %s -mtriple=riscv32 -verify-machineinstrs | FileCheck %s --check-prefix=CHECK-NOTLD
; RUN: llc < %s -mtriple=s390x-unknown -verify-machineinstrs | FileCheck %s --check-prefix=CHECK-S390X
-; RUN: llc < %s -mtriple=x86_64-unknown -verify-machineinstrs | FileCheck %s --check-prefix=CHECK-USELD
+; RUN: llc < %s -mtriple=x86_64-unknown -verify-machineinstrs | FileCheck %s --check-prefix=CHECK-NOTLD
; RUN: llc < %s -mtriple=x86_64-unknown-linux-gnu -verify-machineinstrs | FileCheck %s --check-prefix=CHECK-NOTLD
-; RUN: llc < %s -mtriple=x86_64-unknown-linux-musl -verify-machineinstrs | FileCheck %s --check-prefix=CHECK-USELD
+; RUN: llc < %s -mtriple=x86_64-unknown-linux-musl -verify-machineinstrs | FileCheck %s --check-prefix=CHECK-NOTLD
;
; REQUIRES: aarch64-registered-target
+; REQUIRES: powerpc-registered-target
; REQUIRES: riscv-registered-target
; REQUIRES: systemz-registered-target
; REQUIRES: x86-registered-target
>From 7c0c32e847b185f1db764b517ea448a9bfa06cfe Mon Sep 17 00:00:00 2001
From: Trevor Gross <tmgross at umich.edu>
Date: Thu, 27 Feb 2025 09:38:09 +0000
Subject: [PATCH 3/5] Move changes away from f128 libcalls to an adjust
function
Move to a module flag
Add new musl variants for f128 availability
cleanup
---
clang/lib/Basic/Targets.cpp | 3 +-
clang/lib/Driver/Driver.cpp | 6 +-
.../lib/Driver/ToolChains/Arch/LoongArch.cpp | 2 +
clang/lib/Driver/ToolChains/Linux.cpp | 3 +
clang/test/CodeGen/f128-math-lowering.c | 15 ++
llvm/include/llvm/IR/RuntimeLibcalls.def | 3 +-
llvm/include/llvm/IR/RuntimeLibcalls.h | 27 ++-
llvm/include/llvm/TargetParser/Triple.h | 26 ++-
llvm/lib/IR/RuntimeLibcalls.cpp | 98 +++++------
llvm/lib/Target/Hexagon/HexagonSubtarget.h | 2 +-
.../MCTargetDesc/LoongArchBaseInfo.cpp | 2 +
llvm/lib/TargetParser/Triple.cpp | 8 +
.../CodeGen/Generic/f128-math-lowering.ll | 162 ++++++++++--------
13 files changed, 217 insertions(+), 140 deletions(-)
create mode 100644 clang/test/CodeGen/f128-math-lowering.c
diff --git a/clang/lib/Basic/Targets.cpp b/clang/lib/Basic/Targets.cpp
index c6d228fe98100..fe4e9142c22ae 100644
--- a/clang/lib/Basic/Targets.cpp
+++ b/clang/lib/Basic/Targets.cpp
@@ -124,8 +124,7 @@ std::unique_ptr<TargetInfo> AllocateTarget(const llvm::Triple &Triple,
return std::make_unique<XCoreTargetInfo>(Triple, Opts);
case llvm::Triple::hexagon:
- if (os == llvm::Triple::Linux &&
- Triple.getEnvironment() == llvm::Triple::Musl)
+ if (os == llvm::Triple::Linux && Triple.isMusl())
return std::make_unique<LinuxTargetInfo<HexagonTargetInfo>>(Triple, Opts);
return std::make_unique<HexagonTargetInfo>(Triple, Opts);
diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp
index 2b8c6e35263b1..889dc9806149b 100644
--- a/clang/lib/Driver/Driver.cpp
+++ b/clang/lib/Driver/Driver.cpp
@@ -797,8 +797,7 @@ static llvm::Triple computeTargetTriple(const Driver &D,
Target.getEnvironment() == llvm::Triple::GNUT64 ||
Target.getEnvironment() == llvm::Triple::GNUABI64)
Target.setEnvironment(llvm::Triple::GNUABIN32);
- else if (Target.getEnvironment() == llvm::Triple::Musl ||
- Target.getEnvironment() == llvm::Triple::MuslABI64)
+ else if (Target.isMusl())
Target.setEnvironment(llvm::Triple::MuslABIN32);
} else if (ABIName == "64") {
Target = Target.get64BitArchVariant();
@@ -809,6 +808,9 @@ static llvm::Triple computeTargetTriple(const Driver &D,
else if (Target.getEnvironment() == llvm::Triple::Musl ||
Target.getEnvironment() == llvm::Triple::MuslABIN32)
Target.setEnvironment(llvm::Triple::MuslABI64);
+ else if (Target.getEnvironment() == llvm::Triple::MuslF128 ||
+ Target.getEnvironment() == llvm::Triple::MuslABIN3F128)
+ Target.setEnvironment(llvm::Triple::MuslABI64F128);
}
}
}
diff --git a/clang/lib/Driver/ToolChains/Arch/LoongArch.cpp b/clang/lib/Driver/ToolChains/Arch/LoongArch.cpp
index 0575a1ebef3a6..75f875ab936b1 100644
--- a/clang/lib/Driver/ToolChains/Arch/LoongArch.cpp
+++ b/clang/lib/Driver/ToolChains/Arch/LoongArch.cpp
@@ -105,9 +105,11 @@ StringRef loongarch::getLoongArchABI(const Driver &D, const ArgList &Args,
switch (Triple.getEnvironment()) {
case llvm::Triple::GNUSF:
case llvm::Triple::MuslSF:
+ case llvm::Triple::MuslSFF128:
return IsLA32 ? "ilp32s" : "lp64s";
case llvm::Triple::GNUF32:
case llvm::Triple::MuslF32:
+ case llvm::Triple::MuslF32F128:
return IsLA32 ? "ilp32f" : "lp64f";
case llvm::Triple::GNUF64:
// This was originally permitted (and indeed the canonical way) to
diff --git a/clang/lib/Driver/ToolChains/Linux.cpp b/clang/lib/Driver/ToolChains/Linux.cpp
index 1e9bd3de75f04..1bcba0220d531 100644
--- a/clang/lib/Driver/ToolChains/Linux.cpp
+++ b/clang/lib/Driver/ToolChains/Linux.cpp
@@ -110,15 +110,18 @@ std::string Linux::getMultiarchTriple(const Driver &D,
return TargetTriple.str();
case llvm::Triple::GNUSF:
case llvm::Triple::MuslSF:
+ case llvm::Triple::MuslSFF128:
FPFlavor = "sf";
break;
case llvm::Triple::GNUF32:
case llvm::Triple::MuslF32:
+ case llvm::Triple::MuslF32F128:
FPFlavor = "f32";
break;
case llvm::Triple::GNU:
case llvm::Triple::GNUF64:
case llvm::Triple::Musl:
+ case llvm::Triple::MuslF128:
// This was going to be "f64" in an earlier Toolchain Conventions
// revision, but starting from Feb 2023 the F64 ABI variants are
// unmarked in their canonical forms.
diff --git a/clang/test/CodeGen/f128-math-lowering.c b/clang/test/CodeGen/f128-math-lowering.c
new file mode 100644
index 0000000000000..aa58238faad92
--- /dev/null
+++ b/clang/test/CodeGen/f128-math-lowering.c
@@ -0,0 +1,15 @@
+// RUN: %clang_cc1 -triple x86_64-linux-android -emit-llvm -o - %s \
+// RUN: | FileCheck %s --check-prefix=A64
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -o - %s \
+// RUN: | FileCheck %s --check-prefix=G64
+// RUN: %clang_cc1 -triple powerpc64-linux-gnu -emit-llvm -o - %s \
+// RUN: | FileCheck %s --check-prefix=P64
+// RUN: %clang_cc1 -triple i686-linux-android -emit-llvm -o - %s \
+// RUN: | FileCheck %s --check-prefix=A32
+// RUN: %clang_cc1 -triple i686-linux-gnu -emit-llvm -o - %s \
+// RUN: | FileCheck %s --check-prefix=G32
+// RUN: %clang_cc1 -triple powerpc-linux-gnu -emit-llvm -o - %s \
+// RUN: | FileCheck %s --check-prefix=P32
+// RUN: %clang_cc1 -triple x86_64-nacl -emit-llvm -o - %s \
+// RUN: | FileCheck %s --check-prefix=N64
+
diff --git a/llvm/include/llvm/IR/RuntimeLibcalls.def b/llvm/include/llvm/IR/RuntimeLibcalls.def
index 8680dfb59be30..e5f9ee3b2f384 100644
--- a/llvm/include/llvm/IR/RuntimeLibcalls.def
+++ b/llvm/include/llvm/IR/RuntimeLibcalls.def
@@ -89,7 +89,8 @@ HANDLE_LIBCALL(CTPOP_I32, "__popcountsi2")
HANDLE_LIBCALL(CTPOP_I64, "__popcountdi2")
HANDLE_LIBCALL(CTPOP_I128, "__popcountti2")
-// Floating-point
+// Floating-point. Note that new fp128 math routines should also be added to
+// setF128LibcallFormat in RuntimeLibcalls.cpp.
HANDLE_LIBCALL(ADD_F32, "__addsf3")
HANDLE_LIBCALL(ADD_F64, "__adddf3")
HANDLE_LIBCALL(ADD_F80, "__addxf3")
diff --git a/llvm/include/llvm/IR/RuntimeLibcalls.h b/llvm/include/llvm/IR/RuntimeLibcalls.h
index b3648f5a31e2a..a4fbb61f40bdb 100644
--- a/llvm/include/llvm/IR/RuntimeLibcalls.h
+++ b/llvm/include/llvm/IR/RuntimeLibcalls.h
@@ -14,12 +14,25 @@
#ifndef LLVM_IR_RUNTIME_LIBCALLS_H
#define LLVM_IR_RUNTIME_LIBCALLS_H
+#include "llvm/ADT/APFloat.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/IR/CallingConv.h"
#include "llvm/Support/AtomicOrdering.h"
+#include "llvm/Target/TargetMachine.h"
#include "llvm/TargetParser/Triple.h"
namespace llvm {
+
+/// Library names to use for `fp128` libcalls.
+// If needed, this could be extended with a `Quadmath` option for `q`-suffixed
+// `libquadmath` symbols.
+enum class F128LibcallFormat {
+ /// C23 `*f128` lowering, e.g. `sinf128`
+ Default = 0,
+ /// `long double` *l` lowering, e.g. `sinl`.
+ LongDouble = 1,
+};
+
namespace RTLIB {
/// RTLIB::Libcall enum - This enum defines all of the runtime library calls
@@ -38,9 +51,9 @@ enum Libcall {
/// A simple container for information about the supported runtime calls.
struct RuntimeLibcallsInfo {
- explicit RuntimeLibcallsInfo(const Triple &TT) {
- initLibcalls(TT);
- }
+ /// Default libcalls for the triple. Note that `fixupLibcalls` should also be
+ /// called in order to apply machine-specific and configurable behavior.
+ explicit RuntimeLibcallsInfo(const Triple &TT) { initLibcalls(TT); }
/// Rename the default libcall routine name for the specified libcall.
void setLibcallName(RTLIB::Libcall Call, const char *Name) {
@@ -72,6 +85,14 @@ struct RuntimeLibcallsInfo {
LibcallRoutineNames + RTLIB::UNKNOWN_LIBCALL);
}
+ /// Set a specific lowering convention for `fp128` math libcalls.
+ ///
+ /// By default, `fp128` math functions get lowered to the C23 `sinf128`-
+ /// style symbols. This allows overriding with `sinl`-style symbols on
+ /// platforms where `long double` is known to be identical to _Float128.
+ /// versions, e.g. `sinf128`.
+ void setF128LibcallFormat(F128LibcallFormat Format);
+
private:
/// Stores the name each libcall.
const char *LibcallRoutineNames[RTLIB::UNKNOWN_LIBCALL + 1];
diff --git a/llvm/include/llvm/TargetParser/Triple.h b/llvm/include/llvm/TargetParser/Triple.h
index fb6bbc0163701..8dbebd9e39bcb 100644
--- a/llvm/include/llvm/TargetParser/Triple.h
+++ b/llvm/include/llvm/TargetParser/Triple.h
@@ -262,13 +262,21 @@ class Triple {
EABIHF,
Android,
Musl,
- MuslABIN32,
- MuslABI64,
- MuslEABI,
- MuslEABIHF,
- MuslF32,
- MuslSF,
- MuslX32,
+ MuslABIN32, // MIPS N32 ABI
+ MuslABI64, // MIPS N64 ABI
+ MuslEABI, // Arm32 EABI
+ MuslEABIHF, // Arm32 EABI + HF
+ MuslF32, // LoongArch ILP32F/LP64F
+ MuslSF, // LoongArch ILP32S/LP64S
+ MuslX32, // Musl using 32-bit ABI on x86_64
+ // Musl with `*f128` math symbols available (e.g. `sqrtf128` rather than
+ // only `sqrtl`). 32-bit musl variants are excluded sin e `*f128` symbols
+ // are required to use `fp128` at all.
+ MuslF128,
+ MuslABI64F128,
+ MuslF32F128,
+ MuslSFF128,
+
LLVM,
MSVC,
@@ -827,6 +835,10 @@ class Triple {
getEnvironment() == Triple::MuslF32 ||
getEnvironment() == Triple::MuslSF ||
getEnvironment() == Triple::MuslX32 ||
+ getEnvironment() == Triple::MuslF128 ||
+ getEnvironment() == Triple::MuslABI64F128 ||
+ getEnvironment() == Triple::MuslF32F128 ||
+ getEnvironment() == Triple::MuslSFF128 ||
getEnvironment() == Triple::OpenHOS || isOSLiteOS();
}
diff --git a/llvm/lib/IR/RuntimeLibcalls.cpp b/llvm/lib/IR/RuntimeLibcalls.cpp
index 22de018d2153d..1f752476c82ab 100644
--- a/llvm/lib/IR/RuntimeLibcalls.cpp
+++ b/llvm/lib/IR/RuntimeLibcalls.cpp
@@ -7,6 +7,7 @@
//===----------------------------------------------------------------------===//
#include "llvm/IR/RuntimeLibcalls.h"
+#include "llvm/Target/TargetMachine.h"
using namespace llvm;
using namespace RTLIB;
@@ -25,55 +26,6 @@ void RuntimeLibcallsInfo::initLibcalls(const Triple &TT) {
for (int LC = 0; LC < RTLIB::UNKNOWN_LIBCALL; ++LC)
setLibcallCallingConv((RTLIB::Libcall)LC, CallingConv::C);
- // The long double version of library functions is more common than the
- // f128-specific version. Use these if that is the long double type on the
- // platform, or if the frontend specifies.
- if (TT.isLongDoubleF128("")) {
- setLibcallName(RTLIB::ACOS_F128, "acosl");
- setLibcallName(RTLIB::ASIN_F128, "asinl");
- setLibcallName(RTLIB::ATAN2_F128,"atan2l");
- setLibcallName(RTLIB::ATAN_F128,"atanl");
- setLibcallName(RTLIB::CBRT_F128, "cbrtl");
- setLibcallName(RTLIB::CEIL_F128, "ceill");
- setLibcallName(RTLIB::COPYSIGN_F128, "copysignl");
- setLibcallName(RTLIB::COSH_F128, "coshl");
- setLibcallName(RTLIB::COS_F128, "cosl");
- setLibcallName(RTLIB::EXP10_F128, "exp10l");
- setLibcallName(RTLIB::EXP2_F128, "exp2l");
- setLibcallName(RTLIB::EXP_F128, "expl");
- setLibcallName(RTLIB::FLOOR_F128, "floorl");
- setLibcallName(RTLIB::FMAXIMUMNUM_F128, "fmaximum_numl");
- setLibcallName(RTLIB::FMAXIMUM_F128, "fmaximuml");
- setLibcallName(RTLIB::FMAX_F128, "fmaxl");
- setLibcallName(RTLIB::FMA_F128, "fmal");
- setLibcallName(RTLIB::FMINIMUMNUM_F128, "fminimum_numl");
- setLibcallName(RTLIB::FMINIMUM_F128, "fminimuml");
- setLibcallName(RTLIB::FMIN_F128, "fminl");
- setLibcallName(RTLIB::FREXP_F128, "frexpl");
- setLibcallName(RTLIB::LDEXP_F128, "ldexpl");
- setLibcallName(RTLIB::LLRINT_F128, "llrintl");
- setLibcallName(RTLIB::LLROUND_F128, "llroundl");
- setLibcallName(RTLIB::LOG10_F128, "log10l");
- setLibcallName(RTLIB::LOG2_F128, "log2l");
- setLibcallName(RTLIB::LOG_F128, "logl");
- setLibcallName(RTLIB::LRINT_F128, "lrintl");
- setLibcallName(RTLIB::LROUND_F128, "lroundl");
- setLibcallName(RTLIB::MODF_F128, "modfl");
- setLibcallName(RTLIB::NEARBYINT_F128, "nearbyintl");
- setLibcallName(RTLIB::POW_F128, "powl");
- setLibcallName(RTLIB::REM_F128, "fmodl");
- setLibcallName(RTLIB::RINT_F128, "rintl");
- setLibcallName(RTLIB::ROUNDEVEN_F128, "roundevenl");
- setLibcallName(RTLIB::ROUND_F128, "roundl");
- setLibcallName(RTLIB::SINCOSPI_F128, "sincospil");
- setLibcallName(RTLIB::SINH_F128, "sinhl");
- setLibcallName(RTLIB::SIN_F128, "sinl");
- setLibcallName(RTLIB::SQRT_F128, "sqrtl");
- setLibcallName(RTLIB::TANH_F128,"tanhl");
- setLibcallName(RTLIB::TAN_F128,"tanl");
- setLibcallName(RTLIB::TRUNC_F128, "truncl");
- }
-
// For IEEE quad-precision libcall names, PPC uses "kf" instead of "tf".
if (TT.isPPC()) {
setLibcallName(RTLIB::ADD_F128, "__addkf3");
@@ -254,3 +206,51 @@ void RuntimeLibcallsInfo::initLibcalls(const Triple &TT) {
setLibcallName(RTLIB::MULO_I128, nullptr);
}
}
+
+void RuntimeLibcallsInfo::setF128LibcallFormat(F128LibcallFormat Format) {
+ bool UseLD = Format == F128LibcallFormat::LongDouble;
+
+ setLibcallName(RTLIB::ACOS_F128, UseLD ? "acosl" : "acosf128");
+ setLibcallName(RTLIB::ASIN_F128, UseLD ? "asinl" : "asinf128");
+ setLibcallName(RTLIB::ATAN2_F128, UseLD ? "atan2l" : "atan2f128");
+ setLibcallName(RTLIB::ATAN_F128, UseLD ? "atanl" : "atanf128");
+ setLibcallName(RTLIB::CBRT_F128, UseLD ? "cbrtl" : "cbrtf128");
+ setLibcallName(RTLIB::CEIL_F128, UseLD ? "ceill" : "ceilf128");
+ setLibcallName(RTLIB::COPYSIGN_F128, UseLD ? "copysignl" : "copysignf128");
+ setLibcallName(RTLIB::COSH_F128, UseLD ? "coshl" : "coshf128");
+ setLibcallName(RTLIB::COS_F128, UseLD ? "cosl" : "cosf128");
+ setLibcallName(RTLIB::EXP10_F128, UseLD ? "exp10l" : "exp10f128");
+ setLibcallName(RTLIB::EXP2_F128, UseLD ? "exp2l" : "exp2f128");
+ setLibcallName(RTLIB::EXP_F128, UseLD ? "expl" : "expf128");
+ setLibcallName(RTLIB::FLOOR_F128, UseLD ? "floorl" : "floorf128");
+ setLibcallName(RTLIB::FMAXIMUMNUM_F128, UseLD ? "fmaximum_numl" : "fmaximum_numf128");
+ setLibcallName(RTLIB::FMAXIMUM_F128, UseLD ? "fmaximuml" : "fmaximumf128");
+ setLibcallName(RTLIB::FMAX_F128, UseLD ? "fmaxl" : "fmaxf128");
+ setLibcallName(RTLIB::FMA_F128, UseLD ? "fmal" : "fmaf128");
+ setLibcallName(RTLIB::FMINIMUMNUM_F128, UseLD ? "fminimum_numl" : "fminimum_numf128");
+ setLibcallName(RTLIB::FMINIMUM_F128, UseLD ? "fminimuml" : "fminimumf128");
+ setLibcallName(RTLIB::FMIN_F128, UseLD ? "fminl" : "fminf128");
+ setLibcallName(RTLIB::FREXP_F128, UseLD ? "frexpl" : "frexpf128");
+ setLibcallName(RTLIB::LDEXP_F128, UseLD ? "ldexpl" : "ldexpf128");
+ setLibcallName(RTLIB::LLRINT_F128, UseLD ? "llrintl" : "llrintf128");
+ setLibcallName(RTLIB::LLROUND_F128, UseLD ? "llroundl" : "llroundf128");
+ setLibcallName(RTLIB::LOG10_F128, UseLD ? "log10l" : "log10f128");
+ setLibcallName(RTLIB::LOG2_F128, UseLD ? "log2l" : "log2f128");
+ setLibcallName(RTLIB::LOG_F128, UseLD ? "logl" : "logf128");
+ setLibcallName(RTLIB::LRINT_F128, UseLD ? "lrintl" : "lrintf128");
+ setLibcallName(RTLIB::LROUND_F128, UseLD ? "lroundl" : "lroundf128");
+ setLibcallName(RTLIB::MODF_F128, UseLD ? "modfl" : "modff128");
+ setLibcallName(RTLIB::NEARBYINT_F128, UseLD ? "nearbyintl" : "nearbyintf128");
+ setLibcallName(RTLIB::POW_F128, UseLD ? "powl" : "powf128");
+ setLibcallName(RTLIB::REM_F128, UseLD ? "fmodl" : "fmodf128");
+ setLibcallName(RTLIB::RINT_F128, UseLD ? "rintl" : "rintf128");
+ setLibcallName(RTLIB::ROUNDEVEN_F128, UseLD ? "roundevenl" : "roundevenf128");
+ setLibcallName(RTLIB::ROUND_F128, UseLD ? "roundl" : "roundf128");
+ setLibcallName(RTLIB::SINCOSPI_F128, UseLD ? "sincospil" : "sincospif128");
+ setLibcallName(RTLIB::SINH_F128, UseLD ? "sinhl" : "sinhf128");
+ setLibcallName(RTLIB::SIN_F128, UseLD ? "sinl" : "sinf128");
+ setLibcallName(RTLIB::SQRT_F128, UseLD ? "sqrtl" : "sqrtf128");
+ setLibcallName(RTLIB::TANH_F128, UseLD ? "tanhl" : "tanhf128");
+ setLibcallName(RTLIB::TAN_F128, UseLD ? "tanl" : "tanf128");
+ setLibcallName(RTLIB::TRUNC_F128, UseLD ? "truncl" : "truncf128");
+}
diff --git a/llvm/lib/Target/Hexagon/HexagonSubtarget.h b/llvm/lib/Target/Hexagon/HexagonSubtarget.h
index 41555db4ac662..606bdab37bf93 100644
--- a/llvm/lib/Target/Hexagon/HexagonSubtarget.h
+++ b/llvm/lib/Target/Hexagon/HexagonSubtarget.h
@@ -113,7 +113,7 @@ class HexagonSubtarget : public HexagonGenSubtargetInfo {
const Triple &getTargetTriple() const { return TargetTriple; }
bool isEnvironmentMusl() const {
- return TargetTriple.getEnvironment() == Triple::Musl;
+ return TargetTriple.isMusl();
}
/// getInstrItins - Return the instruction itineraries based on subtarget
diff --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchBaseInfo.cpp b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchBaseInfo.cpp
index 03ce004ed33a5..c15ded457bbe3 100644
--- a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchBaseInfo.cpp
+++ b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchBaseInfo.cpp
@@ -54,10 +54,12 @@ static ABI getTripleABI(const Triple &TT) {
switch (TT.getEnvironment()) {
case llvm::Triple::EnvironmentType::GNUSF:
case llvm::Triple::EnvironmentType::MuslSF:
+ case llvm::Triple::EnvironmentType::MuslSFF128:
TripleABI = Is64Bit ? ABI_LP64S : ABI_ILP32S;
break;
case llvm::Triple::EnvironmentType::GNUF32:
case llvm::Triple::EnvironmentType::MuslF32:
+ case llvm::Triple::EnvironmentType::MuslF32F128:
TripleABI = Is64Bit ? ABI_LP64F : ABI_ILP32F;
break;
// Let the fallback case behave like {ILP32,LP64}D.
diff --git a/llvm/lib/TargetParser/Triple.cpp b/llvm/lib/TargetParser/Triple.cpp
index 74363f8d71b65..0ead84d7ecbad 100644
--- a/llvm/lib/TargetParser/Triple.cpp
+++ b/llvm/lib/TargetParser/Triple.cpp
@@ -361,6 +361,10 @@ StringRef Triple::getEnvironmentTypeName(EnvironmentType Kind) {
case MuslSF:
return "muslsf";
case MuslX32: return "muslx32";
+ case MuslF128: return "musl_f128";
+ case MuslABI64F128: return "muslabi64_f128";
+ case MuslF32F128: return "muslf32_f128";
+ case MuslSFF128: return "muslsf_f128";
case Simulator: return "simulator";
case Pixel: return "pixel";
case Vertex: return "vertex";
@@ -733,6 +737,10 @@ static Triple::EnvironmentType parseEnvironment(StringRef EnvironmentName) {
.StartsWith("gnut64", Triple::GNUT64)
.StartsWith("gnu", Triple::GNU)
.StartsWith("android", Triple::Android)
+ .StartsWith("muslabi64_f128", Triple::MuslABI64F128)
+ .StartsWith("muslf32_f128", Triple::MuslF32F128)
+ .StartsWith("muslsf_f128", Triple::MuslSFF128)
+ .StartsWith("musl_f128", Triple::MuslF128)
.StartsWith("muslabin32", Triple::MuslABIN32)
.StartsWith("muslabi64", Triple::MuslABI64)
.StartsWith("musleabihf", Triple::MuslEABIHF)
diff --git a/llvm/test/CodeGen/Generic/f128-math-lowering.ll b/llvm/test/CodeGen/Generic/f128-math-lowering.ll
index a68cd1c39698e..d8ed0f9d84663 100644
--- a/llvm/test/CodeGen/Generic/f128-math-lowering.ll
+++ b/llvm/test/CodeGen/Generic/f128-math-lowering.ll
@@ -1,12 +1,22 @@
-; RUN: llc < %s -mtriple=aarch64-unknown-none -verify-machineinstrs | FileCheck %s --check-prefix=CHECK-USELD
-; RUN: llc < %s -mtriple=i686-unknown -verify-machineinstrs | FileCheck %s --check-prefix=CHECK-NOTLD
-; RUN: llc < %s -mtriple=powerpc-unknown -verify-machineinstrs | FileCheck %s --check-prefix=CHECK-NOTLD
-; RUN: llc < %s -mtriple=powerpc64-unknown -verify-machineinstrs | FileCheck %s --check-prefix=CHECK-NOTLD
-; RUN: llc < %s -mtriple=riscv32 -verify-machineinstrs | FileCheck %s --check-prefix=CHECK-NOTLD
-; RUN: llc < %s -mtriple=s390x-unknown -verify-machineinstrs | FileCheck %s --check-prefix=CHECK-S390X
-; RUN: llc < %s -mtriple=x86_64-unknown -verify-machineinstrs | FileCheck %s --check-prefix=CHECK-NOTLD
-; RUN: llc < %s -mtriple=x86_64-unknown-linux-gnu -verify-machineinstrs | FileCheck %s --check-prefix=CHECK-NOTLD
-; RUN: llc < %s -mtriple=x86_64-unknown-linux-musl -verify-machineinstrs | FileCheck %s --check-prefix=CHECK-NOTLD
+;
+; RUN: llc < %s -mtriple=aarch64-unknown-none -verify-machineinstrs | FileCheck %s --check-prefixes=CHECK,CHECK-F128
+; RUN: llc < %s -mtriple=i686-unknown -verify-machineinstrs | FileCheck %s --check-prefixes=CHECK,CHECK-F128
+; RUN: llc < %s -mtriple=powerpc-unknown -verify-machineinstrs | FileCheck %s --check-prefixes=CHECK,CHECK-F128
+; RUN: llc < %s -mtriple=powerpc64-unknown -verify-machineinstrs | FileCheck %s --check-prefixes=CHECK,CHECK-F128
+; RUN: llc < %s -mtriple=riscv32 -verify-machineinstrs | FileCheck %s --check-prefixes=CHECK,CHECK-F128
+; RUN: llc < %s -mtriple=s390x-unknown -verify-machineinstrs | FileCheck %s --check-prefixes=CHECK,CHECK-S390X
+; RUN: llc < %s -mtriple=x86_64-unknown -verify-machineinstrs | FileCheck %s --check-prefixes=CHECK,CHECK-F128
+; RUN: llc < %s -mtriple=x86_64-unknown-linux-gnu -verify-machineinstrs | FileCheck %s --check-prefixes=CHECK,CHECK-F128
+; RUN: llc < %s -mtriple=x86_64-unknown-linux-musl -verify-machineinstrs | FileCheck %s --check-prefixes=CHECK,CHECK-F128
+; RUN: sed 's/; flag://' %s | llc -mtriple=aarch64-unknown-none -verify-machineinstrs | FileCheck %s --check-prefixes=CHECK,CHECK-USELD
+; RUN: sed 's/; flag://' %s | llc -mtriple=i686-unknown -verify-machineinstrs | FileCheck %s --check-prefixes=CHECK,CHECK-USELD
+; RUN: sed 's/; flag://' %s | llc -mtriple=powerpc-unknown -verify-machineinstrs | FileCheck %s --check-prefixes=CHECK,CHECK-USELD
+; RUN: sed 's/; flag://' %s | llc -mtriple=powerpc64-unknown -verify-machineinstrs | FileCheck %s --check-prefixes=CHECK,CHECK-USELD
+; RUN: sed 's/; flag://' %s | llc -mtriple=riscv32 -verify-machineinstrs | FileCheck %s --check-prefixes=CHECK,CHECK-USELD
+; RUN: sed 's/; flag://' %s | llc -mtriple=s390x-unknown -verify-machineinstrs | FileCheck %s --check-prefixes=CHECK,CHECK-S390X
+; RUN: sed 's/; flag://' %s | llc -mtriple=x86_64-unknown -verify-machineinstrs | FileCheck %s --check-prefixes=CHECK,CHECK-USELD
+; RUN: sed 's/; flag://' %s | llc -mtriple=x86_64-unknown-linux-gnu -verify-machineinstrs | FileCheck %s --check-prefixes=CHECK,CHECK-USELD
+; RUN: sed 's/; flag://' %s | llc -mtriple=x86_64-unknown-linux-musl -verify-machineinstrs | FileCheck %s --check-prefixes=CHECK,CHECK-USELD
;
; REQUIRES: aarch64-registered-target
; REQUIRES: powerpc-registered-target
@@ -24,16 +34,16 @@
; * riscv32 (long double == f64)
; * s390x (long double == f128, hardware support)
; * A couple assorted environments for x86
-;
-; FIXME: only targets where long double is `f128` should be using `USELD`, all
-; others need to be NOTLD. PowerPC should be added but it currently emits an
-; interesting blend of both (e.g. `acosl` but `ceilf128`).
+
+
+; flag: !0 = !{ i32 1, !"Fp128 Libcall Format", i32 1 }
+; flag: !llvm.module.flags = !{ !0 }
define fp128 @test_acosf128(fp128 %a) {
; CHECK-LABEL: test_acosf128:
-; CHECK-NOTLD: acosf128
+; CHECK-F128: acosf128
; CHECK-USELD: acosl
-; CHECK-S390X: acosl
+; CHECK-S390X: acosf128
start:
%0 = tail call fp128 @llvm.acos.f128(fp128 %a)
ret fp128 %0
@@ -41,9 +51,9 @@ start:
define fp128 @test_asinf128(fp128 %a) {
; CHECK-LABEL: test_asinf128:
-; CHECK-NOTLD: asinf128
+; CHECK-F128: asinf128
; CHECK-USELD: asinl
-; CHECK-S390X: asinl
+; CHECK-S390X: asinf128
start:
%0 = tail call fp128 @llvm.asin.f128(fp128 %a)
ret fp128 %0
@@ -51,9 +61,9 @@ start:
define fp128 @test_atanf128(fp128 %a) {
; CHECK-LABEL: test_atanf128:
-; CHECK-NOTLD: atanf128
+; CHECK-F128: atanf128
; CHECK-USELD: atanl
-; CHECK-S390X: atanl
+; CHECK-S390X: atanf128
start:
%0 = tail call fp128 @llvm.atan.f128(fp128 %a)
ret fp128 %0
@@ -61,19 +71,20 @@ start:
define fp128 @test_ceilf128(fp128 %a) {
; CHECK-LABEL: test_ceilf128:
-; CHECK-NOTLD: ceilf128
+; CHECK-F128: ceilf128
; CHECK-USELD: ceill
-; CHECK-S390X: ceill
+; CHECK-S390X: ceilf128
start:
%0 = tail call fp128 @llvm.ceil.f128(fp128 %a)
ret fp128 %0
}
define fp128 @test_copysignf128(fp128 %a, fp128 %b) {
-; copysign should always get lowered to assembly
+; copysign should always get lowered to assembly. Regex is needed so as not to
+; match the label.
; CHECK-LABEL: test_copysignf128:
-; CHECK-NOT: copysignl
-; CHECK-NOT: copysignf128
+; CHECK-NOT: {{(^|[[:space:]])fabsf128($|[[:space:]])}}
+; CHECK-NOT: {{(^|[[:space:]])fabsl($|[[:space:]])}}
start:
%0 = tail call fp128 @llvm.copysign.f128(fp128 %a, fp128 %b)
ret fp128 %0
@@ -81,19 +92,19 @@ start:
define fp128 @test_cosf128(fp128 %a) {
; CHECK-LABEL: test_cosf128:
-; CHECK-NOTLD: cosf128
+; CHECK-F128: cosf128
; CHECK-USELD: cosl
-; CHECK-S390X: cosl
+; CHECK-S390X: cosf128
start:
%0 = tail call fp128 @llvm.cos.f128(fp128 %a)
ret fp128 %0
}
define fp128 @test_exp10f128(fp128 %a) {
-; CHECK-LABEL: test_exp2f128:
-; CHECK-NOTLD: exp10f128
+; CHECK-LABEL: test_exp10f128:
+; CHECK-F128: exp10f128
; CHECK-USELD: exp10l
-; CHECK-S390X: exp10l
+; CHECK-S390X: exp10f128
start:
%0 = tail call fp128 @llvm.exp10.f128(fp128 %a)
ret fp128 %0
@@ -101,9 +112,9 @@ start:
define fp128 @test_exp2f128(fp128 %a) {
; CHECK-LABEL: test_exp2f128:
-; CHECK-NOTLD: exp2f128
+; CHECK-F128: exp2f128
; CHECK-USELD: exp2l
-; CHECK-S390X: exp2l
+; CHECK-S390X: exp2f128
start:
%0 = tail call fp128 @llvm.exp2.f128(fp128 %a)
ret fp128 %0
@@ -112,19 +123,20 @@ start:
define fp128 @test_expf128(fp128 %a) {
; CHECK-LABEL: test_expf128:
-; CHECK-NOTLD: expf128
+; CHECK-F128: expf128
; CHECK-USELD: expl
-; CHECK-S390X: expl
+; CHECK-S390X: expf128
start:
%0 = tail call fp128 @llvm.exp.f128(fp128 %a)
ret fp128 %0
}
define fp128 @test_fabsf128(fp128 %a) {
-; fabs should always get lowered to assembly
+; fabs should always get lowered to assembly. Regex is needed so as not to
+; match the label.
; CHECK-LABEL: test_fabsf128:
-; CHECK-NOT: fabsl
-; CHECK-NOT: fabsf128
+; CHECK-NOT: {{(^|[[:space:]])fabsf128($|[[:space:]])}}
+; CHECK-NOT: {{(^|[[:space:]])fabsl($|[[:space:]])}}
start:
%0 = tail call fp128 @llvm.fabs.f128(fp128 %a)
ret fp128 %0
@@ -132,9 +144,9 @@ start:
define fp128 @test_floorf128(fp128 %a) {
; CHECK-LABEL: test_floorf128:
-; CHECK-NOTLD: floorf128
+; CHECK-F128: floorf128
; CHECK-USELD: floorl
-; CHECK-S390X: floorl
+; CHECK-S390X: floorf128
start:
%0 = tail call fp128 @llvm.floor.f128(fp128 %a)
ret fp128 %0
@@ -142,9 +154,9 @@ start:
define fp128 @test_fmaf128(fp128 %a, fp128 %b, fp128 %c) {
; CHECK-LABEL: test_fmaf128:
-; CHECK-NOTLD: fmaf128
+; CHECK-F128: fmaf128
; CHECK-USELD: fmal
-; CHECK-S390X: fmal
+; CHECK-S390X: fmaf128
start:
%0 = tail call fp128 @llvm.fma.f128(fp128 %a, fp128 %b, fp128 %c)
ret fp128 %0
@@ -152,9 +164,9 @@ start:
define { fp128, i32 } @test_frexpf128(fp128 %a) {
; CHECK-LABEL: test_frexpf128:
-; CHECK-NOTLD: frexpf128
+; CHECK-F128: frexpf128
; CHECK-USELD: frexpl
-; CHECK-S390X: frexpl
+; CHECK-S390X: frexpf128
start:
%0 = tail call { fp128, i32 } @llvm.frexp.f128(fp128 %a)
ret { fp128, i32 } %0
@@ -162,9 +174,9 @@ start:
define fp128 @test_ldexpf128(fp128 %a, i32 %b) {
; CHECK-LABEL: test_ldexpf128:
-; CHECK-NOTLD: ldexpf128
+; CHECK-F128: ldexpf128
; CHECK-USELD: ldexpl
-; CHECK-S390X: ldexpl
+; CHECK-S390X: ldexpf128
start:
%0 = tail call fp128 @llvm.ldexp.f128(fp128 %a, i32 %b)
ret fp128 %0
@@ -172,9 +184,9 @@ start:
define i64 @test_llrintf128(fp128 %a) {
; CHECK-LABEL: test_llrintf128:
-; CHECK-NOTLD: llrintf128
+; CHECK-F128: llrintf128
; CHECK-USELD: llrintl
-; CHECK-S390X: llrintl
+; CHECK-S390X: llrintf128
start:
%0 = tail call i64 @llvm.llrint.f128(fp128 %a)
ret i64 %0
@@ -182,9 +194,9 @@ start:
define i64 @test_llroundf128(fp128 %a) {
; CHECK-LABEL: test_llroundf128:
-; CHECK-NOTLD: llroundf128
+; CHECK-F128: llroundf128
; CHECK-USELD: llroundl
-; CHECK-S390X: llroundl
+; CHECK-S390X: llroundf128
start:
%0 = tail call i64 @llvm.llround.i64.f128(fp128 %a)
ret i64 %0
@@ -192,9 +204,9 @@ start:
define fp128 @test_log10f128(fp128 %a) {
; CHECK-LABEL: test_log10f128:
-; CHECK-NOTLD: log10f128
+; CHECK-F128: log10f128
; CHECK-USELD: log10l
-; CHECK-S390X: log10l
+; CHECK-S390X: log10f128
start:
%0 = tail call fp128 @llvm.log10.f128(fp128 %a)
ret fp128 %0
@@ -202,9 +214,9 @@ start:
define fp128 @test_log2f128(fp128 %a) {
; CHECK-LABEL: test_log2f128:
-; CHECK-NOTLD: log2f128
+; CHECK-F128: log2f128
; CHECK-USELD: log2l
-; CHECK-S390X: log2l
+; CHECK-S390X: log2f128
start:
%0 = tail call fp128 @llvm.log2.f128(fp128 %a)
ret fp128 %0
@@ -212,19 +224,19 @@ start:
define fp128 @test_logf128(fp128 %a) {
; CHECK-LABEL: test_logf128:
-; CHECK-NOTLD: logf128
+; CHECK-F128: logf128
; CHECK-USELD: logl
-; CHECK-S390X: logl
+; CHECK-S390X: logf128
start:
%0 = tail call fp128 @llvm.log.f128(fp128 %a)
ret fp128 %0
}
define i64 @test_lrintf128(fp128 %a) {
-; CHECK-LABEL: test_exp2f128:
-; CHECK-NOTLD: lrintf128
+; CHECK-LABEL: test_lrintf128:
+; CHECK-F128: lrintf128
; CHECK-USELD: lrintl
-; CHECK-S390X: lrintl
+; CHECK-S390X: lrintf128
start:
%0 = tail call i64 @llvm.lrint.f128(fp128 %a)
ret i64 %0
@@ -232,9 +244,9 @@ start:
define i64 @test_lroundf128(fp128 %a) {
; CHECK-LABEL: test_lroundf128:
-; CHECK-NOTLD: lroundf128
+; CHECK-F128: lroundf128
; CHECK-USELD: lroundl
-; CHECK-S390X: lroundl
+; CHECK-S390X: lroundf128
start:
%0 = tail call i64 @llvm.lround.i64.f128(fp128 %a)
ret i64 %0
@@ -242,9 +254,9 @@ start:
define fp128 @test_nearbyintf128(fp128 %a) {
; CHECK-LABEL: test_nearbyintf128:
-; CHECK-NOTLD: nearbyintf128
+; CHECK-F128: nearbyintf128
; CHECK-USELD: nearbyintl
-; CHECK-S390X: nearbyintl
+; CHECK-S390X: nearbyintf128
start:
%0 = tail call fp128 @llvm.nearbyint.f128(fp128 %a)
ret fp128 %0
@@ -252,9 +264,9 @@ start:
define fp128 @test_powf128(fp128 %a, fp128 %b) {
; CHECK-LABEL: test_powf128:
-; CHECK-NOTLD: powf128
+; CHECK-F128: powf128
; CHECK-USELD: powl
-; CHECK-S390X: powl
+; CHECK-S390X: powf128
start:
%0 = tail call fp128 @llvm.pow.f128(fp128 %a, fp128 %b)
ret fp128 %0
@@ -262,7 +274,7 @@ start:
define fp128 @test_rintf128(fp128 %a) {
; CHECK-LABEL: test_rintf128:
-; CHECK-NOTLD: rintf128
+; CHECK-F128: rintf128
; CHECK-USELD: rintl
; CHECK-S390X: fixbr {{%.*}}, 0, {{%.*}}
start:
@@ -272,9 +284,9 @@ start:
define fp128 @test_roundevenf128(fp128 %a) {
; CHECK-LABEL: test_roundevenf128:
-; CHECK-NOTLD: roundevenf128
+; CHECK-F128: roundevenf128
; CHECK-USELD: roundevenl
-; CHECK-S390X: roundevenl
+; CHECK-S390X: roundevenf128
start:
%0 = tail call fp128 @llvm.roundeven.f128(fp128 %a)
ret fp128 %0
@@ -282,9 +294,9 @@ start:
define fp128 @test_roundf128(fp128 %a) {
; CHECK-LABEL: test_roundf128:
-; CHECK-NOTLD: roundf128
+; CHECK-F128: roundf128
; CHECK-USELD: roundl
-; CHECK-S390X: roundl
+; CHECK-S390X: roundf128
start:
%0 = tail call fp128 @llvm.round.f128(fp128 %a)
ret fp128 %0
@@ -292,9 +304,9 @@ start:
define fp128 @test_sinf128(fp128 %a) {
; CHECK-LABEL: test_sinf128:
-; CHECK-NOTLD: sinf128
+; CHECK-F128: sinf128
; CHECK-USELD: sinl
-; CHECK-S390X: sinl
+; CHECK-S390X: sinf128
start:
%0 = tail call fp128 @llvm.sin.f128(fp128 %a)
ret fp128 %0
@@ -302,7 +314,7 @@ start:
define fp128 @test_sqrtf128(fp128 %a) {
; CHECK-LABEL: test_sqrtf128:
-; CHECK-NOTLD: sqrtf128
+; CHECK-F128: sqrtf128
; CHECK-USELD: sqrtl
; CHECK-S390X: sqxbr {{%.*}}, {{%.*}}
start:
@@ -312,9 +324,9 @@ start:
define fp128 @test_tanf128(fp128 %a) {
; CHECK-LABEL: test_tanf128:
-; CHECK-NOTLD: tanf128
+; CHECK-F128: tanf128
; CHECK-USELD: tanl
-; CHECK-S390X: tanl
+; CHECK-S390X: tanf128
start:
%0 = tail call fp128 @llvm.tan.f128(fp128 %a)
ret fp128 %0
@@ -322,9 +334,9 @@ start:
define fp128 @test_truncf128(fp128 %a) {
; CHECK-LABEL: test_truncf128:
-; CHECK-NOTLD: truncf128
+; CHECK-F128: truncf128
; CHECK-USELD: truncl
-; CHECK-S390X: truncl
+; CHECK-S390X: truncf128
start:
%0 = tail call fp128 @llvm.trunc.f128(fp128 %a)
ret fp128 %0
>From b164f4ca2f87fddb1089f74ef8a0ff3d6bec1c44 Mon Sep 17 00:00:00 2001
From: Trevor Gross <tmgross at umich.edu>
Date: Sun, 27 Apr 2025 07:34:30 +0000
Subject: [PATCH 4/5] updates
---
llvm/include/llvm/IR/RuntimeLibcalls.h | 15 +++++-----
llvm/include/llvm/TargetParser/Triple.h | 6 ++++
llvm/lib/IR/RuntimeLibcalls.cpp | 8 ++++++
llvm/lib/TargetParser/Triple.cpp | 37 +++++++++++++++++++++++++
4 files changed, 58 insertions(+), 8 deletions(-)
diff --git a/llvm/include/llvm/IR/RuntimeLibcalls.h b/llvm/include/llvm/IR/RuntimeLibcalls.h
index a4fbb61f40bdb..0c0c548a1cda1 100644
--- a/llvm/include/llvm/IR/RuntimeLibcalls.h
+++ b/llvm/include/llvm/IR/RuntimeLibcalls.h
@@ -85,14 +85,6 @@ struct RuntimeLibcallsInfo {
LibcallRoutineNames + RTLIB::UNKNOWN_LIBCALL);
}
- /// Set a specific lowering convention for `fp128` math libcalls.
- ///
- /// By default, `fp128` math functions get lowered to the C23 `sinf128`-
- /// style symbols. This allows overriding with `sinl`-style symbols on
- /// platforms where `long double` is known to be identical to _Float128.
- /// versions, e.g. `sinf128`.
- void setF128LibcallFormat(F128LibcallFormat Format);
-
private:
/// Stores the name each libcall.
const char *LibcallRoutineNames[RTLIB::UNKNOWN_LIBCALL + 1];
@@ -118,6 +110,13 @@ struct RuntimeLibcallsInfo {
/// Set default libcall names. If a target wants to opt-out of a libcall it
/// should be placed here.
void initLibcalls(const Triple &TT);
+
+ /// Set a specific lowering convention for `fp128` math libcalls.
+ ///
+ /// By default, `fp128` math functions get lowered to the C23 `sinf128`-
+ /// style symbols. This allows overriding with `sinl`-style symbols on
+ /// platforms where `long double` is known to be identical to _Float128.
+ void setF128LibcallFormat(F128LibcallFormat Format);
};
} // namespace RTLIB
diff --git a/llvm/include/llvm/TargetParser/Triple.h b/llvm/include/llvm/TargetParser/Triple.h
index 8dbebd9e39bcb..c2e91089ad65e 100644
--- a/llvm/include/llvm/TargetParser/Triple.h
+++ b/llvm/include/llvm/TargetParser/Triple.h
@@ -1243,6 +1243,12 @@ class Triple {
/// or an invalid version tuple if this triple doesn't have one.
VersionTuple getMinimumSupportedOSVersion() const;
+ /// Check whether (1) `f128` is the same format as `long double`, and (2)
+ /// `*f128` symbols are not available. In other words platforms for which
+ /// this returns true may safely use `sqrtl` instead of `sqrtf128`, and
+ /// should do so because `sqrtf128` isn't expected to be available.
+ bool shouldLowerf128AsLongDouble() const;
+
/// @}
/// @name Static helpers for IDs.
/// @{
diff --git a/llvm/lib/IR/RuntimeLibcalls.cpp b/llvm/lib/IR/RuntimeLibcalls.cpp
index 1f752476c82ab..cd71d03659731 100644
--- a/llvm/lib/IR/RuntimeLibcalls.cpp
+++ b/llvm/lib/IR/RuntimeLibcalls.cpp
@@ -205,6 +205,14 @@ void RuntimeLibcallsInfo::initLibcalls(const Triple &TT) {
}
setLibcallName(RTLIB::MULO_I128, nullptr);
}
+
+ // By default, `fp128` libcalls get lowered to `*f128` symbols, which is
+ // safest because the symbols are only ever for binary128 on all platforms.
+ // Unfortunately many platforms only have the `*l` (`long double`) symbols,
+ // which vary by architecture and compilation flags, so we have to use them
+ // sometimes.
+ if(TT.shouldLowerf128AsLongDouble())
+ setF128LibcallFormat(F128LibcallFormat::LongDouble);
}
void RuntimeLibcallsInfo::setF128LibcallFormat(F128LibcallFormat Format) {
diff --git a/llvm/lib/TargetParser/Triple.cpp b/llvm/lib/TargetParser/Triple.cpp
index 0ead84d7ecbad..fe3b590d4c5db 100644
--- a/llvm/lib/TargetParser/Triple.cpp
+++ b/llvm/lib/TargetParser/Triple.cpp
@@ -2173,6 +2173,43 @@ VersionTuple Triple::getCanonicalVersionForOS(OSType OSKind,
}
}
+bool Triple::shouldLowerf128AsLongDouble() const {
+ // Always prefer to lower to `*f128` symbols when they are likely to be
+ // available, to avoid any inaccuracies or problems from libc config.
+ //
+ // Note that the logic should be kept in sync with Clang's LongDoubleFormat.
+
+ // Glibc helpfully aliases `*f128` symbols to `*l` symbols on platforms where
+ // that works, so use those.
+ if (isGNUEnvironment())
+ return false;
+
+ // Windows and Apple always use f64 as `long double`.
+ if (isOSWindows() || isOSDarwin())
+ return false;
+
+ // Most 64-bit architectures use use binary128 on all OSs except Windows and
+ // Apple. A few are binary128 on both 64- and 32-bit.
+ if (isAArch64() || isLoongArch() || isRISCV() || isSPARC() || isSystemZ() ||
+ isVE() || isWasm())
+ return true;
+
+ // MIPS64 is usually f128, except on FreeBSD-like operating systems. MIPS32
+ // is f128 with N32 but f64 with the O32 ABI. Triple doesn't know about ABI
+ // here, so allow MIPS32 to hit the safer `ld !== f128` default.
+ if (isMIPS64() && !(isOSFreeBSD() || isOSKFreeBSD() || isOSDragonFly()))
+ return true;
+
+ // Android and Ohos use binary128 on x86_64.
+ if (getArch() == Triple::x86_64 && (isAndroid() || isOHOSFamily()))
+ return true;
+
+ // By default, make the safe assumption that `long double !== f128`. This
+ // also catchex x86 (`long double` is x87 `f80`) and PowerPC (`long double`
+ // is `f64` or PPC double-double).
+ return false;
+}
+
// HLSL triple environment orders are relied on in the front end
static_assert(Triple::Vertex - Triple::Pixel == 1,
"incorrect HLSL stage order");
>From 1014757e47cdbfb90bea3aea13eb40a3535d8f1f Mon Sep 17 00:00:00 2001
From: Trevor Gross <tmgross at umich.edu>
Date: Sun, 27 Apr 2025 07:38:25 +0000
Subject: [PATCH 5/5] cleanup
---
clang/lib/Driver/Driver.cpp | 3 ---
clang/lib/Driver/ToolChains/Arch/LoongArch.cpp | 2 --
clang/lib/Driver/ToolChains/Linux.cpp | 3 ---
llvm/include/llvm/IR/RuntimeLibcalls.h | 6 +++---
llvm/include/llvm/TargetParser/Triple.h | 12 ------------
.../LoongArch/MCTargetDesc/LoongArchBaseInfo.cpp | 2 --
llvm/lib/TargetParser/Triple.cpp | 8 --------
7 files changed, 3 insertions(+), 33 deletions(-)
diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp
index 889dc9806149b..677bc0256653e 100644
--- a/clang/lib/Driver/Driver.cpp
+++ b/clang/lib/Driver/Driver.cpp
@@ -808,9 +808,6 @@ static llvm::Triple computeTargetTriple(const Driver &D,
else if (Target.getEnvironment() == llvm::Triple::Musl ||
Target.getEnvironment() == llvm::Triple::MuslABIN32)
Target.setEnvironment(llvm::Triple::MuslABI64);
- else if (Target.getEnvironment() == llvm::Triple::MuslF128 ||
- Target.getEnvironment() == llvm::Triple::MuslABIN3F128)
- Target.setEnvironment(llvm::Triple::MuslABI64F128);
}
}
}
diff --git a/clang/lib/Driver/ToolChains/Arch/LoongArch.cpp b/clang/lib/Driver/ToolChains/Arch/LoongArch.cpp
index 75f875ab936b1..0575a1ebef3a6 100644
--- a/clang/lib/Driver/ToolChains/Arch/LoongArch.cpp
+++ b/clang/lib/Driver/ToolChains/Arch/LoongArch.cpp
@@ -105,11 +105,9 @@ StringRef loongarch::getLoongArchABI(const Driver &D, const ArgList &Args,
switch (Triple.getEnvironment()) {
case llvm::Triple::GNUSF:
case llvm::Triple::MuslSF:
- case llvm::Triple::MuslSFF128:
return IsLA32 ? "ilp32s" : "lp64s";
case llvm::Triple::GNUF32:
case llvm::Triple::MuslF32:
- case llvm::Triple::MuslF32F128:
return IsLA32 ? "ilp32f" : "lp64f";
case llvm::Triple::GNUF64:
// This was originally permitted (and indeed the canonical way) to
diff --git a/clang/lib/Driver/ToolChains/Linux.cpp b/clang/lib/Driver/ToolChains/Linux.cpp
index 1bcba0220d531..1e9bd3de75f04 100644
--- a/clang/lib/Driver/ToolChains/Linux.cpp
+++ b/clang/lib/Driver/ToolChains/Linux.cpp
@@ -110,18 +110,15 @@ std::string Linux::getMultiarchTriple(const Driver &D,
return TargetTriple.str();
case llvm::Triple::GNUSF:
case llvm::Triple::MuslSF:
- case llvm::Triple::MuslSFF128:
FPFlavor = "sf";
break;
case llvm::Triple::GNUF32:
case llvm::Triple::MuslF32:
- case llvm::Triple::MuslF32F128:
FPFlavor = "f32";
break;
case llvm::Triple::GNU:
case llvm::Triple::GNUF64:
case llvm::Triple::Musl:
- case llvm::Triple::MuslF128:
// This was going to be "f64" in an earlier Toolchain Conventions
// revision, but starting from Feb 2023 the F64 ABI variants are
// unmarked in their canonical forms.
diff --git a/llvm/include/llvm/IR/RuntimeLibcalls.h b/llvm/include/llvm/IR/RuntimeLibcalls.h
index 0c0c548a1cda1..09b0040cca047 100644
--- a/llvm/include/llvm/IR/RuntimeLibcalls.h
+++ b/llvm/include/llvm/IR/RuntimeLibcalls.h
@@ -51,9 +51,9 @@ enum Libcall {
/// A simple container for information about the supported runtime calls.
struct RuntimeLibcallsInfo {
- /// Default libcalls for the triple. Note that `fixupLibcalls` should also be
- /// called in order to apply machine-specific and configurable behavior.
- explicit RuntimeLibcallsInfo(const Triple &TT) { initLibcalls(TT); }
+ explicit RuntimeLibcallsInfo(const Triple &TT) {
+ initLibcalls(TT);
+ }
/// Rename the default libcall routine name for the specified libcall.
void setLibcallName(RTLIB::Libcall Call, const char *Name) {
diff --git a/llvm/include/llvm/TargetParser/Triple.h b/llvm/include/llvm/TargetParser/Triple.h
index c2e91089ad65e..71fc35a1d49ed 100644
--- a/llvm/include/llvm/TargetParser/Triple.h
+++ b/llvm/include/llvm/TargetParser/Triple.h
@@ -269,14 +269,6 @@ class Triple {
MuslF32, // LoongArch ILP32F/LP64F
MuslSF, // LoongArch ILP32S/LP64S
MuslX32, // Musl using 32-bit ABI on x86_64
- // Musl with `*f128` math symbols available (e.g. `sqrtf128` rather than
- // only `sqrtl`). 32-bit musl variants are excluded sin e `*f128` symbols
- // are required to use `fp128` at all.
- MuslF128,
- MuslABI64F128,
- MuslF32F128,
- MuslSFF128,
-
LLVM,
MSVC,
@@ -835,10 +827,6 @@ class Triple {
getEnvironment() == Triple::MuslF32 ||
getEnvironment() == Triple::MuslSF ||
getEnvironment() == Triple::MuslX32 ||
- getEnvironment() == Triple::MuslF128 ||
- getEnvironment() == Triple::MuslABI64F128 ||
- getEnvironment() == Triple::MuslF32F128 ||
- getEnvironment() == Triple::MuslSFF128 ||
getEnvironment() == Triple::OpenHOS || isOSLiteOS();
}
diff --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchBaseInfo.cpp b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchBaseInfo.cpp
index c15ded457bbe3..03ce004ed33a5 100644
--- a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchBaseInfo.cpp
+++ b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchBaseInfo.cpp
@@ -54,12 +54,10 @@ static ABI getTripleABI(const Triple &TT) {
switch (TT.getEnvironment()) {
case llvm::Triple::EnvironmentType::GNUSF:
case llvm::Triple::EnvironmentType::MuslSF:
- case llvm::Triple::EnvironmentType::MuslSFF128:
TripleABI = Is64Bit ? ABI_LP64S : ABI_ILP32S;
break;
case llvm::Triple::EnvironmentType::GNUF32:
case llvm::Triple::EnvironmentType::MuslF32:
- case llvm::Triple::EnvironmentType::MuslF32F128:
TripleABI = Is64Bit ? ABI_LP64F : ABI_ILP32F;
break;
// Let the fallback case behave like {ILP32,LP64}D.
diff --git a/llvm/lib/TargetParser/Triple.cpp b/llvm/lib/TargetParser/Triple.cpp
index fe3b590d4c5db..a8e1512349001 100644
--- a/llvm/lib/TargetParser/Triple.cpp
+++ b/llvm/lib/TargetParser/Triple.cpp
@@ -361,10 +361,6 @@ StringRef Triple::getEnvironmentTypeName(EnvironmentType Kind) {
case MuslSF:
return "muslsf";
case MuslX32: return "muslx32";
- case MuslF128: return "musl_f128";
- case MuslABI64F128: return "muslabi64_f128";
- case MuslF32F128: return "muslf32_f128";
- case MuslSFF128: return "muslsf_f128";
case Simulator: return "simulator";
case Pixel: return "pixel";
case Vertex: return "vertex";
@@ -737,10 +733,6 @@ static Triple::EnvironmentType parseEnvironment(StringRef EnvironmentName) {
.StartsWith("gnut64", Triple::GNUT64)
.StartsWith("gnu", Triple::GNU)
.StartsWith("android", Triple::Android)
- .StartsWith("muslabi64_f128", Triple::MuslABI64F128)
- .StartsWith("muslf32_f128", Triple::MuslF32F128)
- .StartsWith("muslsf_f128", Triple::MuslSFF128)
- .StartsWith("musl_f128", Triple::MuslF128)
.StartsWith("muslabin32", Triple::MuslABIN32)
.StartsWith("muslabi64", Triple::MuslABI64)
.StartsWith("musleabihf", Triple::MuslEABIHF)
More information about the cfe-commits
mailing list