summaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog.wide-int1
-rw-r--r--gcc/tree-core.h10
-rw-r--r--gcc/tree.c8
-rw-r--r--gcc/tree.h12
-rw-r--r--gcc/wide-int.h3
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) \