diff options
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog.wide-int | 1 | ||||
-rw-r--r-- | gcc/tree-core.h | 10 | ||||
-rw-r--r-- | gcc/tree.c | 8 | ||||
-rw-r--r-- | gcc/tree.h | 12 | ||||
-rw-r--r-- | gcc/wide-int.h | 3 |
5 files changed, 29 insertions, 5 deletions
diff --git a/gcc/ChangeLog.wide-int b/gcc/ChangeLog.wide-int index b633c2549d6..116f4546219 100644 --- a/gcc/ChangeLog.wide-int +++ b/gcc/ChangeLog.wide-int @@ -617,6 +617,7 @@ (TREE_INT_CST_HIGH): Delete. (TREE_INT_CST_NUNITS): New. (TREE_INT_CST_EXT_NUNITS): Likewise. + (TREE_INT_CST_OFFSET_NUNITS): Likewise. (TREE_INT_CST_ELT): Likewise. (INT_CST_LT): Use wide-int interfaces. (INT_CST_LE): New. diff --git a/gcc/tree-core.h b/gcc/tree-core.h index ef8bb370917..e31d9b38f23 100644 --- a/gcc/tree-core.h +++ b/gcc/tree-core.h @@ -764,11 +764,17 @@ struct GTY(()) tree_base { struct { /* The number of HOST_WIDE_INTs if the INTEGER_CST is accessed in its native precision. */ - unsigned short unextended; + unsigned char unextended; /* The number of HOST_WIDE_INTs if the INTEGER_CST is extended to wider precisions based on its TYPE_SIGN. */ - unsigned short extended; + unsigned char extended; + + /* The number of HOST_WIDE_INTs if the INTEGER_CST is accessed in + offset_int precision, with smaller integers being extended + according to their TYPE_SIGN. This is equal to one of the two + fields above but is cached for speed. */ + unsigned char offset; } int_length; /* VEC length. This field is only used with TREE_VEC. */ diff --git a/gcc/tree.c b/gcc/tree.c index 5803c1576e7..0196a32c4d1 100644 --- a/gcc/tree.c +++ b/gcc/tree.c @@ -1285,6 +1285,7 @@ wide_int_to_tree (tree type, const wide_int_ref &pcst) /* Make sure no one is clobbering the shared constant. */ gcc_checking_assert (TREE_TYPE (t) == type && TREE_INT_CST_NUNITS (t) == 1 + && TREE_INT_CST_OFFSET_NUNITS (t) == 1 && TREE_INT_CST_EXT_NUNITS (t) == 1 && TREE_INT_CST_ELT (t, 0) == hwi); else @@ -1964,6 +1965,13 @@ make_int_cst_stat (int len, int ext_len MEM_STAT_DECL) TREE_SET_CODE (t, INTEGER_CST); TREE_INT_CST_NUNITS (t) = len; TREE_INT_CST_EXT_NUNITS (t) = ext_len; + /* to_offset can only be applied to trees that are offset_int-sized + or smaller. EXT_LEN is correct if it fits, otherwise the constant + must be exactly the precision of offset_int and so LEN is correct. */ + if (ext_len <= OFFSET_INT_ELTS) + TREE_INT_CST_OFFSET_NUNITS (t) = ext_len; + else + TREE_INT_CST_OFFSET_NUNITS (t) = len; TREE_CONSTANT (t) = 1; diff --git a/gcc/tree.h b/gcc/tree.h index 3a3d5fb30e6..79e38afacf2 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -907,6 +907,8 @@ extern void omp_clause_range_check_failed (const_tree, const char *, int, (INTEGER_CST_CHECK (NODE)->base.u.int_length.unextended) #define TREE_INT_CST_EXT_NUNITS(NODE) \ (INTEGER_CST_CHECK (NODE)->base.u.int_length.extended) +#define TREE_INT_CST_OFFSET_NUNITS(NODE) \ + (INTEGER_CST_CHECK (NODE)->base.u.int_length.offset) #define TREE_INT_CST_ELT(NODE, I) TREE_INT_CST_ELT_CHECK (NODE, I) #define TREE_INT_CST_LOW(NODE) \ ((unsigned HOST_WIDE_INT) TREE_INT_CST_ELT (NODE, 0)) @@ -4623,11 +4625,15 @@ template <int N> inline unsigned int wi::extended_tree <N>::get_len () const { - if (N == MAX_BITSIZE_MODE_ANY_INT - || N > TYPE_PRECISION (TREE_TYPE (m_t))) + if (N == ADDR_MAX_PRECISION) + return TREE_INT_CST_OFFSET_NUNITS (m_t); + else if (N == MAX_BITSIZE_MODE_ANY_INT) return TREE_INT_CST_EXT_NUNITS (m_t); else - return TREE_INT_CST_NUNITS (m_t); + /* This class is designed to be used for specific output precisions + and needs to be as fast as possible, so there is no fallback for + other casees. */ + gcc_unreachable (); } namespace wi diff --git a/gcc/wide-int.h b/gcc/wide-int.h index cd6679164f9..08a90f39d17 100644 --- a/gcc/wide-int.h +++ b/gcc/wide-int.h @@ -256,6 +256,9 @@ along with GCC; see the file COPYING3. If not see #define ADDR_MAX_PRECISION \ ((ADDR_MAX_BITSIZE + 4 + HOST_BITS_PER_WIDE_INT - 1) & ~(HOST_BITS_PER_WIDE_INT - 1)) +/* The number of HWIs needed to store an offset_int. */ +#define OFFSET_INT_ELTS (ADDR_MAX_PRECISION / HOST_BITS_PER_WIDE_INT) + /* The type of result produced by a binary operation on types T1 and T2. Defined purely for brevity. */ #define WI_BINARY_RESULT(T1, T2) \ |