re PR other/25028 (TImode-to-floating conversions broken)

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.

From-SVN: r108598
This commit is contained in:
Joseph Myers 2005-12-15 21:50:10 +00:00 committed by Joseph Myers
parent 4976b95c37
commit 4a73d8657b
8 changed files with 197 additions and 92 deletions

View File

@ -1,3 +1,22 @@
2005-12-15 Joseph S. Myers <joseph@codesourcery.com>
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 <rodrigc@gcc.gnu.org>
* freebsd-spec.h (FBSD_TARGET_OS_CPP_BUILTINS):

View File

@ -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

View File

@ -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");

View File

@ -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

View File

@ -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,6 +1358,9 @@ __floatditf (DWtype u)
TFtype
__floatunditf (UDWtype u)
{
#if W_TYPE_SIZE > TF_SIZE
# error
#endif
TFtype d = (UWtype) (u >> W_TYPE_SIZE);
d *= Wtype_MAXp1_F;
d += (UWtype)u;
@ -1356,86 +1368,81 @@ __floatunditf (UDWtype u)
}
#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;
}
#endif
#if defined(L_floatundidf) && LIBGCC2_HAS_DF_MODE
DFtype
__floatundidf (UDWtype u)
{
DFtype 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
#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_DOUBLE_TYPE_SIZE == 64
#define DF_SIZE DBL_MANT_DIG
#elif LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 64
#define DF_SIZE LDBL_MANT_DIG
#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
#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_DOUBLE_TYPE_SIZE == 64
#define DF_SIZE DBL_MANT_DIG
#elif LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 64
#define DF_SIZE LDBL_MANT_DIG
#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
}

View File

@ -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

View File

@ -1,3 +1,9 @@
2005-12-15 Joseph S. Myers <joseph@codesourcery.com>
PR other/25028
* gcc.dg/torture/fp-int-convert-timode.c: Only XFAIL for LP64 IA64
HP-UX.
2005-12-15 Richard Sandiford <richard@codesourcery.com>
* gcc.dg/20051215-1.c: New file.

View File

@ -1,6 +1,6 @@
/* Test floating-point conversions. TImode types. */
/* Origin: Joseph Myers <joseph@codesourcery.com> */
/* { dg-do run { xfail lp64 } } */
/* { dg-do run { xfail { ia64-*-hpux* && lp64 } } } */
/* { dg-options "" } */
#include <float.h>