This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Add TREE_INT_CST_OFFSET_NUNITS


Richard Biener <richard.guenther@gmail.com> writes:
>>> Looking at the implementation it seems it would also work with
>>>
>>>    return MIN (TREE_INT_CST_EXT_NUNITS (m_t), N / HOST_BITS_PER_WIDE_INT);
>>
>> Yeah, the MIN in the patch was probably bogus sorry.  It only works
>> if we can assume that no bitsizetype will have ADDR_MAX_PRECISION
>> significant (non-sign) bits -- in particular that there's no such thing as
>> an all-1s _unsigned_ bitsizetype.  That might be true in practice given
>> the way we use offsets, but it isn't safe to generalise that to all N.
>>
>> A safer form would be:
>>
>>    if (ext_len > OFFSET_INT_ELTS)
>>      TREE_INT_CST_OFFSET_NUNITS (t) = len;
>>    else
>>      TREE_INT_CST_OFFSET_NUNITS (t) = ext_len;
>>
>> The reason the general form doesn't work for all N is because of the
>> compressed representation.  E.g. the example I gave a while ago about
>> a 256-bit all-1s unsigned number being { -1 } as a 256-bit number and
>> { -1, -1, -1, -1, 0 } as a 257+-bit number.
>>
>> But the point of the patch is to avoid any runtime checks here,
>> so the TYPE_PRECISION case is never actually used now.  I just kept
>> it around for completeness, since we'd been using it successfully so far.
>> I can put in a gcc_unreachable if you prefer.
>
> Yeah, I'd prefer a gcc_unreachable and a comment.

OK, how about this version?  Tested on x86_64-linux-gnu.

Thanks,
Richard


Index: gcc/ChangeLog.wide-int
===================================================================
--- gcc/ChangeLog.wide-int	2013-12-03 23:55:26.142873345 +0000
+++ gcc/ChangeLog.wide-int	2013-12-03 23:59:18.823744425 +0000
@@ -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.
Index: gcc/tree-core.h
===================================================================
--- gcc/tree-core.h	2013-12-03 23:55:26.142873345 +0000
+++ gcc/tree-core.h	2013-12-04 00:02:22.910222722 +0000
@@ -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.  */
Index: gcc/tree.c
===================================================================
--- gcc/tree.c	2013-12-03 23:55:26.142873345 +0000
+++ gcc/tree.c	2013-12-03 23:59:18.821744409 +0000
@@ -1285,6 +1285,7 @@ wide_int_to_tree (tree type, const wide_
 	    /* 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
   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;
 
Index: gcc/tree.h
===================================================================
--- gcc/tree.h	2013-12-03 23:55:26.142873345 +0000
+++ gcc/tree.h	2013-12-04 00:01:48.258944485 +0000
@@ -907,6 +907,8 @@ #define TREE_INT_CST_NUNITS(NODE) \
   (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 @@ wi::extended_tree <N>::get_val () const
 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
Index: gcc/wide-int.h
===================================================================
--- gcc/wide-int.h	2013-12-03 23:59:08.135658583 +0000
+++ gcc/wide-int.h	2013-12-03 23:59:18.823744425 +0000
@@ -256,6 +256,9 @@ #define ADDR_MAX_BITSIZE 64
 #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) \


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]