From d2ce3e9621411f3391def327f89e3a650918989f Mon Sep 17 00:00:00 2001 From: Alexander Richardson Date: Tue, 24 Oct 2023 09:32:01 -0700 Subject: [PATCH] [builtins] Support building the 128-bit float functions on ld80 platforms (#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. --- compiler-rt/lib/builtins/CMakeLists.txt | 2 - compiler-rt/lib/builtins/README.txt | 21 +- 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/extendxftf2.c | 9 +- compiler-rt/lib/builtins/fp_extend.h | 8 +- compiler-rt/lib/builtins/fp_lib.h | 50 +- compiler-rt/lib/builtins/fp_trunc.h | 8 +- compiler-rt/lib/builtins/int_math.h | 10 + compiler-rt/lib/builtins/int_to_fp.h | 2 +- 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/lib/builtins/trunctfxf2.c | 9 +- compiler-rt/test/builtins/Unit/addtf3_test.c | 154 ++--- .../builtins/Unit/compiler_rt_fmaxl_test.c | 13 +- .../builtins/Unit/compiler_rt_logbl_test.c | 57 +- .../builtins/Unit/compiler_rt_scalbnl_test.c | 68 +- compiler-rt/test/builtins/Unit/divtc3_test.c | 639 +++++++++--------- compiler-rt/test/builtins/Unit/divtf3_test.c | 319 ++++----- .../test/builtins/Unit/extendxftf2_test.c | 4 +- .../test/builtins/Unit/floatditf_test.c | 80 ++- .../test/builtins/Unit/floattitf_test.c | 87 ++- .../test/builtins/Unit/floatunditf_test.c | 73 +- .../test/builtins/Unit/floatunsitf_test.c | 57 +- .../test/builtins/Unit/floatuntitf_test.c | 89 +-- compiler-rt/test/builtins/Unit/fp_test.h | 42 +- .../test/builtins/Unit/trunctfxf2_test.c | 12 +- 33 files changed, 1060 insertions(+), 954 deletions(-) diff --git a/compiler-rt/lib/builtins/CMakeLists.txt b/compiler-rt/lib/builtins/CMakeLists.txt index cf2648233b0cf8..a705486e2d3c84 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 5637183cc3b455..2d213d95f333af 100644 --- a/compiler-rt/lib/builtins/README.txt +++ b/compiler-rt/lib/builtins/README.txt @@ -137,49 +137,54 @@ 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( tf_float 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( tf_float a); su_int __fixunssfsi( float a); su_int __fixunsdfsi( double a); su_int __fixunsxfsi(long double a); +su_int __fixunstfsi( tf_float a); du_int __fixunssfdi( float a); du_int __fixunsdfdi( double a); du_int __fixunsxfdi(long double a); +du_int __fixunstfdi( tf_float 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 +tu_int __fixunstfti( tf_float a); float __floatdisf(di_int a); double __floatdidf(di_int a); long double __floatdixf(di_int a); -long double __floatditf(int64_t a); // ppc only +tf_float __floatditf(int64_t a); float __floattisf(ti_int a); double __floattidf(ti_int a); long double __floattixf(ti_int a); +tf_float __floattitf(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 +tf_float __floatunditf(du_int a); float __floatuntisf(tu_int a); double __floatuntidf(tu_int a); long double __floatuntixf(tu_int a); +tf_float __floatuntixf(tu_int a); // Floating point raised to integer power 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 +tf_float __powitf2( tf_float a, int b); // a ^ b // Complex arithmetic @@ -189,8 +194,7 @@ long double __powitf2(long double a, int b); // ppc only, a ^ b double _Complex __muldc3(double a, double b, double c, double d); 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 + tf_float _Complex __multc3(tf_float a, tf_float b, tf_float c, tf_float d); // (a + ib) / (c + id) @@ -198,8 +202,7 @@ long double _Complex __multc3(long double a, long double b, double _Complex __divdc3(double a, double b, double c, double d); 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 + tf_float _Complex __divtc3(tf_float a, tf_float b, tf_float c, tf_float d); // Runtime support diff --git a/compiler-rt/lib/builtins/divtc3.c b/compiler-rt/lib/builtins/divtc3.c index 0e4799295f32fe..e970cef574b21d 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 835076be1f2080..a61ef53147abcf 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 a2cb0f771ee9aa..7609db6f06e4ad 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 0739859bcbc18f..4ab2982ce5142b 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/extendxftf2.c b/compiler-rt/lib/builtins/extendxftf2.c index 20911fe7cf2a00..6cb8a63122f226 100644 --- a/compiler-rt/lib/builtins/extendxftf2.c +++ b/compiler-rt/lib/builtins/extendxftf2.c @@ -9,14 +9,15 @@ // Assumption: long double is a IEEE 80 bit floating point type padded to 128 // bits. -// TODO: use fp_lib.h once QUAD_PRECISION is available on x86_64. -#if __LDBL_MANT_DIG__ == 64 && defined(__x86_64__) && \ - (defined(__FLOAT128__) || defined(__SIZEOF_FLOAT128__)) +#define QUAD_PRECISION +#include "fp_lib.h" + +#if defined(CRT_HAS_TF_MODE) && __LDBL_MANT_DIG__ == 64 && defined(__x86_64__) #define SRC_80 #define DST_QUAD #include "fp_extend_impl.inc" -COMPILER_RT_ABI __float128 __extendxftf2(long double a) { +COMPILER_RT_ABI tf_float __extendxftf2(long double a) { return __extendXfYf2__(a); } diff --git a/compiler-rt/lib/builtins/fp_extend.h b/compiler-rt/lib/builtins/fp_extend.h index d640bdcb0ec1fa..fcd3102bbf9da2 100644 --- a/compiler-rt/lib/builtins/fp_extend.h +++ b/compiler-rt/lib/builtins/fp_extend.h @@ -102,13 +102,7 @@ static const int dstSigFracBits = 52; static const int dstExpBits = 11; #elif defined DST_QUAD -// TODO: use fp_lib.h once QUAD_PRECISION is available on x86_64. -#if __LDBL_MANT_DIG__ == 113 -typedef long double dst_t; -#elif defined(__x86_64__) && \ - (defined(__FLOAT128__) || defined(__SIZEOF_FLOAT128__)) -typedef __float128 dst_t; -#endif +typedef tf_float dst_t; typedef __uint128_t dst_rep_t; #define DST_REP_C (__uint128_t) static const int dstBits = sizeof(dst_t) * CHAR_BIT; diff --git a/compiler-rt/lib/builtins/fp_lib.h b/compiler-rt/lib/builtins/fp_lib.h index 58eb45fcc72929..43bbdd5f873657 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 f62f8bafc7995f..5e81eb73f94103 100644 --- a/compiler-rt/lib/builtins/fp_trunc.h +++ b/compiler-rt/lib/builtins/fp_trunc.h @@ -36,13 +36,7 @@ static const int srcSigFracBits = 52; static const int srcExpBits = 11; #elif defined SRC_QUAD -// TODO: use fp_lib.h once QUAD_PRECISION is available on x86_64. -#if __LDBL_MANT_DIG__ == 113 -typedef long double src_t; -#elif defined(__x86_64__) && \ - (defined(__FLOAT128__) || defined(__SIZEOF_FLOAT128__)) -typedef __float128 src_t; -#endif +typedef tf_float src_t; typedef __uint128_t src_rep_t; #define SRC_REP_C (__uint128_t) static const int srcBits = sizeof(src_t) * CHAR_BIT; diff --git a/compiler-rt/lib/builtins/int_math.h b/compiler-rt/lib/builtins/int_math.h index 48b9580f5961b0..74d3e311db5e71 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_to_fp.h b/compiler-rt/lib/builtins/int_to_fp.h index 9e56a1469679ec..2c1218f1e89c4f 100644 --- a/compiler-rt/lib/builtins/int_to_fp.h +++ b/compiler-rt/lib/builtins/int_to_fp.h @@ -59,7 +59,7 @@ enum { }; #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) diff --git a/compiler-rt/lib/builtins/int_types.h b/compiler-rt/lib/builtins/int_types.h index e94d3154c6d4ef..f705844610f6ac 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 bb7f6aabfe2c8e..f20e53ccbf233b 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 74fe707a4e8c40..e02db40767ac03 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 f0d2e4141f3b04..a5bdded53751fd 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 f7776327251c79..3f031e0f844510 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 242735f738c137..b65b5af2fc0017 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/lib/builtins/trunctfxf2.c b/compiler-rt/lib/builtins/trunctfxf2.c index 4a22a602b38173..6a84477879f0f7 100644 --- a/compiler-rt/lib/builtins/trunctfxf2.c +++ b/compiler-rt/lib/builtins/trunctfxf2.c @@ -9,15 +9,16 @@ // Assumption: long double is a IEEE 80 bit floating point type padded to 128 // bits. -// TODO: use fp_lib.h once QUAD_PRECISION is available on x86_64. -#if __LDBL_MANT_DIG__ == 64 && defined(__x86_64__) && \ - (defined(__FLOAT128__) || defined(__SIZEOF_FLOAT128__)) +#define QUAD_PRECISION +#include "fp_lib.h" + +#if defined(CRT_HAS_TF_MODE) && __LDBL_MANT_DIG__ == 64 && defined(__x86_64__) #define SRC_QUAD #define DST_80 #include "fp_trunc_impl.inc" -COMPILER_RT_ABI long double __trunctfxf2(__float128 a) { +COMPILER_RT_ABI long double __trunctfxf2(tf_float a) { return __truncXfYf2__(a); } diff --git a/compiler-rt/test/builtins/Unit/addtf3_test.c b/compiler-rt/test/builtins/Unit/addtf3_test.c index e6986c236a64f5..cd5872e7dedf40 100644 --- a/compiler-rt/test/builtins/Unit/addtf3_test.c +++ b/compiler-rt/test/builtins/Unit/addtf3_test.c @@ -4,102 +4,90 @@ #include #include -#if __LDBL_MANT_DIG__ == 113 +// The testcase currently assumes IEEE TF format, once that has been +// fixed the defined(CRT_HAS_IEEE_TF) guard can be removed to enable it for +// IBM 128 floats as well. +#if defined(CRT_HAS_IEEE_TF) -#include "int_lib.h" -#include "fp_test.h" +# include "fp_test.h" +# include "int_lib.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, - uint64_t expectedHi, uint64_t expectedLo) -{ - long double x = __addtf3(a, b); - int ret = compareResultF128(x, expectedHi, expectedLo); +int test__addtf3(tf_float a, tf_float b, uint64_t expectedHi, + uint64_t expectedLo) { + tf_float x = __addtf3(a, b); + int ret = compareResultF128(x, expectedHi, expectedLo); - if (ret){ - printf("error in test__addtf3(%.20Lf, %.20Lf) = %.20Lf, " - "expected %.20Lf\n", a, b, x, - fromRep128(expectedHi, expectedLo)); - } + if (ret) { + printf("error in test__addtf3(%.20Lf, %.20Lf) = %.20Lf, " + "expected %.20Lf\n", + a, b, x, fromRep128(expectedHi, expectedLo)); + } - return ret; + return ret; } -char assumption_1[sizeof(long double) * CHAR_BIT == 128] = {0}; +char assumption_1[sizeof(tf_float) * CHAR_BIT == 128] = {0}; #endif -int main() -{ -#if __LDBL_MANT_DIG__ == 113 - // qNaN + any = qNaN - if (test__addtf3(makeQNaN128(), - 0x1.23456789abcdefp+5L, - UINT64_C(0x7fff800000000000), - UINT64_C(0x0))) - return 1; - // NaN + any = NaN - if (test__addtf3(makeNaN128(UINT64_C(0x800030000000)), - 0x1.23456789abcdefp+5L, - UINT64_C(0x7fff800000000000), - UINT64_C(0x0))) - return 1; - // inf + inf = inf - if (test__addtf3(makeInf128(), - makeInf128(), - UINT64_C(0x7fff000000000000), - UINT64_C(0x0))) - return 1; - // inf + any = inf - if (test__addtf3(makeInf128(), - 0x1.2335653452436234723489432abcdefp+5L, - UINT64_C(0x7fff000000000000), - UINT64_C(0x0))) - return 1; - // any + any - if (test__addtf3(0x1.23456734245345543849abcdefp+5L, - 0x1.edcba52449872455634654321fp-1L, - UINT64_C(0x40042afc95c8b579), - UINT64_C(0x61e58dd6c51eb77c))) - return 1; - -#if (defined(__arm__) || defined(__aarch64__)) && defined(__ARM_FP) || \ - 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; - - fesetround(FE_UPWARD); - if (test__addtf3(m, n, - UINT64_C(0x40093480a3d70a3d), - UINT64_C(0x70a3d70a3d70a3d8))) - return 1; - - fesetround(FE_DOWNWARD); - if (test__addtf3(m, n, - UINT64_C(0x40093480a3d70a3d), - UINT64_C(0x70a3d70a3d70a3d7))) - return 1; - - - fesetround(FE_TOWARDZERO); - if (test__addtf3(m, n, - UINT64_C(0x40093480a3d70a3d), - UINT64_C(0x70a3d70a3d70a3d7))) - return 1; - - fesetround(FE_TONEAREST); - if (test__addtf3(m, n, - UINT64_C(0x40093480a3d70a3d), - UINT64_C(0x70a3d70a3d70a3d7))) - return 1; -#endif +int main() { +#if defined(CRT_HAS_IEEE_TF) + // qNaN + any = qNaN + if (test__addtf3(makeQNaN128(), 0x1.23456789abcdefp+5L, + UINT64_C(0x7fff800000000000), UINT64_C(0x0))) + return 1; + // NaN + any = NaN + if (test__addtf3(makeNaN128(UINT64_C(0x800030000000)), + TF_C(0x1.23456789abcdefp+5), UINT64_C(0x7fff800000000000), + UINT64_C(0x0))) + return 1; + // inf + inf = inf + if (test__addtf3(makeInf128(), makeInf128(), UINT64_C(0x7fff000000000000), + UINT64_C(0x0))) + return 1; + // inf + any = inf + if (test__addtf3(makeInf128(), TF_C(0x1.2335653452436234723489432abcdefp+5), + UINT64_C(0x7fff000000000000), UINT64_C(0x0))) + return 1; + // any + any + if (test__addtf3(TF_C(0x1.23456734245345543849abcdefp+5), + TF_C(0x1.edcba52449872455634654321fp-1), + UINT64_C(0x40042afc95c8b579), UINT64_C(0x61e58dd6c51eb77c))) + return 1; + +# if (defined(__arm__) || defined(__aarch64__)) && defined(__ARM_FP) || \ + defined(i386) || defined(__x86_64__) || \ + (defined(__loongarch__) && __loongarch_frlen != 0) + // Rounding mode tests on supported architectures + const tf_float m = 1234.0L, n = 0.01L; + + fesetround(FE_UPWARD); + if (test__addtf3(m, n, UINT64_C(0x40093480a3d70a3d), + UINT64_C(0x70a3d70a3d70a3d8))) + return 1; + + fesetround(FE_DOWNWARD); + if (test__addtf3(m, n, UINT64_C(0x40093480a3d70a3d), + UINT64_C(0x70a3d70a3d70a3d7))) + return 1; + + fesetround(FE_TOWARDZERO); + if (test__addtf3(m, n, UINT64_C(0x40093480a3d70a3d), + UINT64_C(0x70a3d70a3d70a3d7))) + return 1; + + fesetround(FE_TONEAREST); + if (test__addtf3(m, n, UINT64_C(0x40093480a3d70a3d), + UINT64_C(0x70a3d70a3d70a3d7))) + return 1; +# endif #else - printf("skipped\n"); + printf("skipped\n"); #endif - return 0; + return 0; } 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 7b99514aad4e30..44f75cf0c3c2a8 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,10 @@ #include #include "fp_lib.h" -#if defined(CRT_HAS_TF_MODE) +// Since we are comparing the compiler-rt IEEE implementation against libc's +// long double implementation, this test can only succeed if long double +// is an IEEE 128-bit floating point number. +#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 +43,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 +51,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 f48e67e7887cdc..f49ce710b04432 100644 --- a/compiler-rt/test/builtins/Unit/compiler_rt_logbl_test.c +++ b/compiler-rt/test/builtins/Unit/compiler_rt_logbl_test.c @@ -1,18 +1,18 @@ // RUN: %clang_builtins %s %librt -o %t && %run %t #define QUAD_PRECISION -#include -#include #include "fp_lib.h" #include "int_lib.h" +#include +#include #if defined(CRT_HAS_TF_MODE) int test__compiler_rt_logbl(fp_t x) { -#if defined(__ve__) +# if defined(__ve__) if (fpclassify(x) == FP_SUBNORMAL) return 0; -#endif +# endif fp_t crt_value = __compiler_rt_logbl(x); fp_t libm_value = logbl(x); // Compare the values, considering all NaNs equivalent, as the spec doesn't @@ -24,49 +24,62 @@ int test__compiler_rt_logbl(fp_t x) { x_t.all = toRep(x); crt_value_t.all = toRep(crt_value); libm_value_t.all = toRep(libm_value); - printf( - "error: in __compiler_rt_logbl([%llX %llX]) = [%llX %llX] != " - "[%llX %llX]\n", - x_t.s.high, x_t.s.low, crt_value_t.s.high, crt_value_t.s.low, - libm_value_t.s.high, libm_value_t.s.low); + printf("error: in __compiler_rt_logbl([%llX %llX]) = [%llX %llX] != " + "[%llX %llX]\n", + x_t.s.high, x_t.s.low, crt_value_t.s.high, crt_value_t.s.low, + libm_value_t.s.high, libm_value_t.s.low); return 1; } return 0; } -double cases[] = { +fp_t cases[] = { 1.e-6, -1.e-6, NAN, -NAN, INFINITY, -INFINITY, -1, -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) { - if (test__compiler_rt_logbl(cases[i])) return 1; + for (unsigned i = 0; i < N; ++i) { + if (test__compiler_rt_logbl(cases[i])) + return 1; } // Test a moving 1 bit, especially to handle denormal values. // Test the negation as well. + // Since we are comparing the compiler-rt IEEE implementation against libc's + // long double implementation, this test can only succeed if long double + // is an IEEE 128-bit floating point number (otherwise we will see mismatches + // once we reach numbers that cannot be precisely represented in long double + // format). +# if defined(CRT_LDBL_IEEE_F128) rep_t x = signBit; + int i = 0; while (x) { - if (test__compiler_rt_logbl(fromRep(x))) return 1; - if (test__compiler_rt_logbl(fromRep(signBit ^ x))) return 1; + if (test__compiler_rt_logbl(fromRep(x))) + return 1; + if (test__compiler_rt_logbl(fromRep(signBit ^ x))) + return 1; x >>= 1; + printf("l1: %d\n", i++); } // Also try a couple moving ones x = signBit | (signBit >> 1) | (signBit >> 2); while (x) { - if (test__compiler_rt_logbl(fromRep(x))) return 1; - if (test__compiler_rt_logbl(fromRep(signBit ^ x))) return 1; + if (test__compiler_rt_logbl(fromRep(x))) + return 1; + if (test__compiler_rt_logbl(fromRep(signBit ^ x))) + return 1; x >>= 1; + printf("l1: %d\n", i++); } -#else - printf("skipped\n"); #endif return 0; } +#else +int main() { + printf("skipped\n"); + 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 79193334c65d9f..0d9bbdfd68e4a8 100644 --- a/compiler-rt/test/builtins/Unit/compiler_rt_scalbnl_test.c +++ b/compiler-rt/test/builtins/Unit/compiler_rt_scalbnl_test.c @@ -1,12 +1,12 @@ // RUN: %clang_builtins %s %librt -o %t && %run %t #define QUAD_PRECISION +#include "fp_lib.h" #include #include #include #include #include -#include "fp_lib.h" #if defined(CRT_HAS_TF_MODE) @@ -14,7 +14,7 @@ int test__compiler_rt_scalbnl(const char *mode, fp_t x, int y) { #if defined(__ve__) if (fpclassify(x) == FP_SUBNORMAL) return 0; -#endif +# endif fp_t crt_value = __compiler_rt_scalbnl(x, y); fp_t libm_value = scalbnl(x, y); // Consider +/-0 unequal, but disregard the sign/payload of NaN. @@ -39,13 +39,34 @@ int test__compiler_rt_scalbnl(const char *mode, fp_t x, int y) { } fp_t cases[] = { - -NAN, NAN, -INFINITY, INFINITY, -0.0, 0.0, -1, 1, -2, 2, - LDBL_TRUE_MIN, LDBL_MIN, LDBL_MAX, - -1.001, 1.001, -1.002, 1.002, 1.e-6, -1.e-6, - 0x1.0p-16381L, - 0x1.0p-16382L, - 0x1.0p-16383L, // subnormal - 0x1.0p-16384L, // subnormal + -NAN, + NAN, + -INFINITY, + INFINITY, + -0.0, + 0.0, + -1, + 1, + -2, + 2, +// Since we are comparing the compiler-rt IEEE implementation against libc's +// long double implementation, this test can only succeed if long double +// is an IEEE 128-bit floating point number. +# if defined(CRT_LDBL_IEEE_F128) + LDBL_TRUE_MIN, +# endif + LDBL_MIN, + LDBL_MAX, + -1.001, + 1.001, + -1.002, + 1.002, + 1.e-6, + -1.e-6, + TF_C(0x1.0p-16381), + TF_C(0x1.0p-16382), + TF_C(0x1.0p-16383), // subnormal + TF_C(0x1.0p-16384), // subnormal }; int iterate_cases(const char *mode) { @@ -54,28 +75,35 @@ int iterate_cases(const char *mode) { for (i = 0; i < N; ++i) { int j; for (j = -5; j <= 5; ++j) { - if (test__compiler_rt_scalbnl(mode, cases[i], j)) return 1; + printf("%d, %d\n", i, j); + if (test__compiler_rt_scalbnl(mode, cases[i], j)) + return 1; } - if (test__compiler_rt_scalbnl(mode, cases[i], -100000)) return 1; - if (test__compiler_rt_scalbnl(mode, cases[i], 100000)) return 1; - if (test__compiler_rt_scalbnl(mode, cases[i], INT_MIN)) return 1; - if (test__compiler_rt_scalbnl(mode, cases[i], INT_MAX)) return 1; + if (test__compiler_rt_scalbnl(mode, cases[i], -100000)) + return 1; + if (test__compiler_rt_scalbnl(mode, cases[i], 100000)) + return 1; + if (test__compiler_rt_scalbnl(mode, cases[i], INT_MIN)) + return 1; + if (test__compiler_rt_scalbnl(mode, cases[i], INT_MAX)) + return 1; } return 0; } -#endif - int main() { -#if defined(CRT_HAS_TF_MODE) - if (iterate_cases("default")) return 1; + 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 18042031ccf0ba..9ba4880f4a1102 100644 --- a/compiler-rt/test/builtins/Unit/divtc3_test.c +++ b/compiler-rt/test/builtins/Unit/divtc3_test.c @@ -9,362 +9,357 @@ #include #include "int_lib.h" -#include +#include "int_math.h" #include - +#include // 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/divtf3_test.c b/compiler-rt/test/builtins/Unit/divtf3_test.c index da6465636e9232..d46fcc04776938 100644 --- a/compiler-rt/test/builtins/Unit/divtf3_test.c +++ b/compiler-rt/test/builtins/Unit/divtf3_test.c @@ -4,190 +4,161 @@ #include "int_lib.h" #include -#if __LDBL_MANT_DIG__ == 113 +// The testcase currently assumes IEEE TF format, once that has been +// fixed the defined(CRT_HAS_IEEE_TF) guard can be removed to enable it for +// IBM 128 floats as well. +#if defined(CRT_HAS_IEEE_TF) -#include "fp_test.h" +# include "fp_test.h" // Returns: a / b -COMPILER_RT_ABI long double __divtf3(long double a, long double b); - -int test__divtf3(long double a, long double b, - uint64_t expectedHi, uint64_t expectedLo) -{ - long double x = __divtf3(a, b); - int ret = compareResultF128(x, expectedHi, expectedLo); - - if (ret){ - printf("error in test__divtf3(%.20Le, %.20Le) = %.20Le, " - "expected %.20Le\n", a, b, x, - fromRep128(expectedHi, expectedLo)); - } - return ret; +COMPILER_RT_ABI tf_float __divtf3(tf_float a, tf_float b); + +int test__divtf3(tf_float a, tf_float b, uint64_t expectedHi, + uint64_t expectedLo) { + tf_float x = __divtf3(a, b); + int ret = compareResultF128(x, expectedHi, expectedLo); + + if (ret) { + printf("error in test__divtf3(%.20Le, %.20Le) = %.20Le, " + "expected %.20Le\n", + a, b, x, fromRep128(expectedHi, expectedLo)); + } + return ret; } -char assumption_1[sizeof(long double) * CHAR_BIT == 128] = {0}; +char assumption_1[sizeof(tf_float) * CHAR_BIT == 128] = {0}; #endif -int main() -{ -#if __LDBL_MANT_DIG__ == 113 - // Returned NaNs are assumed to be qNaN by default - - // qNaN / any = qNaN - if (test__divtf3(makeQNaN128(), - 0x1.23456789abcdefp+5L, - UINT64_C(0x7fff800000000000), - UINT64_C(0x0))) - return 1; - // NaN / any = NaN - if (test__divtf3(makeNaN128(UINT64_C(0x30000000)), - 0x1.23456789abcdefp+5L, - UINT64_C(0x7fff800000000000), - UINT64_C(0x0))) - return 1; - // any / qNaN = qNaN - if (test__divtf3(0x1.23456789abcdefp+5L, - makeQNaN128(), - UINT64_C(0x7fff800000000000), - UINT64_C(0x0))) - return 1; - // any / NaN = NaN - if (test__divtf3(0x1.23456789abcdefp+5L, - makeNaN128(UINT64_C(0x30000000)), - UINT64_C(0x7fff800000000000), - UINT64_C(0x0))) - return 1; - - // +Inf / positive = +Inf - if (test__divtf3(makeInf128(), 3.L, - UINT64_C(0x7fff000000000000), - UINT64_C(0x0))) - return 1; - // +Inf / negative = -Inf - if (test__divtf3(makeInf128(), -3.L, - UINT64_C(0xffff000000000000), - UINT64_C(0x0))) - return 1; - // -Inf / positive = -Inf - if (test__divtf3(makeNegativeInf128(), 3.L, - UINT64_C(0xffff000000000000), - UINT64_C(0x0))) - return 1; - // -Inf / negative = +Inf - if (test__divtf3(makeNegativeInf128(), -3.L, - UINT64_C(0x7fff000000000000), - UINT64_C(0x0))) - return 1; - - // Inf / Inf = NaN - if (test__divtf3(makeInf128(), makeInf128(), - UINT64_C(0x7fff800000000000), - UINT64_C(0x0))) - return 1; - // 0.0 / 0.0 = NaN - if (test__divtf3(+0x0.0p+0L, +0x0.0p+0L, - UINT64_C(0x7fff800000000000), - UINT64_C(0x0))) - return 1; - // +0.0 / +Inf = +0.0 - if (test__divtf3(+0x0.0p+0L, makeInf128(), - UINT64_C(0x0), - UINT64_C(0x0))) - return 1; - // +Inf / +0.0 = +Inf - if (test__divtf3(makeInf128(), +0x0.0p+0L, - UINT64_C(0x7fff000000000000), - UINT64_C(0x0))) - return 1; - - // positive / +0.0 = +Inf - if (test__divtf3(+1.0L, +0x0.0p+0L, - UINT64_C(0x7fff000000000000), - UINT64_C(0x0))) - return 1; - // positive / -0.0 = -Inf - if (test__divtf3(+1.0L, -0x0.0p+0L, - UINT64_C(0xffff000000000000), - UINT64_C(0x0))) - return 1; - // negative / +0.0 = -Inf - if (test__divtf3(-1.0L, +0x0.0p+0L, - UINT64_C(0xffff000000000000), - UINT64_C(0x0))) - return 1; - // negative / -0.0 = +Inf - if (test__divtf3(-1.0L, -0x0.0p+0L, - UINT64_C(0x7fff000000000000), - UINT64_C(0x0))) - return 1; - - // 1/3 - if (test__divtf3(1.L, 3.L, - UINT64_C(0x3ffd555555555555), - UINT64_C(0x5555555555555555))) - return 1; - // smallest normal result - if (test__divtf3(0x1.0p-16381L, 2.L, - UINT64_C(0x0001000000000000), - UINT64_C(0x0))) - return 1; - - // divisor is exactly 1.0 - if (test__divtf3(0x1.0p+0L, - 0x1.0p+0L, - UINT64_C(0x3fff000000000000), - UINT64_C(0x0))) - return 1; - // divisor is truncated to exactly 1.0 in UQ1.63 - if (test__divtf3(0x1.0p+0L, - 0x1.0000000000000001p+0L, - UINT64_C(0x3ffeffffffffffff), - UINT64_C(0xfffe000000000000))) - return 1; - - // smallest normal value divided by 2.0 - if (test__divtf3(0x1.0p-16382L, 2.L, UINT64_C(0x0000800000000000), UINT64_C(0x0))) - return 1; - // smallest subnormal result - if (test__divtf3(0x1.0p-16382L, 0x1p+112L, UINT64_C(0x0), UINT64_C(0x1))) - return 1; - - // any / any - if (test__divtf3(0x1.a23b45362464523375893ab4cdefp+5L, - 0x1.eedcbaba3a94546558237654321fp-1L, - UINT64_C(0x4004b0b72924d407), - UINT64_C(0x0717e84356c6eba2))) - return 1; - if (test__divtf3(0x1.a2b34c56d745382f9abf2c3dfeffp-50L, - 0x1.ed2c3ba15935332532287654321fp-9L, - UINT64_C(0x3fd5b2af3f828c9b), - UINT64_C(0x40e51f64cde8b1f2))) - return 15; - if (test__divtf3(0x1.2345f6aaaa786555f42432abcdefp+456L, - 0x1.edacbba9874f765463544dd3621fp+6400L, - UINT64_C(0x28c62e15dc464466), - UINT64_C(0xb5a07586348557ac))) - return 1; - if (test__divtf3(0x1.2d3456f789ba6322bc665544edefp-234L, - 0x1.eddcdba39f3c8b7a36564354321fp-4455L, - UINT64_C(0x507b38442b539266), - UINT64_C(0x22ce0f1d024e1252))) - return 1; - if (test__divtf3(0x1.2345f6b77b7a8953365433abcdefp+234L, - 0x1.edcba987d6bb3aa467754354321fp-4055L, - UINT64_C(0x50bf2e02f0798d36), - UINT64_C(0x5e6fcb6b60044078))) - return 1; - if (test__divtf3(6.72420628622418701252535563464350521E-4932L, - 2.L, - UINT64_C(0x0001000000000000), - UINT64_C(0))) - return 1; +int main() { +#if defined(CRT_HAS_IEEE_TF) + // Returned NaNs are assumed to be qNaN by default + + // qNaN / any = qNaN + if (test__divtf3(makeQNaN128(), TF_C(0x1.23456789abcdefp+5), + UINT64_C(0x7fff800000000000), UINT64_C(0x0))) + return 1; + // NaN / any = NaN + if (test__divtf3(makeNaN128(UINT64_C(0x30000000)), + TF_C(0x1.23456789abcdefp+5), UINT64_C(0x7fff800000000000), + UINT64_C(0x0))) + return 1; + // any / qNaN = qNaN + if (test__divtf3(TF_C(0x1.23456789abcdefp+5), makeQNaN128(), + UINT64_C(0x7fff800000000000), UINT64_C(0x0))) + return 1; + // any / NaN = NaN + if (test__divtf3(TF_C(0x1.23456789abcdefp+5), + makeNaN128(UINT64_C(0x30000000)), + UINT64_C(0x7fff800000000000), UINT64_C(0x0))) + return 1; + + // +Inf / positive = +Inf + if (test__divtf3(makeInf128(), TF_C(3.), UINT64_C(0x7fff000000000000), + UINT64_C(0x0))) + return 1; + // +Inf / negative = -Inf + if (test__divtf3(makeInf128(), -TF_C(3.), UINT64_C(0xffff000000000000), + UINT64_C(0x0))) + return 1; + // -Inf / positive = -Inf + if (test__divtf3(makeNegativeInf128(), TF_C(3.), UINT64_C(0xffff000000000000), + UINT64_C(0x0))) + return 1; + // -Inf / negative = +Inf + if (test__divtf3(makeNegativeInf128(), -TF_C(3.), + UINT64_C(0x7fff000000000000), UINT64_C(0x0))) + return 1; + + // Inf / Inf = NaN + if (test__divtf3(makeInf128(), makeInf128(), UINT64_C(0x7fff800000000000), + UINT64_C(0x0))) + return 1; + // 0.0 / 0.0 = NaN + if (test__divtf3(+TF_C(0x0.0p+0), +TF_C(0x0.0p+0), + UINT64_C(0x7fff800000000000), UINT64_C(0x0))) + return 1; + // +0.0 / +Inf = +0.0 + if (test__divtf3(+TF_C(0x0.0p+0), makeInf128(), UINT64_C(0x0), UINT64_C(0x0))) + return 1; + // +Inf / +0.0 = +Inf + if (test__divtf3(makeInf128(), +TF_C(0x0.0p+0), UINT64_C(0x7fff000000000000), + UINT64_C(0x0))) + return 1; + + // positive / +0.0 = +Inf + if (test__divtf3(+TF_C(1.0), +TF_C(0x0.0p+0), UINT64_C(0x7fff000000000000), + UINT64_C(0x0))) + return 1; + // positive / -0.0 = -Inf + if (test__divtf3(+1.0L, -TF_C(0x0.0p+0), UINT64_C(0xffff000000000000), + UINT64_C(0x0))) + return 1; + // negative / +0.0 = -Inf + if (test__divtf3(-1.0L, +TF_C(0x0.0p+0), UINT64_C(0xffff000000000000), + UINT64_C(0x0))) + return 1; + // negative / -0.0 = +Inf + if (test__divtf3(TF_C(-1.0), -TF_C(0x0.0p+0), UINT64_C(0x7fff000000000000), + UINT64_C(0x0))) + return 1; + + // 1/3 + if (test__divtf3(TF_C(1.), TF_C(3.), UINT64_C(0x3ffd555555555555), + UINT64_C(0x5555555555555555))) + return 1; + // smallest normal result + if (test__divtf3(TF_C(0x1.0p-16381), TF_C(2.), UINT64_C(0x0001000000000000), + UINT64_C(0x0))) + return 1; + + // divisor is exactly 1.0 + if (test__divtf3(TF_C(0x1.0p+0), TF_C(0x1.0p+0), UINT64_C(0x3fff000000000000), + UINT64_C(0x0))) + return 1; + // divisor is truncated to exactly 1.0 in UQ1.63 + if (test__divtf3(TF_C(0x1.0p+0), TF_C(0x1.0000000000000001p+0), + UINT64_C(0x3ffeffffffffffff), UINT64_C(0xfffe000000000000))) + return 1; + + // smallest normal value divided by 2.0 + if (test__divtf3(TF_C(0x1.0p-16382), 2.L, UINT64_C(0x0000800000000000), + UINT64_C(0x0))) + return 1; + // smallest subnormal result + if (test__divtf3(TF_C(0x1.0p-16382), TF_C(0x1p+112), UINT64_C(0x0), + UINT64_C(0x1))) + return 1; + + // any / any + if (test__divtf3(TF_C(0x1.a23b45362464523375893ab4cdefp+5), + TF_C(0x1.eedcbaba3a94546558237654321fp-1), + UINT64_C(0x4004b0b72924d407), UINT64_C(0x0717e84356c6eba2))) + return 1; + if (test__divtf3(TF_C(0x1.a2b34c56d745382f9abf2c3dfeffp-50), + TF_C(0x1.ed2c3ba15935332532287654321fp-9), + UINT64_C(0x3fd5b2af3f828c9b), UINT64_C(0x40e51f64cde8b1f2))) + return 15; + if (test__divtf3(TF_C(0x1.2345f6aaaa786555f42432abcdefp+456), + TF_C(0x1.edacbba9874f765463544dd3621fp+6400), + UINT64_C(0x28c62e15dc464466), UINT64_C(0xb5a07586348557ac))) + return 1; + if (test__divtf3(TF_C(0x1.2d3456f789ba6322bc665544edefp-234), + TF_C(0x1.eddcdba39f3c8b7a36564354321fp-4455), + UINT64_C(0x507b38442b539266), UINT64_C(0x22ce0f1d024e1252))) + return 1; + if (test__divtf3(TF_C(0x1.2345f6b77b7a8953365433abcdefp+234), + TF_C(0x1.edcba987d6bb3aa467754354321fp-4055), + UINT64_C(0x50bf2e02f0798d36), UINT64_C(0x5e6fcb6b60044078))) + return 1; + if (test__divtf3(TF_C(6.72420628622418701252535563464350521E-4932), TF_C(2.), + UINT64_C(0x0001000000000000), UINT64_C(0))) + return 1; #else - printf("skipped\n"); + printf("skipped\n"); #endif - return 0; + return 0; } diff --git a/compiler-rt/test/builtins/Unit/extendxftf2_test.c b/compiler-rt/test/builtins/Unit/extendxftf2_test.c index f5211875438c73..7c3b0abdc39246 100644 --- a/compiler-rt/test/builtins/Unit/extendxftf2_test.c +++ b/compiler-rt/test/builtins/Unit/extendxftf2_test.c @@ -9,10 +9,10 @@ #include "fp_test.h" -COMPILER_RT_ABI __float128 __extendxftf2(long double a); +COMPILER_RT_ABI tf_float __extendxftf2(long double a); int test__extendxftf2(long double a, uint64_t expectedHi, uint64_t expectedLo) { - __float128 x = __extendxftf2(a); + tf_float x = __extendxftf2(a); int ret = compareResultF128(x, expectedHi, expectedLo); if (ret) { diff --git a/compiler-rt/test/builtins/Unit/floatditf_test.c b/compiler-rt/test/builtins/Unit/floatditf_test.c index fe7a5fd86ae842..29761d7c8eabc1 100644 --- a/compiler-rt/test/builtins/Unit/floatditf_test.c +++ b/compiler-rt/test/builtins/Unit/floatditf_test.c @@ -2,58 +2,66 @@ // REQUIRES: librt_has_floatditf #include "int_lib.h" -#include #include +#include #include -#if __LDBL_MANT_DIG__ == 113 +// The testcase currently assumes IEEE TF format, once that has been +// fixed the defined(CRT_HAS_IEEE_TF) guard can be removed to enable it for +// IBM 128 floats as well. +#if defined(CRT_HAS_IEEE_TF) -#include "fp_test.h" +# include "fp_test.h" -// Returns: long integer converted to long double +// Returns: long integer converted to tf_float -COMPILER_RT_ABI long double __floatditf(di_int a); +COMPILER_RT_ABI tf_float __floatditf(di_int a); -int test__floatditf(di_int a, uint64_t expectedHi, uint64_t expectedLo) -{ - long double x = __floatditf(a); - int ret = compareResultF128(x, expectedHi, expectedLo); +int test__floatditf(di_int a, uint64_t expectedHi, uint64_t expectedLo) { + tf_float x = __floatditf(a); + int ret = compareResultF128(x, expectedHi, expectedLo); - if (ret) - printf("error in __floatditf(%Ld) = %.20Lf, " - "expected %.20Lf\n", a, x, fromRep128(expectedHi, expectedLo)); - return ret; + if (ret) + printf("error in __floatditf(%Ld) = %.20Lf, " + "expected %.20Lf\n", + a, x, fromRep128(expectedHi, expectedLo)); + return ret; } char assumption_1[sizeof(long double) * CHAR_BIT == 128] = {0}; #endif -int main() -{ -#if __LDBL_MANT_DIG__ == 113 - if (test__floatditf(0x7fffffffffffffff, UINT64_C(0x403dffffffffffff), UINT64_C(0xfffc000000000000))) - return 1; - if (test__floatditf(0x123456789abcdef1, UINT64_C(0x403b23456789abcd), UINT64_C(0xef10000000000000))) - return 1; - if (test__floatditf(0x2, UINT64_C(0x4000000000000000), UINT64_C(0x0))) - return 1; - if (test__floatditf(0x1, UINT64_C(0x3fff000000000000), UINT64_C(0x0))) - return 1; - if (test__floatditf(0x0, UINT64_C(0x0), UINT64_C(0x0))) - return 1; - if (test__floatditf(0xffffffffffffffff, UINT64_C(0xbfff000000000000), UINT64_C(0x0))) - return 1; - if (test__floatditf(0xfffffffffffffffe, UINT64_C(0xc000000000000000), UINT64_C(0x0))) - return 1; - if (test__floatditf(-0x123456789abcdef1, UINT64_C(0xc03b23456789abcd), UINT64_C(0xef10000000000000))) - return 1; - if (test__floatditf(0x8000000000000000, UINT64_C(0xc03e000000000000), UINT64_C(0x0))) - return 1; +int main() { +#if defined(CRT_HAS_IEEE_TF) + if (test__floatditf(0x7fffffffffffffff, UINT64_C(0x403dffffffffffff), + UINT64_C(0xfffc000000000000))) + return 1; + if (test__floatditf(0x123456789abcdef1, UINT64_C(0x403b23456789abcd), + UINT64_C(0xef10000000000000))) + return 1; + if (test__floatditf(0x2, UINT64_C(0x4000000000000000), UINT64_C(0x0))) + return 1; + if (test__floatditf(0x1, UINT64_C(0x3fff000000000000), UINT64_C(0x0))) + return 1; + if (test__floatditf(0x0, UINT64_C(0x0), UINT64_C(0x0))) + return 1; + if (test__floatditf(0xffffffffffffffff, UINT64_C(0xbfff000000000000), + UINT64_C(0x0))) + return 1; + if (test__floatditf(0xfffffffffffffffe, UINT64_C(0xc000000000000000), + UINT64_C(0x0))) + return 1; + if (test__floatditf(-0x123456789abcdef1, UINT64_C(0xc03b23456789abcd), + UINT64_C(0xef10000000000000))) + return 1; + if (test__floatditf(0x8000000000000000, UINT64_C(0xc03e000000000000), + UINT64_C(0x0))) + return 1; #else - printf("skipped\n"); + printf("skipped\n"); #endif - return 0; + return 0; } diff --git a/compiler-rt/test/builtins/Unit/floattitf_test.c b/compiler-rt/test/builtins/Unit/floattitf_test.c index abd3006135b38f..28cf3f4ff58d74 100644 --- a/compiler-rt/test/builtins/Unit/floattitf_test.c +++ b/compiler-rt/test/builtins/Unit/floattitf_test.c @@ -7,7 +7,12 @@ #include #include -#if defined(CRT_HAS_TF_MODE) +// The testcase currently assumes IEEE TF format, once that has been +// fixed the defined(CRT_HAS_IEEE_TF) guard can be removed to enable it for +// IBM 128 floats as well. +#if defined(CRT_HAS_IEEE_TF) + +# include "fp_test.h" /* Returns: convert a ti_int to a fp_t, rounding toward even. */ @@ -21,93 +26,97 @@ COMPILER_RT_ABI fp_t __floattitf(ti_int a); -int test__floattitf(ti_int a, fp_t expected) { +int _test__floattitf(int line, ti_int a, fp_t expected) { fp_t x = __floattitf(a); if (x != expected) { twords at; at.all = a; - printf("error in __floattitf(0x%.16llX%.16llX) = %LA, expected %LA\n", - at.s.high, at.s.low, x, expected); + __uint128_t expected_rep = toRep128(expected); + __uint128_t res_rep = toRep128(x); + printf("%s:%d: error in __floattitf(0x%.16llX%.16llX) = " + "0x%.16llX%.16llX, expected 0x%.16llX%.16llX\n", + __FILE__, line, at.s.high, at.s.low, (uint64_t)(res_rep >> 64), + (uint64_t)res_rep, (uint64_t)(expected_rep >> 64), + (uint64_t)expected_rep); } return x != expected; } +# define test__floattitf(a, e) _test__floattitf(__LINE__, a, e) + 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)) + if (test__floattitf(0, TF_C(0.0))) return 1; - if (test__floattitf(1, 1.0)) + if (test__floattitf(1, TF_C(1.0))) return 1; - if (test__floattitf(2, 2.0)) + if (test__floattitf(2, TF_C(2.0))) return 1; - if (test__floattitf(20, 20.0)) + if (test__floattitf(20, TF_C(20.0))) return 1; - if (test__floattitf(-1, -1.0)) + if (test__floattitf(-1, -TF_C(1.0))) return 1; - if (test__floattitf(-2, -2.0)) + if (test__floattitf(-2, -TF_C(2.0))) return 1; - if (test__floattitf(-20, -20.0)) + if (test__floattitf(-20, -TF_C(20.0))) return 1; - if (test__floattitf(0x7FFFFF8000000000LL, 0x1.FFFFFEp+62)) + if (test__floattitf(0x7FFFFF8000000000LL, TF_C(0x1.FFFFFEp+62))) return 1; - if (test__floattitf(0x7FFFFFFFFFFFF800LL, 0x1.FFFFFFFFFFFFEp+62)) + if (test__floattitf(0x7FFFFFFFFFFFF800LL, TF_C(0x1.FFFFFFFFFFFFEp+62))) return 1; - if (test__floattitf(0x7FFFFF0000000000LL, 0x1.FFFFFCp+62)) + if (test__floattitf(0x7FFFFF0000000000LL, TF_C(0x1.FFFFFCp+62))) return 1; - if (test__floattitf(0x7FFFFFFFFFFFF000LL, 0x1.FFFFFFFFFFFFCp+62)) + if (test__floattitf(0x7FFFFFFFFFFFF000LL, TF_C(0x1.FFFFFFFFFFFFCp+62))) return 1; - if (test__floattitf(make_ti(0x8000008000000000LL, 0), -0x1.FFFFFEp+126)) + if (test__floattitf(make_ti(0x8000008000000000LL, 0), -TF_C(0x1.FFFFFEp+126))) return 1; if (test__floattitf(make_ti(0x8000000000000800LL, 0), - -0x1.FFFFFFFFFFFFEp+126)) + -TF_C(0x1.FFFFFFFFFFFFEp+126))) return 1; - if (test__floattitf(make_ti(0x8000010000000000LL, 0), -0x1.FFFFFCp+126)) + if (test__floattitf(make_ti(0x8000010000000000LL, 0), -TF_C(0x1.FFFFFCp+126))) return 1; if (test__floattitf(make_ti(0x8000000000001000LL, 0), - -0x1.FFFFFFFFFFFFCp+126)) + -TF_C(0x1.FFFFFFFFFFFFCp+126))) return 1; - if (test__floattitf(make_ti(0x8000000000000000LL, 0), -0x1.000000p+127)) + if (test__floattitf(make_ti(0x8000000000000000LL, 0), -TF_C(0x1.000000p+127))) return 1; if (test__floattitf(make_ti(0x8000000000000001LL, 0), -TF_C(0x1.FFFFFFFFFFFFFFFCp+126))) return 1; - if (test__floattitf(0x0007FB72E8000000LL, 0x1.FEDCBAp+50)) + if (test__floattitf(0x0007FB72E8000000LL, TF_C(0x1.FEDCBAp+50))) return 1; - if (test__floattitf(0x0007FB72EA000000LL, 0x1.FEDCBA8p+50)) + if (test__floattitf(0x0007FB72EA000000LL, TF_C(0x1.FEDCBA8p+50))) return 1; - if (test__floattitf(0x0007FB72EB000000LL, 0x1.FEDCBACp+50)) + if (test__floattitf(0x0007FB72EB000000LL, TF_C(0x1.FEDCBACp+50))) return 1; - if (test__floattitf(0x0007FB72EBFFFFFFLL, 0x1.FEDCBAFFFFFFCp+50)) + if (test__floattitf(0x0007FB72EBFFFFFFLL, TF_C(0x1.FEDCBAFFFFFFCp+50))) return 1; - if (test__floattitf(0x0007FB72EC000000LL, 0x1.FEDCBBp+50)) + if (test__floattitf(0x0007FB72EC000000LL, TF_C(0x1.FEDCBBp+50))) return 1; - if (test__floattitf(0x0007FB72E8000001LL, 0x1.FEDCBA0000004p+50)) + if (test__floattitf(0x0007FB72E8000001LL, TF_C(0x1.FEDCBA0000004p+50))) return 1; - if (test__floattitf(0x0007FB72E6000000LL, 0x1.FEDCB98p+50)) + if (test__floattitf(0x0007FB72E6000000LL, TF_C(0x1.FEDCB98p+50))) return 1; - if (test__floattitf(0x0007FB72E7000000LL, 0x1.FEDCB9Cp+50)) + if (test__floattitf(0x0007FB72E7000000LL, TF_C(0x1.FEDCB9Cp+50))) return 1; - if (test__floattitf(0x0007FB72E7FFFFFFLL, 0x1.FEDCB9FFFFFFCp+50)) + if (test__floattitf(0x0007FB72E7FFFFFFLL, TF_C(0x1.FEDCB9FFFFFFCp+50))) return 1; - if (test__floattitf(0x0007FB72E4000001LL, 0x1.FEDCB90000004p+50)) + if (test__floattitf(0x0007FB72E4000001LL, TF_C(0x1.FEDCB90000004p+50))) return 1; - if (test__floattitf(0x0007FB72E4000000LL, 0x1.FEDCB9p+50)) + if (test__floattitf(0x0007FB72E4000000LL, TF_C(0x1.FEDCB9p+50))) return 1; - if (test__floattitf(0x023479FD0E092DC0LL, 0x1.1A3CFE870496Ep+57)) + if (test__floattitf(0x023479FD0E092DC0LL, TF_C(0x1.1A3CFE870496Ep+57))) return 1; if (test__floattitf(0x023479FD0E092DA1LL, TF_C(0x1.1A3CFE870496D08p+57))) return 1; @@ -135,7 +144,7 @@ int main() { return 1; if (test__floattitf(0x023479FD0E092DDFLL, TF_C(0x1.1A3CFE870496EF8p+57))) return 1; - if (test__floattitf(0x023479FD0E092DE0LL, 0x1.1A3CFE870496Fp+57)) + if (test__floattitf(0x023479FD0E092DE0LL, TF_C(0x1.1A3CFE870496Fp+57))) return 1; if (test__floattitf(make_ti(0x023479FD0E092DC0LL, 0), @@ -215,8 +224,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 8da78da9760293..98c2262546f204 100644 --- a/compiler-rt/test/builtins/Unit/floatunditf_test.c +++ b/compiler-rt/test/builtins/Unit/floatunditf_test.c @@ -2,56 +2,63 @@ // REQUIRES: librt_has_floatunditf #include "int_lib.h" -#include #include +#include #include -#if __LDBL_MANT_DIG__ == 113 +// The testcase currently assumes IEEE TF format, once that has been +// fixed the defined(CRT_HAS_IEEE_TF) guard can be removed to enable it for +// IBM 128 floats as well. +#if defined(CRT_HAS_IEEE_TF) -#include "fp_test.h" +# include "fp_test.h" // 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) -{ - long double x = __floatunditf(a); - int ret = compareResultF128(x, expectedHi, expectedLo); +int test__floatunditf(du_int a, uint64_t expectedHi, uint64_t expectedLo) { + tf_float x = __floatunditf(a); + int ret = compareResultF128(x, expectedHi, expectedLo); - if (ret) - printf("error in __floatunditf(%Lu) = %.20Lf, " - "expected %.20Lf\n", a, x, fromRep128(expectedHi, expectedLo)); - return ret; + if (ret) + printf("error in __floatunditf(%Lu) = %.20Lf, " + "expected %.20Lf\n", + a, x, fromRep128(expectedHi, expectedLo)); + return ret; } char assumption_1[sizeof(long double) * CHAR_BIT == 128] = {0}; #endif -int main() -{ -#if __LDBL_MANT_DIG__ == 113 - if (test__floatunditf(0xffffffffffffffffULL, UINT64_C(0x403effffffffffff), UINT64_C(0xfffe000000000000))) - return 1; - if (test__floatunditf(0xfffffffffffffffeULL, UINT64_C(0x403effffffffffff), UINT64_C(0xfffc000000000000))) - return 1; - if (test__floatunditf(0x8000000000000000ULL, UINT64_C(0x403e000000000000), UINT64_C(0x0))) - return 1; - if (test__floatunditf(0x7fffffffffffffffULL, UINT64_C(0x403dffffffffffff), UINT64_C(0xfffc000000000000))) - return 1; - if (test__floatunditf(0x123456789abcdef1ULL, UINT64_C(0x403b23456789abcd), UINT64_C(0xef10000000000000))) - return 1; - if (test__floatunditf(0x2ULL, UINT64_C(0x4000000000000000), UINT64_C(0x0))) - return 1; - if (test__floatunditf(0x1ULL, UINT64_C(0x3fff000000000000), UINT64_C(0x0))) - return 1; - if (test__floatunditf(0x0ULL, UINT64_C(0x0), UINT64_C(0x0))) - return 1; +int main() { +#if defined(CRT_HAS_IEEE_TF) + if (test__floatunditf(0xffffffffffffffffULL, UINT64_C(0x403effffffffffff), + UINT64_C(0xfffe000000000000))) + return 1; + if (test__floatunditf(0xfffffffffffffffeULL, UINT64_C(0x403effffffffffff), + UINT64_C(0xfffc000000000000))) + return 1; + if (test__floatunditf(0x8000000000000000ULL, UINT64_C(0x403e000000000000), + UINT64_C(0x0))) + return 1; + if (test__floatunditf(0x7fffffffffffffffULL, UINT64_C(0x403dffffffffffff), + UINT64_C(0xfffc000000000000))) + return 1; + if (test__floatunditf(0x123456789abcdef1ULL, UINT64_C(0x403b23456789abcd), + UINT64_C(0xef10000000000000))) + return 1; + if (test__floatunditf(0x2ULL, UINT64_C(0x4000000000000000), UINT64_C(0x0))) + return 1; + if (test__floatunditf(0x1ULL, UINT64_C(0x3fff000000000000), UINT64_C(0x0))) + return 1; + if (test__floatunditf(0x0ULL, UINT64_C(0x0), UINT64_C(0x0))) + return 1; #else - printf("skipped\n"); + printf("skipped\n"); #endif - return 0; + return 0; } diff --git a/compiler-rt/test/builtins/Unit/floatunsitf_test.c b/compiler-rt/test/builtins/Unit/floatunsitf_test.c index b6b1ba04573990..44337cc81e7360 100644 --- a/compiler-rt/test/builtins/Unit/floatunsitf_test.c +++ b/compiler-rt/test/builtins/Unit/floatunsitf_test.c @@ -4,43 +4,48 @@ #include "int_lib.h" #include -#if __LDBL_MANT_DIG__ == 113 +// The testcase currently assumes IEEE TF format, once that has been +// fixed the defined(CRT_HAS_IEEE_TF) guard can be removed to enable it for +// IBM 128 floats as well. +#if defined(CRT_HAS_IEEE_TF) -#include "fp_test.h" +# include "fp_test.h" -COMPILER_RT_ABI long double __floatunsitf(su_int a); +COMPILER_RT_ABI tf_float __floatunsitf(su_int a); -int test__floatunsitf(su_int a, uint64_t expectedHi, uint64_t expectedLo) -{ - long double x = __floatunsitf(a); - int ret = compareResultF128(x, expectedHi, expectedLo); +int test__floatunsitf(su_int a, uint64_t expectedHi, uint64_t expectedLo) { + tf_float x = __floatunsitf(a); + int ret = compareResultF128(x, expectedHi, expectedLo); - if (ret){ - printf("error in test__floatunsitf(%u) = %.20Lf, " - "expected %.20Lf\n", a, x, fromRep128(expectedHi, expectedLo)); - } - return ret; + if (ret) { + printf("error in test__floatunsitf(%u) = %.20Lf, " + "expected %.20Lf\n", + a, x, fromRep128(expectedHi, expectedLo)); + } + return ret; } -char assumption_1[sizeof(long double) * CHAR_BIT == 128] = {0}; +char assumption_1[sizeof(tf_float) * CHAR_BIT == 128] = {0}; #endif -int main() -{ -#if __LDBL_MANT_DIG__ == 113 - if (test__floatunsitf(0x7fffffff, UINT64_C(0x401dfffffffc0000), UINT64_C(0x0))) - return 1; - if (test__floatunsitf(0, UINT64_C(0x0), UINT64_C(0x0))) - return 1; - if (test__floatunsitf(0xffffffff, UINT64_C(0x401efffffffe0000), UINT64_C(0x0))) - return 1; - if (test__floatunsitf(0x12345678, UINT64_C(0x401b234567800000), UINT64_C(0x0))) - return 1; +int main() { +#if defined(CRT_HAS_IEEE_TF) + if (test__floatunsitf(0x7fffffff, UINT64_C(0x401dfffffffc0000), + UINT64_C(0x0))) + return 1; + if (test__floatunsitf(0, UINT64_C(0x0), UINT64_C(0x0))) + return 1; + if (test__floatunsitf(0xffffffff, UINT64_C(0x401efffffffe0000), + UINT64_C(0x0))) + return 1; + if (test__floatunsitf(0x12345678, UINT64_C(0x401b234567800000), + UINT64_C(0x0))) + return 1; #else - printf("skipped\n"); + printf("skipped\n"); #endif - return 0; + return 0; } diff --git a/compiler-rt/test/builtins/Unit/floatuntitf_test.c b/compiler-rt/test/builtins/Unit/floatuntitf_test.c index db25f2b0230cd1..727d6477bba1e4 100644 --- a/compiler-rt/test/builtins/Unit/floatuntitf_test.c +++ b/compiler-rt/test/builtins/Unit/floatuntitf_test.c @@ -7,11 +7,16 @@ #include #include -#if defined(CRT_HAS_TF_MODE) +// The testcase currently assumes IEEE TF format, once that has been +// fixed the defined(CRT_HAS_IEEE_TF) guard can be removed to enable it for +// IBM 128 floats as well. +#if defined(CRT_HAS_IEEE_TF) -/* Returns: convert a tu_int to a fp_t, rounding toward even. */ +# include "fp_test.h" -/* Assumption: fp_t is a IEEE 128 bit floating point type +/* Returns: convert a tu_int to a tf_float, rounding toward even. */ + +/* Assumption: tf_float is a IEEE 128 bit floating point type * tu_int is a 128 bit integral type */ @@ -19,92 +24,98 @@ * 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(int line, tu_int a, tf_float expected) { + tf_float x = __floatuntitf(a); if (x != expected) { utwords at; at.all = a; - printf("error in __floatuntitf(0x%.16llX%.16llX) = %LA, expected %LA\n", - at.s.high, at.s.low, x, expected); + __uint128_t expected_rep = toRep128(expected); + __uint128_t res_rep = toRep128(x); + printf("%s:%d: error in __floatuntitf(0x%.16llX%.16llX) = " + "0x%.16llX%.16llX, expected 0x%.16llX%.16llX\n", + __FILE__, line, at.s.high, at.s.low, (uint64_t)(res_rep >> 64), + (uint64_t)res_rep, (uint64_t)(expected_rep >> 64), + (uint64_t)expected_rep); } return x != expected; } +# define test__floatuntitf(a, e) _test__floatuntitf(__LINE__, a, e) 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 int main() { -#if defined(CRT_HAS_TF_MODE) - if (test__floatuntitf(0, 0.0)) +#if defined(CRT_HAS_IEEE_TF) + if (test__floatuntitf(0, TF_C(0.0))) return 1; - if (test__floatuntitf(1, 1.0)) + if (test__floatuntitf(1, TF_C(1.0))) return 1; - if (test__floatuntitf(2, 2.0)) + if (test__floatuntitf(2, TF_C(2.0))) return 1; - if (test__floatuntitf(20, 20.0)) + if (test__floatuntitf(20, TF_C(20.0))) return 1; - if (test__floatuntitf(0x7FFFFF8000000000ULL, 0x1.FFFFFEp+62)) + if (test__floatuntitf(0x7FFFFF8000000000ULL, TF_C(0x1.FFFFFEp+62))) return 1; - if (test__floatuntitf(0x7FFFFFFFFFFFF800ULL, 0x1.FFFFFFFFFFFFEp+62)) + if (test__floatuntitf(0x7FFFFFFFFFFFF800ULL, TF_C(0x1.FFFFFFFFFFFFEp+62))) return 1; - if (test__floatuntitf(0x7FFFFF0000000000ULL, 0x1.FFFFFCp+62)) + if (test__floatuntitf(0x7FFFFF0000000000ULL, TF_C(0x1.FFFFFCp+62))) return 1; - if (test__floatuntitf(0x7FFFFFFFFFFFF000ULL, 0x1.FFFFFFFFFFFFCp+62)) + if (test__floatuntitf(0x7FFFFFFFFFFFF000ULL, TF_C(0x1.FFFFFFFFFFFFCp+62))) return 1; - if (test__floatuntitf(0x7FFFFFFFFFFFFFFFULL, 0xF.FFFFFFFFFFFFFFEp+59L)) + if (test__floatuntitf(0x7FFFFFFFFFFFFFFFULL, TF_C(0xF.FFFFFFFFFFFFFFEp+59))) return 1; - if (test__floatuntitf(0xFFFFFFFFFFFFFFFEULL, 0xF.FFFFFFFFFFFFFFEp+60L)) + if (test__floatuntitf(0xFFFFFFFFFFFFFFFEULL, TF_C(0xF.FFFFFFFFFFFFFFEp+60))) return 1; - if (test__floatuntitf(0xFFFFFFFFFFFFFFFFULL, 0xF.FFFFFFFFFFFFFFFp+60L)) + if (test__floatuntitf(0xFFFFFFFFFFFFFFFFULL, TF_C(0xF.FFFFFFFFFFFFFFFp+60))) return 1; - if (test__floatuntitf(0x8000008000000000ULL, 0x8.000008p+60)) + if (test__floatuntitf(0x8000008000000000ULL, TF_C(0x8.000008p+60))) return 1; - if (test__floatuntitf(0x8000000000000800ULL, 0x8.0000000000008p+60)) + if (test__floatuntitf(0x8000000000000800ULL, TF_C(0x8.0000000000008p+60))) return 1; - if (test__floatuntitf(0x8000010000000000ULL, 0x8.00001p+60)) + if (test__floatuntitf(0x8000010000000000ULL, TF_C(0x8.00001p+60))) return 1; - if (test__floatuntitf(0x8000000000001000ULL, 0x8.000000000001p+60)) + if (test__floatuntitf(0x8000000000001000ULL, TF_C(0x8.000000000001p+60))) return 1; - if (test__floatuntitf(0x8000000000000000ULL, 0x8p+60)) + if (test__floatuntitf(0x8000000000000000ULL, TF_C(0x8p+60))) return 1; if (test__floatuntitf(0x8000000000000001ULL, TF_C(0x8.000000000000001p+60))) return 1; - if (test__floatuntitf(0x0007FB72E8000000LL, 0x1.FEDCBAp+50)) + if (test__floatuntitf(0x0007FB72E8000000LL, TF_C(0x1.FEDCBAp+50))) return 1; - if (test__floatuntitf(0x0007FB72EA000000LL, 0x1.FEDCBA8p+50)) + if (test__floatuntitf(0x0007FB72EA000000LL, TF_C(0x1.FEDCBA8p+50))) return 1; - if (test__floatuntitf(0x0007FB72EB000000LL, 0x1.FEDCBACp+50)) + if (test__floatuntitf(0x0007FB72EB000000LL, TF_C(0x1.FEDCBACp+50))) return 1; - if (test__floatuntitf(0x0007FB72EBFFFFFFLL, 0x1.FEDCBAFFFFFFCp+50)) + if (test__floatuntitf(0x0007FB72EBFFFFFFLL, TF_C(0x1.FEDCBAFFFFFFCp+50))) return 1; - if (test__floatuntitf(0x0007FB72EC000000LL, 0x1.FEDCBBp+50)) + if (test__floatuntitf(0x0007FB72EC000000LL, TF_C(0x1.FEDCBBp+50))) return 1; - if (test__floatuntitf(0x0007FB72E8000001LL, 0x1.FEDCBA0000004p+50)) + if (test__floatuntitf(0x0007FB72E8000001LL, TF_C(0x1.FEDCBA0000004p+50))) return 1; - if (test__floatuntitf(0x0007FB72E6000000LL, 0x1.FEDCB98p+50)) + if (test__floatuntitf(0x0007FB72E6000000LL, TF_C(0x1.FEDCB98p+50))) return 1; - if (test__floatuntitf(0x0007FB72E7000000LL, 0x1.FEDCB9Cp+50)) + if (test__floatuntitf(0x0007FB72E7000000LL, TF_C(0x1.FEDCB9Cp+50))) return 1; - if (test__floatuntitf(0x0007FB72E7FFFFFFLL, 0x1.FEDCB9FFFFFFCp+50)) + if (test__floatuntitf(0x0007FB72E7FFFFFFLL, TF_C(0x1.FEDCB9FFFFFFCp+50))) return 1; - if (test__floatuntitf(0x0007FB72E4000001LL, 0x1.FEDCB90000004p+50)) + if (test__floatuntitf(0x0007FB72E4000001LL, TF_C(0x1.FEDCB90000004p+50))) return 1; - if (test__floatuntitf(0x0007FB72E4000000LL, 0x1.FEDCB9p+50)) + if (test__floatuntitf(0x0007FB72E4000000LL, TF_C(0x1.FEDCB9p+50))) return 1; - if (test__floatuntitf(0x023479FD0E092DC0LL, 0x1.1A3CFE870496Ep+57)) + if (test__floatuntitf(0x023479FD0E092DC0LL, TF_C(0x1.1A3CFE870496Ep+57))) return 1; if (test__floatuntitf(0x023479FD0E092DA1LL, TF_C(0x1.1A3CFE870496D08p+57))) return 1; @@ -132,7 +143,7 @@ int main() { return 1; if (test__floatuntitf(0x023479FD0E092DDFLL, TF_C(0x1.1A3CFE870496EF8p+57))) return 1; - if (test__floatuntitf(0x023479FD0E092DE0LL, 0x1.1A3CFE870496Fp+57)) + if (test__floatuntitf(0x023479FD0E092DE0LL, TF_C(0x1.1A3CFE870496Fp+57))) return 1; if (test__floatuntitf(make_ti(0x023479FD0E092DC0LL, 0), diff --git a/compiler-rt/test/builtins/Unit/fp_test.h b/compiler-rt/test/builtins/Unit/fp_test.h index f095ae0701d77e..4eb54b7425c107 100644 --- a/compiler-rt/test/builtins/Unit/fp_test.h +++ b/compiler-rt/test/builtins/Unit/fp_test.h @@ -3,24 +3,14 @@ #include #include +#include "int_types.h" + #ifdef COMPILER_RT_HAS_FLOAT16 #define TYPE_FP16 _Float16 #else #define TYPE_FP16 uint16_t #endif -// TODO: Switch to using fp_lib.h once QUAD_PRECISION is available on x86_64. -#if __LDBL_MANT_DIG__ == 113 || \ - ((__LDBL_MANT_DIG__ == 64) && defined(__x86_64__) && \ - (defined(__FLOAT128__) || defined(__SIZEOF_FLOAT128__))) -#if __LDBL_MANT_DIG__ == 113 -#define TYPE_FP128 long double -#else -#define TYPE_FP128 __float128 -#endif -#define TEST_COMPILER_RT_HAS_FLOAT128 -#endif - enum EXPECTED_RESULT { LESS_0, LESS_EQUAL_0, EQUAL_0, GREATER_0, GREATER_EQUAL_0, NEQUAL_0 }; @@ -50,10 +40,10 @@ static inline double fromRep64(uint64_t x) return ret; } -#ifdef TEST_COMPILER_RT_HAS_FLOAT128 -static inline TYPE_FP128 fromRep128(uint64_t hi, uint64_t lo) { +#if defined(CRT_HAS_TF_MODE) +static inline tf_float fromRep128(uint64_t hi, uint64_t lo) { __uint128_t x = ((__uint128_t)hi << 64) + lo; - TYPE_FP128 ret; + tf_float ret; memcpy(&ret, &x, 16); return ret; } @@ -84,8 +74,8 @@ static inline uint64_t toRep64(double x) return ret; } -#ifdef TEST_COMPILER_RT_HAS_FLOAT128 -static inline __uint128_t toRep128(TYPE_FP128 x) { +#if defined(CRT_HAS_TF_MODE) +static inline __uint128_t toRep128(tf_float x) { __uint128_t ret; memcpy(&ret, &x, 16); return ret; @@ -146,11 +136,11 @@ static inline int compareResultD(double result, return 1; } -#ifdef TEST_COMPILER_RT_HAS_FLOAT128 +#if defined(CRT_HAS_TF_MODE) // return 0 if equal // use two 64-bit integers instead of one 128-bit integer // because 128-bit integer constant can't be assigned directly -static inline int compareResultF128(TYPE_FP128 result, uint64_t expectedHi, +static inline int compareResultF128(tf_float result, uint64_t expectedHi, uint64_t expectedLo) { __uint128_t rep = toRep128(result); uint64_t hi = rep >> 64; @@ -277,8 +267,8 @@ static inline long double makeInf80(void) { } #endif -#ifdef TEST_COMPILER_RT_HAS_FLOAT128 -static inline TYPE_FP128 makeQNaN128(void) { +#if defined(CRT_HAS_TF_MODE) +static inline tf_float makeQNaN128(void) { return fromRep128(0x7fff800000000000UL, 0x0UL); } #endif @@ -298,8 +288,8 @@ static inline double makeNaN64(uint64_t rand) return fromRep64(0x7ff0000000000000UL | (rand & 0xfffffffffffffUL)); } -#ifdef TEST_COMPILER_RT_HAS_FLOAT128 -static inline TYPE_FP128 makeNaN128(uint64_t rand) { +#if defined(CRT_HAS_TF_MODE) +static inline tf_float makeNaN128(uint64_t rand) { return fromRep128(0x7fff000000000000UL | (rand & 0xffffffffffffUL), 0x0UL); } #endif @@ -329,12 +319,12 @@ static inline double makeNegativeInf64(void) return fromRep64(0xfff0000000000000UL); } -#ifdef TEST_COMPILER_RT_HAS_FLOAT128 -static inline TYPE_FP128 makeInf128(void) { +#if defined(CRT_HAS_TF_MODE) +static inline tf_float makeInf128(void) { return fromRep128(0x7fff000000000000UL, 0x0UL); } -static inline TYPE_FP128 makeNegativeInf128(void) { +static inline tf_float makeNegativeInf128(void) { return fromRep128(0xffff000000000000UL, 0x0UL); } #endif diff --git a/compiler-rt/test/builtins/Unit/trunctfxf2_test.c b/compiler-rt/test/builtins/Unit/trunctfxf2_test.c index 53024ef139624a..76885e255e4c49 100644 --- a/compiler-rt/test/builtins/Unit/trunctfxf2_test.c +++ b/compiler-rt/test/builtins/Unit/trunctfxf2_test.c @@ -9,9 +9,9 @@ #include "fp_test.h" -COMPILER_RT_ABI long double __trunctfxf2(__float128 a); +COMPILER_RT_ABI long double __trunctfxf2(tf_float a); -int test__trunctfxf2(__float128 a, uint64_t expectedHi, uint64_t expectedLo) { +int test__trunctfxf2(tf_float a, uint64_t expectedHi, uint64_t expectedLo) { long double x = __trunctfxf2(a); int ret = compareResultF80(x, expectedHi, expectedLo); ; @@ -59,24 +59,24 @@ int main() { return 1; // Test rounding near halfway. - __float128 halfwayPlus = + tf_float halfwayPlus = fromRep128(UINT64_C(0x7ffa000000000000), ((UINT64_C(1) << (112 - 63 - 1)) + UINT64_C(1))); if (test__trunctfxf2(halfwayPlus, UINT64_C(0x7ffa), UINT64_C(0x8000000000000001))) return 1; - __float128 halfwayExactOdd = fromRep128( + tf_float halfwayExactOdd = fromRep128( UINT64_C(0x7ffa000000000000), ((UINT64_C(1) << (112 - 63)) + (UINT64_C(1) << (112 - 63 - 1)))); if (test__trunctfxf2(halfwayExactOdd, UINT64_C(0x7ffa), UINT64_C(0x8000000000000002))) return 1; - __float128 halfwayExactEven = + tf_float halfwayExactEven = fromRep128(UINT64_C(0x7ffa000000000000), (UINT64_C(1) << (112 - 63 - 1))); if (test__trunctfxf2(halfwayExactEven, UINT64_C(0x7ffa), UINT64_C(0x8000000000000000))) return 1; - __float128 halfwayRoundingWillChangeExponent = + tf_float halfwayRoundingWillChangeExponent = fromRep128(UINT64_C(0x7ffaffffffffffff), UINT64_C(0xffff000000000001)); if (test__trunctfxf2(halfwayRoundingWillChangeExponent, UINT64_C(0x7ffb), UINT64_C(0x8000000000000000)))