[compiler-rt] [builtins] Support building the 128-bit float functions on x86 (PR #68132)
Alexander Richardson via llvm-commits
llvm-commits at lists.llvm.org
Tue Oct 3 10:27:25 PDT 2023
https://github.com/arichardson created https://github.com/llvm/llvm-project/pull/68132
GCC provides these functions (e.g. __addtf3, etc.) in libgcc on x86_64. Since Clang supports float128, we can also enable the existing code by using float128 for fp_t if either __FLOAT128__ or __SIZEOF_FLOAT128__ is defined instead of only supporting these builtins for platforms with 128-bit IEEE long doubles.
This commit defines a new tf_float typedef that matches a float with attribute((mode(TF)) on each given architecture.
There are more tests that could be enabled for x86, but to keep the diff smaller, I restricted test changes to ones that started failing as part of this refactoring.
This change has been tested on x86 (natively) and aarch64,powerpc64,riscv64 and sparc64 via qemu-user.
This supersedes https://reviews.llvm.org/D98261 and should also cover the changes from https://github.com/llvm/llvm-project/pull/68041.
>From 58742dd68f4527b13561592e19d64a5f07991872 Mon Sep 17 00:00:00 2001
From: Alex Richardson <alexrichardson at google.com>
Date: Fri, 23 Jun 2023 16:34:59 -0700
Subject: [PATCH] [builtins] Support building the 128-bit float functions on
x86
GCC provides these functions (e.g. __addtf3, etc.) in libgcc on x86_64.
Since Clang supports float128, we can also enable the existing code by
using float128 for fp_t if either __FLOAT128__ or __SIZEOF_FLOAT128__
is defined instead of only supporting these builtins for platforms with
128-bit IEEE long doubles.
This commit defines a new tf_float typedef that matches a float with
attribute((mode(TF)) on each given architecture.
There are more tests that could be enabled for x86, but to keep the diff
smaller, I restricted test changes to ones that started failing as part of
this refactoring.
This change has been tested on x86 (natively) and aarch64,powerpc64,riscv64
and sparc64 via qemu-user.
This supersedes https://reviews.llvm.org/D98261.
---
compiler-rt/lib/builtins/CMakeLists.txt | 2 -
compiler-rt/lib/builtins/README.txt | 15 +-
compiler-rt/lib/builtins/divtc3.c | 51 +-
compiler-rt/lib/builtins/extenddftf2.c | 4 +-
compiler-rt/lib/builtins/extendhftf2.c | 4 +-
compiler-rt/lib/builtins/extendsftf2.c | 4 +-
compiler-rt/lib/builtins/floattitf.c | 2 +-
compiler-rt/lib/builtins/floatuntitf.c | 2 +-
compiler-rt/lib/builtins/fp_extend.h | 2 +-
compiler-rt/lib/builtins/fp_lib.h | 50 +-
compiler-rt/lib/builtins/fp_trunc.h | 2 +-
compiler-rt/lib/builtins/int_math.h | 10 +
compiler-rt/lib/builtins/int_types.h | 73 ++
compiler-rt/lib/builtins/multc3.c | 53 +-
compiler-rt/lib/builtins/powitf2.c | 4 +-
compiler-rt/lib/builtins/trunctfdf2.c | 2 +-
compiler-rt/lib/builtins/trunctfhf2.c | 4 +-
compiler-rt/lib/builtins/trunctfsf2.c | 2 +-
compiler-rt/test/builtins/Unit/addtf3_test.c | 18 +-
.../builtins/Unit/compiler_rt_fmaxl_test.c | 12 +-
.../builtins/Unit/compiler_rt_logbl_test.c | 14 +-
.../builtins/Unit/compiler_rt_scalbnl_test.c | 15 +-
compiler-rt/test/builtins/Unit/divtc3_test.c | 639 +++++++++---------
.../test/builtins/Unit/floattitf_test.c | 11 +-
.../test/builtins/Unit/floatunditf_test.c | 2 +-
.../test/builtins/Unit/floatuntitf_test.c | 12 +-
26 files changed, 547 insertions(+), 462 deletions(-)
diff --git a/compiler-rt/lib/builtins/CMakeLists.txt b/compiler-rt/lib/builtins/CMakeLists.txt
index 1afceddc62d846f..5b42b5a49385965 100644
--- a/compiler-rt/lib/builtins/CMakeLists.txt
+++ b/compiler-rt/lib/builtins/CMakeLists.txt
@@ -187,8 +187,6 @@ set(BF16_SOURCES
truncsfbf2.c
)
-# TODO: Several "tf" files (and divtc3.c, but not multc3.c) are in
-# GENERIC_SOURCES instead of here.
set(GENERIC_TF_SOURCES
addtf3.c
comparetf2.c
diff --git a/compiler-rt/lib/builtins/README.txt b/compiler-rt/lib/builtins/README.txt
index 5637183cc3b4551..ff68aea580f3ea8 100644
--- a/compiler-rt/lib/builtins/README.txt
+++ b/compiler-rt/lib/builtins/README.txt
@@ -137,11 +137,12 @@ si_int __ucmpti2(tu_int a, tu_int b);
di_int __fixsfdi( float a);
di_int __fixdfdi( double a);
di_int __fixxfdi(long double a);
+di_int __fixtfdi(long double a);
ti_int __fixsfti( float a);
ti_int __fixdfti( double a);
ti_int __fixxfti(long double a);
-uint64_t __fixtfdi(long double input); // ppc only, doesn't match documentation
+ti_int __fixtfti(long double a);
su_int __fixunssfsi( float a);
su_int __fixunsdfsi( double a);
@@ -154,12 +155,12 @@ du_int __fixunsxfdi(long double a);
tu_int __fixunssfti( float a);
tu_int __fixunsdfti( double a);
tu_int __fixunsxfti(long double a);
-uint64_t __fixunstfdi(long double input); // ppc only
+uint64_t __fixunstfdi(long double input);
float __floatdisf(di_int a);
double __floatdidf(di_int a);
long double __floatdixf(di_int a);
-long double __floatditf(int64_t a); // ppc only
+long double __floatditf(int64_t a);
float __floattisf(ti_int a);
double __floattidf(ti_int a);
@@ -168,7 +169,7 @@ long double __floattixf(ti_int a);
float __floatundisf(du_int a);
double __floatundidf(du_int a);
long double __floatundixf(du_int a);
-long double __floatunditf(uint64_t a); // ppc only
+long double __floatunditf(uint64_t a);
float __floatuntisf(tu_int a);
double __floatuntidf(tu_int a);
@@ -179,7 +180,7 @@ long double __floatuntixf(tu_int a);
float __powisf2( float a, int b); // a ^ b
double __powidf2( double a, int b); // a ^ b
long double __powixf2(long double a, int b); // a ^ b
-long double __powitf2(long double a, int b); // ppc only, a ^ b
+long double __powitf2(long double a, int b); // a ^ b
// Complex arithmetic
@@ -190,7 +191,7 @@ long double __powitf2(long double a, int b); // ppc only, a ^ b
long double _Complex __mulxc3(long double a, long double b,
long double c, long double d);
long double _Complex __multc3(long double a, long double b,
- long double c, long double d); // ppc only
+ long double c, long double d);
// (a + ib) / (c + id)
@@ -199,7 +200,7 @@ long double _Complex __multc3(long double a, long double b,
long double _Complex __divxc3(long double a, long double b,
long double c, long double d);
long double _Complex __divtc3(long double a, long double b,
- long double c, long double d); // ppc only
+ long double c, long double d);
// Runtime support
diff --git a/compiler-rt/lib/builtins/divtc3.c b/compiler-rt/lib/builtins/divtc3.c
index 0e4799295f32fe3..e970cef574b21dd 100644
--- a/compiler-rt/lib/builtins/divtc3.c
+++ b/compiler-rt/lib/builtins/divtc3.c
@@ -12,44 +12,45 @@
#define QUAD_PRECISION
#include "fp_lib.h"
-#include "int_lib.h"
-#include "int_math.h"
+
+#if defined(CRT_HAS_TF_MODE)
// Returns: the quotient of (a + ib) / (c + id)
-COMPILER_RT_ABI Lcomplex __divtc3(long double __a, long double __b,
- long double __c, long double __d) {
+COMPILER_RT_ABI Qcomplex __divtc3(fp_t __a, fp_t __b, fp_t __c, fp_t __d) {
int __ilogbw = 0;
- long double __logbw =
- __compiler_rt_logbl(__compiler_rt_fmaxl(crt_fabsl(__c), crt_fabsl(__d)));
+ fp_t __logbw = __compiler_rt_logbtf(
+ __compiler_rt_fmaxtf(crt_fabstf(__c), crt_fabstf(__d)));
if (crt_isfinite(__logbw)) {
__ilogbw = (int)__logbw;
- __c = __compiler_rt_scalbnl(__c, -__ilogbw);
- __d = __compiler_rt_scalbnl(__d, -__ilogbw);
+ __c = __compiler_rt_scalbntf(__c, -__ilogbw);
+ __d = __compiler_rt_scalbntf(__d, -__ilogbw);
}
- long double __denom = __c * __c + __d * __d;
- Lcomplex z;
- COMPLEX_REAL(z) =
- __compiler_rt_scalbnl((__a * __c + __b * __d) / __denom, -__ilogbw);
- COMPLEX_IMAGINARY(z) =
- __compiler_rt_scalbnl((__b * __c - __a * __d) / __denom, -__ilogbw);
- if (crt_isnan(COMPLEX_REAL(z)) && crt_isnan(COMPLEX_IMAGINARY(z))) {
+ fp_t __denom = __c * __c + __d * __d;
+ Qcomplex z;
+ COMPLEXTF_REAL(z) =
+ __compiler_rt_scalbntf((__a * __c + __b * __d) / __denom, -__ilogbw);
+ COMPLEXTF_IMAGINARY(z) =
+ __compiler_rt_scalbntf((__b * __c - __a * __d) / __denom, -__ilogbw);
+ if (crt_isnan(COMPLEXTF_REAL(z)) && crt_isnan(COMPLEXTF_IMAGINARY(z))) {
if ((__denom == 0.0) && (!crt_isnan(__a) || !crt_isnan(__b))) {
- COMPLEX_REAL(z) = crt_copysignl(CRT_INFINITY, __c) * __a;
- COMPLEX_IMAGINARY(z) = crt_copysignl(CRT_INFINITY, __c) * __b;
+ COMPLEXTF_REAL(z) = crt_copysigntf(CRT_INFINITY, __c) * __a;
+ COMPLEXTF_IMAGINARY(z) = crt_copysigntf(CRT_INFINITY, __c) * __b;
} else if ((crt_isinf(__a) || crt_isinf(__b)) && crt_isfinite(__c) &&
crt_isfinite(__d)) {
- __a = crt_copysignl(crt_isinf(__a) ? 1.0 : 0.0, __a);
- __b = crt_copysignl(crt_isinf(__b) ? 1.0 : 0.0, __b);
- COMPLEX_REAL(z) = CRT_INFINITY * (__a * __c + __b * __d);
- COMPLEX_IMAGINARY(z) = CRT_INFINITY * (__b * __c - __a * __d);
+ __a = crt_copysigntf(crt_isinf(__a) ? (fp_t)1.0 : (fp_t)0.0, __a);
+ __b = crt_copysigntf(crt_isinf(__b) ? (fp_t)1.0 : (fp_t)0.0, __b);
+ COMPLEXTF_REAL(z) = CRT_INFINITY * (__a * __c + __b * __d);
+ COMPLEXTF_IMAGINARY(z) = CRT_INFINITY * (__b * __c - __a * __d);
} else if (crt_isinf(__logbw) && __logbw > 0.0 && crt_isfinite(__a) &&
crt_isfinite(__b)) {
- __c = crt_copysignl(crt_isinf(__c) ? 1.0 : 0.0, __c);
- __d = crt_copysignl(crt_isinf(__d) ? 1.0 : 0.0, __d);
- COMPLEX_REAL(z) = 0.0 * (__a * __c + __b * __d);
- COMPLEX_IMAGINARY(z) = 0.0 * (__b * __c - __a * __d);
+ __c = crt_copysigntf(crt_isinf(__c) ? (fp_t)1.0 : (fp_t)0.0, __c);
+ __d = crt_copysigntf(crt_isinf(__d) ? (fp_t)1.0 : (fp_t)0.0, __d);
+ COMPLEXTF_REAL(z) = 0.0 * (__a * __c + __b * __d);
+ COMPLEXTF_IMAGINARY(z) = 0.0 * (__b * __c - __a * __d);
}
}
return z;
}
+
+#endif
diff --git a/compiler-rt/lib/builtins/extenddftf2.c b/compiler-rt/lib/builtins/extenddftf2.c
index 835076be1f2080d..a61ef53147abcfb 100644
--- a/compiler-rt/lib/builtins/extenddftf2.c
+++ b/compiler-rt/lib/builtins/extenddftf2.c
@@ -14,8 +14,6 @@
#define DST_QUAD
#include "fp_extend_impl.inc"
-COMPILER_RT_ABI fp_t __extenddftf2(double a) {
- return __extendXfYf2__(a);
-}
+COMPILER_RT_ABI dst_t __extenddftf2(src_t a) { return __extendXfYf2__(a); }
#endif
diff --git a/compiler-rt/lib/builtins/extendhftf2.c b/compiler-rt/lib/builtins/extendhftf2.c
index a2cb0f771ee9aa9..7609db6f06e4ad4 100644
--- a/compiler-rt/lib/builtins/extendhftf2.c
+++ b/compiler-rt/lib/builtins/extendhftf2.c
@@ -15,8 +15,6 @@
#define DST_QUAD
#include "fp_extend_impl.inc"
-COMPILER_RT_ABI long double __extendhftf2(_Float16 a) {
- return __extendXfYf2__(a);
-}
+COMPILER_RT_ABI dst_t __extendhftf2(src_t a) { return __extendXfYf2__(a); }
#endif
diff --git a/compiler-rt/lib/builtins/extendsftf2.c b/compiler-rt/lib/builtins/extendsftf2.c
index 0739859bcbc18fa..4ab2982ce5142ba 100644
--- a/compiler-rt/lib/builtins/extendsftf2.c
+++ b/compiler-rt/lib/builtins/extendsftf2.c
@@ -14,8 +14,6 @@
#define DST_QUAD
#include "fp_extend_impl.inc"
-COMPILER_RT_ABI fp_t __extendsftf2(float a) {
- return __extendXfYf2__(a);
-}
+COMPILER_RT_ABI dst_t __extendsftf2(src_t a) { return __extendXfYf2__(a); }
#endif
diff --git a/compiler-rt/lib/builtins/floattitf.c b/compiler-rt/lib/builtins/floattitf.c
index fff0755c3bb46a3..c0e61edee8d522d 100644
--- a/compiler-rt/lib/builtins/floattitf.c
+++ b/compiler-rt/lib/builtins/floattitf.c
@@ -67,7 +67,7 @@ COMPILER_RT_ABI fp_t __floattitf(ti_int a) {
// a is now rounded to LDBL_MANT_DIG bits
}
- long_double_bits fb;
+ tf_bits fb;
fb.u.high.all = (s & 0x8000000000000000LL) // sign
| (du_int)(e + 16383) << 48 // exponent
| ((a >> 64) & 0x0000ffffffffffffLL); // significand
diff --git a/compiler-rt/lib/builtins/floatuntitf.c b/compiler-rt/lib/builtins/floatuntitf.c
index 33a81b34eeb195b..b774bb1c37c4351 100644
--- a/compiler-rt/lib/builtins/floatuntitf.c
+++ b/compiler-rt/lib/builtins/floatuntitf.c
@@ -65,7 +65,7 @@ COMPILER_RT_ABI fp_t __floatuntitf(tu_int a) {
// a is now rounded to TF_MANT_DIG bits
}
- long_double_bits fb;
+ tf_bits fb;
fb.u.high.all = (du_int)(e + 16383) << 48 // exponent
| ((a >> 64) & 0x0000ffffffffffffLL); // significand
fb.u.low.all = (du_int)(a);
diff --git a/compiler-rt/lib/builtins/fp_extend.h b/compiler-rt/lib/builtins/fp_extend.h
index eee4722bf90e69f..40b0dab812e70a5 100644
--- a/compiler-rt/lib/builtins/fp_extend.h
+++ b/compiler-rt/lib/builtins/fp_extend.h
@@ -67,7 +67,7 @@ typedef uint64_t dst_rep_t;
static const int dstSigBits = 52;
#elif defined DST_QUAD
-typedef long double dst_t;
+typedef tf_float dst_t;
typedef __uint128_t dst_rep_t;
#define DST_REP_C (__uint128_t)
static const int dstSigBits = 112;
diff --git a/compiler-rt/lib/builtins/fp_lib.h b/compiler-rt/lib/builtins/fp_lib.h
index 58eb45fcc729296..43bbdd5f8736575 100644
--- a/compiler-rt/lib/builtins/fp_lib.h
+++ b/compiler-rt/lib/builtins/fp_lib.h
@@ -105,18 +105,11 @@ static __inline void wideMultiply(rep_t a, rep_t b, rep_t *hi, rep_t *lo) {
COMPILER_RT_ABI fp_t __adddf3(fp_t a, fp_t b);
#elif defined QUAD_PRECISION
-#if __LDBL_MANT_DIG__ == 113 && defined(__SIZEOF_INT128__)
-// TODO: Availability of the *tf functions should not depend on long double
-// being IEEE 128, but instead on being able to use a 128-bit floating-point
-// type, which includes __float128.
-// Right now this (incorrectly) stops the builtins from being used for x86.
-#define CRT_LDBL_128BIT
-#define CRT_HAS_TF_MODE
-#define TF_C(c) c##L
+#if defined(CRT_HAS_TF_MODE)
typedef uint64_t half_rep_t;
typedef __uint128_t rep_t;
typedef __int128_t srep_t;
-typedef long double fp_t;
+typedef tf_float fp_t;
#define HALF_REP_C UINT64_C
#define REP_C (__uint128_t)
// Note: Since there is no explicit way to tell compiler the constant is a
@@ -207,13 +200,13 @@ static __inline void wideMultiply(rep_t a, rep_t b, rep_t *hi, rep_t *lo) {
#undef Word_HiMask
#undef Word_LoMask
#undef Word_FullMask
-#endif // __LDBL_MANT_DIG__ == 113 && __SIZEOF_INT128__
+#endif // defined(CRT_HAS_TF_MODE)
#else
#error SINGLE_PRECISION, DOUBLE_PRECISION or QUAD_PRECISION must be defined.
#endif
#if defined(SINGLE_PRECISION) || defined(DOUBLE_PRECISION) || \
- defined(CRT_LDBL_128BIT)
+ (defined(QUAD_PRECISION) && defined(CRT_HAS_TF_MODE))
#define typeWidth (sizeof(rep_t) * CHAR_BIT)
#define exponentBits (typeWidth - significandBits - 1)
#define maxExponent ((1 << exponentBits) - 1)
@@ -393,31 +386,40 @@ static __inline fp_t __compiler_rt_fmax(fp_t x, fp_t y) {
#endif
}
-#elif defined(QUAD_PRECISION)
-
-#if defined(CRT_LDBL_128BIT)
-static __inline fp_t __compiler_rt_logbl(fp_t x) {
+#elif defined(QUAD_PRECISION) && defined(CRT_HAS_TF_MODE)
+// The generic implementation only works for ieee754 floating point. For other
+// floating point types, continue to rely on the libm implementation for now.
+#if defined(CRT_HAS_IEEE_TF)
+static __inline tf_float __compiler_rt_logbtf(tf_float x) {
return __compiler_rt_logbX(x);
}
-static __inline fp_t __compiler_rt_scalbnl(fp_t x, int y) {
+static __inline tf_float __compiler_rt_scalbntf(tf_float x, int y) {
return __compiler_rt_scalbnX(x, y);
}
-static __inline fp_t __compiler_rt_fmaxl(fp_t x, fp_t y) {
+static __inline tf_float __compiler_rt_fmaxtf(tf_float x, tf_float y) {
return __compiler_rt_fmaxX(x, y);
}
-#else
-// The generic implementation only works for ieee754 floating point. For other
-// floating point types, continue to rely on the libm implementation for now.
-static __inline long double __compiler_rt_logbl(long double x) {
+#define __compiler_rt_logbl __compiler_rt_logbtf
+#define __compiler_rt_scalbnl __compiler_rt_scalbntf
+#define __compiler_rt_fmaxl __compiler_rt_fmaxtf
+#define crt_fabstf crt_fabsf128
+#define crt_copysigntf crt_copysignf128
+#elif defined(CRT_LDBL_128BIT)
+static __inline tf_float __compiler_rt_logbtf(tf_float x) {
return crt_logbl(x);
}
-static __inline long double __compiler_rt_scalbnl(long double x, int y) {
+static __inline tf_float __compiler_rt_scalbntf(tf_float x, int y) {
return crt_scalbnl(x, y);
}
-static __inline long double __compiler_rt_fmaxl(long double x, long double y) {
+static __inline tf_float __compiler_rt_fmaxtf(tf_float x, tf_float y) {
return crt_fmaxl(x, y);
}
-#endif // CRT_LDBL_128BIT
+#define __compiler_rt_logbl crt_logbl
+#define __compiler_rt_scalbnl crt_scalbnl
+#define __compiler_rt_fmaxl crt_fmaxl
+#else
+#error Unsupported TF mode type
+#endif
#endif // *_PRECISION
diff --git a/compiler-rt/lib/builtins/fp_trunc.h b/compiler-rt/lib/builtins/fp_trunc.h
index 91f614528ab3f42..791156ac6b5870c 100644
--- a/compiler-rt/lib/builtins/fp_trunc.h
+++ b/compiler-rt/lib/builtins/fp_trunc.h
@@ -28,7 +28,7 @@ typedef uint64_t src_rep_t;
static const int srcSigBits = 52;
#elif defined SRC_QUAD
-typedef long double src_t;
+typedef tf_float src_t;
typedef __uint128_t src_rep_t;
#define SRC_REP_C (__uint128_t)
static const int srcSigBits = 112;
diff --git a/compiler-rt/lib/builtins/int_math.h b/compiler-rt/lib/builtins/int_math.h
index 48b9580f5961b01..74d3e311db5e710 100644
--- a/compiler-rt/lib/builtins/int_math.h
+++ b/compiler-rt/lib/builtins/int_math.h
@@ -65,6 +65,11 @@
#define crt_copysign(x, y) __builtin_copysign((x), (y))
#define crt_copysignf(x, y) __builtin_copysignf((x), (y))
#define crt_copysignl(x, y) __builtin_copysignl((x), (y))
+#if __has_builtin(__builtin_copysignf128)
+#define crt_copysignf128(x, y) __builtin_copysignf128((x), (y))
+#elif __has_builtin(__builtin_copysignq) || (defined(__GNUC__) && __GNUC__ >= 7)
+#define crt_copysignf128(x, y) __builtin_copysignq((x), (y))
+#endif
#endif
#if defined(_MSC_VER) && !defined(__clang__)
@@ -75,6 +80,11 @@
#define crt_fabs(x) __builtin_fabs((x))
#define crt_fabsf(x) __builtin_fabsf((x))
#define crt_fabsl(x) __builtin_fabsl((x))
+#if __has_builtin(__builtin_fabsf128)
+#define crt_fabsf128(x) __builtin_fabsf128((x))
+#elif __has_builtin(__builtin_fabsq) || (defined(__GNUC__) && __GNUC__ >= 7)
+#define crt_fabsf128(x) __builtin_fabsq((x))
+#endif
#endif
#if defined(_MSC_VER) && !defined(__clang__)
diff --git a/compiler-rt/lib/builtins/int_types.h b/compiler-rt/lib/builtins/int_types.h
index e94d3154c6d4ef6..f705844610f6ac5 100644
--- a/compiler-rt/lib/builtins/int_types.h
+++ b/compiler-rt/lib/builtins/int_types.h
@@ -165,6 +165,53 @@ typedef struct {
#define HAS_80_BIT_LONG_DOUBLE 0
#endif
+#ifdef __powerpc64__
+// From https://gcc.gnu.org/wiki/Ieee128PowerPC:
+// PowerPC64 uses the following suffixes:
+// IFmode: IBM extended double
+// KFmode: IEEE 128-bit floating point
+// TFmode: Matches the default for long double. With -mabi=ieeelongdouble,
+// it is IEEE 128-bit, with -mabi=ibmlongdouble IBM extended double
+// Since compiler-rt only implements the tf set of libcalls, we use long double
+// for the tf_float typedef.
+typedef long double tf_float;
+#define CRT_LDBL_128BIT
+#define CRT_HAS_F128
+#if __LDBL_MANT_DIG__ == 113 && !defined(__LONG_DOUBLE_IBM128__)
+#define CRT_HAS_IEEE_TF
+#define CRT_LDBL_IEEE_F128
+#endif
+#define TF_C(x) x##L
+#elif __LDBL_MANT_DIG__ == 113
+// Use long double instead of __float128 if it matches the IEEE 128-bit format.
+#define CRT_LDBL_128BIT
+#define CRT_HAS_F128
+#define CRT_HAS_IEEE_TF
+#define CRT_LDBL_IEEE_F128
+typedef long double tf_float;
+#define TF_C(x) x##L
+#elif defined(__FLOAT128__) || defined(__SIZEOF_FLOAT128__)
+#define CRT_HAS___FLOAT128_KEYWORD
+#define CRT_HAS_F128
+// NB: we assume the __float128 type uses IEEE representation.
+#define CRT_HAS_IEEE_TF
+typedef __float128 tf_float;
+#define TF_C(x) x##Q
+#endif
+
+#ifdef CRT_HAS_F128
+typedef union {
+ uqwords u;
+ tf_float f;
+} tf_bits;
+#endif
+
+// __(u)int128_t is currently needed to compile the *tf builtins as we would
+// otherwise need to manually expand the bit manipulation on two 64-bit value.
+#if defined(CRT_HAS_128BIT) && defined(CRT_HAS_F128)
+#define CRT_HAS_TF_MODE
+#endif
+
#if CRT_HAS_FLOATING_POINT
typedef union {
uqwords u;
@@ -175,6 +222,20 @@ typedef union {
typedef float _Complex Fcomplex;
typedef double _Complex Dcomplex;
typedef long double _Complex Lcomplex;
+#if defined(CRT_LDBL_128BIT)
+typedef Lcomplex Qcomplex;
+#define CRT_HAS_NATIVE_COMPLEX_F128
+#elif defined(CRT_HAS___FLOAT128_KEYWORD)
+#if defined(__clang_major__) && __clang_major__ > 10
+// Clang prior to 11 did not support __float128 _Complex.
+typedef __float128 _Complex Qcomplex;
+#define CRT_HAS_NATIVE_COMPLEX_F128
+#elif defined(__GNUC__) && __GNUC__ >= 7
+// GCC does not allow __float128 _Complex, but accepts _Float128 _Complex.
+typedef _Float128 _Complex Qcomplex;
+#define CRT_HAS_NATIVE_COMPLEX_F128
+#endif
+#endif
#define COMPLEX_REAL(x) __real__(x)
#define COMPLEX_IMAGINARY(x) __imag__(x)
@@ -194,5 +255,17 @@ typedef struct {
#define COMPLEX_REAL(x) (x).real
#define COMPLEX_IMAGINARY(x) (x).imaginary
#endif
+
+#ifdef CRT_HAS_NATIVE_COMPLEX_F128
+#define COMPLEXTF_REAL(x) __real__(x)
+#define COMPLEXTF_IMAGINARY(x) __imag__(x)
+#elif defined(CRT_HAS_F128)
+typedef struct {
+ tf_float real, imaginary;
+} Qcomplex;
+#define COMPLEXTF_REAL(x) (x).real
+#define COMPLEXTF_IMAGINARY(x) (x).imaginary
+#endif
+
#endif
#endif // INT_TYPES_H
diff --git a/compiler-rt/lib/builtins/multc3.c b/compiler-rt/lib/builtins/multc3.c
index bb7f6aabfe2c8ec..f20e53ccbf233bb 100644
--- a/compiler-rt/lib/builtins/multc3.c
+++ b/compiler-rt/lib/builtins/multc3.c
@@ -10,56 +10,61 @@
//
//===----------------------------------------------------------------------===//
+#define QUAD_PRECISION
+#include "fp_lib.h"
#include "int_lib.h"
#include "int_math.h"
+#if defined(CRT_HAS_TF_MODE)
+
// Returns: the product of a + ib and c + id
-COMPILER_RT_ABI long double _Complex __multc3(long double a, long double b,
- long double c, long double d) {
- long double ac = a * c;
- long double bd = b * d;
- long double ad = a * d;
- long double bc = b * c;
- long double _Complex z;
- __real__ z = ac - bd;
- __imag__ z = ad + bc;
- if (crt_isnan(__real__ z) && crt_isnan(__imag__ z)) {
+COMPILER_RT_ABI Qcomplex __multc3(fp_t a, fp_t b, fp_t c, fp_t d) {
+ fp_t ac = a * c;
+ fp_t bd = b * d;
+ fp_t ad = a * d;
+ fp_t bc = b * c;
+ Qcomplex z;
+ COMPLEXTF_REAL(z) = ac - bd;
+ COMPLEXTF_IMAGINARY(z) = ad + bc;
+ if (crt_isnan(COMPLEXTF_REAL(z)) && crt_isnan(COMPLEXTF_IMAGINARY(z))) {
int recalc = 0;
if (crt_isinf(a) || crt_isinf(b)) {
- a = crt_copysignl(crt_isinf(a) ? 1 : 0, a);
- b = crt_copysignl(crt_isinf(b) ? 1 : 0, b);
+ a = crt_copysigntf(crt_isinf(a) ? 1 : 0, a);
+ b = crt_copysigntf(crt_isinf(b) ? 1 : 0, b);
if (crt_isnan(c))
- c = crt_copysignl(0, c);
+ c = crt_copysigntf(0, c);
if (crt_isnan(d))
- d = crt_copysignl(0, d);
+ d = crt_copysigntf(0, d);
recalc = 1;
}
if (crt_isinf(c) || crt_isinf(d)) {
- c = crt_copysignl(crt_isinf(c) ? 1 : 0, c);
- d = crt_copysignl(crt_isinf(d) ? 1 : 0, d);
+ c = crt_copysigntf(crt_isinf(c) ? 1 : 0, c);
+ d = crt_copysigntf(crt_isinf(d) ? 1 : 0, d);
if (crt_isnan(a))
- a = crt_copysignl(0, a);
+ a = crt_copysigntf(0, a);
if (crt_isnan(b))
- b = crt_copysignl(0, b);
+ b = crt_copysigntf(0, b);
recalc = 1;
}
if (!recalc &&
(crt_isinf(ac) || crt_isinf(bd) || crt_isinf(ad) || crt_isinf(bc))) {
if (crt_isnan(a))
- a = crt_copysignl(0, a);
+ a = crt_copysigntf(0, a);
if (crt_isnan(b))
- b = crt_copysignl(0, b);
+ b = crt_copysigntf(0, b);
if (crt_isnan(c))
- c = crt_copysignl(0, c);
+ c = crt_copysigntf(0, c);
if (crt_isnan(d))
- d = crt_copysignl(0, d);
+ d = crt_copysigntf(0, d);
recalc = 1;
}
if (recalc) {
- __real__ z = CRT_INFINITY * (a * c - b * d);
- __imag__ z = CRT_INFINITY * (a * d + b * c);
+ COMPLEXTF_REAL(z) = CRT_INFINITY * (a * c - b * d);
+ COMPLEXTF_IMAGINARY(z) = CRT_INFINITY * (a * d + b * c);
}
}
return z;
}
+
+#endif
diff --git a/compiler-rt/lib/builtins/powitf2.c b/compiler-rt/lib/builtins/powitf2.c
index 74fe707a4e8c40e..e02db40767ac03d 100644
--- a/compiler-rt/lib/builtins/powitf2.c
+++ b/compiler-rt/lib/builtins/powitf2.c
@@ -17,9 +17,9 @@
// Returns: a ^ b
-COMPILER_RT_ABI long double __powitf2(long double a, int b) {
+COMPILER_RT_ABI fp_t __powitf2(fp_t a, int b) {
const int recip = b < 0;
- long double r = 1;
+ fp_t r = 1;
while (1) {
if (b & 1)
r *= a;
diff --git a/compiler-rt/lib/builtins/trunctfdf2.c b/compiler-rt/lib/builtins/trunctfdf2.c
index f0d2e4141f3b04d..a5bdded53751fdb 100644
--- a/compiler-rt/lib/builtins/trunctfdf2.c
+++ b/compiler-rt/lib/builtins/trunctfdf2.c
@@ -14,6 +14,6 @@
#define DST_DOUBLE
#include "fp_trunc_impl.inc"
-COMPILER_RT_ABI double __trunctfdf2(long double a) { return __truncXfYf2__(a); }
+COMPILER_RT_ABI dst_t __trunctfdf2(src_t a) { return __truncXfYf2__(a); }
#endif
diff --git a/compiler-rt/lib/builtins/trunctfhf2.c b/compiler-rt/lib/builtins/trunctfhf2.c
index f7776327251c79f..3f031e0f844510c 100644
--- a/compiler-rt/lib/builtins/trunctfhf2.c
+++ b/compiler-rt/lib/builtins/trunctfhf2.c
@@ -15,8 +15,6 @@
#define DST_HALF
#include "fp_trunc_impl.inc"
-COMPILER_RT_ABI _Float16 __trunctfhf2(long double a) {
- return __truncXfYf2__(a);
-}
+COMPILER_RT_ABI dst_t __trunctfhf2(src_t a) { return __truncXfYf2__(a); }
#endif
diff --git a/compiler-rt/lib/builtins/trunctfsf2.c b/compiler-rt/lib/builtins/trunctfsf2.c
index 242735f738c1373..b65b5af2fc00178 100644
--- a/compiler-rt/lib/builtins/trunctfsf2.c
+++ b/compiler-rt/lib/builtins/trunctfsf2.c
@@ -14,6 +14,6 @@
#define DST_SINGLE
#include "fp_trunc_impl.inc"
-COMPILER_RT_ABI float __trunctfsf2(long double a) { return __truncXfYf2__(a); }
+COMPILER_RT_ABI dst_t __trunctfsf2(src_t a) { return __truncXfYf2__(a); }
#endif
diff --git a/compiler-rt/test/builtins/Unit/addtf3_test.c b/compiler-rt/test/builtins/Unit/addtf3_test.c
index fe2e2c80f655b7a..9d2ccf027d73025 100644
--- a/compiler-rt/test/builtins/Unit/addtf3_test.c
+++ b/compiler-rt/test/builtins/Unit/addtf3_test.c
@@ -10,12 +10,12 @@
#include "fp_test.h"
// Returns: a + b
-COMPILER_RT_ABI long double __addtf3(long double a, long double b);
+COMPILER_RT_ABI tf_float __addtf3(tf_float a, tf_float b);
-int test__addtf3(long double a, long double b,
+int test__addtf3(tf_float a, tf_float b,
uint64_t expectedHi, uint64_t expectedLo)
{
- long double x = __addtf3(a, b);
+ tf_float x = __addtf3(a, b);
int ret = compareResultLD(x, expectedHi, expectedLo);
if (ret){
@@ -27,7 +27,7 @@ int test__addtf3(long double a, long double b,
return ret;
}
-char assumption_1[sizeof(long double) * CHAR_BIT == 128] = {0};
+char assumption_1[sizeof(tf_float) * CHAR_BIT == 128] = {0};
#endif
@@ -42,7 +42,7 @@ int main()
return 1;
// NaN + any = NaN
if (test__addtf3(makeNaN128(UINT64_C(0x800030000000)),
- 0x1.23456789abcdefp+5L,
+ TF_C(0x1.23456789abcdefp+5),
UINT64_C(0x7fff800000000000),
UINT64_C(0x0)))
return 1;
@@ -54,13 +54,13 @@ int main()
return 1;
// inf + any = inf
if (test__addtf3(makeInf128(),
- 0x1.2335653452436234723489432abcdefp+5L,
+ TF_C(0x1.2335653452436234723489432abcdefp+5),
UINT64_C(0x7fff000000000000),
UINT64_C(0x0)))
return 1;
// any + any
- if (test__addtf3(0x1.23456734245345543849abcdefp+5L,
- 0x1.edcba52449872455634654321fp-1L,
+ if (test__addtf3(TF_C(0x1.23456734245345543849abcdefp+5),
+ TF_C(0x1.edcba52449872455634654321fp-1),
UINT64_C(0x40042afc95c8b579),
UINT64_C(0x61e58dd6c51eb77c)))
return 1;
@@ -69,7 +69,7 @@ int main()
defined(i386) || defined(__x86_64__) || (defined(__loongarch__) && \
__loongarch_frlen != 0)
// Rounding mode tests on supported architectures
- const long double m = 1234.0L, n = 0.01L;
+ const tf_float m = 1234.0L, n = 0.01L;
fesetround(FE_UPWARD);
if (test__addtf3(m, n,
diff --git a/compiler-rt/test/builtins/Unit/compiler_rt_fmaxl_test.c b/compiler-rt/test/builtins/Unit/compiler_rt_fmaxl_test.c
index 7b99514aad4e30a..693461452455d9e 100644
--- a/compiler-rt/test/builtins/Unit/compiler_rt_fmaxl_test.c
+++ b/compiler-rt/test/builtins/Unit/compiler_rt_fmaxl_test.c
@@ -6,7 +6,9 @@
#include <stdio.h>
#include "fp_lib.h"
-#if defined(CRT_HAS_TF_MODE)
+// TODO: This test currently only works if long double is the same as fp_t.
+// On x86_64 we get undefined references to __trunctfxf2 and __extendxftf2
+#if defined(CRT_HAS_TF_MODE) && defined(CRT_LDBL_IEEE_F128)
int test__compiler_rt_fmaxl(fp_t x, fp_t y) {
fp_t crt_value = __compiler_rt_fmaxl(x, y);
@@ -40,10 +42,7 @@ fp_t cases[] = {
-1.001, 1.001, -1.002, 1.002,
};
-#endif
-
int main() {
-#if defined(CRT_HAS_TF_MODE)
const unsigned N = sizeof(cases) / sizeof(cases[0]);
unsigned i, j;
for (i = 0; i < N; ++i) {
@@ -51,8 +50,11 @@ int main() {
if (test__compiler_rt_fmaxl(cases[i], cases[j])) return 1;
}
}
+ return 0;
+}
#else
+int main() {
printf("skipped\n");
-#endif
return 0;
}
+#endif
diff --git a/compiler-rt/test/builtins/Unit/compiler_rt_logbl_test.c b/compiler-rt/test/builtins/Unit/compiler_rt_logbl_test.c
index f48e67e7887cdc7..d169d18274867bd 100644
--- a/compiler-rt/test/builtins/Unit/compiler_rt_logbl_test.c
+++ b/compiler-rt/test/builtins/Unit/compiler_rt_logbl_test.c
@@ -6,7 +6,9 @@
#include "fp_lib.h"
#include "int_lib.h"
-#if defined(CRT_HAS_TF_MODE)
+// TODO: This test currently only works if long double is the same as fp_t.
+// On x86_64 we get undefined references to __trunctfxf2 and __extendxftf2
+#if defined(CRT_HAS_TF_MODE) && defined(CRT_LDBL_IEEE_F128)
int test__compiler_rt_logbl(fp_t x) {
#if defined(__ve__)
@@ -39,10 +41,7 @@ double cases[] = {
-0.0, 0.0, 1, -2, 2, -0.5, 0.5,
};
-#endif
-
int main() {
-#if defined(CRT_HAS_TF_MODE)
const unsigned N = sizeof(cases) / sizeof(cases[0]);
unsigned i;
for (i = 0; i < N; ++i) {
@@ -64,9 +63,12 @@ int main() {
if (test__compiler_rt_logbl(fromRep(signBit ^ x))) return 1;
x >>= 1;
}
+
+ return 0;
+}
#else
+int main() {
printf("skipped\n");
-#endif
-
return 0;
}
+#endif
diff --git a/compiler-rt/test/builtins/Unit/compiler_rt_scalbnl_test.c b/compiler-rt/test/builtins/Unit/compiler_rt_scalbnl_test.c
index 79193334c65d9f9..59c95e73dacc1bc 100644
--- a/compiler-rt/test/builtins/Unit/compiler_rt_scalbnl_test.c
+++ b/compiler-rt/test/builtins/Unit/compiler_rt_scalbnl_test.c
@@ -8,7 +8,9 @@
#include <stdio.h>
#include "fp_lib.h"
-#if defined(CRT_HAS_TF_MODE)
+// TODO: This test currently only works if long double is the same as fp_t.
+// On x86_64 we get undefined references to __trunctfxf2 and __extendxftf2
+#if defined(CRT_HAS_TF_MODE) && defined(CRT_LDBL_IEEE_F128)
int test__compiler_rt_scalbnl(const char *mode, fp_t x, int y) {
#if defined(__ve__)
@@ -64,18 +66,19 @@ int iterate_cases(const char *mode) {
return 0;
}
-#endif
-
int main() {
-#if defined(CRT_HAS_TF_MODE)
if (iterate_cases("default")) return 1;
// Skip rounding mode tests (fesetround) because compiler-rt's quad-precision
// multiply also ignores the current rounding mode.
+ return 0;
+}
+
#else
+int main() {
printf("skipped\n");
-#endif
-
return 0;
}
+#endif
+
diff --git a/compiler-rt/test/builtins/Unit/divtc3_test.c b/compiler-rt/test/builtins/Unit/divtc3_test.c
index 18042031ccf0ba1..9ba4880f4a11027 100644
--- a/compiler-rt/test/builtins/Unit/divtc3_test.c
+++ b/compiler-rt/test/builtins/Unit/divtc3_test.c
@@ -9,362 +9,357 @@
#include <stdio.h>
#include "int_lib.h"
-#include <math.h>
+#include "int_math.h"
#include <complex.h>
-
+#include <math.h>
// Returns: the quotient of (a + ib) / (c + id)
-COMPILER_RT_ABI long double _Complex
-__divtc3(long double __a, long double __b, long double __c, long double __d);
+COMPILER_RT_ABI Qcomplex __divtc3(tf_float __a, tf_float __b, tf_float __c,
+ tf_float __d);
enum {zero, non_zero, inf, NaN, non_zero_nan};
-int
-classify(long double _Complex x)
-{
- if (x == 0)
- return zero;
- if (isinf(creall(x)) || isinf(cimagl(x)))
- return inf;
- if (isnan(creall(x)) && isnan(cimagl(x)))
- return NaN;
- if (isnan(creall(x)))
- {
- if (cimagl(x) == 0)
- return NaN;
- return non_zero_nan;
- }
- if (isnan(cimagl(x)))
- {
- if (creall(x) == 0)
- return NaN;
- return non_zero_nan;
- }
- return non_zero;
+static int classify(Qcomplex x) {
+ tf_float real = COMPLEXTF_REAL(x);
+ tf_float imag = COMPLEXTF_IMAGINARY(x);
+ if (real == 0.0 && imag == 0.0)
+ return zero;
+ if (crt_isinf(real) || crt_isinf(imag))
+ return inf;
+ if (crt_isnan(real) && crt_isnan(imag))
+ return NaN;
+ if (crt_isnan(real)) {
+ if (imag == 0.0)
+ return NaN;
+ return non_zero_nan;
+ }
+ if (crt_isnan(imag)) {
+ if (real == 0.0)
+ return NaN;
+ return non_zero_nan;
+ }
+ return non_zero;
}
-int test__divtc3(long double a, long double b, long double c, long double d)
-{
- long double _Complex r = __divtc3(a, b, c, d);
-// printf("test__divtc3(%Lf, %Lf, %Lf, %Lf) = %Lf + I%Lf\n",
-// a, b, c, d, creall(r), cimagl(r));
-
- long double _Complex dividend;
- long double _Complex divisor;
-
- __real__ dividend = a;
- __imag__ dividend = b;
- __real__ divisor = c;
- __imag__ divisor = d;
-
- switch (classify(dividend))
- {
+static int test__divtc3(tf_float a, tf_float b, tf_float c, tf_float d) {
+ Qcomplex r = __divtc3(a, b, c, d);
+ Qcomplex dividend;
+ Qcomplex divisor;
+
+ COMPLEXTF_REAL(dividend) = a;
+ COMPLEXTF_IMAGINARY(dividend) = b;
+ COMPLEXTF_REAL(divisor) = c;
+ COMPLEXTF_IMAGINARY(divisor) = d;
+
+ switch (classify(dividend)) {
+ case zero:
+ switch (classify(divisor)) {
+ case zero:
+ if (classify(r) != NaN)
+ return 1;
+ break;
+ case non_zero:
+ if (classify(r) != zero)
+ return 1;
+ break;
+ case inf:
+ if (classify(r) != zero)
+ return 1;
+ break;
+ case NaN:
+ if (classify(r) != NaN)
+ return 1;
+ break;
+ case non_zero_nan:
+ if (classify(r) != NaN)
+ return 1;
+ break;
+ }
+ break;
+ case non_zero:
+ switch (classify(divisor)) {
+ case zero:
+ if (classify(r) != inf)
+ return 1;
+ break;
+ case non_zero:
+ if (classify(r) != non_zero)
+ return 1;
+ {
+ tf_float zReal = (a * c + b * d) / (c * c + d * d);
+ tf_float zImag = (b * c - a * d) / (c * c + d * d);
+ Qcomplex diff =
+ __divtc3(COMPLEXTF_REAL(r) - zReal, COMPLEXTF_IMAGINARY(r) - zImag,
+ COMPLEXTF_REAL(r), COMPLEXTF_IMAGINARY(r));
+ // cabsl(z) == hypotl(creall(z), cimagl(z))
+#ifdef CRT_LDBL_128BIT
+ if (hypotl(COMPLEXTF_REAL(diff), COMPLEXTF_IMAGINARY(diff)) > 1.e-6)
+#else
+ // Avoid dependency on __trunctfxf2 for ld80 platforms and use double instead.
+ if (hypot(COMPLEXTF_REAL(diff), COMPLEXTF_IMAGINARY(diff)) > 1.e-6)
+#endif
+ return 1;
+ }
+ break;
+ case inf:
+ if (classify(r) != zero)
+ return 1;
+ break;
+ case NaN:
+ if (classify(r) != NaN)
+ return 1;
+ break;
+ case non_zero_nan:
+ if (classify(r) != NaN)
+ return 1;
+ break;
+ }
+ break;
+ case inf:
+ switch (classify(divisor)) {
+ case zero:
+ if (classify(r) != inf)
+ return 1;
+ break;
+ case non_zero:
+ if (classify(r) != inf)
+ return 1;
+ break;
+ case inf:
+ if (classify(r) != NaN)
+ return 1;
+ break;
+ case NaN:
+ if (classify(r) != NaN)
+ return 1;
+ break;
+ case non_zero_nan:
+ if (classify(r) != NaN)
+ return 1;
+ break;
+ }
+ break;
+ case NaN:
+ switch (classify(divisor)) {
+ case zero:
+ if (classify(r) != NaN)
+ return 1;
+ break;
+ case non_zero:
+ if (classify(r) != NaN)
+ return 1;
+ break;
+ case inf:
+ if (classify(r) != NaN)
+ return 1;
+ break;
+ case NaN:
+ if (classify(r) != NaN)
+ return 1;
+ break;
+ case non_zero_nan:
+ if (classify(r) != NaN)
+ return 1;
+ break;
+ }
+ break;
+ case non_zero_nan:
+ switch (classify(divisor)) {
case zero:
- switch (classify(divisor))
- {
- case zero:
- if (classify(r) != NaN)
- return 1;
- break;
- case non_zero:
- if (classify(r) != zero)
- return 1;
- break;
- case inf:
- if (classify(r) != zero)
- return 1;
- break;
- case NaN:
- if (classify(r) != NaN)
- return 1;
- break;
- case non_zero_nan:
- if (classify(r) != NaN)
- return 1;
- break;
- }
- break;
+ if (classify(r) != inf)
+ return 1;
+ break;
case non_zero:
- switch (classify(divisor))
- {
- case zero:
- if (classify(r) != inf)
- return 1;
- break;
- case non_zero:
- if (classify(r) != non_zero)
- return 1;
- {
- long double _Complex z = (a * c + b * d) / (c * c + d * d)
- + (b * c - a * d) / (c * c + d * d) * _Complex_I;
- if (cabsl((r - z)/r) > 1.e-6)
- return 1;
- }
- break;
- case inf:
- if (classify(r) != zero)
- return 1;
- break;
- case NaN:
- if (classify(r) != NaN)
- return 1;
- break;
- case non_zero_nan:
- if (classify(r) != NaN)
- return 1;
- break;
- }
- break;
+ if (classify(r) != NaN)
+ return 1;
+ break;
case inf:
- switch (classify(divisor))
- {
- case zero:
- if (classify(r) != inf)
- return 1;
- break;
- case non_zero:
- if (classify(r) != inf)
- return 1;
- break;
- case inf:
- if (classify(r) != NaN)
- return 1;
- break;
- case NaN:
- if (classify(r) != NaN)
- return 1;
- break;
- case non_zero_nan:
- if (classify(r) != NaN)
- return 1;
- break;
- }
- break;
+ if (classify(r) != NaN)
+ return 1;
+ break;
case NaN:
- switch (classify(divisor))
- {
- case zero:
- if (classify(r) != NaN)
- return 1;
- break;
- case non_zero:
- if (classify(r) != NaN)
- return 1;
- break;
- case inf:
- if (classify(r) != NaN)
- return 1;
- break;
- case NaN:
- if (classify(r) != NaN)
- return 1;
- break;
- case non_zero_nan:
- if (classify(r) != NaN)
- return 1;
- break;
- }
- break;
+ if (classify(r) != NaN)
+ return 1;
+ break;
case non_zero_nan:
- switch (classify(divisor))
- {
- case zero:
- if (classify(r) != inf)
- return 1;
- break;
- case non_zero:
- if (classify(r) != NaN)
- return 1;
- break;
- case inf:
- if (classify(r) != NaN)
- return 1;
- break;
- case NaN:
- if (classify(r) != NaN)
- return 1;
- break;
- case non_zero_nan:
- if (classify(r) != NaN)
- return 1;
- break;
- }
- break;
+ if (classify(r) != NaN)
+ return 1;
+ break;
}
-
- return 0;
+ break;
+ }
+
+ return 0;
}
-long double x[][2] =
-{
- { 1.e-6, 1.e-6},
- {-1.e-6, 1.e-6},
- {-1.e-6, -1.e-6},
- { 1.e-6, -1.e-6},
+tf_float x[][2] = {{1.e-6, 1.e-6},
+ {-1.e-6, 1.e-6},
+ {-1.e-6, -1.e-6},
+ {1.e-6, -1.e-6},
- { 1.e+6, 1.e-6},
- {-1.e+6, 1.e-6},
- {-1.e+6, -1.e-6},
- { 1.e+6, -1.e-6},
+ {1.e+6, 1.e-6},
+ {-1.e+6, 1.e-6},
+ {-1.e+6, -1.e-6},
+ {1.e+6, -1.e-6},
- { 1.e-6, 1.e+6},
- {-1.e-6, 1.e+6},
- {-1.e-6, -1.e+6},
- { 1.e-6, -1.e+6},
+ {1.e-6, 1.e+6},
+ {-1.e-6, 1.e+6},
+ {-1.e-6, -1.e+6},
+ {1.e-6, -1.e+6},
- { 1.e+6, 1.e+6},
- {-1.e+6, 1.e+6},
- {-1.e+6, -1.e+6},
- { 1.e+6, -1.e+6},
+ {1.e+6, 1.e+6},
+ {-1.e+6, 1.e+6},
+ {-1.e+6, -1.e+6},
+ {1.e+6, -1.e+6},
- {NAN, NAN},
- {-INFINITY, NAN},
- {-2, NAN},
- {-1, NAN},
- {-0.5, NAN},
- {-0., NAN},
- {+0., NAN},
- {0.5, NAN},
- {1, NAN},
- {2, NAN},
- {INFINITY, NAN},
+ {NAN, NAN},
+ {-INFINITY, NAN},
+ {-2, NAN},
+ {-1, NAN},
+ {-0.5, NAN},
+ {-0., NAN},
+ {+0., NAN},
+ {0.5, NAN},
+ {1, NAN},
+ {2, NAN},
+ {INFINITY, NAN},
- {NAN, -INFINITY},
- {-INFINITY, -INFINITY},
- {-2, -INFINITY},
- {-1, -INFINITY},
- {-0.5, -INFINITY},
- {-0., -INFINITY},
- {+0., -INFINITY},
- {0.5, -INFINITY},
- {1, -INFINITY},
- {2, -INFINITY},
- {INFINITY, -INFINITY},
+ {NAN, -INFINITY},
+ {-INFINITY, -INFINITY},
+ {-2, -INFINITY},
+ {-1, -INFINITY},
+ {-0.5, -INFINITY},
+ {-0., -INFINITY},
+ {+0., -INFINITY},
+ {0.5, -INFINITY},
+ {1, -INFINITY},
+ {2, -INFINITY},
+ {INFINITY, -INFINITY},
- {NAN, -2},
- {-INFINITY, -2},
- {-2, -2},
- {-1, -2},
- {-0.5, -2},
- {-0., -2},
- {+0., -2},
- {0.5, -2},
- {1, -2},
- {2, -2},
- {INFINITY, -2},
+ {NAN, -2},
+ {-INFINITY, -2},
+ {-2, -2},
+ {-1, -2},
+ {-0.5, -2},
+ {-0., -2},
+ {+0., -2},
+ {0.5, -2},
+ {1, -2},
+ {2, -2},
+ {INFINITY, -2},
- {NAN, -1},
- {-INFINITY, -1},
- {-2, -1},
- {-1, -1},
- {-0.5, -1},
- {-0., -1},
- {+0., -1},
- {0.5, -1},
- {1, -1},
- {2, -1},
- {INFINITY, -1},
+ {NAN, -1},
+ {-INFINITY, -1},
+ {-2, -1},
+ {-1, -1},
+ {-0.5, -1},
+ {-0., -1},
+ {+0., -1},
+ {0.5, -1},
+ {1, -1},
+ {2, -1},
+ {INFINITY, -1},
- {NAN, -0.5},
- {-INFINITY, -0.5},
- {-2, -0.5},
- {-1, -0.5},
- {-0.5, -0.5},
- {-0., -0.5},
- {+0., -0.5},
- {0.5, -0.5},
- {1, -0.5},
- {2, -0.5},
- {INFINITY, -0.5},
+ {NAN, -0.5},
+ {-INFINITY, -0.5},
+ {-2, -0.5},
+ {-1, -0.5},
+ {-0.5, -0.5},
+ {-0., -0.5},
+ {+0., -0.5},
+ {0.5, -0.5},
+ {1, -0.5},
+ {2, -0.5},
+ {INFINITY, -0.5},
- {NAN, -0.},
- {-INFINITY, -0.},
- {-2, -0.},
- {-1, -0.},
- {-0.5, -0.},
- {-0., -0.},
- {+0., -0.},
- {0.5, -0.},
- {1, -0.},
- {2, -0.},
- {INFINITY, -0.},
+ {NAN, -0.},
+ {-INFINITY, -0.},
+ {-2, -0.},
+ {-1, -0.},
+ {-0.5, -0.},
+ {-0., -0.},
+ {+0., -0.},
+ {0.5, -0.},
+ {1, -0.},
+ {2, -0.},
+ {INFINITY, -0.},
- {NAN, 0.},
- {-INFINITY, 0.},
- {-2, 0.},
- {-1, 0.},
- {-0.5, 0.},
- {-0., 0.},
- {+0., 0.},
- {0.5, 0.},
- {1, 0.},
- {2, 0.},
- {INFINITY, 0.},
+ {NAN, 0.},
+ {-INFINITY, 0.},
+ {-2, 0.},
+ {-1, 0.},
+ {-0.5, 0.},
+ {-0., 0.},
+ {+0., 0.},
+ {0.5, 0.},
+ {1, 0.},
+ {2, 0.},
+ {INFINITY, 0.},
- {NAN, 0.5},
- {-INFINITY, 0.5},
- {-2, 0.5},
- {-1, 0.5},
- {-0.5, 0.5},
- {-0., 0.5},
- {+0., 0.5},
- {0.5, 0.5},
- {1, 0.5},
- {2, 0.5},
- {INFINITY, 0.5},
+ {NAN, 0.5},
+ {-INFINITY, 0.5},
+ {-2, 0.5},
+ {-1, 0.5},
+ {-0.5, 0.5},
+ {-0., 0.5},
+ {+0., 0.5},
+ {0.5, 0.5},
+ {1, 0.5},
+ {2, 0.5},
+ {INFINITY, 0.5},
- {NAN, 1},
- {-INFINITY, 1},
- {-2, 1},
- {-1, 1},
- {-0.5, 1},
- {-0., 1},
- {+0., 1},
- {0.5, 1},
- {1, 1},
- {2, 1},
- {INFINITY, 1},
+ {NAN, 1},
+ {-INFINITY, 1},
+ {-2, 1},
+ {-1, 1},
+ {-0.5, 1},
+ {-0., 1},
+ {+0., 1},
+ {0.5, 1},
+ {1, 1},
+ {2, 1},
+ {INFINITY, 1},
- {NAN, 2},
- {-INFINITY, 2},
- {-2, 2},
- {-1, 2},
- {-0.5, 2},
- {-0., 2},
- {+0., 2},
- {0.5, 2},
- {1, 2},
- {2, 2},
- {INFINITY, 2},
+ {NAN, 2},
+ {-INFINITY, 2},
+ {-2, 2},
+ {-1, 2},
+ {-0.5, 2},
+ {-0., 2},
+ {+0., 2},
+ {0.5, 2},
+ {1, 2},
+ {2, 2},
+ {INFINITY, 2},
- {NAN, INFINITY},
- {-INFINITY, INFINITY},
- {-2, INFINITY},
- {-1, INFINITY},
- {-0.5, INFINITY},
- {-0., INFINITY},
- {+0., INFINITY},
- {0.5, INFINITY},
- {1, INFINITY},
- {2, INFINITY},
- {INFINITY, INFINITY}
+ {NAN, INFINITY},
+ {-INFINITY, INFINITY},
+ {-2, INFINITY},
+ {-1, INFINITY},
+ {-0.5, INFINITY},
+ {-0., INFINITY},
+ {+0., INFINITY},
+ {0.5, INFINITY},
+ {1, INFINITY},
+ {2, INFINITY},
+ {INFINITY, INFINITY}
};
-int main()
-{
- const unsigned N = sizeof(x) / sizeof(x[0]);
- unsigned i, j;
- for (i = 0; i < N; ++i)
- {
- for (j = 0; j < N; ++j)
- {
- if (test__divtc3(x[i][0], x[i][1], x[j][0], x[j][1]))
- return 1;
- }
+int main() {
+ const unsigned N = sizeof(x) / sizeof(x[0]);
+ unsigned i, j;
+ for (i = 0; i < N; ++i) {
+ for (j = 0; j < N; ++j) {
+ if (test__divtc3(x[i][0], x[i][1], x[j][0], x[j][1])) {
+ fprintf(stderr, "Failed for %g, %g, %g, %g\n", (double)x[i][0],
+ (double)x[i][1], (double)x[j][0], (double)x[j][1]);
+ return 1;
+ }
}
+ }
-// printf("No errors found.\n");
- return 0;
+ fprintf(stderr, "No errors found.\n");
+ return 0;
}
diff --git a/compiler-rt/test/builtins/Unit/floattitf_test.c b/compiler-rt/test/builtins/Unit/floattitf_test.c
index abd3006135b38f7..34eed3cdaceb21d 100644
--- a/compiler-rt/test/builtins/Unit/floattitf_test.c
+++ b/compiler-rt/test/builtins/Unit/floattitf_test.c
@@ -7,7 +7,7 @@
#include <float.h>
#include <stdio.h>
-#if defined(CRT_HAS_TF_MODE)
+#if defined(CRT_HAS_TF_MODE) && defined(CRT_LDBL_IEEE_F128)
/* Returns: convert a ti_int to a fp_t, rounding toward even. */
@@ -36,10 +36,7 @@ char assumption_1[sizeof(ti_int) == 2 * sizeof(di_int)] = {0};
char assumption_2[sizeof(ti_int) * CHAR_BIT == 128] = {0};
char assumption_3[sizeof(fp_t) * CHAR_BIT == 128] = {0};
-#endif
-
int main() {
-#if defined(CRT_HAS_TF_MODE)
if (test__floattitf(0, 0.0))
return 1;
@@ -215,8 +212,12 @@ int main() {
if (test__floattitf(make_ti(0x123456789ABCDEF0LL, 0x123456789ABC57FFLL),
TF_C(0x1.23456789ABCDEF0123456789ABC5p+124)))
return 1;
+ return 0;
+}
+
#else
+int main() {
printf("skipped\n");
-#endif
return 0;
}
+#endif
diff --git a/compiler-rt/test/builtins/Unit/floatunditf_test.c b/compiler-rt/test/builtins/Unit/floatunditf_test.c
index d44ae7934145a6d..f46b3e8f4c0f096 100644
--- a/compiler-rt/test/builtins/Unit/floatunditf_test.c
+++ b/compiler-rt/test/builtins/Unit/floatunditf_test.c
@@ -12,7 +12,7 @@
// Returns: long integer converted to long double
-COMPILER_RT_ABI long double __floatunditf(du_int a);
+COMPILER_RT_ABI tf_float __floatunditf(du_int a);
int test__floatunditf(du_int a, uint64_t expectedHi, uint64_t expectedLo)
{
diff --git a/compiler-rt/test/builtins/Unit/floatuntitf_test.c b/compiler-rt/test/builtins/Unit/floatuntitf_test.c
index db25f2b0230cd14..39cc6ea6aab60dd 100644
--- a/compiler-rt/test/builtins/Unit/floatuntitf_test.c
+++ b/compiler-rt/test/builtins/Unit/floatuntitf_test.c
@@ -9,9 +9,9 @@
#if defined(CRT_HAS_TF_MODE)
-/* Returns: convert a tu_int to a fp_t, rounding toward even. */
+/* Returns: convert a tu_int to a tf_float, rounding toward even. */
-/* Assumption: fp_t is a IEEE 128 bit floating point type
+/* Assumption: tf_float is a IEEE 128 bit floating point type
* tu_int is a 128 bit integral type
*/
@@ -19,10 +19,10 @@
* mmmm mmmm mmmm mmmm mmmm mmmm mmmm mmmm | mmmm mmmm mmmm mmmm mmmm mmmm mmmm mmmm
*/
-COMPILER_RT_ABI fp_t __floatuntitf(tu_int a);
+COMPILER_RT_ABI tf_float __floatuntitf(tu_int a);
-int test__floatuntitf(tu_int a, fp_t expected) {
- fp_t x = __floatuntitf(a);
+int test__floatuntitf(tu_int a, tf_float expected) {
+ tf_float x = __floatuntitf(a);
if (x != expected) {
utwords at;
at.all = a;
@@ -34,7 +34,7 @@ int test__floatuntitf(tu_int a, fp_t expected) {
char assumption_1[sizeof(tu_int) == 2 * sizeof(du_int)] = {0};
char assumption_2[sizeof(tu_int) * CHAR_BIT == 128] = {0};
-char assumption_3[sizeof(fp_t) * CHAR_BIT == 128] = {0};
+char assumption_3[sizeof(tf_float) * CHAR_BIT == 128] = {0};
#endif
More information about the llvm-commits
mailing list