This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [wide-int] Make the main tree decompose cheaper
- From: Richard Biener <rguenther at suse dot de>
- To: Richard Sandiford <rdsandiford at googlemail dot com>
- Cc: zadeck at naturalbridge dot com, mikestump at comcast dot net, gcc-patches at gcc dot gnu dot org
- Date: Thu, 24 Oct 2013 10:43:41 +0200 (CEST)
- Subject: Re: [wide-int] Make the main tree decompose cheaper
- Authentication-results: sourceware.org; auth=none
- References: <877gd34rmr dot fsf at talisman dot default>
On Wed, 23 Oct 2013, Richard Sandiford wrote:
> This patch stores two array lengths in an INTEGER_CST: the length that
> should be used when accessing the constant in its TYPE_PRECISION,
> and the one that should be used for wider precisions. This means that
> the main tree decompose routine is just a simple storage_ref constructor.
> It also means that cst_fits_shwi_p can be simplified back to its earlier
> form (before r203602).
>
> The patch also fixes wi::extended_tree <N>::get_len so that it uses
> the right length when a tree has the same precision as addr_wide_int.
> I just noticed this by inspection, I don't have a testcase.
>
> (It might be better to require "address" trees to be smaller than
> addr_wide_int though -- I can look into that if you agree. But just
> changing:
>
> gcc_checking_assert (TYPE_PRECISION (TREE_TYPE (t)) <= N);
>
> to:
>
> gcc_checking_assert (TYPE_PRECISION (TREE_TYPE (t)) < N);
>
> did trigger when I tried it in the first version of the wi::address patch.)
>
> Tested on powerpc64-linux-gnu. OK for wide-int?
I like how this simplifies code, still storing two lengths is a bit
odd ... ah well.
Minor nits:
+ /* Make sure no one is clobbering the shared constant. We
+ must be careful here because tree-csts and wide-ints are
+ not canonicalized in the same way. */
+ gcc_assert (TREE_TYPE (t) == type);
+ gcc_assert (TREE_INT_CST_NUNITS (t) == 1);
+ gcc_assert (TREE_INT_CST_EXT_NUNITS (t) == 1);
+ gcc_assert (TREE_INT_CST_ELT (t, 0) == hwi);
please merge into a single gcc_assert.
> + /* The number of HOST_WIDE_INTs in an INTEGER_CST. */
> + struct {
> + /* The number of HOST_WIDE_INTs if the INTEGER_CST is accessed in
> + its native precision. */
> + unsigned short unextended;
> +
> + /* The number of HOST_WIDE_INTs if the INTEGER_CST is extended to
> + wider precisions based on its TYPE_SIGN. */
> + unsigned short extended;
> + } split_length;
split_length sounds generic while unextended and extended not. I suggest
to either rename split_length to something clearly integer constant
specific or renaming unextended and extended to length1 and length2.
Otherwise ok.
Thanks,
Richard.
> Thanks,
> Richard
>
>
> Index: gcc/c-family/c-common.c
> ===================================================================
> --- gcc/c-family/c-common.c 2013-10-23 17:43:03.339574704 +0100
> +++ gcc/c-family/c-common.c 2013-10-23 17:43:21.593731522 +0100
> @@ -5463,7 +5463,7 @@ c_common_nodes_and_builtins (void)
> }
>
> /* This node must not be shared. */
> - void_zero_node = make_int_cst (1);
> + void_zero_node = make_int_cst (1, 1);
> TREE_TYPE (void_zero_node) = void_type_node;
>
> void_list_node = build_void_list_node ();
> @@ -5674,7 +5674,7 @@ c_common_nodes_and_builtins (void)
>
> /* Create the built-in __null node. It is important that this is
> not shared. */
> - null_node = make_int_cst (1);
> + null_node = make_int_cst (1, 1);
> TREE_TYPE (null_node) = c_common_type_for_size (POINTER_SIZE, 0);
>
> /* Since builtin_types isn't gc'ed, don't export these nodes. */
> Index: gcc/lto-streamer-out.c
> ===================================================================
> --- gcc/lto-streamer-out.c 2013-10-23 17:42:54.691500411 +0100
> +++ gcc/lto-streamer-out.c 2013-10-23 17:43:05.853596301 +0100
> @@ -712,6 +712,7 @@ #define visit(SIBLING) \
> {
> int i;
> v = iterative_hash_host_wide_int (TREE_INT_CST_NUNITS (t), v);
> + v = iterative_hash_host_wide_int (TREE_INT_CST_EXT_NUNITS (t), v);
> for (i = 0; i < TREE_INT_CST_NUNITS (t); i++)
> v = iterative_hash_host_wide_int (TREE_INT_CST_ELT (t, i), v);
> }
> Index: gcc/tree-core.h
> ===================================================================
> --- gcc/tree-core.h 2013-10-23 17:42:54.691500411 +0100
> +++ gcc/tree-core.h 2013-10-23 17:48:33.634415070 +0100
> @@ -741,12 +741,25 @@ struct GTY(()) tree_base {
> of the field must be large enough to hold addr_space_t values. */
> unsigned address_space : 8;
> } bits;
> +
> /* The following fields are present in tree_base to save space. The
> nodes using them do not require any of the flags above and so can
> make better use of the 4-byte sized word. */
> - /* VEC length. This field is only used with TREE_VEC and
> - TREE_INT_CST. */
> +
> + /* The number of HOST_WIDE_INTs in an INTEGER_CST. */
> + struct {
> + /* The number of HOST_WIDE_INTs if the INTEGER_CST is accessed in
> + its native precision. */
> + unsigned short unextended;
> +
> + /* The number of HOST_WIDE_INTs if the INTEGER_CST is extended to
> + wider precisions based on its TYPE_SIGN. */
> + unsigned short extended;
> + } split_length;
> +
> + /* VEC length. This field is only used with TREE_VEC. */
> int length;
> +
> /* SSA version number. This field is only used with SSA_NAME. */
> unsigned int version;
> } GTY((skip(""))) u;
> Index: gcc/tree-streamer-in.c
> ===================================================================
> --- gcc/tree-streamer-in.c 2013-10-23 17:42:54.691500411 +0100
> +++ gcc/tree-streamer-in.c 2013-10-23 19:46:18.512517370 +0100
> @@ -147,7 +147,7 @@ unpack_ts_base_value_fields (struct bitp
> unpack_ts_int_cst_value_fields (struct bitpack_d *bp, tree expr)
> {
> int i;
> - for (i = 0; i < TREE_INT_CST_NUNITS (expr); i++)
> + for (i = 0; i < TREE_INT_CST_EXT_NUNITS (expr); i++)
> TREE_INT_CST_ELT (expr, i) = bp_unpack_var_len_int (bp);
> }
>
> @@ -571,8 +571,8 @@ streamer_alloc_tree (struct lto_input_bl
> else if (CODE_CONTAINS_STRUCT (code, TS_INT_CST))
> {
> unsigned HOST_WIDE_INT len = streamer_read_uhwi (ib);
> - result = make_int_cst (len);
> - TREE_INT_CST_NUNITS (result) = len;
> + unsigned HOST_WIDE_INT ext_len = streamer_read_uhwi (ib);
> + result = make_int_cst (len, ext_len);
> }
> else if (code == CALL_EXPR)
> {
> Index: gcc/tree-streamer-out.c
> ===================================================================
> --- gcc/tree-streamer-out.c 2013-10-23 17:42:54.691500411 +0100
> +++ gcc/tree-streamer-out.c 2013-10-23 22:06:08.864297213 +0100
> @@ -124,7 +124,7 @@ pack_ts_int_cst_value_fields (struct bit
> int i;
> /* Note that the number of elements has already been written out in
> streamer_write_tree_header. */
> - for (i = 0; i < TREE_INT_CST_NUNITS (expr); i++)
> + for (i = 0; i < TREE_INT_CST_EXT_NUNITS (expr); i++)
> bp_pack_var_len_int (bp, TREE_INT_CST_ELT (expr, i));
> }
>
> @@ -962,8 +962,9 @@ streamer_write_tree_header (struct outpu
> streamer_write_uhwi (ob, call_expr_nargs (expr));
> else if (CODE_CONTAINS_STRUCT (code, TS_INT_CST))
> {
> - gcc_assert (TREE_INT_CST_NUNITS (expr));
> - streamer_write_uhwi (ob, TREE_INT_CST_NUNITS (expr));
> + gcc_checking_assert (TREE_INT_CST_NUNITS (expr));
> + streamer_write_uhwi (ob, TREE_INT_CST_NUNITS (expr));
> + streamer_write_uhwi (ob, TREE_INT_CST_EXT_NUNITS (expr));
> }
> }
>
> @@ -979,6 +980,10 @@ streamer_write_integer_cst (struct outpu
> gcc_assert (!TREE_OVERFLOW (cst));
> streamer_write_record_start (ob, LTO_integer_cst);
> stream_write_tree (ob, TREE_TYPE (cst), ref_p);
> + /* We're effectively streaming a non-sign-extended wide_int here,
> + so there's no need to stream TREE_INT_CST_EXT_NUNITS or any
> + array members beyond LEN. We'll recreate the tree from the
> + wide_int and the type. */
> streamer_write_uhwi (ob, len);
> for (i = 0; i < len; i++)
> streamer_write_hwi (ob, TREE_INT_CST_ELT (cst, i));
> Index: gcc/tree.c
> ===================================================================
> --- gcc/tree.c 2013-10-23 17:42:54.691500411 +0100
> +++ gcc/tree.c 2013-10-23 21:27:23.241475405 +0100
> @@ -559,7 +559,7 @@ init_ttree (void)
> int_cst_hash_table = htab_create_ggc (1024, int_cst_hash_hash,
> int_cst_hash_eq, NULL);
>
> - int_cst_node = make_int_cst (1);
> + int_cst_node = make_int_cst (1, 1);
>
> cl_option_hash_table = htab_create_ggc (64, cl_option_hash_hash,
> cl_option_hash_eq, NULL);
> @@ -759,7 +759,7 @@ tree_size (const_tree node)
> {
> case INTEGER_CST:
> return (sizeof (struct tree_int_cst)
> - + (TREE_INT_CST_NUNITS (node) - 1) * sizeof (HOST_WIDE_INT));
> + + (TREE_INT_CST_EXT_NUNITS (node) - 1) * sizeof (HOST_WIDE_INT));
>
> case TREE_BINFO:
> return (offsetof (struct tree_binfo, base_binfos)
> @@ -1083,6 +1083,53 @@ copy_list (tree list)
> }
>
>
> +/* Return the value that TREE_INT_CST_EXT_NUNITS should have for an
> + INTEGER_CST with value CST and type TYPE. */
> +
> +static unsigned int
> +get_int_cst_ext_nunits (tree type, const wide_int &cst)
> +{
> + gcc_checking_assert (cst.get_precision () == TYPE_PRECISION (type));
> + /* We need an extra zero HWI if CST is an unsigned integer with its
> + upper bit set, and if CST occupies a whole number of HWIs. */
> + if (TYPE_UNSIGNED (type)
> + && wi::neg_p (cst)
> + && (cst.get_precision () % HOST_BITS_PER_WIDE_INT) == 0)
> + return cst.get_precision () / HOST_BITS_PER_WIDE_INT + 1;
> + return cst.get_len ();
> +}
> +
> +/* Return a new INTEGER_CST with value CST and type TYPE. */
> +
> +static tree
> +build_new_int_cst (tree type, const wide_int &cst)
> +{
> + unsigned int len = cst.get_len ();
> + unsigned int ext_len = get_int_cst_ext_nunits (type, cst);
> + tree nt = make_int_cst (len, ext_len);
> +
> + if (len < ext_len)
> + {
> + --ext_len;
> + TREE_INT_CST_ELT (nt, ext_len) = 0;
> + for (unsigned int i = len; i < ext_len; ++i)
> + TREE_INT_CST_ELT (nt, i) = -1;
> + }
> + else if (TYPE_UNSIGNED (type)
> + && cst.get_precision () < len * HOST_BITS_PER_WIDE_INT)
> + {
> + len--;
> + TREE_INT_CST_ELT (nt, len)
> + = zext_hwi (cst.elt (len),
> + cst.get_precision () % HOST_BITS_PER_WIDE_INT);
> + }
> +
> + for (unsigned int i = 0; i < len; i++)
> + TREE_INT_CST_ELT (nt, i) = cst.elt (i);
> + TREE_TYPE (nt) = type;
> + return nt;
> +}
> +
> /* Create an INT_CST node with a LOW value sign extended to TYPE. */
>
> tree
> @@ -1148,20 +1195,7 @@ force_fit_type (tree type, const wide_in
> || (overflowable > 0 && sign == SIGNED))
> {
> wide_int tmp = wide_int::from (cst, TYPE_PRECISION (type), sign);
> - int l = tmp.get_len ();
> - tree t = make_int_cst (l);
> - if (l > 1)
> - {
> - if (tmp.elt (l - 1) == 0)
> - gcc_assert (tmp.elt (l - 2) < 0);
> - if (tmp.elt (l - 1) == (HOST_WIDE_INT) -1)
> - gcc_assert (tmp.elt (l - 2) >= 0);
> - }
> -
> - for (int i = 0; i < l; i++)
> - TREE_INT_CST_ELT (t, i) = tmp.elt (i);
> -
> - TREE_TYPE (t) = type;
> + tree t = build_new_int_cst (type, tmp);
> TREE_OVERFLOW (t) = 1;
> return t;
> }
> @@ -1199,7 +1233,8 @@ int_cst_hash_eq (const void *x, const vo
> const_tree const yt = (const_tree) y;
>
> if (TREE_TYPE (xt) != TREE_TYPE (yt)
> - || TREE_INT_CST_NUNITS (xt) != TREE_INT_CST_NUNITS (yt))
> + || TREE_INT_CST_NUNITS (xt) != TREE_INT_CST_NUNITS (yt)
> + || TREE_INT_CST_EXT_NUNITS (xt) != TREE_INT_CST_EXT_NUNITS (yt))
> return false;
>
> for (int i = 0; i < TREE_INT_CST_NUNITS (xt); i++)
> @@ -1223,7 +1258,6 @@ wide_int_to_tree (tree type, const wide_
> tree t;
> int ix = -1;
> int limit = 0;
> - unsigned int i;
>
> gcc_assert (type);
> unsigned int prec = TYPE_PRECISION (type);
> @@ -1240,11 +1274,7 @@ wide_int_to_tree (tree type, const wide_
> }
>
> wide_int cst = wide_int::from (pcst, prec, sgn);
> - unsigned int len = cst.get_len ();
> - unsigned int small_prec = prec & (HOST_BITS_PER_WIDE_INT - 1);
> - bool recanonize = sgn == UNSIGNED
> - && small_prec
> - && (prec + HOST_BITS_PER_WIDE_INT - 1) / HOST_BITS_PER_WIDE_INT == len;
> + unsigned int ext_len = get_int_cst_ext_nunits (type, cst);
>
> switch (TREE_CODE (type))
> {
> @@ -1314,74 +1344,60 @@ wide_int_to_tree (tree type, const wide_
> gcc_unreachable ();
> }
>
> - if (ix >= 0)
> + if (ext_len == 1)
> {
> - /* Look for it in the type's vector of small shared ints. */
> - if (!TYPE_CACHED_VALUES_P (type))
> + /* We just need to store a single HOST_WIDE_INT. */
> + HOST_WIDE_INT hwi;
> + if (TYPE_UNSIGNED (type))
> + hwi = cst.to_uhwi ();
> + else
> + hwi = cst.to_shwi ();
> + if (ix >= 0)
> {
> - TYPE_CACHED_VALUES_P (type) = 1;
> - TYPE_CACHED_VALUES (type) = make_tree_vec (limit);
> - }
> + /* Look for it in the type's vector of small shared ints. */
> + if (!TYPE_CACHED_VALUES_P (type))
> + {
> + TYPE_CACHED_VALUES_P (type) = 1;
> + TYPE_CACHED_VALUES (type) = make_tree_vec (limit);
> + }
>
> - t = TREE_VEC_ELT (TYPE_CACHED_VALUES (type), ix);
> - if (t)
> - {
> - /* Make sure no one is clobbering the shared constant. We
> - must be careful here because tree-csts and wide-ints are
> - not canonicalized in the same way. */
> - gcc_assert (TREE_TYPE (t) == type);
> - gcc_assert (TREE_INT_CST_NUNITS (t) == (int)len);
> - if (recanonize)
> + t = TREE_VEC_ELT (TYPE_CACHED_VALUES (type), ix);
> + if (t)
> {
> - len--;
> - gcc_assert (sext_hwi (TREE_INT_CST_ELT (t, len), small_prec)
> - == cst.elt (len));
> + /* Make sure no one is clobbering the shared constant. We
> + must be careful here because tree-csts and wide-ints are
> + not canonicalized in the same way. */
> + gcc_assert (TREE_TYPE (t) == type);
> + gcc_assert (TREE_INT_CST_NUNITS (t) == 1);
> + gcc_assert (TREE_INT_CST_EXT_NUNITS (t) == 1);
> + gcc_assert (TREE_INT_CST_ELT (t, 0) == hwi);
> }
> - for (i = 0; i < len; i++)
> - gcc_assert (TREE_INT_CST_ELT (t, i) == cst.elt (i));
> - }
> - else
> - {
> - /* Create a new shared int. */
> - t = make_int_cst (cst.get_len ());
> - TREE_INT_CST_NUNITS (t) = len;
> - if (recanonize)
> + else
> {
> - len--;
> - TREE_INT_CST_ELT (t, len) = zext_hwi (cst.elt (len), small_prec);
> + /* Create a new shared int. */
> + t = build_new_int_cst (type, cst);
> + TREE_VEC_ELT (TYPE_CACHED_VALUES (type), ix) = t;
> }
> - for (i = 0; i < len; i++)
> - TREE_INT_CST_ELT (t, i) = cst.elt (i);
> - TREE_TYPE (t) = type;
> -
> - TREE_VEC_ELT (TYPE_CACHED_VALUES (type), ix) = t;
> }
> - }
> - else if (cst.get_len () == 1
> - && (TYPE_SIGN (type) == SIGNED
> - || recanonize
> - || cst.elt (0) >= 0))
> - {
> - /* 99.99% of all int csts will fit in a single HWI. Do that one
> - efficiently. */
> - /* Use the cache of larger shared ints. */
> - void **slot;
> -
> - if (recanonize)
> - TREE_INT_CST_ELT (int_cst_node, 0) = zext_hwi (cst.elt (0), small_prec);
> else
> - TREE_INT_CST_ELT (int_cst_node, 0) = cst.elt (0);
> - TREE_TYPE (int_cst_node) = type;
> -
> - slot = htab_find_slot (int_cst_hash_table, int_cst_node, INSERT);
> - t = (tree) *slot;
> - if (!t)
> {
> - /* Insert this one into the hash table. */
> - t = int_cst_node;
> - *slot = t;
> - /* Make a new node for next time round. */
> - int_cst_node = make_int_cst (1);
> + /* Use the cache of larger shared ints, using int_cst_node as
> + a temporary. */
> + void **slot;
> +
> + TREE_INT_CST_ELT (int_cst_node, 0) = hwi;
> + TREE_TYPE (int_cst_node) = type;
> +
> + slot = htab_find_slot (int_cst_hash_table, int_cst_node, INSERT);
> + t = (tree) *slot;
> + if (!t)
> + {
> + /* Insert this one into the hash table. */
> + t = int_cst_node;
> + *slot = t;
> + /* Make a new node for next time round. */
> + int_cst_node = make_int_cst (1, 1);
> + }
> }
> }
> else
> @@ -1390,32 +1406,8 @@ wide_int_to_tree (tree type, const wide_
> for the gc to take care of. There will not be enough of them
> to worry about. */
> void **slot;
> - tree nt;
> - if (!recanonize
> - && TYPE_SIGN (type) == UNSIGNED
> - && cst.elt (len - 1) < 0)
> - {
> - unsigned int blocks_needed
> - = (prec + HOST_BITS_PER_WIDE_INT - 1) / HOST_BITS_PER_WIDE_INT;
> -
> - nt = make_int_cst (blocks_needed + 1);
> - for (i = len; i < blocks_needed; i++)
> - TREE_INT_CST_ELT (nt, i) = (HOST_WIDE_INT)-1;
> -
> - TREE_INT_CST_ELT (nt, blocks_needed) = 0;
> - }
> - else
> - nt = make_int_cst (len);
> - if (recanonize)
> - {
> - len--;
> - TREE_INT_CST_ELT (nt, len) = zext_hwi (cst.elt (len), small_prec);
> - }
> -
> - for (i = 0; i < len; i++)
> - TREE_INT_CST_ELT (nt, i) = cst.elt (i);
> - TREE_TYPE (nt) = type;
>
> + tree nt = build_new_int_cst (type, cst);
> slot = htab_find_slot (int_cst_hash_table, nt, INSERT);
> t = (tree) *slot;
> if (!t)
> @@ -2028,10 +2020,10 @@ build_case_label (tree low_value, tree h
> /* Build a newly constructed INETEGER_CST node of length LEN. */
>
> tree
> -make_int_cst_stat (int len MEM_STAT_DECL)
> +make_int_cst_stat (int len, int ext_len MEM_STAT_DECL)
> {
> tree t;
> - int length = (len - 1) * sizeof (tree) + sizeof (struct tree_int_cst);
> + int length = (ext_len - 1) * sizeof (tree) + sizeof (struct tree_int_cst);
>
> gcc_assert (len);
> record_node_allocation_statistics (INTEGER_CST, length);
> @@ -2040,6 +2032,7 @@ make_int_cst_stat (int len MEM_STAT_DECL
>
> TREE_SET_CODE (t, INTEGER_CST);
> TREE_INT_CST_NUNITS (t) = len;
> + TREE_INT_CST_EXT_NUNITS (t) = ext_len;
>
> TREE_CONSTANT (t) = 1;
>
> @@ -10658,18 +10651,16 @@ widest_int_cst_value (const_tree x)
>
> #if HOST_BITS_PER_WIDEST_INT > HOST_BITS_PER_WIDE_INT
> gcc_assert (HOST_BITS_PER_WIDEST_INT >= HOST_BITS_PER_DOUBLE_INT);
> - gcc_assert (TREE_INT_CST_NUNITS (x) <= 2
> - || (TREE_INT_CST_NUNITS (x) == 3 && TREE_INT_CST_ELT (x, 2) == 0));
> + gcc_assert (TREE_INT_CST_NUNITS (x) == 2);
>
> if (TREE_INT_CST_NUNITS (x) == 1)
> - val = ((HOST_WIDEST_INT)val << HOST_BITS_PER_WIDE_INT) >> HOST_BITS_PER_WIDE_INT;
> + val = HOST_WIDE_INT (val);
> else
> val |= (((unsigned HOST_WIDEST_INT) TREE_INT_CST_ELT (x, 1))
> << HOST_BITS_PER_WIDE_INT);
> #else
> /* Make sure the sign-extended value will fit in a HOST_WIDE_INT. */
> - gcc_assert (TREE_INT_CST_NUNITS (x) == 1
> - || (TREE_INT_CST_NUNITS (x) == 2 && TREE_INT_CST_ELT (x, 1) == 0));
> + gcc_assert (TREE_INT_CST_NUNITS (x) == 1);
> #endif
>
> if (bits < HOST_BITS_PER_WIDEST_INT)
> Index: gcc/tree.def
> ===================================================================
> --- gcc/tree.def 2013-10-23 17:43:03.340574712 +0100
> +++ gcc/tree.def 2013-10-23 21:35:09.182917109 +0100
> @@ -257,16 +257,24 @@ DEFTREECODE (LANG_TYPE, "lang_type", tcc
>
> /* First, the constants. */
>
> -/* Contents are in an array of HOST_WIDE_INTS. The array may be as
> - wide as the precision requires but may be shorter when all of the
> - upper bits are sign bits. The length of the array is given in
> - TREE_INT_CST_NUNITS and each element can be obtained using
> - TREE_INT_CST_ELT. INTEGER_CST nodes can be shared, and therefore
> - should be considered read only. They should be copied, before
> - setting a flag such as TREE_OVERFLOW. If an INTEGER_CST has
> - TREE_OVERFLOW already set, it is known to be unique. INTEGER_CST
> - nodes are created for the integral types, for pointer types and for
> - vector and float types in some circumstances. */
> +/* Contents are in an array of HOST_WIDE_INTs.
> +
> + We often access these constants both in their native precision and
> + in wider precisions (with the constant being implicitly extended
> + according to TYPE_SIGN). In each case, the useful part of the array
> + may be as wide as the precision requires but may be shorter when all
> + of the upper bits are sign bits. The length of the array when accessed
> + in the constant's native precision is given by TREE_INT_CST_NUNITS.
> + The length of the array when accessed in wider precisions is given
> + by TREE_INT_CST_EXT_NUNITS. Each element can be obtained using
> + TREE_INT_CST_ELT.
> +
> + INTEGER_CST nodes can be shared, and therefore should be considered
> + read only. They should be copied before setting a flag such as
> + TREE_OVERFLOW. If an INTEGER_CST has TREE_OVERFLOW already set,
> + it is known to be unique. INTEGER_CST nodes are created for the
> + integral types, for pointer types and for vector and float types in
> + some circumstances. */
> DEFTREECODE (INTEGER_CST, "integer_cst", tcc_constant, 0)
>
> /* Contents are in TREE_REAL_CST field. */
> Index: gcc/tree.h
> ===================================================================
> --- gcc/tree.h 2013-10-23 17:42:54.691500411 +0100
> +++ gcc/tree.h 2013-10-23 17:43:05.857596336 +0100
> @@ -883,7 +883,10 @@ #define INT_CST_LT(A, B) \
> #define INT_CST_LT_UNSIGNED(A, B) \
> (wi::ltu_p (A, B))
>
> -#define TREE_INT_CST_NUNITS(NODE) (INTEGER_CST_CHECK (NODE)->base.u.length)
> +#define TREE_INT_CST_NUNITS(NODE) \
> + (INTEGER_CST_CHECK (NODE)->base.u.split_length.unextended)
> +#define TREE_INT_CST_EXT_NUNITS(NODE) \
> + (INTEGER_CST_CHECK (NODE)->base.u.split_length.extended)
> #define TREE_INT_CST_ELT(NODE, I) TREE_INT_CST_ELT_CHECK (NODE, I)
>
> #define TREE_REAL_CST_PTR(NODE) (REAL_CST_CHECK (NODE)->real_cst.real_cst_ptr)
> @@ -2862,8 +2865,9 @@ tree_int_cst_elt_check (const_tree __t,
> {
> if (TREE_CODE (__t) != INTEGER_CST)
> tree_check_failed (__t, __f, __l, __g, INTEGER_CST, 0);
> - if (__i < 0 || __i >= __t->base.u.length)
> - tree_int_cst_elt_check_failed (__i, __t->base.u.length, __f, __l, __g);
> + if (__i < 0 || __i >= __t->base.u.split_length.extended)
> + tree_int_cst_elt_check_failed (__i, __t->base.u.split_length.extended,
> + __f, __l, __g);
> return &CONST_CAST_TREE (__t)->int_cst.val[__i];
> }
>
> @@ -2873,8 +2877,9 @@ tree_int_cst_elt_check (tree __t, int __
> {
> if (TREE_CODE (__t) != INTEGER_CST)
> tree_check_failed (__t, __f, __l, __g, INTEGER_CST, 0);
> - if (__i < 0 || __i >= __t->base.u.length)
> - tree_int_cst_elt_check_failed (__i, __t->base.u.length, __f, __l, __g);
> + if (__i < 0 || __i >= __t->base.u.split_length.extended)
> + tree_int_cst_elt_check_failed (__i, __t->base.u.split_length.extended,
> + __f, __l, __g);
> return &CONST_CAST_TREE (__t)->int_cst.val[__i];
> }
>
> @@ -3111,7 +3116,7 @@ omp_clause_elt_check (const_tree __t, in
>
> /* Checks that X is integer constant that can be expressed in signed
> HOST_WIDE_INT without loss of precision. This function differs
> - from the tree_fits_* versions in that the type of signedness of the
> + from the tree_fits_* versions in that the signedness of the
> type of X is not considered. */
>
> static inline bool
> @@ -3120,13 +3125,12 @@ cst_fits_shwi_p (const_tree x)
> if (TREE_CODE (x) != INTEGER_CST)
> return false;
>
> - return TREE_INT_CST_NUNITS (x) == 1
> - || (TREE_INT_CST_NUNITS (x) == 2 && TREE_INT_CST_ELT (x, 1) == 0);
> + return TREE_INT_CST_NUNITS (x) == 1;
> }
>
> /* Checks that X is integer constant that can be expressed in signed
> HOST_WIDE_INT without loss of precision. This function differs
> - from the tree_fits_* versions in that the type of signedness of the
> + from the tree_fits_* versions in that the signedness of the
> type of X is not considered. */
>
> static inline bool
> @@ -3580,8 +3584,9 @@ #define make_tree_binfo(t) make_tree_bin
>
> /* Make a INTEGER_CST. */
>
> -extern tree make_int_cst_stat (int MEM_STAT_DECL);
> -#define make_int_cst(t) make_int_cst_stat (t MEM_STAT_INFO)
> +extern tree make_int_cst_stat (int, int MEM_STAT_DECL);
> +#define make_int_cst(LEN, EXT_LEN) \
> + make_int_cst_stat (LEN, EXT_LEN MEM_STAT_INFO)
>
> /* Make a TREE_VEC. */
>
> @@ -5291,24 +5296,8 @@ wi::int_traits <const_tree>::get_precisi
> wi::int_traits <const_tree>::decompose (HOST_WIDE_INT *,
> unsigned int precision, const_tree x)
> {
> - unsigned int len = TREE_INT_CST_NUNITS (x);
> - const HOST_WIDE_INT *val = (const HOST_WIDE_INT *) &TREE_INT_CST_ELT (x, 0);
> - unsigned int max_len = ((precision + HOST_BITS_PER_WIDE_INT - 1)
> - / HOST_BITS_PER_WIDE_INT);
> -
> - gcc_checking_assert (precision == get_precision (x));
> -
> - /* If an unsigned constant occupies a whole number of HWIs and has the
> - upper bit set, its representation includes an extra zero HWI,
> - so that the representation can be used for wider precisions.
> - Trim the length if we're accessing the tree in its own precision. */
> - if (__builtin_expect (len > max_len, 0))
> - do
> - len--;
> - while (len > 1 && val[len - 1] == -1 && val[len - 2] < 0);
> -
> - /* Signed and the rest of the unsigned cases are easy. */
> - return wi::storage_ref (val, len, precision);
> + return wi::storage_ref (&TREE_INT_CST_ELT (x, 0), TREE_INT_CST_NUNITS (x),
> + precision);
> }
>
> inline generic_wide_int <wi::extended_tree <MAX_BITSIZE_MODE_ANY_INT> >
> @@ -5348,7 +5337,11 @@ wi::extended_tree <N>::get_val () const
> inline unsigned int
> wi::extended_tree <N>::get_len () const
> {
> - return TREE_INT_CST_NUNITS (m_t);
> + if (N == MAX_BITSIZE_MODE_ANY_INT
> + || N > TYPE_PRECISION (TREE_TYPE (m_t)))
> + return TREE_INT_CST_EXT_NUNITS (m_t);
> + else
> + return TREE_INT_CST_NUNITS (m_t);
> }
>
> namespace wi
>
>
--
Richard Biener <rguenther@suse.de>
SUSE / SUSE Labs
SUSE LINUX Products GmbH - Nuernberg - AG Nuernberg - HRB 16746
GF: Jeff Hawn, Jennifer Guild, Felix Imend