Patchwork wide-int branch now up for public comment and review

login
register
mail settings
Submitter Mike Stump
Date Aug. 29, 2013, 7:22 p.m.
Message ID <7A01F437-449D-4F23-B002-7132AA6350CD@comcast.net>
Download mbox | patch
Permalink /patch/270896/
State New
Headers show

Comments

Mike Stump - Aug. 29, 2013, 7:22 p.m.
On Aug 29, 2013, at 12:36 AM, Richard Biener <rguenther@suse.de> wrote:
> On Wed, 28 Aug 2013, Mike Stump wrote:
> 
>> On Aug 28, 2013, at 3:22 AM, Richard Biener <rguenther@suse.de> wrote:
>>> Btw, rtl.h still wastes space with
>>> 
>>> struct GTY((variable_size)) hwivec_def {
>>> int num_elem;         /* number of elements */
>>> HOST_WIDE_INT elem[1];
>>> };
>>> 
>>> struct GTY((chain_next ("RTX_NEXT (&%h)"),
>>>           chain_prev ("RTX_PREV (&%h)"), variable_size)) rtx_def {
>>> ...
>>> /* The first element of the operands of this rtx.
>>>    The number of operands and their types are controlled
>>>    by the `code' field, according to rtl.def.  */
>>> union u {
>>>   rtunion fld[1];
>>>   HOST_WIDE_INT hwint[1];
>>>   struct block_symbol block_sym;
>>>   struct real_value rv;
>>>   struct fixed_value fv;
>>>   struct hwivec_def hwiv;
>>> } GTY ((special ("rtx_def"), desc ("GET_CODE (&%0)"))) u;
>>> };
>>> 
>>> there are 32bits available before the union.  If you don't use
>>> those for num_elem then all wide-ints will at least take as
>>> much space as DOUBLE_INTs originally took - and large ints
>>> that would have required DOUBLE_INTs in the past will now
>>> require more space than before.  Which means your math
>>> motivating the 'num_elem' encoding stuff is wrong.  With
>>> moving 'num_elem' before u you can even re-use the hwint
>>> field in the union as the existing double-int code does
>>> (which in fact could simply do the encoding trick in the
>>> old CONST_DOUBLE scheme, similar for the tree INTEGER_CST
>>> container).
>> 
>> So, HOST_WIDE_INT is likely 64 bits, and likely is 64 bit aligned.  The 
>> base (stuff before the union) is 32 bits.  There is a 32 bit gap, even 
>> if not used before the HOST_WIDE_INT elem.  We place the num_elem is 
>> this gap.
> 
> No, you don't.  You place num_elem 64bit aligned _after_ the gap.
> And you have another 32bit gap, as you say, before elem.

Ah, ok, I get it, thanks for the explanation.  This removes the second gap creator and puts the field into the gap before the u union.
Richard Guenther - Aug. 30, 2013, 8:45 a.m.
On Thu, 29 Aug 2013, Mike Stump wrote:

> On Aug 29, 2013, at 12:36 AM, Richard Biener <rguenther@suse.de> wrote:
> > On Wed, 28 Aug 2013, Mike Stump wrote:
> > 
> >> On Aug 28, 2013, at 3:22 AM, Richard Biener <rguenther@suse.de> wrote:
> >>> Btw, rtl.h still wastes space with
> >>> 
> >>> struct GTY((variable_size)) hwivec_def {
> >>> int num_elem;         /* number of elements */
> >>> HOST_WIDE_INT elem[1];
> >>> };
> >>> 
> >>> struct GTY((chain_next ("RTX_NEXT (&%h)"),
> >>>           chain_prev ("RTX_PREV (&%h)"), variable_size)) rtx_def {
> >>> ...
> >>> /* The first element of the operands of this rtx.
> >>>    The number of operands and their types are controlled
> >>>    by the `code' field, according to rtl.def.  */
> >>> union u {
> >>>   rtunion fld[1];
> >>>   HOST_WIDE_INT hwint[1];
> >>>   struct block_symbol block_sym;
> >>>   struct real_value rv;
> >>>   struct fixed_value fv;
> >>>   struct hwivec_def hwiv;
> >>> } GTY ((special ("rtx_def"), desc ("GET_CODE (&%0)"))) u;
> >>> };
> >>> 
> >>> there are 32bits available before the union.  If you don't use
> >>> those for num_elem then all wide-ints will at least take as
> >>> much space as DOUBLE_INTs originally took - and large ints
> >>> that would have required DOUBLE_INTs in the past will now
> >>> require more space than before.  Which means your math
> >>> motivating the 'num_elem' encoding stuff is wrong.  With
> >>> moving 'num_elem' before u you can even re-use the hwint
> >>> field in the union as the existing double-int code does
> >>> (which in fact could simply do the encoding trick in the
> >>> old CONST_DOUBLE scheme, similar for the tree INTEGER_CST
> >>> container).
> >> 
> >> So, HOST_WIDE_INT is likely 64 bits, and likely is 64 bit aligned.  The 
> >> base (stuff before the union) is 32 bits.  There is a 32 bit gap, even 
> >> if not used before the HOST_WIDE_INT elem.  We place the num_elem is 
> >> this gap.
> > 
> > No, you don't.  You place num_elem 64bit aligned _after_ the gap.
> > And you have another 32bit gap, as you say, before elem.
> 
> Ah, ok, I get it, thanks for the explanation.  This removes the second 
> gap creator and puts the field into the gap before the u union.

 struct GTY((variable_size)) hwivec_def {
-  int num_elem;		/* number of elements */
   HOST_WIDE_INT elem[1];
 };

no need to wrap this in an extra struct type.  In fact you can
re-use the hwint member and its accessors in

  union u {
    rtunion fld[1];
    HOST_WIDE_INT hwint[1];
    struct block_symbol block_sym;
    struct real_value rv;
    struct fixed_value fv;
  } GTY ((special ("rtx_def"), desc ("GET_CODE (&%0)"))) u;

Richard.

Patch

diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c
index ce40347..143f298 100644
--- a/gcc/emit-rtl.c
+++ b/gcc/emit-rtl.c
@@ -594,7 +594,7 @@  immed_wide_int_const (const wide_int &v, enum machine_mode mode)
     /* It is so tempting to just put the mode in here.  Must control
        myself ... */
     PUT_MODE (value, VOIDmode);
-    HWI_PUT_NUM_ELEM (CONST_WIDE_INT_VEC (value), len);
+    CWI_PUT_NUM_ELEM (value, len);
 
     for (i = 0; i < len; i++)
       CONST_WIDE_INT_ELT (value, i) = v.elt (i);
diff --git a/gcc/print-rtl.c b/gcc/print-rtl.c
index 3620bd6..8dad9f6 100644
--- a/gcc/print-rtl.c
+++ b/gcc/print-rtl.c
@@ -616,7 +616,7 @@  print_rtx (const_rtx in_rtx)
     case CONST_WIDE_INT:
       if (! flag_simple)
 	fprintf (outfile, " ");
-      hwivec_output_hex (outfile, CONST_WIDE_INT_VEC (in_rtx));
+      cwi_output_hex (outfile, in_rtx);
       break;
 #endif
 
diff --git a/gcc/read-rtl.c b/gcc/read-rtl.c
index 707ef3f..c198b5b 100644
--- a/gcc/read-rtl.c
+++ b/gcc/read-rtl.c
@@ -1352,7 +1352,6 @@  read_rtx_code (const char *code_name)
       read_name (&name);
       validate_const_wide_int (name.string);
       {
-	hwivec hwiv;
 	const char *s = name.string;
 	int len;
 	int index = 0;
@@ -1377,7 +1376,6 @@  read_rtx_code (const char *code_name)
 
 	return_rtx = const_wide_int_alloc (wlen);
 
-	hwiv = CONST_WIDE_INT_VEC (return_rtx);
 	while (pos > 0)
 	  {
 #if HOST_BITS_PER_WIDE_INT == 64
@@ -1385,13 +1383,13 @@  read_rtx_code (const char *code_name)
 #else
 	    sscanf (s + pos, "%8" HOST_WIDE_INT_PRINT "x", &wi);
 #endif
-	    XHWIVEC_ELT (hwiv, index++) = wi;
+	    CWI_ELT (return_rtx, index++) = wi;
 	    pos -= gs;
 	  }
 	strncpy (buf, s, gs - pos);
 	buf [gs - pos] = 0;
 	sscanf (buf, "%" HOST_WIDE_INT_PRINT "x", &wi);
-	XHWIVEC_ELT (hwiv, index++) = wi;
+	CWI_ELT (return_rtx, index++) = wi;
 	/* TODO: After reading, do we want to canonicalize with:
 	   value = lookup_const_wide_int (value); ? */
       }
diff --git a/gcc/rtl.c b/gcc/rtl.c
index 074e425..b913d0d 100644
--- a/gcc/rtl.c
+++ b/gcc/rtl.c
@@ -225,18 +225,18 @@  rtx_alloc_stat (RTX_CODE code MEM_STAT_DECL)
   return rtx_alloc_stat_v (code PASS_MEM_STAT, 0);
 }
 
-/* Write the wide constant OP0 to OUTFILE.  */
+/* Write the wide constant X to OUTFILE.  */
 
 void
-hwivec_output_hex (FILE *outfile, const_hwivec op0)
+cwi_output_hex (FILE *outfile, const_rtx x)
 {
-  int i = HWI_GET_NUM_ELEM (op0);
+  int i = CWI_GET_NUM_ELEM (x);
   gcc_assert (i > 0);
-  if (XHWIVEC_ELT (op0, i-1) == 0)
+  if (CWI_ELT (x, i-1) == 0)
     fprintf (outfile, "0x");
-  fprintf (outfile, HOST_WIDE_INT_PRINT_HEX, XHWIVEC_ELT (op0, --i));
+  fprintf (outfile, HOST_WIDE_INT_PRINT_HEX, CWI_ELT (x, --i));
   while (--i >= 0)
-    fprintf (outfile, HOST_WIDE_INT_PRINT_PADDED_HEX, XHWIVEC_ELT (op0, i));
+    fprintf (outfile, HOST_WIDE_INT_PRINT_PADDED_HEX, CWI_ELT (x, i));
 }
 
 
@@ -843,12 +843,12 @@  rtl_check_failed_block_symbol (const char *file, int line, const char *func)
 
 /* XXX Maybe print the vector?  */
 void
-hwivec_check_failed_bounds (const_hwivec r, int n, const char *file, int line,
-			    const char *func)
+cwi_check_failed_bounds (const_rtx x, int n, const char *file, int line,
+			 const char *func)
 {
   internal_error
     ("RTL check: access of hwi elt %d of vector with last elt %d in %s, at %s:%d",
-     n, GET_NUM_ELEM (r) - 1, func, trim_filename (file), line);
+     n, CWI_GET_NUM_ELEM (x) - 1, func, trim_filename (file), line);
 }
 
 /* XXX Maybe print the vector?  */
diff --git a/gcc/rtl.h b/gcc/rtl.h
index 6b45b41..a218ee9 100644
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -252,12 +252,14 @@  struct GTY(()) object_block {
 };
 
 struct GTY((variable_size)) hwivec_def {
-  int num_elem;		/* number of elements */
   HOST_WIDE_INT elem[1];
 };
 
-#define HWI_GET_NUM_ELEM(HWIVEC)	((HWIVEC)->num_elem)
-#define HWI_PUT_NUM_ELEM(HWIVEC, NUM)	((HWIVEC)->num_elem = (NUM))
+/* Number of elements of the HWIVEC if RTX is a CONST_WIDE_INT.  */
+#define CWI_GET_NUM_ELEM(RTX)					\
+  ((int)RTL_FLAG_CHECK1("CWI_GET_NUM_ELEM", (RTX), CONST_WIDE_INT)->u2.num_elem)
+#define CWI_PUT_NUM_ELEM(RTX, NUM)					\
+  (RTL_FLAG_CHECK1("CWI_PUT_NUM_ELEM", (RTX), CONST_WIDE_INT)->u2.num_elem = (NUM))
 
 /* RTL expression ("rtx").  */
 
@@ -345,6 +347,14 @@  struct GTY((chain_next ("RTX_NEXT (&%h)"),
      1 in a VALUE or DEBUG_EXPR is NO_LOC_P in var-tracking.c.  */
   unsigned return_val : 1;
 
+  union {
+    /* RTXs are free to use up to 32 bit from here.  */
+
+    /* In a CONST_WIDE_INT (aka hwivec_def), this is the number of HOST_WIDE_INTs
+       in the hwivec_def.  */
+    unsigned  GTY ((tag ("CONST_WIDE_INT"))) num_elem:32;
+  } GTY ((desc ("GET_CODE (&%0)"))) u2;
+
   /* The first element of the operands of this rtx.
      The number of operands and their types are controlled
      by the `code' field, according to rtl.def.  */
@@ -643,12 +653,14 @@  equality.  */
 			       __FUNCTION__);				\
      &_rtx->u.hwint[_n]; }))
 
-#define XHWIVEC_ELT(HWIVEC, I) __extension__				\
-(*({ __typeof (HWIVEC) const _hwivec = (HWIVEC); const int _i = (I);	\
-     if (_i < 0 || _i >= HWI_GET_NUM_ELEM (_hwivec))			\
-       hwivec_check_failed_bounds (_hwivec, _i, __FILE__, __LINE__,	\
-				  __FUNCTION__);			\
-     &_hwivec->elem[_i]; }))
+#define CWI_ELT(RTX, I) __extension__					\
+(*({ __typeof (RTX) const _rtx = (RTX);					\
+     int _max = CWI_GET_NUM_ELEM (_rtx);				\
+     const int _i = (I);						\
+     if (_i < 0 || _i >= _max)						\
+       cwi_check_failed_bounds (_rtx, _i, __FILE__, __LINE__,	\
+				__FUNCTION__);				\
+     &_rtx->u.hwiv.elem[_i]; }))
 
 #define XCWINT(RTX, N, C) __extension__					\
 (*({ __typeof (RTX) const _rtx = (RTX);					\
@@ -711,8 +723,8 @@  extern void rtl_check_failed_code_mode (const_rtx, enum rtx_code, enum machine_m
     ATTRIBUTE_NORETURN;
 extern void rtl_check_failed_block_symbol (const char *, int, const char *)
     ATTRIBUTE_NORETURN;
-extern void hwivec_check_failed_bounds (const_hwivec, int, const char *, int,
-					const char *)
+extern void cwi_check_failed_bounds (const_rtx, int, const char *, int,
+				     const char *)
     ATTRIBUTE_NORETURN;
 extern void rtvec_check_failed_bounds (const_rtvec, int, const char *, int,
 				       const char *)
@@ -726,7 +738,7 @@  extern void rtvec_check_failed_bounds (const_rtvec, int, const char *, int,
 #define RTL_CHECKC2(RTX, N, C1, C2) ((RTX)->u.fld[N])
 #define RTVEC_ELT(RTVEC, I)	    ((RTVEC)->elem[I])
 #define XWINT(RTX, N)		    ((RTX)->u.hwint[N])
-#define XHWIVEC_ELT(HWIVEC, I)	    ((HWIVEC)->elem[I])
+#define CWI_ELT(RTX, I)		    ((RTX)->u.hwiv.elem[I])
 #define XCWINT(RTX, N, C)	    ((RTX)->u.hwint[N])
 #define XCMWINT(RTX, N, C, M)	    ((RTX)->u.hwint[N])
 #define XCNMWINT(RTX, N, C, M)	    ((RTX)->u.hwint[N])
@@ -1223,8 +1235,8 @@  rhs_regno (const_rtx x)
    CONST_WIDE_INT_ELT gets one of the elements.  0 is the least
    significant HOST_WIDE_INT.  */
 #define CONST_WIDE_INT_VEC(RTX) HWIVEC_CHECK (RTX, CONST_WIDE_INT)
-#define CONST_WIDE_INT_NUNITS(RTX) HWI_GET_NUM_ELEM (CONST_WIDE_INT_VEC (RTX))
-#define CONST_WIDE_INT_ELT(RTX, N) XHWIVEC_ELT (CONST_WIDE_INT_VEC (RTX), N) 
+#define CONST_WIDE_INT_NUNITS(RTX) CWI_GET_NUM_ELEM (RTX)
+#define CONST_WIDE_INT_ELT(RTX, N) CWI_ELT (RTX, N)
 
 /* For a CONST_DOUBLE:
 #if TARGET_SUPPORTS_WIDE_INT == 0
@@ -1982,7 +1994,7 @@  extern void end_sequence (void);
 #if TARGET_SUPPORTS_WIDE_INT == 0
 extern double_int rtx_to_double_int (const_rtx);
 #endif
-extern void hwivec_output_hex (FILE *, const_hwivec);
+extern void cwi_output_hex (FILE *, const_rtx);
 #ifndef GENERATOR_FILE
 extern rtx immed_wide_int_const (const wide_int &cst, enum machine_mode mode);
 #endif