From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 7722 invoked by alias); 21 Feb 2006 14:47:10 -0000 Received: (qmail 7713 invoked by uid 22791); 21 Feb 2006 14:47:09 -0000 X-Spam-Check-By: sourceware.org Received: from eyesopen.com (HELO www.eyesopen.com) (208.41.78.163) by sourceware.org (qpsmtpd/0.31) with ESMTP; Tue, 21 Feb 2006 14:47:06 +0000 Received: from localhost (roger@localhost) by www.eyesopen.com (8.11.6/8.11.6) with ESMTP id k1LEiGW16925; Tue, 21 Feb 2006 07:44:16 -0700 Date: Tue, 21 Feb 2006 14:47:00 -0000 From: Roger Sayle To: Zdenek Dvorak cc: Paolo Bonzini , , Subject: Re: Patch ping In-Reply-To: <20060221091531.GA26781@atrey.karlin.mff.cuni.cz> Message-ID: MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org X-SW-Source: 2006-02/txt/msg01683.txt.bz2 Hi Zdenek, On Tue, 21 Feb 2006, Zdenek Dvorak wrote: > > * gengtype.c (main): Handle double_int type. > * tree.h (struct tree_int_cst): Make type of int_cst double_int. > * doubleint.c: New file. > * doubleint.h: New file. > * system.h: Include doubleint.h. > * Makefile.in (SYSTEM_H): Include doubleint.h. > (doubleint.o): Add. Hmmm, not quite. > + /* A large integer. The precision of the represented number is between > + 1 and 2 * HOST_BITS_PER_WIDE_INT and it must be provided in each > + operation in form of mask that prescribes the significant bits > + (such mask is also double_int and can be obtained using > + double_int_mask). Signedness is only relevant for some operations > + (comparisons, division), in these cases the description of > + the function states whether the numbers are assumed to be signed > + or unsigned. */ > + > + typedef struct > + { > + unsigned HOST_WIDE_INT low; > + HOST_WIDE_INT high; /* High is signed for historical reasons (it replaces > + a similar structure that was used previously). It > + makes manipulation with the numbers more cumbersome, > + so it would be nice to change it. */ > + } double_int; > + #define DI_LOW(X) (X).low > + #define DI_HIGH(X) ((unsigned HOST_WIDE_INT) (X).high) > + #define DI_LOW_SET(X, L) ((X).low = (unsigned HOST_WIDE_INT) (L)) > + #define DI_HIGH_SET(X, L) ((X).high = (HOST_WIDE_INT) (L)) I believe that the last sixty years of digital computation have decisively shown the superiority of two's complement arithmetic for representing signed integers as binary, and convenient for interconversion with unsigned values. You should treat double_int like you would a TImode. For example, -1 should be represented by both the high an low words containing all one bits. + /* Returns true if CST is minus one in precision of MASK. */ + + static inline bool + double_int_minus_one_p (double_int mask, double_int cst) + { + return (DI_LOW (cst) == DI_LOW (mask) + && DI_HIGH (cst) == DI_HIGH (mask)); + } Then you wouldn't need a mask to test for minus one! + /* Returns true if SCALE is negative in precision of MASK. */ + + bool + double_int_negative_p (double_int mask, double_int scale) + { + if (DI_HIGH (mask)) + return (DI_HIGH (scale) & ~(DI_HIGH (mask) >> 1)) != 0; + else + return (DI_LOW (scale) & ~(DI_LOW (mask) >> 1)) != 0; + } And you wouldn't have to do pass in a mask to determine whether a value is negative. You would be able to implement a signed comparison, which is not so mysteriously missing from from your patch. But most importantly.... + mul_double (DI_LOW (a), DI_HIGH (a), + DI_LOW (b), DI_HIGH (b), &lo, &hi); ... + add_double (DI_LOW (a), DI_HIGH (a), + DI_LOW (b), DI_HIGH (b), &lo, &hi); ... + neg_double (DI_LOW (a), DI_HIGH (a), &lo, &hi); ... + div_and_round_double (FLOOR_DIV_EXPR, true, + DI_LOW (a), DI_HIGH (a), + DI_LOW (b), DI_HIGH (b), + &lo, &hi, &rem_lo, &rem_hi); You'll now get the correct results out of all of these routines, which assume the same sign-extended two's complement representation of integers as used in the rest of the compiler, and the vast majority of the rest of the planet. The most bizarre thing is that all of the code that you want/need to perform 2*HOST_WIDE_INT arithmetic is already in the compiler. Perhaps I'm thinking about this all wrong. Anyone whose done a first-year Computer Science course would be aware of my side of the argument above, and I'd hope its safe to say you'd be able to predict these objections. Maybe you could describe the benefits of your novel approach? Why not normalize mask to double_int_all, which allows values to be represented independently of their precision? Roger --