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? 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