diff --git a/modules/fdlibm/patches/19_remove_unneeded_round_to_integer_helpers.patch b/modules/fdlibm/patches/19_remove_unneeded_round_to_integer_helpers.patch index 6d1baa23a806..056987c590ea 100644 --- a/modules/fdlibm/patches/19_remove_unneeded_round_to_integer_helpers.patch +++ b/modules/fdlibm/patches/19_remove_unneeded_round_to_integer_helpers.patch @@ -1,46 +1,15 @@ diff --git a/modules/fdlibm/src/math_private.h b/modules/fdlibm/src/math_private.h --- a/modules/fdlibm/src/math_private.h +++ b/modules/fdlibm/src/math_private.h -@@ -586,126 +586,16 @@ CMPLXL(long double x, long double y) - REALPART(z) = x; - IMAGPART(z) = y; - return (z.f); +@@ -617,95 +617,32 @@ rnint(double x) + * magic number would need to be variable. Assuming that the + * rounding precision is always the default is too fragile. This + * and many other complications will move when the default is + * changed to FP_PE. + */ + return ((double)(x + 0x1.8p52) - 0x1.8p52); } - #endif - #endif /* _COMPLEX_H */ - --/* -- * The rnint() family rounds to the nearest integer for a restricted range -- * range of args (up to about 2**MANT_DIG). We assume that the current -- * rounding mode is FE_TONEAREST so that this can be done efficiently. -- * Extra precision causes more problems in practice, and we only centralize -- * this here to reduce those problems, and have not solved the efficiency -- * problems. The exp2() family uses a more delicate version of this that -- * requires extracting bits from the intermediate value, so it is not -- * centralized here and should copy any solution of the efficiency problems. -- */ -- --static inline double --rnint(__double_t x) --{ -- /* -- * This casts to double to kill any extra precision. This depends -- * on the cast being applied to a double_t to avoid compiler bugs -- * (this is a cleaner version of STRICT_ASSIGN()). This is -- * inefficient if there actually is extra precision, but is hard -- * to improve on. We use double_t in the API to minimise conversions -- * for just calling here. Note that we cannot easily change the -- * magic number to the one that works directly with double_t, since -- * the rounding precision is variable at runtime on x86 so the -- * magic number would need to be variable. Assuming that the -- * rounding precision is always the default is too fragile. This -- * and many other complications will move when the default is -- * changed to FP_PE. -- */ -- return ((double)(x + 0x1.8p52) - 0x1.8p52); --} -- -static inline float -rnintf(__float_t x) -{ @@ -71,22 +40,22 @@ diff --git a/modules/fdlibm/src/math_private.h b/modules/fdlibm/src/math_private -} -#endif /* LDBL_MANT_DIG */ - --/* -- * irint() and i64rint() give the same result as casting to their integer -- * return type provided their arg is a floating point integer. They can -- * sometimes be more efficient because no rounding is required. -- */ --#if (defined(amd64) || defined(__i386__)) && defined(__GNUCLIKE_ASM) --#define irint(x) \ -- (sizeof(x) == sizeof(float) && \ -- sizeof(__float_t) == sizeof(long double) ? irintf(x) : \ -- sizeof(x) == sizeof(double) && \ -- sizeof(__double_t) == sizeof(long double) ? irintd(x) : \ -- sizeof(x) == sizeof(long double) ? irintl(x) : (int)(x)) --#else --#define irint(x) ((int)(x)) --#endif -- + /* + * irint() and i64rint() give the same result as casting to their integer + * return type provided their arg is a floating point integer. They can + * sometimes be more efficient because no rounding is required. + */ + #if (defined(amd64) || defined(__i386__)) && defined(__GNUCLIKE_ASM) + #define irint(x) \ + (sizeof(x) == sizeof(float) && \ + sizeof(__float_t) == sizeof(long double) ? irintf(x) : \ + sizeof(x) == sizeof(double) && \ + sizeof(__double_t) == sizeof(long double) ? irintd(x) : \ + sizeof(x) == sizeof(long double) ? irintl(x) : (int)(x)) + #else + #define irint(x) ((int)(x)) + #endif + -#define i64rint(x) ((int64_t)(x)) /* only needed for ld128 so not opt. */ - -#if defined(__i386__) && defined(__GNUCLIKE_ASM) diff --git a/modules/fdlibm/patches/20_emulate_freebsd_internal_double_types.patch b/modules/fdlibm/patches/20_emulate_freebsd_internal_double_types.patch new file mode 100644 index 000000000000..f6e65034e9cf --- /dev/null +++ b/modules/fdlibm/patches/20_emulate_freebsd_internal_double_types.patch @@ -0,0 +1,32 @@ +diff --git a/modules/fdlibm/src/math_private.h b/modules/fdlibm/src/math_private.h +--- a/modules/fdlibm/src/math_private.h ++++ b/modules/fdlibm/src/math_private.h +@@ -21,16 +21,28 @@ + #include + #include + + #include "fdlibm.h" + + #include "mozilla/EndianUtils.h" + + /* ++ * Emulate FreeBSD internal double types. ++ * Adapted from https://github.com/freebsd/freebsd-src/search?q=__double_t ++ */ ++ ++#if defined(__i386__) ++typedef long double __double_t; ++#else ++typedef double __double_t; ++#endif ++typedef __double_t double_t; ++ ++/* + * The original fdlibm code used statements like: + * n0 = ((*(int*)&one)>>29)^1; * index of high word * + * ix0 = *(n0+(int*)&x); * high word of x * + * ix1 = *((1-n0)+(int*)&x); * low word of x * + * to dig two 32 bit words out of the 64 bit IEEE floating point + * value. That is non-ANSI, and, moreover, the gcc instruction + * scheduler gets it wrong. We instead use the following macros. + * Unlike the original code, we determine the endianness at compile diff --git a/modules/fdlibm/src/math_private.h b/modules/fdlibm/src/math_private.h index 69f0b78cdcdb..99392012649f 100644 --- a/modules/fdlibm/src/math_private.h +++ b/modules/fdlibm/src/math_private.h @@ -25,6 +25,18 @@ #include "mozilla/EndianUtils.h" +/* + * Emulate FreeBSD internal double types. + * Adapted from https://github.com/freebsd/freebsd-src/search?q=__double_t + */ + +#if defined(__i386__) +typedef long double __double_t; +#else +typedef double __double_t; +#endif +typedef __double_t double_t; + /* * The original fdlibm code used statements like: * n0 = ((*(int*)&one)>>29)^1; * index of high word * @@ -591,6 +603,53 @@ CMPLXL(long double x, long double y) #endif /* _COMPLEX_H */ +/* + * The rnint() family rounds to the nearest integer for a restricted range + * range of args (up to about 2**MANT_DIG). We assume that the current + * rounding mode is FE_TONEAREST so that this can be done efficiently. + * Extra precision causes more problems in practice, and we only centralize + * this here to reduce those problems, and have not solved the efficiency + * problems. The exp2() family uses a more delicate version of this that + * requires extracting bits from the intermediate value, so it is not + * centralized here and should copy any solution of the efficiency problems. + */ + +static inline double +rnint(__double_t x) +{ + /* + * This casts to double to kill any extra precision. This depends + * on the cast being applied to a double_t to avoid compiler bugs + * (this is a cleaner version of STRICT_ASSIGN()). This is + * inefficient if there actually is extra precision, but is hard + * to improve on. We use double_t in the API to minimise conversions + * for just calling here. Note that we cannot easily change the + * magic number to the one that works directly with double_t, since + * the rounding precision is variable at runtime on x86 so the + * magic number would need to be variable. Assuming that the + * rounding precision is always the default is too fragile. This + * and many other complications will move when the default is + * changed to FP_PE. + */ + return ((double)(x + 0x1.8p52) - 0x1.8p52); +} + +/* + * irint() and i64rint() give the same result as casting to their integer + * return type provided their arg is a floating point integer. They can + * sometimes be more efficient because no rounding is required. + */ +#if (defined(amd64) || defined(__i386__)) && defined(__GNUCLIKE_ASM) +#define irint(x) \ + (sizeof(x) == sizeof(float) && \ + sizeof(__float_t) == sizeof(long double) ? irintf(x) : \ + sizeof(x) == sizeof(double) && \ + sizeof(__double_t) == sizeof(long double) ? irintd(x) : \ + sizeof(x) == sizeof(long double) ? irintl(x) : (int)(x)) +#else +#define irint(x) ((int)(x)) +#endif + #ifdef DEBUG #if defined(__amd64__) || defined(__i386__) #define breakpoint() asm("int $3")