From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 1771 invoked by alias); 22 Feb 2006 00:20:36 -0000 Received: (qmail 1754 invoked by uid 22791); 22 Feb 2006 00:20:33 -0000 X-Spam-Check-By: sourceware.org Received: from atrey.karlin.mff.cuni.cz (HELO atrey.karlin.mff.cuni.cz) (195.113.31.123) by sourceware.org (qpsmtpd/0.31) with ESMTP; Wed, 22 Feb 2006 00:20:28 +0000 Received: by atrey.karlin.mff.cuni.cz (Postfix, from userid 29025) id 6EF194B425D; Wed, 22 Feb 2006 01:20:25 +0100 (CET) Date: Wed, 22 Feb 2006 00:20:00 -0000 From: Zdenek Dvorak To: Richard Henderson , Roger Sayle , Paolo Bonzini , gcc-patches@gcc.gnu.org Subject: Re: Patch ping Message-ID: <20060222002025.GA23636@atrey.karlin.mff.cuni.cz> References: <20060221091531.GA26781@atrey.karlin.mff.cuni.cz> <20060221154317.GA27569@atrey.karlin.mff.cuni.cz> <20060221180114.GA16778@redhat.com> <20060221230437.GA4783@atrey.karlin.mff.cuni.cz> <20060221231555.GA18756@redhat.com> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20060221231555.GA18756@redhat.com> User-Agent: Mutt/1.5.9i 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/msg01733.txt.bz2 Hello, > On Wed, Feb 22, 2006 at 12:04:37AM +0100, Zdenek Dvorak wrote: > > If w <= HOST_BITS_PER_WIDE_INT, the functions returns just CONST_INT, not > > CONST_DOUBLE. In this case, rule (b) -- filling bits above w with s -- > > is used. > > Yep. > > > Suppose now w > HOST_BITS_PER_WIDE_INT. If i1 == 0 and i0 >=0, or > > i1 == -1 and i1 < 0, we return CONST_INT for i0, anyway. > > Sure. It saves memory. > > > Otherwise, the components i0 and i1 are put into the constant unchanged. > > Note that there exists no rtl mode for which w > HBPWI and w < 2*HBPWI. > That is, if w > HBPWI, then w == 2*HBPWI. So the point you're trying to > make here doesn't actually apply, so rule (b) continues to hold. ehm... immed_double_const would really need clean up, and pruning of completely missleading comments... I will send patch once it passes testing. Anyway, here is the patch for double_ints with rule (b). Zdenek * 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. (doubleint.o): Add. Index: gengtype.c =================================================================== *** gengtype.c (revision 111309) --- gengtype.c (working copy) *************** main(int ARG_UNUSED (argc), char ** ARG_ *** 3037,3042 **** --- 3037,3043 ---- do_scalar_typedef ("CUMULATIVE_ARGS", &pos); do_scalar_typedef ("REAL_VALUE_TYPE", &pos); + do_scalar_typedef ("double_int", &pos); do_scalar_typedef ("uint8", &pos); do_scalar_typedef ("jword", &pos); do_scalar_typedef ("JCF_u2", &pos); Index: tree.h =================================================================== *** tree.h (revision 111309) --- tree.h (working copy) *************** extern void omp_clause_range_check_faile *** 1239,1251 **** struct tree_int_cst GTY(()) { struct tree_common common; ! /* A sub-struct is necessary here because the function `const_hash' ! wants to scan both words as a unit and taking the address of the ! sub-struct yields the properly inclusive bounded pointer. */ ! struct tree_int_cst_lowhi { ! unsigned HOST_WIDE_INT low; ! HOST_WIDE_INT high; ! } int_cst; }; /* In a REAL_CST node. struct real_value is an opaque entity, with --- 1239,1245 ---- struct tree_int_cst GTY(()) { struct tree_common common; ! double_int int_cst; }; /* In a REAL_CST node. struct real_value is an opaque entity, with Index: doubleint.c =================================================================== *** doubleint.c (revision 0) --- doubleint.c (revision 0) *************** *** 0 **** --- 1,298 ---- + /* Operations with long integers. + Copyright (C) 2006 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 2, or (at your option) any + later version. + + GCC is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with GCC; see the file COPYING. If not, write to the Free + Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. */ + + #include "config.h" + #include "system.h" + #include "coretypes.h" + #include "tm.h" + #include "tree.h" + + /* Restricts constant CST to the precision given by MASK. */ + + static inline double_int + restrict_cst_to_precision (double_int mask, double_int cst) + { + double_int r; + bool negative; + unsigned HOST_WIDE_INT sbit, snum; + + /* Copy the sign bit to the bits outside of mask. */ + if (DI_HIGH (mask)) + { + sbit = (DI_HIGH (mask) >> 1) + 1; + snum = DI_HIGH (cst); + } + else + { + sbit = (DI_LOW (mask) >> 1) + 1; + snum = DI_LOW (cst); + } + negative = (snum & sbit) != 0; + + if (negative) + { + DI_LOW_SET (r, DI_LOW (cst) | ~DI_LOW (mask)); + DI_HIGH_SET (r, DI_HIGH (cst) | ~DI_HIGH (mask)); + } + else + { + DI_LOW_SET (r, DI_LOW (cst) & DI_LOW (mask)); + DI_HIGH_SET (r, DI_HIGH (cst) & DI_HIGH (mask)); + } + + return r; + } + + /* Zeros bits of CST outside of MASK. */ + + static inline double_int + zero_excess_bits (double_int mask, double_int cst) + { + double_int r; + + DI_LOW_SET (r, DI_LOW (cst) & DI_LOW (mask)); + DI_HIGH_SET (r, DI_HIGH (cst) & DI_HIGH (mask)); + + return r; + } + + /* Constructs double_int from tree CST. */ + + double_int + tree_to_double_int (tree cst) + { + tree type = TREE_TYPE (cst); + double_int mask = double_int_mask (TYPE_PRECISION (type)); + return restrict_cst_to_precision (mask, TREE_INT_CST (cst)); + } + + /* Returns true if X fits in HOST_WIDE_INT. */ + + bool + double_int_fits_in_hwi_p (double_int x) + { + return ((DI_HIGH (x) == 0 && (HOST_WIDE_INT) DI_LOW (x) >= 0) + || (DI_HIGH (x) == ALL_ONES && (HOST_WIDE_INT) DI_LOW (x) < 0)); + } + + /* Returns true if X fits in unsigned HOST_WIDE_INT. */ + + bool + double_int_fits_in_unsigned_hwi_p (double_int x) + { + return DI_HIGH (x) == 0; + } + + /* Returns true if SCALE is negative. */ + + bool + double_int_negative_p (double_int scale) + { + return (HOST_WIDE_INT) DI_HIGH (scale) < 0; + } + + /* Returns value of X as a signed number. X must satisfy + double_int_fits_in_hwi_p. */ + + HOST_WIDE_INT + double_int_to_hwi (double_int x) + { + return DI_LOW (x); + } + + /* Returns value of X as an unsigned number. X must satisfy + double_int_fits_in_unsigned_hwi_p. */ + + unsigned HOST_WIDE_INT + double_int_to_unsigned_hwi (double_int x) + { + return DI_LOW (x); + } + + /* Returns A * B, in precision given by MASK. */ + + double_int + double_int_mul (double_int mask, double_int a, double_int b) + { + unsigned HOST_WIDE_INT lo; + HOST_WIDE_INT hi; + double_int ret; + + mul_double (DI_LOW (a), DI_HIGH (a), + DI_LOW (b), DI_HIGH (b), &lo, &hi); + DI_LOW_SET (ret, lo); + DI_HIGH_SET (ret, hi); + + return restrict_cst_to_precision (mask, ret); + } + + /* Returns A + B, in precision given by MASK. */ + + double_int + double_int_add (double_int mask, double_int a, double_int b) + { + unsigned HOST_WIDE_INT lo; + HOST_WIDE_INT hi; + double_int ret; + + add_double (DI_LOW (a), DI_HIGH (a), + DI_LOW (b), DI_HIGH (b), &lo, &hi); + DI_LOW_SET (ret, lo); + DI_HIGH_SET (ret, hi); + + return restrict_cst_to_precision (mask, ret); + } + + /* Returns -A, in precision given by MASK. */ + + double_int + double_int_negate (double_int mask, double_int a) + { + unsigned HOST_WIDE_INT lo; + HOST_WIDE_INT hi; + double_int ret; + + neg_double (DI_LOW (a), DI_HIGH (a), &lo, &hi); + DI_LOW_SET (ret, lo); + DI_HIGH_SET (ret, hi); + + return restrict_cst_to_precision (mask, ret); + } + + /* Returns A / B (computed as unsigned in precision given by MASK, rounded + down). */ + + double_int + double_int_divide (double_int mask, double_int a, double_int b) + { + unsigned HOST_WIDE_INT lo, rem_lo; + HOST_WIDE_INT hi, rem_hi; + double_int ret; + + a = zero_excess_bits (mask, a); + b = zero_excess_bits (mask, b); + 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); + DI_LOW_SET (ret, lo); + DI_HIGH_SET (ret, hi); + + return restrict_cst_to_precision (mask, ret); + } + + /* Constructs tree in type TYPE from with value given by CST (precision of CST + is the same as the precision of TYPE). */ + + tree + double_int_to_tree (tree type, double_int cst) + { + unsigned HOST_WIDE_INT lo = DI_LOW (cst); + HOST_WIDE_INT hi = DI_HIGH (cst); + + if (TYPE_UNSIGNED (type)) + cst = zero_excess_bits (double_int_mask (TYPE_PRECISION (type)), cst); + return build_int_cst_wide (type, lo, hi); + } + + /* Returns true if A < B, unsigned comparison, in precision given by MASK. */ + + bool + double_int_smaller_p (double_int mask, double_int a, double_int b) + { + a = zero_excess_bits (mask, a); + b = zero_excess_bits (mask, b); + if (DI_HIGH (a) < DI_HIGH (b)) + return true; + if (DI_HIGH (a) > DI_HIGH (b)) + return false; + return DI_LOW (a) < DI_LOW (b); + } + + /* Splits last digit of *X (taken as unsigned in precision + of 2 * HOST_BITS_PER_WIDE_INT bits) in BASE and returns it. */ + + static unsigned + double_int_split_digit (double_int *x, unsigned base) + { + unsigned HOST_WIDE_INT resl, reml; + HOST_WIDE_INT resh, remh; + + div_and_round_double (FLOOR_DIV_EXPR, true, x->low, x->high, base, 0, + &resl, &resh, &reml, &remh); + x->high = resh; + x->low = resl; + + return reml; + } + + /* Dumps X (in precision given by MASK) to FILE. If SIGN is true, X is + considered to be signed. */ + + void + dump_double_int (FILE *file, double_int mask, double_int x, bool sign) + { + unsigned digits[100], n; + int i; + + if (double_int_zero_p (x)) + { + fprintf (file, "0"); + return; + } + + if (double_int_negative_p (x)) + { + if (sign) + { + fprintf (file, "-"); + x = double_int_negate (mask, x); + } + else + x = zero_excess_bits (mask, x); + } + + for (n = 0; !double_int_zero_p (x); n++) + digits[n] = double_int_split_digit (&x, 10); + for (i = n - 1; i >= 0; i--) + fprintf (file, "%u", digits[i]); + } + + /* Returns a MASK for precision of PREC bits. */ + + double_int + double_int_mask (unsigned prec) + { + double_int mask; + + if (prec > HOST_BITS_PER_WIDE_INT) + { + prec -= HOST_BITS_PER_WIDE_INT; + DI_HIGH_SET (mask, (((unsigned HOST_WIDE_INT) 2 << (prec - 1)) - 1)); + DI_LOW_SET (mask, ~(unsigned HOST_WIDE_INT) 0); + } + else + { + DI_HIGH_SET (mask, 0); + DI_LOW_SET (mask, (((unsigned HOST_WIDE_INT) 2 << (prec - 1)) - 1)); + } + + return mask; + } Index: doubleint.h =================================================================== *** doubleint.h (revision 0) --- doubleint.h (revision 0) *************** *** 0 **** --- 1,126 ---- + /* Operations with long integers. + Copyright (C) 2006 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 2, or (at your option) any + later version. + + GCC is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with GCC; see the file COPYING. If not, write to the Free + Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. */ + + #ifndef DOUBLE_INT_H + #define DOUBLE_INT_H + + /* 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. The bits outside of the precision of the number are + set to be equal to the sign bit, for compatibility with rtl + representation (and tree representation of numbers in signed types; + in unsigned ones, such bits are zeroed). */ + + 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)) + #define ALL_ONES (~((unsigned HOST_WIDE_INT) 0)) + + union tree_node; + + union tree_node *double_int_to_tree (union tree_node *, double_int); + double_int tree_to_double_int (union tree_node *tree); + bool double_int_fits_in_hwi_p (double_int); + HOST_WIDE_INT double_int_to_hwi (double_int); + bool double_int_fits_in_unsigned_hwi_p (double_int); + unsigned HOST_WIDE_INT double_int_to_unsigned_hwi (double_int); + double_int double_int_mul (double_int, double_int, double_int); + double_int double_int_add (double_int, double_int, double_int); + double_int double_int_negate (double_int, double_int); + double_int double_int_divide (double_int, double_int, double_int); + bool double_int_negative_p (double_int); + bool double_int_smaller_p (double_int, double_int, double_int); + void dump_double_int (FILE *, double_int, double_int, bool); + double_int double_int_mask (unsigned); + + /* Constructs double_int from integer CST. Note that this number may need to + be masked for a given precison in order to be valid. */ + + static inline double_int + hwi_to_double_int (HOST_WIDE_INT cst) + { + double_int r; + + DI_LOW_SET (r, cst); + DI_HIGH_SET (r, cst < 0 ? ALL_ONES : 0); + + return r; + } + + /* Constructs mask with all bits 1. */ + + static inline double_int + double_int_all (void) + { + double_int r; + + DI_LOW_SET (r, ALL_ONES); + DI_HIGH_SET (r, ALL_ONES); + + return r; + } + + /* Returns true if CST is zero. */ + + static inline bool + double_int_zero_p (double_int cst) + { + return DI_LOW (cst) == 0 && DI_HIGH (cst) == 0; + } + + /* Returns true if CST is one. */ + + static inline bool + double_int_one_p (double_int cst) + { + return DI_LOW (cst) == 1 && DI_HIGH (cst) == 0; + } + + /* Returns true if CST is minus one. */ + + static inline bool + double_int_minus_one_p (double_int cst) + { + return (DI_LOW (cst) == ALL_ONES && DI_HIGH (cst) == ALL_ONES); + } + + /* Returns true if CST1 == CST2. */ + + static inline bool + double_int_equal_p (double_int cst1, double_int cst2) + { + return DI_LOW (cst1) == DI_LOW (cst2) && DI_HIGH (cst1) == DI_HIGH (cst2); + } + + #endif /* DOUBLE_INT_H */ Index: system.h =================================================================== *** system.h (revision 111309) --- system.h (working copy) *************** extern void fancy_abort (const char *, i *** 609,614 **** --- 609,616 ---- # define FALSE false #endif /* !__cplusplus */ + /* Get definition of double_int. */ + #include "doubleint.h" /* Some compilers do not allow the use of unsigned char in bitfields. */ #define BOOL_BITFIELD unsigned int Index: Makefile.in =================================================================== *** Makefile.in (revision 111309) --- Makefile.in (working copy) *************** INSN_ATTR_H = insn-attr.h $(srcdir)/insn *** 773,779 **** C_COMMON_H = c-common.h $(SPLAY_TREE_H) $(CPPLIB_H) $(GGC_H) C_PRAGMA_H = c-pragma.h $(CPPLIB_H) C_TREE_H = c-tree.h $(C_COMMON_H) toplev.h $(DIAGNOSTIC_H) ! SYSTEM_H = system.h hwint.h $(srcdir)/../include/libiberty.h PREDICT_H = predict.h predict.def CPPLIB_H = $(srcdir)/../libcpp/include/line-map.h \ $(srcdir)/../libcpp/include/cpplib.h --- 773,779 ---- C_COMMON_H = c-common.h $(SPLAY_TREE_H) $(CPPLIB_H) $(GGC_H) C_PRAGMA_H = c-pragma.h $(CPPLIB_H) C_TREE_H = c-tree.h $(C_COMMON_H) toplev.h $(DIAGNOSTIC_H) ! SYSTEM_H = system.h hwint.h doubleint.h $(srcdir)/../include/libiberty.h PREDICT_H = predict.h predict.def CPPLIB_H = $(srcdir)/../libcpp/include/line-map.h \ $(srcdir)/../libcpp/include/cpplib.h *************** prefix.o: prefix.c $(CONFIG_H) $(SYSTEM_ *** 1779,1784 **** --- 1779,1786 ---- convert.o: convert.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \ $(FLAGS_H) convert.h toplev.h langhooks.h real.h + doubleint.o: doubleint.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) + langhooks.o : langhooks.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ $(TREE_H) toplev.h $(TREE_INLINE_H) $(RTL_H) insn-config.h $(INTEGRATE_H) \ langhooks.h $(LANGHOOKS_DEF_H) $(FLAGS_H) $(GGC_H) $(DIAGNOSTIC_H) intl.h \