* Re: libgcc2 __fixsfdi
[not found] <20021005002244.H25369@bubble.sa.bigpond.net.au>
@ 2002-10-04 11:49 ` Geoff Keating
2002-10-04 18:41 ` Alan Modra
0 siblings, 1 reply; 5+ messages in thread
From: Geoff Keating @ 2002-10-04 11:49 UTC (permalink / raw)
To: Alan Modra; +Cc: gcc-patches
Alan Modra <amodra@bigpond.net.au> writes:
> gcc's __fixsfdi function returns extremely surprising results for
> floats that overflow the range of DWtype.
Why is this surprising? That's how all the integer conversions work,
for instance.
[I'm not objecting to the patch, I'm just surprised you're surprised.]
--
- Geoffrey Keating <geoffk@geoffk.org>
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: libgcc2 __fixsfdi
2002-10-04 11:49 ` libgcc2 __fixsfdi Geoff Keating
@ 2002-10-04 18:41 ` Alan Modra
[not found] ` <jmhef4pwnq.fsf@desire.geoffk.org>
0 siblings, 1 reply; 5+ messages in thread
From: Alan Modra @ 2002-10-04 18:41 UTC (permalink / raw)
To: Geoff Keating; +Cc: gcc-patches
On Fri, Oct 04, 2002 at 11:48:57AM -0700, Geoff Keating wrote:
> Alan Modra <amodra@bigpond.net.au> writes:
>
> > gcc's __fixsfdi function returns extremely surprising results for
> > floats that overflow the range of DWtype.
>
> Why is this surprising? That's how all the integer conversions work,
> for instance.
>
> [I'm not objecting to the patch, I'm just surprised you're surprised.]
:-) Well, it's not so much that I personally am surprised. There are
at least two independent internal IBM bug reports related to this
feature, one involving a java certification kit. I guess it's
surprising to someone used to working with floating point, and
particularly people who have worked with AIX or S390 where these
conversions peg at the min/max values.
--
Alan Modra
IBM OzLabs - Linux Technology Centre
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: libgcc2 __fixsfdi
[not found] ` <jmhef4pwnq.fsf@desire.geoffk.org>
@ 2002-11-04 16:33 ` Alan Modra
0 siblings, 0 replies; 5+ messages in thread
From: Alan Modra @ 2002-11-04 16:33 UTC (permalink / raw)
To: Geoff Keating; +Cc: gcc-patches
On Tue, Oct 29, 2002 at 05:01:29PM -0800, Geoff Keating wrote:
> Did this get approved?
No. And to do the job properly I need quite a few more changes. This
patch makes gcc follow the Java conventions for floating point
conversions.
* defaults.h (FLOAT_FIX_BOUND_OVERFLOW): Define
(FLOAT_FIX_NANS_TO_ZERO): Define.
* fold-const.c (fold_convert): Handle FLOAT_FIX_BOUND_OVERFLOW.
* simplify-rtx.c (simplify_unary_operation): Likewise.
* optabs.c (expand_fix): Likewise, also FLOAT_FIX_NANS_TO_ZERO.
* config/rs6000/rs6000.h (FLOAT_FIX_BOUND_OVERFLOW): Define
(FLOAT_FIX_NANS_TO_ZERO): Define.
* libgcc2.c (__fixunstfDI): Reorganize so that NaNs convert to zero.
(__fixunsxfDI, __fixunsdfDI, __fixunssfDI): Likewise.
(__fixunsxfSI, __fixunsdfSI, __fixunssfSI): Likewise.
(__fixtfdi): Handle FLOAT_FIX_BOUND_OVERFLOW.
(__fixxfdi, __fixdfdi, __fixsfdi): Likewise.
Unfortunately, this tickles a problem which caused me to lose interest.
.../libgcc2.c: In function `__fixdfti':
.../libgcc2.c:1013: internal compiler error: in output_toc, at
config/rs6000/rs6000.c:11824
I suppose I ought to post a bugreport..
Index: gcc/defaults.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/defaults.h,v
retrieving revision 1.96
diff -c -p -r1.96 defaults.h
*** gcc/defaults.h 22 Sep 2002 14:09:30 -0000 1.96
--- gcc/defaults.h 4 Nov 2002 22:58:46 -0000
*************** You Lose! You must define PREFERRED_DEB
*** 535,540 ****
--- 535,557 ----
#define TARGET_FLOAT_FORMAT IEEE_FLOAT_FORMAT
#endif
+ /* For floating point to integer conversions, defines the result for
+ conversions of values (including +/-inf) that overflow the
+ destination integer type. If set, gcc generates extra code to
+ return the max/min value. The "destination integer type" is
+ considered to be "int" or "unsigned int" for types smaller than an
+ "int". */
+ #ifndef FLOAT_FIX_BOUND_OVERFLOW
+ #define FLOAT_FIX_BOUND_OVERFLOW 0
+ #endif
+
+ /* For floating point to integer conversions, defines the result for
+ conversions of NaNs. If set, gcc generates extra code to convert
+ NaNs to zero. */
+ #ifndef FLOAT_FIX_NANS_TO_ZERO
+ #define FLOAT_FIX_NANS_TO_ZERO 0
+ #endif
+
/* Determine the register class for registers suitable to be the base
address register in a MEM. Allow the choice to be dependent upon
the mode of the memory access. */
Index: gcc/fold-const.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/fold-const.c,v
retrieving revision 1.225
diff -c -p -r1.225 fold-const.c
*** gcc/fold-const.c 30 Oct 2002 23:07:47 -0000 1.225
--- gcc/fold-const.c 4 Nov 2002 22:58:51 -0000
*************** fold_convert (t, arg1)
*** 1549,1589 ****
}
else if (TREE_CODE (arg1) == REAL_CST)
{
! /* Don't initialize these, use assignments.
Initialized local aggregates don't work on old compilers. */
REAL_VALUE_TYPE x;
! REAL_VALUE_TYPE l;
! REAL_VALUE_TYPE u;
! tree type1 = TREE_TYPE (arg1);
! int no_upper_bound;
x = TREE_REAL_CST (arg1);
- l = real_value_from_int_cst (type1, TYPE_MIN_VALUE (type));
- no_upper_bound = (TYPE_MAX_VALUE (type) == NULL);
- if (!no_upper_bound)
- u = real_value_from_int_cst (type1, TYPE_MAX_VALUE (type));
-
- /* See if X will be in range after truncation towards 0.
- To compensate for truncation, move the bounds away from 0,
- but reject if X exactly equals the adjusted bounds. */
- REAL_ARITHMETIC (l, MINUS_EXPR, l, dconst1);
- if (!no_upper_bound)
- REAL_ARITHMETIC (u, PLUS_EXPR, u, dconst1);
/* If X is a NaN, use zero instead and show we have an overflow.
Otherwise, range check. */
if (REAL_VALUE_ISNAN (x))
! overflow = 1, x = dconst0;
! else if (! (REAL_VALUES_LESS (l, x)
! && !no_upper_bound
! && REAL_VALUES_LESS (x, u)))
! overflow = 1;
!
! {
! HOST_WIDE_INT low, high;
! REAL_VALUE_TO_INT (&low, &high, x);
! t = build_int_2 (low, high);
! }
TREE_TYPE (t) = type;
TREE_OVERFLOW (t)
= TREE_OVERFLOW (arg1) | force_fit_type (t, overflow);
--- 1549,1655 ----
}
else if (TREE_CODE (arg1) == REAL_CST)
{
! /* Don't initialize REAL_VALUE_TYPE vars, use assignments.
Initialized local aggregates don't work on old compilers. */
REAL_VALUE_TYPE x;
! HOST_WIDE_INT low = 0, high = 0;
! int converted = 0;
x = TREE_REAL_CST (arg1);
/* If X is a NaN, use zero instead and show we have an overflow.
Otherwise, range check. */
if (REAL_VALUE_ISNAN (x))
! {
! overflow = 1;
! converted = 1;
! }
! else
! {
! REAL_VALUE_TYPE l;
! REAL_VALUE_TYPE u;
! tree type1 = TREE_TYPE (arg1);
! int no_upper_bound, too_small, too_big;
!
! l = real_value_from_int_cst (type1, TYPE_MIN_VALUE (type));
!
! no_upper_bound = TYPE_MAX_VALUE (type) == NULL;
! if (!no_upper_bound)
! u = real_value_from_int_cst (type1, TYPE_MAX_VALUE (type));
!
! /* See if X will be in range after truncation towards 0.
! To compensate for truncation, move the bounds away from 0,
! but reject if X exactly equals the adjusted bounds. */
! REAL_ARITHMETIC (l, MINUS_EXPR, l, dconst1);
! if (!no_upper_bound)
! REAL_ARITHMETIC (u, PLUS_EXPR, u, dconst1);
!
! too_big = 0;
! too_small = !REAL_VALUES_LESS (l, x);
! if (too_small)
! overflow = 1;
! else
! {
! too_big = !no_upper_bound && !REAL_VALUES_LESS (x, u);
! if (too_big)
! overflow = 1;
! }
!
! if (FLOAT_FIX_BOUND_OVERFLOW)
! {
! /* We want to peg overflows to the min/max values in
! the target integer representation, except when
! the target integer is smaller than an int. In
! that case, we peg to int min/max. */
! tree bound = type;
! tree utype = integer_types[itk_unsigned_int];
! tree stype = integer_types[itk_int];
!
! if (TREE_UNSIGNED (type) && !no_upper_bound
! && INT_CST_LT_UNSIGNED (TYPE_MAX_VALUE (type),
! TYPE_MAX_VALUE (utype)))
! bound = utype;
!
! if (!TREE_UNSIGNED (type)
! && INT_CST_LT (TYPE_MAX_VALUE (type),
! TYPE_MAX_VALUE (stype)))
! bound = stype;
!
! if (bound != type)
! {
! l = real_value_from_int_cst (type1,
! TYPE_MIN_VALUE (bound));
! u = real_value_from_int_cst (type1,
! TYPE_MAX_VALUE (bound));
! REAL_ARITHMETIC (l, MINUS_EXPR, l, dconst1);
! REAL_ARITHMETIC (u, PLUS_EXPR, u, dconst1);
! too_big = 0;
! too_small = !REAL_VALUES_LESS (l, x);
! if (!too_small)
! too_big = !REAL_VALUES_LESS (x, u);
! }
!
! if (too_small)
! {
! low = TREE_INT_CST_LOW (TYPE_MIN_VALUE (bound));
! high = TREE_INT_CST_HIGH (TYPE_MIN_VALUE (bound));
! converted = 1;
! }
! else if (too_big)
! {
! low = TREE_INT_CST_LOW (TYPE_MAX_VALUE (bound));
! high = TREE_INT_CST_HIGH (TYPE_MAX_VALUE (bound));
! converted = 1;
! }
! }
! }
!
! if (!converted)
! {
! REAL_VALUE_TO_INT (&low, &high, x);
! }
!
! t = build_int_2 (low, high);
TREE_TYPE (t) = type;
TREE_OVERFLOW (t)
= TREE_OVERFLOW (arg1) | force_fit_type (t, overflow);
Index: gcc/libgcc2.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/libgcc2.c,v
retrieving revision 1.153
diff -c -p -r1.153 libgcc2.c
*** gcc/libgcc2.c 23 Oct 2002 10:47:24 -0000 1.153
--- gcc/libgcc2.c 4 Nov 2002 22:58:52 -0000
*************** DWtype
*** 850,886 ****
__fixunstfDI (TFtype a)
{
TFtype b;
! UDWtype v;
! if (a < 0)
! return 0;
!
! /* Compute high word of result, as a flonum. */
! b = (a / HIGH_WORD_COEFF);
! /* Convert that to fixed (but not to DWtype!),
! and shift it into the high word. */
! v = (UWtype) b;
! v <<= WORD_SIZE;
! /* Remove high part from the TFtype, leaving the low part as flonum. */
! a -= (TFtype)v;
! /* Convert that to fixed (but not to DWtype!) and add it in.
! Sometimes A comes out negative. This is significant, since
! A has more bits than a long int does. */
! if (a < 0)
! v -= (UWtype) (- a);
! else
! v += (UWtype) a;
return v;
}
#endif
#if defined(L_fixtfdi) && (LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 128)
DWtype
__fixtfdi (TFtype a)
{
! if (a < 0)
! return - __fixunstfDI (-a);
! return __fixunstfDI (a);
}
#endif
--- 850,901 ----
__fixunstfDI (TFtype a)
{
TFtype b;
! UDWtype v = 0;
! if (a > 0)
! {
! /* Compute high word of result, as a flonum. */
! b = (a / HIGH_WORD_COEFF);
! /* Convert that to fixed (but not to DWtype!),
! and shift it into the high word. */
! v = (UWtype) b;
! v <<= WORD_SIZE;
! /* Remove high part from the TFtype, leaving the low part as flonum. */
! a -= (TFtype) v;
! /* Convert that to fixed (but not to DWtype!) and add it in.
! Sometimes A comes out negative. This is significant, since
! A has more bits than a long int does. */
! if (a < 0)
! v -= (UWtype) (- a);
! else
! v += (UWtype) a;
! }
return v;
}
#endif
#if defined(L_fixtfdi) && (LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 128)
+ #define DWORD_SIZE (sizeof (DWtype) * BITS_PER_UNIT)
+ #define MAXDWtype ((DWtype) (((UDWtype) 1 << (DWORD_SIZE - 1)) - 1))
+
DWtype
__fixtfdi (TFtype a)
{
! DWtype tmp;
!
! if (a >= 0)
! {
! tmp = __fixunstfDI (a);
! if (FLOAT_FIX_BOUND_OVERFLOW && tmp < 0)
! tmp = MAXDWtype;
! return tmp;
! }
!
! tmp = __fixunstfDI (-a);
! tmp = -tmp;
! if (FLOAT_FIX_BOUND_OVERFLOW && tmp > 0)
! tmp = -MAXDWtype - 1;
! return tmp;
}
#endif
*************** DWtype
*** 892,928 ****
__fixunsxfDI (XFtype a)
{
XFtype b;
! UDWtype v;
!
! if (a < 0)
! return 0;
! /* Compute high word of result, as a flonum. */
! b = (a / HIGH_WORD_COEFF);
! /* Convert that to fixed (but not to DWtype!),
! and shift it into the high word. */
! v = (UWtype) b;
! v <<= WORD_SIZE;
! /* Remove high part from the XFtype, leaving the low part as flonum. */
! a -= (XFtype)v;
! /* Convert that to fixed (but not to DWtype!) and add it in.
! Sometimes A comes out negative. This is significant, since
! A has more bits than a long int does. */
! if (a < 0)
! v -= (UWtype) (- a);
! else
! v += (UWtype) a;
return v;
}
#endif
#if defined(L_fixxfdi) && (LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 96)
DWtype
__fixxfdi (XFtype a)
{
! if (a < 0)
! return - __fixunsxfDI (-a);
! return __fixunsxfDI (a);
}
#endif
--- 907,958 ----
__fixunsxfDI (XFtype a)
{
XFtype b;
! UDWtype v = 0;
! if (a > 0)
! {
! /* Compute high word of result, as a flonum. */
! b = (a / HIGH_WORD_COEFF);
! /* Convert that to fixed (but not to DWtype!),
! and shift it into the high word. */
! v = (UWtype) b;
! v <<= WORD_SIZE;
! /* Remove high part from the XFtype, leaving the low part as flonum. */
! a -= (XFtype) v;
! /* Convert that to fixed (but not to DWtype!) and add it in.
! Sometimes A comes out negative. This is significant, since
! A has more bits than a long int does. */
! if (a < 0)
! v -= (UWtype) (- a);
! else
! v += (UWtype) a;
! }
return v;
}
#endif
#if defined(L_fixxfdi) && (LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 96)
+ #define DWORD_SIZE (sizeof (DWtype) * BITS_PER_UNIT)
+ #define MAXDWtype ((DWtype) (((UDWtype) 1 << (DWORD_SIZE - 1)) - 1))
+
DWtype
__fixxfdi (XFtype a)
{
! DWtype tmp;
!
! if (a >= 0)
! {
! tmp = __fixunsxfDI (a);
! if (FLOAT_FIX_BOUND_OVERFLOW && tmp < 0)
! tmp = MAXDWtype;
! return tmp;
! }
!
! tmp = __fixunsxfDI (-a);
! tmp = -tmp;
! if (FLOAT_FIX_BOUND_OVERFLOW && tmp > 0)
! tmp = -MAXDWtype - 1;
! return tmp;
}
#endif
*************** DWtype
*** 934,970 ****
__fixunsdfDI (DFtype a)
{
DFtype b;
! UDWtype v;
!
! if (a < 0)
! return 0;
! /* Compute high word of result, as a flonum. */
! b = (a / HIGH_WORD_COEFF);
! /* Convert that to fixed (but not to DWtype!),
! and shift it into the high word. */
! v = (UWtype) b;
! v <<= WORD_SIZE;
! /* Remove high part from the DFtype, leaving the low part as flonum. */
! a -= (DFtype)v;
! /* Convert that to fixed (but not to DWtype!) and add it in.
! Sometimes A comes out negative. This is significant, since
! A has more bits than a long int does. */
! if (a < 0)
! v -= (UWtype) (- a);
! else
! v += (UWtype) a;
return v;
}
#endif
#ifdef L_fixdfdi
DWtype
__fixdfdi (DFtype a)
{
! if (a < 0)
! return - __fixunsdfDI (-a);
! return __fixunsdfDI (a);
}
#endif
--- 964,1015 ----
__fixunsdfDI (DFtype a)
{
DFtype b;
! UDWtype v = 0;
! if (a > 0)
! {
! /* Compute high word of result, as a flonum. */
! b = (a / HIGH_WORD_COEFF);
! /* Convert that to fixed (but not to DWtype!),
! and shift it into the high word. */
! v = (UWtype) b;
! v <<= WORD_SIZE;
! /* Remove high part from the DFtype, leaving the low part as flonum. */
! a -= (DFtype) v;
! /* Convert that to fixed (but not to DWtype!) and add it in.
! Sometimes A comes out negative. This is significant, since
! A has more bits than a long int does. */
! if (a < 0)
! v -= (UWtype) (- a);
! else
! v += (UWtype) a;
! }
return v;
}
#endif
#ifdef L_fixdfdi
+ #define DWORD_SIZE (sizeof (DWtype) * BITS_PER_UNIT)
+ #define MAXDWtype ((DWtype) (((UDWtype) 1 << (DWORD_SIZE - 1)) - 1))
+
DWtype
__fixdfdi (DFtype a)
{
! DWtype tmp;
!
! if (a >= 0)
! {
! tmp = __fixunsdfDI (a);
! if (FLOAT_FIX_BOUND_OVERFLOW && tmp < 0)
! tmp = MAXDWtype;
! return tmp;
! }
!
! tmp = __fixunsdfDI (-a);
! tmp = -tmp;
! if (FLOAT_FIX_BOUND_OVERFLOW && tmp > 0)
! tmp = -MAXDWtype - 1;
! return tmp;
}
#endif
*************** __fixunssfDI (SFtype original_a)
*** 980,1016 ****
that avoids converting to DFtype, and verify it really works right. */
DFtype a = original_a;
DFtype b;
! UDWtype v;
!
! if (a < 0)
! return 0;
! /* Compute high word of result, as a flonum. */
! b = (a / HIGH_WORD_COEFF);
! /* Convert that to fixed (but not to DWtype!),
! and shift it into the high word. */
! v = (UWtype) b;
! v <<= WORD_SIZE;
! /* Remove high part from the DFtype, leaving the low part as flonum. */
! a -= (DFtype) v;
! /* Convert that to fixed (but not to DWtype!) and add it in.
! Sometimes A comes out negative. This is significant, since
! A has more bits than a long int does. */
! if (a < 0)
! v -= (UWtype) (- a);
! else
! v += (UWtype) a;
return v;
}
#endif
#ifdef L_fixsfdi
DWtype
__fixsfdi (SFtype a)
{
! if (a < 0)
! return - __fixunssfDI (-a);
! return __fixunssfDI (a);
}
#endif
--- 1025,1076 ----
that avoids converting to DFtype, and verify it really works right. */
DFtype a = original_a;
DFtype b;
! UDWtype v = 0;
! if (a > 0)
! {
! /* Compute high word of result, as a flonum. */
! b = (a / HIGH_WORD_COEFF);
! /* Convert that to fixed (but not to DWtype!),
! and shift it into the high word. */
! v = (UWtype) b;
! v <<= WORD_SIZE;
! /* Remove high part from the DFtype, leaving the low part as flonum. */
! a -= (DFtype) v;
! /* Convert that to fixed (but not to DWtype!) and add it in.
! Sometimes A comes out negative. This is significant, since
! A has more bits than a long int does. */
! if (a < 0)
! v -= (UWtype) (- a);
! else
! v += (UWtype) a;
! }
return v;
}
#endif
#ifdef L_fixsfdi
+ #define DWORD_SIZE (sizeof (DWtype) * BITS_PER_UNIT)
+ #define MAXDWtype ((DWtype) (((UDWtype) 1 << (DWORD_SIZE - 1)) - 1))
+
DWtype
__fixsfdi (SFtype a)
{
! DWtype tmp;
!
! if (a >= 0)
! {
! tmp = __fixunssfDI (a);
! if (FLOAT_FIX_BOUND_OVERFLOW && tmp < 0)
! tmp = MAXDWtype;
! return tmp;
! }
!
! tmp = __fixunssfDI (-a);
! tmp = -tmp;
! if (FLOAT_FIX_BOUND_OVERFLOW && tmp > 0)
! tmp = -MAXDWtype - 1;
! return tmp;
}
#endif
*************** __floatdisf (DWtype u)
*** 1133,1141 ****
UWtype
__fixunsxfSI (XFtype a)
{
! if (a >= - (DFtype) Wtype_MIN)
! return (Wtype) (a + Wtype_MIN) - Wtype_MIN;
! return (Wtype) a;
}
#endif
--- 1193,1208 ----
UWtype
__fixunsxfSI (XFtype a)
{
! UWtype v = 0;
!
! if (!FLOAT_FIX_BOUND_OVERFLOW || a > 0)
! {
! if (a >= - (XFtype) Wtype_MIN)
! v = (Wtype) (a + Wtype_MIN) - Wtype_MIN;
! else
! v = (Wtype) a;
! }
! return v;
}
#endif
*************** __fixunsxfSI (XFtype a)
*** 1155,1163 ****
UWtype
__fixunsdfSI (DFtype a)
{
! if (a >= - (DFtype) Wtype_MIN)
! return (Wtype) (a + Wtype_MIN) - Wtype_MIN;
! return (Wtype) a;
}
#endif
--- 1222,1237 ----
UWtype
__fixunsdfSI (DFtype a)
{
! UWtype v = 0;
!
! if (!FLOAT_FIX_BOUND_OVERFLOW || a > 0)
! {
! if (a >= - (DFtype) Wtype_MIN)
! v = (Wtype) (a + Wtype_MIN) - Wtype_MIN;
! else
! v = (Wtype) a;
! }
! return v;
}
#endif
*************** __fixunsdfSI (DFtype a)
*** 1177,1185 ****
UWtype
__fixunssfSI (SFtype a)
{
! if (a >= - (SFtype) Wtype_MIN)
! return (Wtype) (a + Wtype_MIN) - Wtype_MIN;
! return (Wtype) a;
}
#endif
\f
--- 1251,1266 ----
UWtype
__fixunssfSI (SFtype a)
{
! UWtype v = 0;
!
! if (!FLOAT_FIX_BOUND_OVERFLOW || a > 0)
! {
! if (a >= - (SFtype) Wtype_MIN)
! v = (Wtype) (a + Wtype_MIN) - Wtype_MIN;
! else
! v = (Wtype) a;
! }
! return v;
}
#endif
\f
Index: gcc/optabs.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/optabs.c,v
retrieving revision 1.150
diff -c -p -r1.150 optabs.c
*** gcc/optabs.c 24 Oct 2002 08:48:27 -0000 1.150
--- gcc/optabs.c 4 Nov 2002 22:59:02 -0000
*************** expand_fix (to, from, unsignedp)
*** 4750,4755 ****
--- 4750,4757 ----
if (icode != CODE_FOR_nothing)
{
+ rtx lab1 = NULL_RTX;
+
to = protect_from_queue (to, 1);
from = protect_from_queue (from, 0);
*************** expand_fix (to, from, unsignedp)
*** 4759,4771 ****
if (must_trunc)
from = ftruncify (from);
if (imode != GET_MODE (to))
target = gen_reg_rtx (imode);
emit_unop_insn (icode, target, from,
doing_unsigned ? UNSIGNED_FIX : FIX);
if (target != to)
! convert_move (to, target, unsignedp);
return;
}
}
--- 4761,4827 ----
if (must_trunc)
from = ftruncify (from);
+ if (FLOAT_FIX_NANS_TO_ZERO)
+ {
+ lab1 = gen_label_rtx ();
+ emit_move_insn (to, const0_rtx);
+ do_pending_stack_adjust ();
+ emit_cmp_and_jump_insns (from, from, NE, NULL_RTX,
+ fmode, 0, lab1);
+ }
+
if (imode != GET_MODE (to))
target = gen_reg_rtx (imode);
emit_unop_insn (icode, target, from,
doing_unsigned ? UNSIGNED_FIX : FIX);
if (target != to)
! {
! convert_move (to, target, unsignedp);
!
! if (FLOAT_FIX_BOUND_OVERFLOW)
! {
! rtx wide, lab2;
! HOST_WIDE_INT lim;
!
! lab2 = gen_label_rtx ();
! wide = gen_reg_rtx (imode);
! convert_move (wide, to, unsignedp);
!
! if (!FLOAT_FIX_NANS_TO_ZERO)
! do_pending_stack_adjust ();
! emit_cmp_and_jump_insns (target, wide, EQ, NULL_RTX,
! imode, unsignedp, lab2);
!
! lim = 0;
! if (!unsignedp)
! {
! int bitsize = GET_MODE_BITSIZE (GET_MODE (to));
! lim = (HOST_WIDE_INT) -1 << (bitsize - 1);
! }
!
! emit_move_insn (to, GEN_INT (lim));
! emit_cmp_and_jump_insns (target, CONST0_RTX (imode), LT,
! NULL_RTX, imode, 0, lab2);
! emit_move_insn (to, GEN_INT (~lim));
! emit_label (lab2);
! }
!
! if (mov_optab->handlers[(int) GET_MODE (to)].insn_code
! != CODE_FOR_nothing)
! {
! rtx insn, x;
!
! /* Make a place for a REG_NOTE and add it. */
! insn = emit_move_insn (to, to);
! x = gen_rtx_fmt_e (unsignedp ? UNSIGNED_FIX : FIX,
! GET_MODE (to), copy_rtx (from));
! set_unique_reg_note (insn, REG_EQUAL, x);
! }
! }
!
! if (lab1 != NULL_RTX)
! emit_label (lab1);
return;
}
}
*************** expand_fix (to, from, unsignedp)
*** 4782,4791 ****
if (unsignedp && GET_MODE_BITSIZE (GET_MODE (to)) <= HOST_BITS_PER_WIDE_INT)
for (fmode = GET_MODE (from); fmode != VOIDmode;
fmode = GET_MODE_WIDER_MODE (fmode))
! /* Make sure we won't lose significant bits doing this. */
! if (GET_MODE_BITSIZE (fmode) > GET_MODE_BITSIZE (GET_MODE (to))
! && CODE_FOR_nothing != can_fix_p (GET_MODE (to), fmode, 0,
! &must_trunc))
{
int bitsize;
REAL_VALUE_TYPE offset;
--- 4838,4844 ----
if (unsignedp && GET_MODE_BITSIZE (GET_MODE (to)) <= HOST_BITS_PER_WIDE_INT)
for (fmode = GET_MODE (from); fmode != VOIDmode;
fmode = GET_MODE_WIDER_MODE (fmode))
! if (CODE_FOR_nothing != can_fix_p (GET_MODE (to), fmode, 0, &must_trunc))
{
int bitsize;
REAL_VALUE_TYPE offset;
*************** expand_fix (to, from, unsignedp)
*** 4814,4819 ****
--- 4867,4882 ----
/* If not, do the signed "fix" and branch around fixup code. */
expand_fix (to, from, 0);
+
+ if (FLOAT_FIX_BOUND_OVERFLOW)
+ {
+ /* Test for underflow. */
+ emit_cmp_and_jump_insns (from, CONST0_RTX (fmode), GT, NULL_RTX,
+ GET_MODE (from), 0, lab2);
+
+ emit_move_insn (to, CONST0_RTX (GET_MODE (to)));
+ }
+
emit_jump_insn (gen_jump (lab2));
emit_barrier ();
Index: gcc/simplify-rtx.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/simplify-rtx.c,v
retrieving revision 1.126
diff -c -p -r1.126 simplify-rtx.c
*** gcc/simplify-rtx.c 4 Nov 2002 16:57:03 -0000 1.126
--- gcc/simplify-rtx.c 4 Nov 2002 22:59:06 -0000
*************** simplify_unary_operation (code, mode, op
*** 643,654 ****
&& width <= HOST_BITS_PER_WIDE_INT && width > 0)
{
HOST_WIDE_INT i;
REAL_VALUE_TYPE d;
REAL_VALUE_FROM_CONST_DOUBLE (d, trueop);
switch (code)
{
! case FIX: i = REAL_VALUE_FIX (d); break;
! case UNSIGNED_FIX: i = REAL_VALUE_UNSIGNED_FIX (d); break;
default:
abort ();
}
--- 643,690 ----
&& width <= HOST_BITS_PER_WIDE_INT && width > 0)
{
HOST_WIDE_INT i;
+ int bitsize;
+ REAL_VALUE_TYPE lim;
REAL_VALUE_TYPE d;
REAL_VALUE_FROM_CONST_DOUBLE (d, trueop);
switch (code)
{
! case FIX:
! if (FLOAT_FIX_BOUND_OVERFLOW)
! {
! bitsize = GET_MODE_BITSIZE (mode);
! if (bitsize < GET_MODE_BITSIZE (SImode))
! bitsize = GET_MODE_BITSIZE (SImode);
! real_ldexp (&lim, &dconstm1, bitsize - 1);
!
! i = (HOST_WIDE_INT) -1 << (bitsize - 1);
! if (REAL_VALUES_LESS (d, lim))
! break;
! i = ~i;
! REAL_VALUE_NEGATE (lim);
! if (!REAL_VALUES_LESS (d, lim))
! break;
! }
! i = REAL_VALUE_FIX (d);
! break;
!
! case UNSIGNED_FIX:
! if (FLOAT_FIX_BOUND_OVERFLOW)
! {
! i = 0;
! if (REAL_VALUES_LESS (d, dconst0))
! break;
! bitsize = GET_MODE_BITSIZE (mode);
! if (bitsize < GET_MODE_BITSIZE (SImode))
! bitsize = GET_MODE_BITSIZE (SImode);
! real_ldexp (&lim, &dconst1, bitsize);
! i = ~i;
! if (!REAL_VALUES_LESS (d, lim))
! break;
! }
! i = REAL_VALUE_UNSIGNED_FIX (d);
! break;
!
default:
abort ();
}
Index: gcc/config/rs6000/rs6000.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/rs6000/rs6000.h,v
retrieving revision 1.234
diff -c -p -r1.234 rs6000.h
*** gcc/config/rs6000/rs6000.h 4 Nov 2002 16:57:09 -0000 1.234
--- gcc/config/rs6000/rs6000.h 4 Nov 2002 22:59:17 -0000
*************** extern int rs6000_default_long_calls;
*** 607,612 ****
--- 607,619 ----
/* No data type wants to be aligned rounder than this. */
#define BIGGEST_ALIGNMENT 128
+ /* Ensure conversions of floating point numbers that overflow the target
+ integer type result in the max/min value rather than wrapping. */
+ #define FLOAT_FIX_BOUND_OVERFLOW 1
+
+ /* When converting floating point to integer, convert NaNs to zero. */
+ #define FLOAT_FIX_NANS_TO_ZERO 1
+
/* A C expression to compute the alignment for a variables in the
local store. TYPE is the data type, and ALIGN is the alignment
that the object would ordinarily have. */
--
Alan Modra
IBM OzLabs - Linux Technology Centre
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: libgcc2 __fixsfdi
2002-11-04 16:55 Ulrich Weigand
@ 2002-11-04 17:54 ` Alan Modra
0 siblings, 0 replies; 5+ messages in thread
From: Alan Modra @ 2002-11-04 17:54 UTC (permalink / raw)
To: Ulrich Weigand; +Cc: geoffk, gcc-patches
On Tue, Nov 05, 2002 at 01:55:41AM +0100, Ulrich Weigand wrote:
> Alan Modra wrote:
> > * defaults.h (FLOAT_FIX_BOUND_OVERFLOW): Define
> > (FLOAT_FIX_NANS_TO_ZERO): Define.
>
> Hmm, I just noticed that. I guess this would allow me to get
> rid of the weird hack that is s390/fixdfdi.h ...
Yes, it should do. I see an extra expand_fix hunk (4782,4791) crept
into my posted patch. Please ignore that one.
--
Alan Modra
IBM OzLabs - Linux Technology Centre
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: libgcc2 __fixsfdi
@ 2002-11-04 16:55 Ulrich Weigand
2002-11-04 17:54 ` Alan Modra
0 siblings, 1 reply; 5+ messages in thread
From: Ulrich Weigand @ 2002-11-04 16:55 UTC (permalink / raw)
To: amodra; +Cc: geoffk, gcc-patches
Alan Modra wrote:
> * defaults.h (FLOAT_FIX_BOUND_OVERFLOW): Define
> (FLOAT_FIX_NANS_TO_ZERO): Define.
Hmm, I just noticed that. I guess this would allow me to get
rid of the weird hack that is s390/fixdfdi.h ...
Bye,
Ulrich
--
Dr. Ulrich Weigand
weigand@informatik.uni-erlangen.de
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2002-11-05 1:54 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
[not found] <20021005002244.H25369@bubble.sa.bigpond.net.au>
2002-10-04 11:49 ` libgcc2 __fixsfdi Geoff Keating
2002-10-04 18:41 ` Alan Modra
[not found] ` <jmhef4pwnq.fsf@desire.geoffk.org>
2002-11-04 16:33 ` Alan Modra
2002-11-04 16:55 Ulrich Weigand
2002-11-04 17:54 ` Alan Modra
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).