From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 768 invoked by alias); 21 Feb 2006 09:15:44 -0000 Received: (qmail 759 invoked by uid 22791); 21 Feb 2006 09:15:43 -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; Tue, 21 Feb 2006 09:15:37 +0000 Received: by atrey.karlin.mff.cuni.cz (Postfix, from userid 29025) id 81C3B4B4250; Tue, 21 Feb 2006 10:15:31 +0100 (CET) Date: Tue, 21 Feb 2006 09:15:00 -0000 From: Zdenek Dvorak To: Roger Sayle Cc: Paolo Bonzini , gcc-patches@gcc.gnu.org, rth@redhat.com Subject: Re: Patch ping Message-ID: <20060221091531.GA26781@atrey.karlin.mff.cuni.cz> References: <43F5A6BF.70206@lu.unisi.ch> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: 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/msg01678.txt.bz2 Hello, > > While I agree on the code duplication issues, on the other hand, I like > > the struct double_int much more than HOST_WIDE_INT pairs. > > > > Don't hold your breath, but if Zdenek's patch goes in I might work on > > using his struct double_int in fold-const.c as well. That's probably 4.3. > > Ok, I see a plan... > > The new double_int bears more than a passing similarity to tree.h's struct > tree_int_cst_lowhi. It looks like we already have a suitable double_int, > we're just not using it as the basis of our low-level arithmetic routines. > > Ok, Zdenek, it looks like the way to proceed is to break out all of > your new wrappers into their own doubleint.h and doubleint.c, and > to change tree.h:tree_int_cst.int_cst to be of type double_int as a > single preparatory patch. For compatability with the existing usage, > you'll probably want to keep the high word signed. Clearly these > prototypes don't belong in tree-affine.h, and I'd prefer to leave > hwint.h untouched so it can potentially be used in other projects > (generator programs?) without a hwint.c (i.e. like longlong.h). here is the proposed patch; bootstrapped & regtested on x86_64. 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.h. (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,288 ---- + /* 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" + + /* Constructs double_int from tree CST. */ + + double_int + tree_to_double_int (tree cst) + { + return TREE_INT_CST (cst); + } + + /* 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; + + DI_LOW_SET (r, DI_LOW (cst) & DI_LOW (mask)); + DI_HIGH_SET (r, DI_HIGH (cst) & DI_HIGH (mask)); + + return r; + } + + /* Returns true if X (whose precision is given by MASK) fits in + HOST_WIDE_INT. */ + + bool + double_int_fits_in_hwi_p (double_int mask, double_int x) + { + if (double_int_negative_p (mask, x)) + return DI_HIGH (x) == DI_HIGH (mask); + else + return DI_HIGH (x) == 0 && (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 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; + } + + /* Returns value of X, whose precision is given by MASK. X must satisfy + double_int_fits_in_hwi_p. */ + + HOST_WIDE_INT + double_int_to_hwi (double_int mask, double_int x) + { + if (DI_HIGH (mask) || !double_int_negative_p (mask, x)) + return DI_LOW (x); + else + return DI_LOW (x) | ~DI_LOW (mask); + } + + /* Returns value of X. 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, truncated so that it fits into 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, truncated so that it fits into 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, truncated so that it fits into 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, rounded down). */ + + double_int + double_int_divide (double_int a, double_int b) + { + unsigned HOST_WIDE_INT lo, rem_lo; + HOST_WIDE_INT hi, rem_hi; + double_int ret; + + 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 ret; + } + + /* Constructs tree in type TYPE from with value given by CST (precision of CST + is the same as the precision of TYPE -- in particular, it must satisfy + double_int_fits_to_type_p). */ + + 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); + unsigned prec = TYPE_PRECISION (type); + bool negative; + + if (prec > HOST_BITS_PER_WIDE_INT) + { + prec -= HOST_BITS_PER_WIDE_INT; + negative = (hi >> (prec - 1)) & 1; + if (negative) + hi |= (~(unsigned HOST_WIDE_INT) 0) << (prec - 1) << 1; + } + else + { + negative = (DI_LOW (cst) >> (prec - 1)) & 1; + if (negative) + { + lo |= (~(unsigned HOST_WIDE_INT) 0) << (prec - 1) << 1; + hi = ~(unsigned HOST_WIDE_INT) 0; + } + } + + return build_int_cst_wide (type, lo, hi); + } + + /* Returns true if VAL is smaller or equal to the maximal value + representable in TYPE. */ + + bool + double_int_fits_to_type_p (tree type, double_int val) + { + unsigned prec = TYPE_PRECISION (type); + double_int mask = double_int_mask (TYPE_UNSIGNED (type) ? prec : prec - 1); + + return (((DI_LOW (val) & DI_LOW (mask)) == DI_LOW (val)) + && ((DI_HIGH (val) & DI_HIGH (mask)) == DI_HIGH (val))); + } + + /* Returns true if A < B, unsigned comparison. */ + + bool + double_int_smaller_p (double_int a, double_int 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 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 (sign && double_int_negative_p (mask, x)) + { + fprintf (file, "-"); + x = double_int_negate (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,118 ---- + /* 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. */ + + 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)) + + union tree_node; + + union tree_node *double_int_to_tree (union tree_node *, double_int); + bool double_int_fits_to_type_p (union tree_node *, double_int); + double_int tree_to_double_int (union tree_node *tree); + bool double_int_fits_in_hwi_p (double_int, double_int); + HOST_WIDE_INT double_int_to_hwi (double_int, 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); + bool double_int_negative_p (double_int, double_int); + bool double_int_smaller_p (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. */ + + 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 ? ~(unsigned HOST_WIDE_INT) 0 : 0); + + return r; + } + + /* Constructs mask with all bits 1. */ + + static inline double_int + double_int_all (void) + { + return hwi_to_double_int (-1); + } + + /* 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 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)); + } + + /* 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 \