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 <rguent...@suse.de> SUSE / SUSE Labs SUSE LINUX Products GmbH - Nuernberg - AG Nuernberg - HRB 16746 GF: Jeff Hawn, Jennifer Guild, Felix Imend