Skip to content

Commit d2ce3e9

Browse files
authored
[builtins] Support building the 128-bit float functions on ld80 platforms (llvm#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 llvm#68041.
1 parent 16fe53c commit d2ce3e9

33 files changed

+1060
-954
lines changed

compiler-rt/lib/builtins/CMakeLists.txt

-2
Original file line numberDiff line numberDiff line change
@@ -187,8 +187,6 @@ set(BF16_SOURCES
187187
truncsfbf2.c
188188
)
189189

190-
# TODO: Several "tf" files (and divtc3.c, but not multc3.c) are in
191-
# GENERIC_SOURCES instead of here.
192190
set(GENERIC_TF_SOURCES
193191
addtf3.c
194192
comparetf2.c

compiler-rt/lib/builtins/README.txt

+12-9
Original file line numberDiff line numberDiff line change
@@ -137,49 +137,54 @@ si_int __ucmpti2(tu_int a, tu_int b);
137137
di_int __fixsfdi( float a);
138138
di_int __fixdfdi( double a);
139139
di_int __fixxfdi(long double a);
140+
di_int __fixtfdi( tf_float a);
140141

141142
ti_int __fixsfti( float a);
142143
ti_int __fixdfti( double a);
143144
ti_int __fixxfti(long double a);
144-
uint64_t __fixtfdi(long double input); // ppc only, doesn't match documentation
145+
ti_int __fixtfti( tf_float a);
145146

146147
su_int __fixunssfsi( float a);
147148
su_int __fixunsdfsi( double a);
148149
su_int __fixunsxfsi(long double a);
150+
su_int __fixunstfsi( tf_float a);
149151

150152
du_int __fixunssfdi( float a);
151153
du_int __fixunsdfdi( double a);
152154
du_int __fixunsxfdi(long double a);
155+
du_int __fixunstfdi( tf_float a);
153156

154157
tu_int __fixunssfti( float a);
155158
tu_int __fixunsdfti( double a);
156159
tu_int __fixunsxfti(long double a);
157-
uint64_t __fixunstfdi(long double input); // ppc only
160+
tu_int __fixunstfti( tf_float a);
158161

159162
float __floatdisf(di_int a);
160163
double __floatdidf(di_int a);
161164
long double __floatdixf(di_int a);
162-
long double __floatditf(int64_t a); // ppc only
165+
tf_float __floatditf(int64_t a);
163166

164167
float __floattisf(ti_int a);
165168
double __floattidf(ti_int a);
166169
long double __floattixf(ti_int a);
170+
tf_float __floattitf(ti_int a);
167171

168172
float __floatundisf(du_int a);
169173
double __floatundidf(du_int a);
170174
long double __floatundixf(du_int a);
171-
long double __floatunditf(uint64_t a); // ppc only
175+
tf_float __floatunditf(du_int a);
172176

173177
float __floatuntisf(tu_int a);
174178
double __floatuntidf(tu_int a);
175179
long double __floatuntixf(tu_int a);
180+
tf_float __floatuntixf(tu_int a);
176181

177182
// Floating point raised to integer power
178183

179184
float __powisf2( float a, int b); // a ^ b
180185
double __powidf2( double a, int b); // a ^ b
181186
long double __powixf2(long double a, int b); // a ^ b
182-
long double __powitf2(long double a, int b); // ppc only, a ^ b
187+
tf_float __powitf2( tf_float a, int b); // a ^ b
183188

184189
// Complex arithmetic
185190

@@ -189,17 +194,15 @@ long double __powitf2(long double a, int b); // ppc only, a ^ b
189194
double _Complex __muldc3(double a, double b, double c, double d);
190195
long double _Complex __mulxc3(long double a, long double b,
191196
long double c, long double d);
192-
long double _Complex __multc3(long double a, long double b,
193-
long double c, long double d); // ppc only
197+
tf_float _Complex __multc3(tf_float a, tf_float b, tf_float c, tf_float d);
194198

195199
// (a + ib) / (c + id)
196200

197201
float _Complex __divsc3( float a, float b, float c, float d);
198202
double _Complex __divdc3(double a, double b, double c, double d);
199203
long double _Complex __divxc3(long double a, long double b,
200204
long double c, long double d);
201-
long double _Complex __divtc3(long double a, long double b,
202-
long double c, long double d); // ppc only
205+
tf_float _Complex __divtc3(tf_float a, tf_float b, tf_float c, tf_float d);
203206

204207

205208
// Runtime support

compiler-rt/lib/builtins/divtc3.c

+26-25
Original file line numberDiff line numberDiff line change
@@ -12,44 +12,45 @@
1212

1313
#define QUAD_PRECISION
1414
#include "fp_lib.h"
15-
#include "int_lib.h"
16-
#include "int_math.h"
15+
16+
#if defined(CRT_HAS_TF_MODE)
1717

1818
// Returns: the quotient of (a + ib) / (c + id)
1919

20-
COMPILER_RT_ABI Lcomplex __divtc3(long double __a, long double __b,
21-
long double __c, long double __d) {
20+
COMPILER_RT_ABI Qcomplex __divtc3(fp_t __a, fp_t __b, fp_t __c, fp_t __d) {
2221
int __ilogbw = 0;
23-
long double __logbw =
24-
__compiler_rt_logbl(__compiler_rt_fmaxl(crt_fabsl(__c), crt_fabsl(__d)));
22+
fp_t __logbw = __compiler_rt_logbtf(
23+
__compiler_rt_fmaxtf(crt_fabstf(__c), crt_fabstf(__d)));
2524
if (crt_isfinite(__logbw)) {
2625
__ilogbw = (int)__logbw;
27-
__c = __compiler_rt_scalbnl(__c, -__ilogbw);
28-
__d = __compiler_rt_scalbnl(__d, -__ilogbw);
26+
__c = __compiler_rt_scalbntf(__c, -__ilogbw);
27+
__d = __compiler_rt_scalbntf(__d, -__ilogbw);
2928
}
30-
long double __denom = __c * __c + __d * __d;
31-
Lcomplex z;
32-
COMPLEX_REAL(z) =
33-
__compiler_rt_scalbnl((__a * __c + __b * __d) / __denom, -__ilogbw);
34-
COMPLEX_IMAGINARY(z) =
35-
__compiler_rt_scalbnl((__b * __c - __a * __d) / __denom, -__ilogbw);
36-
if (crt_isnan(COMPLEX_REAL(z)) && crt_isnan(COMPLEX_IMAGINARY(z))) {
29+
fp_t __denom = __c * __c + __d * __d;
30+
Qcomplex z;
31+
COMPLEXTF_REAL(z) =
32+
__compiler_rt_scalbntf((__a * __c + __b * __d) / __denom, -__ilogbw);
33+
COMPLEXTF_IMAGINARY(z) =
34+
__compiler_rt_scalbntf((__b * __c - __a * __d) / __denom, -__ilogbw);
35+
if (crt_isnan(COMPLEXTF_REAL(z)) && crt_isnan(COMPLEXTF_IMAGINARY(z))) {
3736
if ((__denom == 0.0) && (!crt_isnan(__a) || !crt_isnan(__b))) {
38-
COMPLEX_REAL(z) = crt_copysignl(CRT_INFINITY, __c) * __a;
39-
COMPLEX_IMAGINARY(z) = crt_copysignl(CRT_INFINITY, __c) * __b;
37+
COMPLEXTF_REAL(z) = crt_copysigntf(CRT_INFINITY, __c) * __a;
38+
COMPLEXTF_IMAGINARY(z) = crt_copysigntf(CRT_INFINITY, __c) * __b;
4039
} else if ((crt_isinf(__a) || crt_isinf(__b)) && crt_isfinite(__c) &&
4140
crt_isfinite(__d)) {
42-
__a = crt_copysignl(crt_isinf(__a) ? 1.0 : 0.0, __a);
43-
__b = crt_copysignl(crt_isinf(__b) ? 1.0 : 0.0, __b);
44-
COMPLEX_REAL(z) = CRT_INFINITY * (__a * __c + __b * __d);
45-
COMPLEX_IMAGINARY(z) = CRT_INFINITY * (__b * __c - __a * __d);
41+
__a = crt_copysigntf(crt_isinf(__a) ? (fp_t)1.0 : (fp_t)0.0, __a);
42+
__b = crt_copysigntf(crt_isinf(__b) ? (fp_t)1.0 : (fp_t)0.0, __b);
43+
COMPLEXTF_REAL(z) = CRT_INFINITY * (__a * __c + __b * __d);
44+
COMPLEXTF_IMAGINARY(z) = CRT_INFINITY * (__b * __c - __a * __d);
4645
} else if (crt_isinf(__logbw) && __logbw > 0.0 && crt_isfinite(__a) &&
4746
crt_isfinite(__b)) {
48-
__c = crt_copysignl(crt_isinf(__c) ? 1.0 : 0.0, __c);
49-
__d = crt_copysignl(crt_isinf(__d) ? 1.0 : 0.0, __d);
50-
COMPLEX_REAL(z) = 0.0 * (__a * __c + __b * __d);
51-
COMPLEX_IMAGINARY(z) = 0.0 * (__b * __c - __a * __d);
47+
__c = crt_copysigntf(crt_isinf(__c) ? (fp_t)1.0 : (fp_t)0.0, __c);
48+
__d = crt_copysigntf(crt_isinf(__d) ? (fp_t)1.0 : (fp_t)0.0, __d);
49+
COMPLEXTF_REAL(z) = 0.0 * (__a * __c + __b * __d);
50+
COMPLEXTF_IMAGINARY(z) = 0.0 * (__b * __c - __a * __d);
5251
}
5352
}
5453
return z;
5554
}
55+
56+
#endif

compiler-rt/lib/builtins/extenddftf2.c

+1-3
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,6 @@
1414
#define DST_QUAD
1515
#include "fp_extend_impl.inc"
1616

17-
COMPILER_RT_ABI fp_t __extenddftf2(double a) {
18-
return __extendXfYf2__(a);
19-
}
17+
COMPILER_RT_ABI dst_t __extenddftf2(src_t a) { return __extendXfYf2__(a); }
2018

2119
#endif

compiler-rt/lib/builtins/extendhftf2.c

+1-3
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,6 @@
1515
#define DST_QUAD
1616
#include "fp_extend_impl.inc"
1717

18-
COMPILER_RT_ABI long double __extendhftf2(_Float16 a) {
19-
return __extendXfYf2__(a);
20-
}
18+
COMPILER_RT_ABI dst_t __extendhftf2(src_t a) { return __extendXfYf2__(a); }
2119

2220
#endif

compiler-rt/lib/builtins/extendsftf2.c

+1-3
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,6 @@
1414
#define DST_QUAD
1515
#include "fp_extend_impl.inc"
1616

17-
COMPILER_RT_ABI fp_t __extendsftf2(float a) {
18-
return __extendXfYf2__(a);
19-
}
17+
COMPILER_RT_ABI dst_t __extendsftf2(src_t a) { return __extendXfYf2__(a); }
2018

2119
#endif

compiler-rt/lib/builtins/extendxftf2.c

+5-4
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,15 @@
99
// Assumption: long double is a IEEE 80 bit floating point type padded to 128
1010
// bits.
1111

12-
// TODO: use fp_lib.h once QUAD_PRECISION is available on x86_64.
13-
#if __LDBL_MANT_DIG__ == 64 && defined(__x86_64__) && \
14-
(defined(__FLOAT128__) || defined(__SIZEOF_FLOAT128__))
12+
#define QUAD_PRECISION
13+
#include "fp_lib.h"
14+
15+
#if defined(CRT_HAS_TF_MODE) && __LDBL_MANT_DIG__ == 64 && defined(__x86_64__)
1516
#define SRC_80
1617
#define DST_QUAD
1718
#include "fp_extend_impl.inc"
1819

19-
COMPILER_RT_ABI __float128 __extendxftf2(long double a) {
20+
COMPILER_RT_ABI tf_float __extendxftf2(long double a) {
2021
return __extendXfYf2__(a);
2122
}
2223

compiler-rt/lib/builtins/fp_extend.h

+1-7
Original file line numberDiff line numberDiff line change
@@ -102,13 +102,7 @@ static const int dstSigFracBits = 52;
102102
static const int dstExpBits = 11;
103103

104104
#elif defined DST_QUAD
105-
// TODO: use fp_lib.h once QUAD_PRECISION is available on x86_64.
106-
#if __LDBL_MANT_DIG__ == 113
107-
typedef long double dst_t;
108-
#elif defined(__x86_64__) && \
109-
(defined(__FLOAT128__) || defined(__SIZEOF_FLOAT128__))
110-
typedef __float128 dst_t;
111-
#endif
105+
typedef tf_float dst_t;
112106
typedef __uint128_t dst_rep_t;
113107
#define DST_REP_C (__uint128_t)
114108
static const int dstBits = sizeof(dst_t) * CHAR_BIT;

compiler-rt/lib/builtins/fp_lib.h

+26-24
Original file line numberDiff line numberDiff line change
@@ -105,18 +105,11 @@ static __inline void wideMultiply(rep_t a, rep_t b, rep_t *hi, rep_t *lo) {
105105
COMPILER_RT_ABI fp_t __adddf3(fp_t a, fp_t b);
106106

107107
#elif defined QUAD_PRECISION
108-
#if __LDBL_MANT_DIG__ == 113 && defined(__SIZEOF_INT128__)
109-
// TODO: Availability of the *tf functions should not depend on long double
110-
// being IEEE 128, but instead on being able to use a 128-bit floating-point
111-
// type, which includes __float128.
112-
// Right now this (incorrectly) stops the builtins from being used for x86.
113-
#define CRT_LDBL_128BIT
114-
#define CRT_HAS_TF_MODE
115-
#define TF_C(c) c##L
108+
#if defined(CRT_HAS_TF_MODE)
116109
typedef uint64_t half_rep_t;
117110
typedef __uint128_t rep_t;
118111
typedef __int128_t srep_t;
119-
typedef long double fp_t;
112+
typedef tf_float fp_t;
120113
#define HALF_REP_C UINT64_C
121114
#define REP_C (__uint128_t)
122115
// 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) {
207200
#undef Word_HiMask
208201
#undef Word_LoMask
209202
#undef Word_FullMask
210-
#endif // __LDBL_MANT_DIG__ == 113 && __SIZEOF_INT128__
203+
#endif // defined(CRT_HAS_TF_MODE)
211204
#else
212205
#error SINGLE_PRECISION, DOUBLE_PRECISION or QUAD_PRECISION must be defined.
213206
#endif
214207

215208
#if defined(SINGLE_PRECISION) || defined(DOUBLE_PRECISION) || \
216-
defined(CRT_LDBL_128BIT)
209+
(defined(QUAD_PRECISION) && defined(CRT_HAS_TF_MODE))
217210
#define typeWidth (sizeof(rep_t) * CHAR_BIT)
218211
#define exponentBits (typeWidth - significandBits - 1)
219212
#define maxExponent ((1 << exponentBits) - 1)
@@ -393,31 +386,40 @@ static __inline fp_t __compiler_rt_fmax(fp_t x, fp_t y) {
393386
#endif
394387
}
395388

396-
#elif defined(QUAD_PRECISION)
397-
398-
#if defined(CRT_LDBL_128BIT)
399-
static __inline fp_t __compiler_rt_logbl(fp_t x) {
389+
#elif defined(QUAD_PRECISION) && defined(CRT_HAS_TF_MODE)
390+
// The generic implementation only works for ieee754 floating point. For other
391+
// floating point types, continue to rely on the libm implementation for now.
392+
#if defined(CRT_HAS_IEEE_TF)
393+
static __inline tf_float __compiler_rt_logbtf(tf_float x) {
400394
return __compiler_rt_logbX(x);
401395
}
402-
static __inline fp_t __compiler_rt_scalbnl(fp_t x, int y) {
396+
static __inline tf_float __compiler_rt_scalbntf(tf_float x, int y) {
403397
return __compiler_rt_scalbnX(x, y);
404398
}
405-
static __inline fp_t __compiler_rt_fmaxl(fp_t x, fp_t y) {
399+
static __inline tf_float __compiler_rt_fmaxtf(tf_float x, tf_float y) {
406400
return __compiler_rt_fmaxX(x, y);
407401
}
408-
#else
409-
// The generic implementation only works for ieee754 floating point. For other
410-
// floating point types, continue to rely on the libm implementation for now.
411-
static __inline long double __compiler_rt_logbl(long double x) {
402+
#define __compiler_rt_logbl __compiler_rt_logbtf
403+
#define __compiler_rt_scalbnl __compiler_rt_scalbntf
404+
#define __compiler_rt_fmaxl __compiler_rt_fmaxtf
405+
#define crt_fabstf crt_fabsf128
406+
#define crt_copysigntf crt_copysignf128
407+
#elif defined(CRT_LDBL_128BIT)
408+
static __inline tf_float __compiler_rt_logbtf(tf_float x) {
412409
return crt_logbl(x);
413410
}
414-
static __inline long double __compiler_rt_scalbnl(long double x, int y) {
411+
static __inline tf_float __compiler_rt_scalbntf(tf_float x, int y) {
415412
return crt_scalbnl(x, y);
416413
}
417-
static __inline long double __compiler_rt_fmaxl(long double x, long double y) {
414+
static __inline tf_float __compiler_rt_fmaxtf(tf_float x, tf_float y) {
418415
return crt_fmaxl(x, y);
419416
}
420-
#endif // CRT_LDBL_128BIT
417+
#define __compiler_rt_logbl crt_logbl
418+
#define __compiler_rt_scalbnl crt_scalbnl
419+
#define __compiler_rt_fmaxl crt_fmaxl
420+
#else
421+
#error Unsupported TF mode type
422+
#endif
421423

422424
#endif // *_PRECISION
423425

compiler-rt/lib/builtins/fp_trunc.h

+1-7
Original file line numberDiff line numberDiff line change
@@ -36,13 +36,7 @@ static const int srcSigFracBits = 52;
3636
static const int srcExpBits = 11;
3737

3838
#elif defined SRC_QUAD
39-
// TODO: use fp_lib.h once QUAD_PRECISION is available on x86_64.
40-
#if __LDBL_MANT_DIG__ == 113
41-
typedef long double src_t;
42-
#elif defined(__x86_64__) && \
43-
(defined(__FLOAT128__) || defined(__SIZEOF_FLOAT128__))
44-
typedef __float128 src_t;
45-
#endif
39+
typedef tf_float src_t;
4640
typedef __uint128_t src_rep_t;
4741
#define SRC_REP_C (__uint128_t)
4842
static const int srcBits = sizeof(src_t) * CHAR_BIT;

compiler-rt/lib/builtins/int_math.h

+10
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,11 @@
6565
#define crt_copysign(x, y) __builtin_copysign((x), (y))
6666
#define crt_copysignf(x, y) __builtin_copysignf((x), (y))
6767
#define crt_copysignl(x, y) __builtin_copysignl((x), (y))
68+
#if __has_builtin(__builtin_copysignf128)
69+
#define crt_copysignf128(x, y) __builtin_copysignf128((x), (y))
70+
#elif __has_builtin(__builtin_copysignq) || (defined(__GNUC__) && __GNUC__ >= 7)
71+
#define crt_copysignf128(x, y) __builtin_copysignq((x), (y))
72+
#endif
6873
#endif
6974

7075
#if defined(_MSC_VER) && !defined(__clang__)
@@ -75,6 +80,11 @@
7580
#define crt_fabs(x) __builtin_fabs((x))
7681
#define crt_fabsf(x) __builtin_fabsf((x))
7782
#define crt_fabsl(x) __builtin_fabsl((x))
83+
#if __has_builtin(__builtin_fabsf128)
84+
#define crt_fabsf128(x) __builtin_fabsf128((x))
85+
#elif __has_builtin(__builtin_fabsq) || (defined(__GNUC__) && __GNUC__ >= 7)
86+
#define crt_fabsf128(x) __builtin_fabsq((x))
87+
#endif
7888
#endif
7989

8090
#if defined(_MSC_VER) && !defined(__clang__)

compiler-rt/lib/builtins/int_to_fp.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ enum {
5959
};
6060

6161
#elif defined DST_QUAD
62-
typedef long double dst_t;
62+
typedef tf_float dst_t;
6363
typedef __uint128_t dst_rep_t;
6464
#define DST_REP_C (__uint128_t)
6565

0 commit comments

Comments
 (0)