On Wed, Dec 4, 2013 at 1:03 AM, Richard Sandiford <rdsandif...@googlemail.com> wrote: > Richard Biener <richard.guent...@gmail.com> writes: >>>> Looking at the implementation it seems it would also work with >>>> >>>> return MIN (TREE_INT_CST_EXT_NUNITS (m_t), N / HOST_BITS_PER_WIDE_INT); >>> >>> Yeah, the MIN in the patch was probably bogus sorry. It only works >>> if we can assume that no bitsizetype will have ADDR_MAX_PRECISION >>> significant (non-sign) bits -- in particular that there's no such thing as >>> an all-1s _unsigned_ bitsizetype. That might be true in practice given >>> the way we use offsets, but it isn't safe to generalise that to all N. >>> >>> A safer form would be: >>> >>> if (ext_len > OFFSET_INT_ELTS) >>> TREE_INT_CST_OFFSET_NUNITS (t) = len; >>> else >>> TREE_INT_CST_OFFSET_NUNITS (t) = ext_len; >>> >>> The reason the general form doesn't work for all N is because of the >>> compressed representation. E.g. the example I gave a while ago about >>> a 256-bit all-1s unsigned number being { -1 } as a 256-bit number and >>> { -1, -1, -1, -1, 0 } as a 257+-bit number. >>> >>> But the point of the patch is to avoid any runtime checks here, >>> so the TYPE_PRECISION case is never actually used now. I just kept >>> it around for completeness, since we'd been using it successfully so far. >>> I can put in a gcc_unreachable if you prefer. >> >> Yeah, I'd prefer a gcc_unreachable and a comment. > > OK, how about this version? Tested on x86_64-linux-gnu.
Ok. Thanks, Richard. > Thanks, > Richard > > > Index: gcc/ChangeLog.wide-int > =================================================================== > --- gcc/ChangeLog.wide-int 2013-12-03 23:55:26.142873345 +0000 > +++ gcc/ChangeLog.wide-int 2013-12-03 23:59:18.823744425 +0000 > @@ -617,6 +617,7 @@ > (TREE_INT_CST_HIGH): Delete. > (TREE_INT_CST_NUNITS): New. > (TREE_INT_CST_EXT_NUNITS): Likewise. > + (TREE_INT_CST_OFFSET_NUNITS): Likewise. > (TREE_INT_CST_ELT): Likewise. > (INT_CST_LT): Use wide-int interfaces. > (INT_CST_LE): New. > Index: gcc/tree-core.h > =================================================================== > --- gcc/tree-core.h 2013-12-03 23:55:26.142873345 +0000 > +++ gcc/tree-core.h 2013-12-04 00:02:22.910222722 +0000 > @@ -764,11 +764,17 @@ struct GTY(()) tree_base { > struct { > /* The number of HOST_WIDE_INTs if the INTEGER_CST is accessed in > its native precision. */ > - unsigned short unextended; > + unsigned char unextended; > > /* The number of HOST_WIDE_INTs if the INTEGER_CST is extended to > wider precisions based on its TYPE_SIGN. */ > - unsigned short extended; > + unsigned char extended; > + > + /* The number of HOST_WIDE_INTs if the INTEGER_CST is accessed in > + offset_int precision, with smaller integers being extended > + according to their TYPE_SIGN. This is equal to one of the two > + fields above but is cached for speed. */ > + unsigned char offset; > } int_length; > > /* VEC length. This field is only used with TREE_VEC. */ > Index: gcc/tree.c > =================================================================== > --- gcc/tree.c 2013-12-03 23:55:26.142873345 +0000 > +++ gcc/tree.c 2013-12-03 23:59:18.821744409 +0000 > @@ -1285,6 +1285,7 @@ wide_int_to_tree (tree type, const wide_ > /* Make sure no one is clobbering the shared constant. */ > gcc_checking_assert (TREE_TYPE (t) == type > && TREE_INT_CST_NUNITS (t) == 1 > + && TREE_INT_CST_OFFSET_NUNITS (t) == 1 > && TREE_INT_CST_EXT_NUNITS (t) == 1 > && TREE_INT_CST_ELT (t, 0) == hwi); > else > @@ -1964,6 +1965,13 @@ make_int_cst_stat (int len, int ext_len > TREE_SET_CODE (t, INTEGER_CST); > TREE_INT_CST_NUNITS (t) = len; > TREE_INT_CST_EXT_NUNITS (t) = ext_len; > + /* to_offset can only be applied to trees that are offset_int-sized > + or smaller. EXT_LEN is correct if it fits, otherwise the constant > + must be exactly the precision of offset_int and so LEN is correct. */ > + if (ext_len <= OFFSET_INT_ELTS) > + TREE_INT_CST_OFFSET_NUNITS (t) = ext_len; > + else > + TREE_INT_CST_OFFSET_NUNITS (t) = len; > > TREE_CONSTANT (t) = 1; > > Index: gcc/tree.h > =================================================================== > --- gcc/tree.h 2013-12-03 23:55:26.142873345 +0000 > +++ gcc/tree.h 2013-12-04 00:01:48.258944485 +0000 > @@ -907,6 +907,8 @@ #define TREE_INT_CST_NUNITS(NODE) \ > (INTEGER_CST_CHECK (NODE)->base.u.int_length.unextended) > #define TREE_INT_CST_EXT_NUNITS(NODE) \ > (INTEGER_CST_CHECK (NODE)->base.u.int_length.extended) > +#define TREE_INT_CST_OFFSET_NUNITS(NODE) \ > + (INTEGER_CST_CHECK (NODE)->base.u.int_length.offset) > #define TREE_INT_CST_ELT(NODE, I) TREE_INT_CST_ELT_CHECK (NODE, I) > #define TREE_INT_CST_LOW(NODE) \ > ((unsigned HOST_WIDE_INT) TREE_INT_CST_ELT (NODE, 0)) > @@ -4623,11 +4625,15 @@ wi::extended_tree <N>::get_val () const > inline unsigned int > wi::extended_tree <N>::get_len () const > { > - if (N == MAX_BITSIZE_MODE_ANY_INT > - || N > TYPE_PRECISION (TREE_TYPE (m_t))) > + if (N == ADDR_MAX_PRECISION) > + return TREE_INT_CST_OFFSET_NUNITS (m_t); > + else if (N == MAX_BITSIZE_MODE_ANY_INT) > return TREE_INT_CST_EXT_NUNITS (m_t); > else > - return TREE_INT_CST_NUNITS (m_t); > + /* This class is designed to be used for specific output precisions > + and needs to be as fast as possible, so there is no fallback for > + other casees. */ > + gcc_unreachable (); > } > > namespace wi > Index: gcc/wide-int.h > =================================================================== > --- gcc/wide-int.h 2013-12-03 23:59:08.135658583 +0000 > +++ gcc/wide-int.h 2013-12-03 23:59:18.823744425 +0000 > @@ -256,6 +256,9 @@ #define ADDR_MAX_BITSIZE 64 > #define ADDR_MAX_PRECISION \ > ((ADDR_MAX_BITSIZE + 4 + HOST_BITS_PER_WIDE_INT - 1) & > ~(HOST_BITS_PER_WIDE_INT - 1)) > > +/* The number of HWIs needed to store an offset_int. */ > +#define OFFSET_INT_ELTS (ADDR_MAX_PRECISION / HOST_BITS_PER_WIDE_INT) > + > /* The type of result produced by a binary operation on types T1 and T2. > Defined purely for brevity. */ > #define WI_BINARY_RESULT(T1, T2) \