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