From 3212edfa491e970255dd03c6991c868399c7be1d Mon Sep 17 00:00:00 2001 From: jsm28 Date: Thu, 15 Dec 2005 21:50:10 +0000 Subject: [PATCH] PR other/25028 * libgcc2.h (SF_SIZE, DF_SIZE, XF_SIZE, TF_SIZE): Define. * libgcc2.c (__floatdixf, __floatundixf, __floatditf, __floatunditf): Use #error if type sizes don't match requirements of implementation. (__floatdisf, __floatdidf): Unify. Possibly use XFmode or TFmode as wider floating-point type. Use #error if type sizes don't match requirements of implementation. Avoid overflow in computing Wtype_MAXp1_F * Wtype_MAXp1_F. When special casing conversion, shift one more bit. Cast 1 to DWtype or UDWtype for shifting. (__floatundisf, __floatundidf): Likewise. * config/ia64/hpux.h (XF_SIZE, TF_SIZE): Define. * config/ia64/ia64.c (ia64_init_libfuncs): Use _U_Qfcnvfxt_quad_to_quad and _U_Qfcnvxf_quad_to_quad for TFmode-TImode conversions. * doc/tm.texi (SF_SIZE, DF_SIZE, XF_SIZE, TF_SIZE): Document. testsuite: * gcc.dg/torture/fp-int-convert-timode.c: Only XFAIL for LP64 IA64 HP-UX. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@108598 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 19 ++ gcc/config/ia64/hpux.h | 2 + gcc/config/ia64/ia64.c | 2 + gcc/doc/tm.texi | 14 ++ gcc/libgcc2.c | 210 ++++++++++++--------- gcc/libgcc2.h | 38 ++++ gcc/testsuite/ChangeLog | 6 + .../gcc.dg/torture/fp-int-convert-timode.c | 2 +- 8 files changed, 199 insertions(+), 94 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 208beb2deb4..4170cbc9dc8 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,22 @@ +2005-12-15 Joseph S. Myers + + PR other/25028 + * libgcc2.h (SF_SIZE, DF_SIZE, XF_SIZE, TF_SIZE): Define. + * libgcc2.c (__floatdixf, __floatundixf, __floatditf, + __floatunditf): Use #error if type sizes don't match requirements + of implementation. + (__floatdisf, __floatdidf): Unify. Possibly use XFmode or TFmode + as wider floating-point type. Use #error if type sizes don't + match requirements of implementation. Avoid overflow in computing + Wtype_MAXp1_F * Wtype_MAXp1_F. When special casing conversion, + shift one more bit. Cast 1 to DWtype or UDWtype for shifting. + (__floatundisf, __floatundidf): Likewise. + * config/ia64/hpux.h (XF_SIZE, TF_SIZE): Define. + * config/ia64/ia64.c (ia64_init_libfuncs): Use + _U_Qfcnvfxt_quad_to_quad and _U_Qfcnvxf_quad_to_quad for + TFmode-TImode conversions. + * doc/tm.texi (SF_SIZE, DF_SIZE, XF_SIZE, TF_SIZE): Document. + 2005-12-14 Craig Rodrigues * freebsd-spec.h (FBSD_TARGET_OS_CPP_BUILTINS): diff --git a/gcc/config/ia64/hpux.h b/gcc/config/ia64/hpux.h index 512f7c8f7ad..9ffe1fddf30 100644 --- a/gcc/config/ia64/hpux.h +++ b/gcc/config/ia64/hpux.h @@ -195,10 +195,12 @@ do { \ /* Put all *xf routines in libgcc, regardless of long double size. */ #undef LIBGCC2_HAS_XF_MODE #define LIBGCC2_HAS_XF_MODE 1 +#define XF_SIZE 64 /* Put all *tf routines in libgcc, regardless of long double size. */ #undef LIBGCC2_HAS_TF_MODE #define LIBGCC2_HAS_TF_MODE 1 +#define TF_SIZE 113 /* HP-UX headers are C++-compatible. */ #define NO_IMPLICIT_EXTERN_C diff --git a/gcc/config/ia64/ia64.c b/gcc/config/ia64/ia64.c index 2da3383d0f8..e6767538d68 100644 --- a/gcc/config/ia64/ia64.c +++ b/gcc/config/ia64/ia64.c @@ -8437,11 +8437,13 @@ ia64_init_libfuncs (void) set_conv_libfunc (sfix_optab, SImode, TFmode, "_U_Qfcnvfxt_quad_to_sgl"); set_conv_libfunc (sfix_optab, DImode, TFmode, "_U_Qfcnvfxt_quad_to_dbl"); + set_conv_libfunc (sfix_optab, TImode, TFmode, "_U_Qfcnvfxt_quad_to_quad"); set_conv_libfunc (ufix_optab, SImode, TFmode, "_U_Qfcnvfxut_quad_to_sgl"); set_conv_libfunc (ufix_optab, DImode, TFmode, "_U_Qfcnvfxut_quad_to_dbl"); set_conv_libfunc (sfloat_optab, TFmode, SImode, "_U_Qfcnvxf_sgl_to_quad"); set_conv_libfunc (sfloat_optab, TFmode, DImode, "_U_Qfcnvxf_dbl_to_quad"); + set_conv_libfunc (sfloat_optab, TFmode, TImode, "_U_Qfcnvxf_quad_to_quad"); /* HP-UX 11.23 libc does not have a function for unsigned SImode-to-TFmode conversion. */ set_conv_libfunc (ufloat_optab, TFmode, DImode, "_U_Qfcnvxuf_dbl_to_quad"); diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi index 64a1a22f9cb..b0dd8e1b10a 100644 --- a/gcc/doc/tm.texi +++ b/gcc/doc/tm.texi @@ -1548,6 +1548,20 @@ anyway. If you don't define this and @code{LIBGCC2_LONG_DOUBLE_TYPE_SIZE} is 128 then the default is 1, otherwise it is 0. @end defmac +@defmac SF_SIZE +@defmacx DF_SIZE +@defmacx XF_SIZE +@defmacx TF_SIZE +Define these macros to be the size in bits of the mantissa of +@code{SFmode}, @code{DFmode}, @code{XFmode} and @code{TFmode} values, +if the defaults in @file{libgcc2.h} are inappropriate. By default, +@code{FLT_MANT_DIG} is used for @code{SF_SIZE}, @code{LDBL_MANT_DIG} +for @code{XF_SIZE} and @code{TF_SIZE}, and @code{DBL_MANT_DIG} or +@code{LDBL_MANT_DIG} for @code{DF_SIZE} according to whether +@code{LIBGCC2_DOUBLE_TYPE_SIZE} or +@code{LIBGCC2_LONG_DOUBLE_TYPE_SIZE} is 64. +@end defmac + @defmac TARGET_FLT_EVAL_METHOD A C expression for the value for @code{FLT_EVAL_METHOD} in @file{float.h}, assuming, if applicable, that the floating-point control word is in its diff --git a/gcc/libgcc2.c b/gcc/libgcc2.c index d6bd8723458..03cc448cab3 100644 --- a/gcc/libgcc2.c +++ b/gcc/libgcc2.c @@ -1316,6 +1316,9 @@ __fixsfdi (SFtype a) XFtype __floatdixf (DWtype u) { +#if W_TYPE_SIZE > XF_SIZE +# error +#endif XFtype d = (Wtype) (u >> W_TYPE_SIZE); d *= Wtype_MAXp1_F; d += (UWtype)u; @@ -1327,6 +1330,9 @@ __floatdixf (DWtype u) XFtype __floatundixf (UDWtype u) { +#if W_TYPE_SIZE > XF_SIZE +# error +#endif XFtype d = (UWtype) (u >> W_TYPE_SIZE); d *= Wtype_MAXp1_F; d += (UWtype)u; @@ -1338,6 +1344,9 @@ __floatundixf (UDWtype u) TFtype __floatditf (DWtype u) { +#if W_TYPE_SIZE > TF_SIZE +# error +#endif TFtype d = (Wtype) (u >> W_TYPE_SIZE); d *= Wtype_MAXp1_F; d += (UWtype)u; @@ -1349,93 +1358,91 @@ __floatditf (DWtype u) TFtype __floatunditf (UDWtype u) { - TFtype d = (UWtype) (u >> W_TYPE_SIZE); - d *= Wtype_MAXp1_F; - d += (UWtype)u; - return d; -} -#endif - -#if defined(L_floatdidf) && LIBGCC2_HAS_DF_MODE -DFtype -__floatdidf (DWtype u) -{ - DFtype d = (Wtype) (u >> W_TYPE_SIZE); - d *= Wtype_MAXp1_F; - d += (UWtype)u; - return d; -} +#if W_TYPE_SIZE > TF_SIZE +# error #endif - -#if defined(L_floatundidf) && LIBGCC2_HAS_DF_MODE -DFtype -__floatundidf (UDWtype u) -{ - DFtype d = (UWtype) (u >> W_TYPE_SIZE); + TFtype d = (UWtype) (u >> W_TYPE_SIZE); d *= Wtype_MAXp1_F; d += (UWtype)u; return d; } #endif -#if defined(L_floatdisf) && LIBGCC2_HAS_SF_MODE +#if (defined(L_floatdisf) && LIBGCC2_HAS_SF_MODE) \ + || (defined(L_floatdidf) && LIBGCC2_HAS_DF_MODE) #define DI_SIZE (W_TYPE_SIZE * 2) -#define SF_SIZE FLT_MANT_DIG +#define F_MODE_OK(SIZE) (SIZE < DI_SIZE && SIZE > (DI_SIZE - SIZE + FSSIZE)) +#if defined(L_floatdisf) +#define FUNC __floatdisf +#define FSTYPE SFtype +#define FSSIZE SF_SIZE +#else +#define FUNC __floatdidf +#define FSTYPE DFtype +#define FSSIZE DF_SIZE +#endif -SFtype -__floatdisf (DWtype u) +FSTYPE +FUNC (DWtype u) { -#if SF_SIZE >= W_TYPE_SIZE +#if FSSIZE >= W_TYPE_SIZE /* When the word size is small, we never get any rounding error. */ - SFtype f = (Wtype) (u >> W_TYPE_SIZE); + FSTYPE f = (Wtype) (u >> W_TYPE_SIZE); f *= Wtype_MAXp1_F; f += (UWtype)u; return f; -#elif LIBGCC2_HAS_DF_MODE - -#if LIBGCC2_DOUBLE_TYPE_SIZE == 64 -#define DF_SIZE DBL_MANT_DIG -#elif LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 64 -#define DF_SIZE LDBL_MANT_DIG +#elif (LIBGCC2_HAS_DF_MODE && F_MODE_OK (DF_SIZE)) \ + || (LIBGCC2_HAS_XF_MODE && F_MODE_OK (XF_SIZE)) \ + || (LIBGCC2_HAS_TF_MODE && F_MODE_OK (TF_SIZE)) + +#if (LIBGCC2_HAS_DF_MODE && F_MODE_OK (DF_SIZE)) +# define FSIZE DF_SIZE +# define FTYPE DFtype +#elif (LIBGCC2_HAS_XF_MODE && F_MODE_OK (XF_SIZE)) +# define FSIZE XF_SIZE +# define FTYPE XFtype +#elif (LIBGCC2_HAS_TF_MODE && F_MODE_OK (TF_SIZE)) +# define FSIZE TF_SIZE +# define FTYPE TFtype #else # error #endif -#define REP_BIT ((UDWtype) 1 << (DI_SIZE - DF_SIZE)) +#define REP_BIT ((UDWtype) 1 << (DI_SIZE - FSIZE)) /* Protect against double-rounding error. Represent any low-order bits, that might be truncated by a bit that won't be lost. The bit can go in anywhere below the rounding position - of the SFmode. A fixed mask and bit position handles all usual - configurations. It doesn't handle the case of 128-bit DImode, however. */ - if (DF_SIZE < DI_SIZE - && DF_SIZE > (DI_SIZE - DF_SIZE + SF_SIZE)) + of the FSTYPE. A fixed mask and bit position handles all usual + configurations. */ + if (! (- ((DWtype) 1 << FSIZE) < u + && u < ((DWtype) 1 << FSIZE))) { - if (! (- ((DWtype) 1 << DF_SIZE) < u - && u < ((DWtype) 1 << DF_SIZE))) + if ((UDWtype) u & (REP_BIT - 1)) { - if ((UDWtype) u & (REP_BIT - 1)) - { - u &= ~ (REP_BIT - 1); - u |= REP_BIT; - } + u &= ~ (REP_BIT - 1); + u |= REP_BIT; } } - /* Do the calculation in DFmode so that we don't lose any of the - precision of the high word while multiplying it. */ - DFtype f = (Wtype) (u >> W_TYPE_SIZE); + /* Do the calculation in a wider type so that we don't lose any of + the precision of the high word while multiplying it. */ + FTYPE f = (Wtype) (u >> W_TYPE_SIZE); f *= Wtype_MAXp1_F; f += (UWtype)u; - return (SFtype) f; + return (FSTYPE) f; #else - /* Finally, the word size is larger than the number of bits in SFmode, - and we've got no DFmode. The only way to avoid double rounding is - to special case the extraction. */ +#if FSSIZE >= W_TYPE_SIZE - 2 +# error +#endif + /* Finally, the word size is larger than the number of bits in the + required FSTYPE, and we've got no suitable wider type. The only + way to avoid double rounding is to special case the + extraction. */ /* If there are no high bits set, fall back to one conversion. */ if ((Wtype)u == u) - return (SFtype)(Wtype)u; + return (FSTYPE)(Wtype)u; /* Otherwise, find the power of two. */ Wtype hi = u >> W_TYPE_SIZE; @@ -1447,82 +1454,99 @@ __floatdisf (DWtype u) /* No leading bits means u == minimum. */ if (count == 0) - return -(Wtype_MAXp1_F * Wtype_MAXp1_F / 2); + return -(Wtype_MAXp1_F * (Wtype_MAXp1_F / 2)); - shift = W_TYPE_SIZE - count; + shift = 1 + W_TYPE_SIZE - count; /* Shift down the most significant bits. */ hi = u >> shift; /* If we lost any nonzero bits, set the lsb to ensure correct rounding. */ - if (u & ((1 << shift) - 1)) + if (u & (((DWtype)1 << shift) - 1)) hi |= 1; /* Convert the one word of data, and rescale. */ - SFtype f = hi; - f *= (UWtype)1 << shift; + FSTYPE f = hi; + f *= (UDWtype)1 << shift; return f; #endif } #endif -#if defined(L_floatundisf) && LIBGCC2_HAS_SF_MODE +#if (defined(L_floatundisf) && LIBGCC2_HAS_SF_MODE) \ + || (defined(L_floatundidf) && LIBGCC2_HAS_DF_MODE) #define DI_SIZE (W_TYPE_SIZE * 2) -#define SF_SIZE FLT_MANT_DIG +#define F_MODE_OK(SIZE) (SIZE < DI_SIZE && SIZE > (DI_SIZE - SIZE + FSSIZE)) +#if defined(L_floatundisf) +#define FUNC __floatundisf +#define FSTYPE SFtype +#define FSSIZE SF_SIZE +#else +#define FUNC __floatundidf +#define FSTYPE DFtype +#define FSSIZE DF_SIZE +#endif -SFtype -__floatundisf (UDWtype u) +FSTYPE +FUNC (UDWtype u) { -#if SF_SIZE >= W_TYPE_SIZE +#if FSSIZE >= W_TYPE_SIZE /* When the word size is small, we never get any rounding error. */ - SFtype f = (UWtype) (u >> W_TYPE_SIZE); + FSTYPE f = (UWtype) (u >> W_TYPE_SIZE); f *= Wtype_MAXp1_F; f += (UWtype)u; return f; -#elif LIBGCC2_HAS_DF_MODE - -#if LIBGCC2_DOUBLE_TYPE_SIZE == 64 -#define DF_SIZE DBL_MANT_DIG -#elif LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 64 -#define DF_SIZE LDBL_MANT_DIG +#elif (LIBGCC2_HAS_DF_MODE && F_MODE_OK (DF_SIZE)) \ + || (LIBGCC2_HAS_XF_MODE && F_MODE_OK (XF_SIZE)) \ + || (LIBGCC2_HAS_TF_MODE && F_MODE_OK (TF_SIZE)) + +#if (LIBGCC2_HAS_DF_MODE && F_MODE_OK (DF_SIZE)) +# define FSIZE DF_SIZE +# define FTYPE DFtype +#elif (LIBGCC2_HAS_XF_MODE && F_MODE_OK (XF_SIZE)) +# define FSIZE XF_SIZE +# define FTYPE XFtype +#elif (LIBGCC2_HAS_TF_MODE && F_MODE_OK (TF_SIZE)) +# define FSIZE TF_SIZE +# define FTYPE TFtype #else # error #endif -#define REP_BIT ((UDWtype) 1 << (DI_SIZE - DF_SIZE)) +#define REP_BIT ((UDWtype) 1 << (DI_SIZE - FSIZE)) /* Protect against double-rounding error. Represent any low-order bits, that might be truncated by a bit that won't be lost. The bit can go in anywhere below the rounding position - of the SFmode. A fixed mask and bit position handles all usual - configurations. It doesn't handle the case of 128-bit DImode, however. */ - if (DF_SIZE < DI_SIZE - && DF_SIZE > (DI_SIZE - DF_SIZE + SF_SIZE)) + of the FSTYPE. A fixed mask and bit position handles all usual + configurations. */ + if (u >= ((UDWtype) 1 << FSIZE)) { - if (u >= ((UDWtype) 1 << DF_SIZE)) + if ((UDWtype) u & (REP_BIT - 1)) { - if ((UDWtype) u & (REP_BIT - 1)) - { - u &= ~ (REP_BIT - 1); - u |= REP_BIT; - } + u &= ~ (REP_BIT - 1); + u |= REP_BIT; } } - /* Do the calculation in DFmode so that we don't lose any of the - precision of the high word while multiplying it. */ - DFtype f = (UWtype) (u >> W_TYPE_SIZE); + /* Do the calculation in a wider type so that we don't lose any of + the precision of the high word while multiplying it. */ + FTYPE f = (UWtype) (u >> W_TYPE_SIZE); f *= Wtype_MAXp1_F; f += (UWtype)u; - return (SFtype) f; + return (FSTYPE) f; #else - /* Finally, the word size is larger than the number of bits in SFmode, - and we've got no DFmode. The only way to avoid double rounding is - to special case the extraction. */ +#if FSSIZE == W_TYPE_SIZE - 1 +# error +#endif + /* Finally, the word size is larger than the number of bits in the + required FSTYPE, and we've got no suitable wider type. The only + way to avoid double rounding is to special case the + extraction. */ /* If there are no high bits set, fall back to one conversion. */ if ((UWtype)u == u) - return (SFtype)(UWtype)u; + return (FSTYPE)(UWtype)u; /* Otherwise, find the power of two. */ UWtype hi = u >> W_TYPE_SIZE; @@ -1536,12 +1560,12 @@ __floatundisf (UDWtype u) hi = u >> shift; /* If we lost any nonzero bits, set the lsb to ensure correct rounding. */ - if (u & ((1 << shift) - 1)) + if (u & (((UDWtype)1 << shift) - 1)) hi |= 1; /* Convert the one word of data, and rescale. */ - SFtype f = hi; - f *= (UWtype)1 << shift; + FSTYPE f = hi; + f *= (UDWtype)1 << shift; return f; #endif } diff --git a/gcc/libgcc2.h b/gcc/libgcc2.h index 11a1d9a3ff8..f8056d66e14 100644 --- a/gcc/libgcc2.h +++ b/gcc/libgcc2.h @@ -79,6 +79,44 @@ extern short int __get_eh_table_version (struct exception_descriptor *); (BITS_PER_UNIT == 8 && LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 128) #endif +#ifndef SF_SIZE +#if LIBGCC2_HAS_SF_MODE +#define SF_SIZE FLT_MANT_DIG +#else +#define SF_SIZE 0 +#endif +#endif + +#ifndef DF_SIZE +#if LIBGCC2_HAS_DF_MODE +#if LIBGCC2_DOUBLE_TYPE_SIZE == 64 +#define DF_SIZE DBL_MANT_DIG +#elif LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 64 +#define DF_SIZE LDBL_MANT_DIG +#else +#define DF_SIZE 0 +#endif +#else +#define DF_SIZE 0 +#endif +#endif + +#ifndef XF_SIZE +#if LIBGCC2_HAS_XF_MODE +#define XF_SIZE LDBL_MANT_DIG +#else +#define XF_SIZE 0 +#endif +#endif + +#ifndef TF_SIZE +#if LIBGCC2_HAS_TF_MODE +#define TF_SIZE LDBL_MANT_DIG +#else +#define TF_SIZE 0 +#endif +#endif + #ifndef MIN_UNITS_PER_WORD #define MIN_UNITS_PER_WORD UNITS_PER_WORD #endif diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index efeb2a51c4f..39fa89ceb60 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2005-12-15 Joseph S. Myers + + PR other/25028 + * gcc.dg/torture/fp-int-convert-timode.c: Only XFAIL for LP64 IA64 + HP-UX. + 2005-12-15 Richard Sandiford * gcc.dg/20051215-1.c: New file. diff --git a/gcc/testsuite/gcc.dg/torture/fp-int-convert-timode.c b/gcc/testsuite/gcc.dg/torture/fp-int-convert-timode.c index e60b5409d5f..244fc31728a 100644 --- a/gcc/testsuite/gcc.dg/torture/fp-int-convert-timode.c +++ b/gcc/testsuite/gcc.dg/torture/fp-int-convert-timode.c @@ -1,6 +1,6 @@ /* Test floating-point conversions. TImode types. */ /* Origin: Joseph Myers */ -/* { dg-do run { xfail lp64 } } */ +/* { dg-do run { xfail { ia64-*-hpux* && lp64 } } } */ /* { dg-options "" } */ #include -- 2.11.4.GIT