From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 2557 invoked by alias); 8 Oct 2002 07:42:18 -0000 Mailing-List: contact gcc-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Archive: List-Post: List-Help: Sender: gcc-owner@gcc.gnu.org Received: (qmail 2548 invoked from network); 8 Oct 2002 07:42:17 -0000 Received: from unknown (HELO mta03bw.bigpond.com) (139.134.6.86) by sources.redhat.com with SMTP; 8 Oct 2002 07:42:17 -0000 Received: from bubble.local ([144.135.24.87]) by mta03bw.bigpond.com (Netscape Messaging Server 4.15 mta03bw Jul 16 2002 22:47:55) with SMTP id H3NK2E00.5T7 for ; Tue, 8 Oct 2002 17:42:14 +1000 Received: from CPE-144-136-184-138.sa.bigpond.net.au ([144.136.184.138]) by bwmam07.mailsvc.email.bigpond.com(MailRouter V3.0n 62/27168544); 08 Oct 2002 17:42:13 Received: (qmail 728 invoked by uid 179); 8 Oct 2002 07:42:13 -0000 Date: Tue, 08 Oct 2002 01:46:00 -0000 From: Alan Modra To: Richard Henderson , gcc@gcc.gnu.org Subject: Re: libgcc2 __fixsfdi Message-ID: <20021008171213.D979@bubble.sa.bigpond.net.au> Mail-Followup-To: Richard Henderson , gcc@gcc.gnu.org References: <20021005002244.H25369@bubble.sa.bigpond.net.au> <20021004190042.GD16257@redhat.com> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.2.5i In-Reply-To: <20021004190042.GD16257@redhat.com>; from rth@redhat.com on Fri, Oct 04, 2002 at 12:00:42PM -0700 X-SW-Source: 2002-10/txt/msg00453.txt.bz2 On Fri, Oct 04, 2002 at 12:00:42PM -0700, Richard Henderson wrote: > On Sat, Oct 05, 2002 at 12:22:44AM +0930, Alan Modra wrote: > > gcc's __fixsfdi function returns extremely surprising results for > > floats that overflow the range of DWtype. The integer value > > wraps rather than limiting to min/max values. > > Well, rather it crops to the unsigned max and then wraps. Yes, and that's probably the strongest argument I have for float -> int conversions to peg at signed max/min. If float -> unsigned peg at unsigned max, then it why not something similar for signed conversions? The following test gives some rather odd results for compile time conversions on i686-linux. int main (void) { #define BIGF 1.0e+30F printf ("%#llx, %#llx\n", (long long) -BIGF, (long long) BIGF); printf ("%#x, %#x\n", (int) -BIGF, (int) BIGF); return 0; } gcc-2.95.3 0x100000000, 0xffffffff00000000 0, 0 mainline without my patch 0x8000000000000000, 0x7fffffffffffffff 0, 0xffffffff mainline with patch 0x8000000000000000, 0x7fffffffffffffff 0x80000000, 0x7fffffff > Surprisingly, while implementing the new real.c, I found > that something in gcc relied on this. I forget what, > exactly, but if you change real_to_integer (which returns > a signed result) to crop to the maximum signed integer > (rather than wrapping), you'll get some test suite failures. Hmm, real_to_integer crops to max/min HOST_WIDE_INT. > I hadn't been interested in understanding why at the time. > But we should if we go making this sort of change, we should > be consistent between runtime and compiletime, which means > addressing this half-remembered failure. OK, I've addressed the consistency issue by the patch to fold-const.c. At least, this makes libgcc runtime consistent with compile time. We can't be consistent with everybody's fp hardware. :-( Bootstrapped and regression tested i686-linux and powerpc-linux. Also, a reminder that neither your or my fix to __floatdisf has been applied yet.. * fold-const.c (fold_convert): Overflowing float->int conversions clip to min/max int values. * libgcc2.c (__fixtfdi, __fixxfdi, __fixdfdi, __fixsfdi): Similarly. (__floatdisf): Properly cure double rounding. Index: gcc/fold-const.c =================================================================== RCS file: /cvs/gcc/gcc/gcc/fold-const.c,v retrieving revision 1.222 diff -u -p -r1.222 fold-const.c --- gcc/fold-const.c 22 Sep 2002 14:09:32 -0000 1.222 +++ gcc/fold-const.c 8 Oct 2002 04:57:27 -0000 @@ -1556,6 +1556,7 @@ fold_convert (t, arg1) REAL_VALUE_TYPE u; tree type1 = TREE_TYPE (arg1); int no_upper_bound; + HOST_WIDE_INT low, high; x = TREE_REAL_CST (arg1); l = real_value_from_int_cst (type1, TYPE_MIN_VALUE (type)); @@ -1573,17 +1574,27 @@ fold_convert (t, 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, x = dconst0; - else if (! (REAL_VALUES_LESS (l, x) - && !no_upper_bound - && REAL_VALUES_LESS (x, u))) - overflow = 1; - - { - HOST_WIDE_INT low, high; + { + overflow = 1; + low = 0; + high = 0; + } + else if (!REAL_VALUES_LESS (l, x)) + { + overflow = 1; + low = TREE_INT_CST_LOW (TYPE_MIN_VALUE (type)); + high = TREE_INT_CST_HIGH (TYPE_MIN_VALUE (type)); + } + else if (!no_upper_bound && !REAL_VALUES_LESS (x, u)) + { + overflow = 1; + low = TREE_INT_CST_LOW (TYPE_MAX_VALUE (type)); + high = TREE_INT_CST_HIGH (TYPE_MAX_VALUE (type)); + } + else REAL_VALUE_TO_INT (&low, &high, x); - t = build_int_2 (low, high); - } + + 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.149 diff -u -p -r1.149 libgcc2.c --- gcc/libgcc2.c 8 Sep 2002 12:47:26 -0000 1.149 +++ gcc/libgcc2.c 8 Oct 2002 04:57:29 -0000 @@ -864,12 +864,27 @@ __fixunstfDI (TFtype a) #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) - return - __fixunstfDI (-a); - return __fixunstfDI (a); + { + tmp = __fixunstfDI (-a); + tmp = -tmp; + if (tmp > 0) + tmp = -MAXDWtype - 1; + return tmp; + } + + tmp = __fixunstfDI (a); + if (tmp < 0) + tmp = MAXDWtype; + return tmp; } #endif @@ -906,12 +921,27 @@ __fixunsxfDI (XFtype a) #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) - return - __fixunsxfDI (-a); - return __fixunsxfDI (a); + { + tmp = __fixunsxfDI (-a); + tmp = -tmp; + if (tmp > 0) + tmp = -MAXDWtype - 1; + return tmp; + } + + tmp = __fixunsxfDI (a); + if (tmp < 0) + tmp = MAXDWtype; + return tmp; } #endif @@ -948,12 +978,27 @@ __fixunsdfDI (DFtype a) #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) - return - __fixunsdfDI (-a); - return __fixunsdfDI (a); + { + tmp = __fixunsdfDI (-a); + tmp = -tmp; + if (tmp > 0) + tmp = -MAXDWtype - 1; + return tmp; + } + + tmp = __fixunsdfDI (a); + if (tmp < 0) + tmp = MAXDWtype; + return tmp; } #endif @@ -994,12 +1039,27 @@ __fixunssfDI (SFtype original_a) #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) - return - __fixunssfDI (-a); - return __fixunssfDI (a); + { + tmp = __fixunssfDI (-a); + tmp = -tmp; + if (tmp > 0) + tmp = -MAXDWtype - 1; + return tmp; + } + + tmp = __fixunssfDI (a); + if (tmp < 0) + tmp = MAXDWtype; + return tmp; } #endif @@ -1091,7 +1151,10 @@ __floatdisf (DWtype u) && u < ((DWtype) 1 << DF_SIZE))) { if ((UDWtype) u & (REP_BIT - 1)) - u |= REP_BIT; + { + u &= ~ (REP_BIT - 1); + u |= REP_BIT; + } } } f = (Wtype) (u >> WORD_SIZE); -- Alan Modra IBM OzLabs - Linux Technology Centre