wide-int, gimple

Richard Sandiford rdsandiford@googlemail.com
Thu Nov 28 14:21:00 GMT 2013


Jakub Jelinek <jakub@redhat.com> writes:
> On Mon, Nov 25, 2013 at 12:24:30PM +0100, Richard Biener wrote:
>> On Sat, Nov 23, 2013 at 8:21 PM, Mike Stump <mikestump@comcast.net> wrote:
>> > Richi has asked the we break the wide-int patch so that the
>> > individual port and front end maintainers can review their parts
>> > without have to go through the entire patch.  This patch covers the
>> > gimple code.
>> 
>> @@ -1754,7 +1754,7 @@ dump_ssaname_info (pretty_printer *buffer, tree
>> node, int spc)
>>    if (!POINTER_TYPE_P (TREE_TYPE (node))
>>        && SSA_NAME_RANGE_INFO (node))
>>      {
>> -      double_int min, max, nonzero_bits;
>> +      widest_int min, max, nonzero_bits;
>>        value_range_type range_type = get_range_info (node, &min, &max);
>> 
>>        if (range_type == VR_VARYING)
>> 
>> this makes me suspect you are changing SSA_NAME_RANGE_INFO
>> to embed two max wide_ints.  That's a no-no.
>
> Well, the range_info_def struct right now contains 3 double_ints, which is
> unnecessary overhead for the most of the cases where the SSA_NAME's type
> has just at most HOST_BITS_PER_WIDE_INT bits and thus we could fit all 3 of
> them into 3 HOST_WIDE_INTs rather than 3 double_ints.  So supposedly struct
> range_info_def could be a template on the type's precision rounded up to HWI
> bits, or say have 3 alternatives there, use
> FIXED_WIDE_INT (HOST_BITS_PER_WIDE_INT) for the smallest types,
> FIXED_WIDE_INT (2 * HOST_BITS_PER_WIDE_INT) aka double_int for the larger
> but still common ones, and widest_int for the rest, then the API to set/get
> it could use widest_int everywhere, and just what storage we'd use would
> depend on the precision of the type.

This patch adds a trailing_wide_ints <N> that can be used at the end of
a variable-length structure to store N wide_ints.  There's also a macro
to declare get/set methods for each of the N elements.

At the moment I've only defined non-const operator[].  It'd be possible
to add a const version later if necessary.

The size of range_info_def for precisions that fit in M HWIs is then
1 + 3 * M, so 4 for the common case (down from 6 on trunk).  The maximum
is 7 for current x86_64 types (up from 6 on trunk).

I wondered whether to keep the interface using widest_int, but I think
wide_int works out more naturally.  The only caller that wants to extend
beyond the precision is CCP, but that's already special because the upper
bits are supposed to be set (i.e. it's not a normal sign or zero extension).

This relies on the SSA_NAME_ANTI_RANGE_P patch I just posted.

If this is OK I'll look at using the same structure elsewhere.

Thanks,
Richard


Index: gcc/ChangeLog.wide-int
===================================================================
--- gcc/ChangeLog.wide-int	2013-11-27 18:45:17.448816304 +0000
+++ gcc/ChangeLog.wide-int	2013-11-28 11:37:15.320020047 +0000
@@ -677,6 +677,7 @@
 	* tree-ssa-ccp.c: Update comment at top of file.  Include
 	wide-int-print.h.
 	(struct prop_value_d): Change type of mask to widest_int.
+	(extend_mask): New function.
 	(dump_lattice_value): Use wide-int interfaces.
 	(get_default_value): Likewise.
 	(set_constant_value): Likewise.
@@ -768,16 +769,20 @@
 	* tree-ssa-math-opts.c
 	(gimple_expand_builtin_pow): Update calls to real_to_integer.
 	* tree-ssanames.c
-	(set_range_info): Use widest_ints rather than double_ints.
-	(get_range_info): Likewise.
+	(set_range_info): Use wide_int_refs rather than double_ints.
+	Adjust for trailing_wide_ints <3> representation.
 	(set_nonzero_bits): Likewise.
+	(get_range_info): Return wide_ints rather than double_ints.
+	Adjust for trailing_wide_ints <3> representation.
 	(get_nonzero_bits): Likewise.
+	(duplicate_ssa_name_range_info): Adjust for trailing_wide_ints <3>
+	representation.
 	* tree-ssanames.h
-	(struct range_info_def): Change type of min, max and nonzero_bits
-	to widest_int.
-	(set_range_info): Use widest_ints rather than double_ints.
-	(get_range_info): Likewise.
+	(struct range_info_def): Replace min, max and nonzero_bits with
+	a trailing_wide_ints <3>.
+	(set_range_info): Use wide_int_refs rather than double_ints.
 	(set_nonzero_bits): Likewise.
+	(get_range_info): Return wide_ints rather than double_ints.
 	(get_nonzero_bits): Likewise.
 	* tree-ssa-phiopt.c
 	(jump_function_from_stmt): Use wide-int interfaces.
Index: gcc/builtins.c
===================================================================
--- gcc/builtins.c	2013-11-27 18:45:17.448816304 +0000
+++ gcc/builtins.c	2013-11-27 18:45:46.710684576 +0000
@@ -3125,7 +3125,7 @@ determine_block_size (tree len, rtx len_
     }
   else
     {
-      widest_int min, max;
+      wide_int min, max;
       enum value_range_type range_type = VR_UNDEFINED;
 
       /* Determine bounds from the type.  */
@@ -3152,9 +3152,8 @@ determine_block_size (tree len, rtx len_
 	  /* Anti range 0...N lets us to determine minmal size to N+1.  */
 	  if (min == 0)
 	    {
-	      widest_int max_plus_one = max + 1;
-	      if (wi::fits_uhwi_p (max_plus_one))
-		*min_size = max_plus_one.to_uhwi ();
+	      if (wi::fits_uhwi_p (max) && max.to_uhwi () + 1 != 0)
+		*min_size = max.to_uhwi () + 1;
 	    }
 	  /* Code like
 
Index: gcc/gimple-pretty-print.c
===================================================================
--- gcc/gimple-pretty-print.c	2013-11-27 18:45:17.448816304 +0000
+++ gcc/gimple-pretty-print.c	2013-11-27 18:45:46.706684594 +0000
@@ -1754,7 +1754,7 @@ dump_ssaname_info (pretty_printer *buffe
   if (!POINTER_TYPE_P (TREE_TYPE (node))
       && SSA_NAME_RANGE_INFO (node))
     {
-      widest_int min, max, nonzero_bits;
+      wide_int min, max, nonzero_bits;
       value_range_type range_type = get_range_info (node, &min, &max);
 
       if (range_type == VR_VARYING)
@@ -1769,9 +1769,7 @@ dump_ssaname_info (pretty_printer *buffe
 	  pp_printf (buffer, "]");
 	}
       nonzero_bits = get_nonzero_bits (node);
-      if (nonzero_bits != -1
-	  && (nonzero_bits
-	      != wi::mask <widest_int> (TYPE_PRECISION (TREE_TYPE (node)), false)))
+      if (nonzero_bits != -1)
 	{
 	  pp_string (buffer, " NONZERO ");
 	  pp_wide_int (buffer, nonzero_bits, UNSIGNED);
Index: gcc/tree-ssa-ccp.c
===================================================================
--- gcc/tree-ssa-ccp.c	2013-11-27 18:45:17.448816304 +0000
+++ gcc/tree-ssa-ccp.c	2013-11-27 18:45:46.707684590 +0000
@@ -237,6 +237,14 @@ debug_lattice_value (prop_value_t val)
   fprintf (stderr, "\n");
 }
 
+/* Extend NONZERO_BITS to a full mask, with the upper bits being set.  */
+
+static widest_int
+extend_mask (const wide_int &nonzero_bits)
+{
+  return (wi::mask <widest_int> (wi::get_precision (nonzero_bits), true)
+	  | widest_int::from (nonzero_bits, UNSIGNED));
+}
 
 /* Compute a default value for variable VAR and store it in the
    CONST_VAL array.  The following rules are used to get default
@@ -279,15 +287,12 @@ get_default_value (tree var)
 	  val.mask = -1;
 	  if (flag_tree_bit_ccp)
 	    {
-	      widest_int nonzero_bits = get_nonzero_bits (var);
-	      widest_int mask
-		= wi::mask <widest_int> (TYPE_PRECISION (TREE_TYPE (var)), false);
-	      if (nonzero_bits != -1 && nonzero_bits != mask)
+	      wide_int nonzero_bits = get_nonzero_bits (var);
+	      if (nonzero_bits != -1)
 		{
 		  val.lattice_val = CONSTANT;
 		  val.value = build_zero_cst (TREE_TYPE (var));
-		  /* CCP wants the bits above precision set.  */
-		  val.mask = nonzero_bits | ~mask;
+		  val.mask = extend_mask (nonzero_bits);
 		}
 	    }
 	}
@@ -895,7 +900,9 @@ ccp_finalize (void)
 	}
       else
 	{
-	  widest_int nonzero_bits = val->mask | wi::to_widest (val->value);
+	  unsigned int precision = TYPE_PRECISION (TREE_TYPE (val->value));
+	  wide_int nonzero_bits = wide_int::from (val->mask, precision,
+						  UNSIGNED) | val->value;
 	  nonzero_bits &= get_nonzero_bits (name);
 	  set_nonzero_bits (name, nonzero_bits);
 	}
@@ -1758,29 +1765,25 @@ evaluate_stmt (gimple stmt)
       && TREE_CODE (gimple_get_lhs (stmt)) == SSA_NAME)
     {
       tree lhs = gimple_get_lhs (stmt);
-      widest_int nonzero_bits = get_nonzero_bits (lhs);
-      widest_int mask
-	= wi::mask <widest_int> (TYPE_PRECISION (TREE_TYPE (lhs)), false);
-      if (nonzero_bits != -1 && nonzero_bits != mask)
+      wide_int nonzero_bits = get_nonzero_bits (lhs);
+      if (nonzero_bits != -1)
 	{
 	  if (!is_constant)
 	    {
 	      val.lattice_val = CONSTANT;
 	      val.value = build_zero_cst (TREE_TYPE (lhs));
-	      /* CCP wants the bits above precision set.  */
-	      val.mask = nonzero_bits | ~mask;
+	      val.mask = extend_mask (nonzero_bits);
 	      is_constant = true;
 	    }
 	  else
 	    {
-	      widest_int valv = wi::to_widest (val.value);
-	      if ((valv & ~nonzero_bits & mask) != 0)
+	      if (wi::bit_and_not (val.value, nonzero_bits) != 0)
 		val.value = wide_int_to_tree (TREE_TYPE (lhs),
-					      valv & nonzero_bits);
+					      nonzero_bits & val.value);
 	      if (nonzero_bits == 0)
 		val.mask = 0;
 	      else
-		val.mask = val.mask & (nonzero_bits | ~mask);
+		val.mask = extend_mask (nonzero_bits);
 	    }
 	}
     }
Index: gcc/tree-ssa-loop-niter.c
===================================================================
--- gcc/tree-ssa-loop-niter.c	2013-11-27 18:45:17.448816304 +0000
+++ gcc/tree-ssa-loop-niter.c	2013-11-27 18:45:46.711684572 +0000
@@ -125,7 +125,7 @@ split_to_var_and_offset (tree expr, tree
 determine_value_range (struct loop *loop, tree type, tree var, mpz_t off,
 		       mpz_t min, mpz_t max)
 {
-  widest_int minv, maxv;
+  wide_int minv, maxv;
   enum value_range_type rtype = VR_VARYING;
 
   /* If the expression is a constant, we know its value exactly.  */
@@ -142,6 +142,7 @@ determine_value_range (struct loop *loop
   if (TREE_CODE (var) == SSA_NAME && INTEGRAL_TYPE_P (type))
     {
       edge e = loop_preheader_edge (loop);
+      signop sgn = TYPE_SIGN (type);
       gimple_stmt_iterator gsi;
 
       /* Either for VAR itself...  */
@@ -151,7 +152,7 @@ determine_value_range (struct loop *loop
       for (gsi = gsi_start_phis (loop->header); !gsi_end_p (gsi); gsi_next (&gsi))
 	{
 	  gimple phi = gsi_stmt (gsi);
-	  widest_int minc, maxc;
+	  wide_int minc, maxc;
 	  if (PHI_ARG_DEF_FROM_EDGE (phi, e) == var
 	      && (get_range_info (gimple_phi_result (phi), &minc, &maxc)
 		  == VR_RANGE))
@@ -164,20 +165,20 @@ determine_value_range (struct loop *loop
 		}
 	      else
 		{
-		  minv = wi::smax (minv, minc);
-		  maxv = wi::smin (maxv, maxc);
-		  gcc_assert (wi::les_p (minv, maxv));
+		  minv = wi::max (minv, minc, sgn);
+		  maxv = wi::min (maxv, maxc, sgn);
+		  gcc_assert (wi::le_p (minv, maxv, sgn));
 		}
 	    }
 	}
       if (rtype == VR_RANGE)
 	{
 	  mpz_t minm, maxm;
-	  gcc_assert (wi::les_p (minv, maxv));
+	  gcc_assert (wi::le_p (minv, maxv, sgn));
 	  mpz_init (minm);
 	  mpz_init (maxm);
-	  wi::to_mpz (minv, minm, SIGNED);
-	  wi::to_mpz (maxv, maxm, SIGNED);
+	  wi::to_mpz (minv, minm, sgn);
+	  wi::to_mpz (maxv, maxm, sgn);
 	  mpz_add (minm, minm, off);
 	  mpz_add (maxm, maxm, off);
 	  /* If the computation may not wrap or off is zero, then this
Index: gcc/tree-ssanames.c
===================================================================
--- gcc/tree-ssanames.c	2013-11-27 18:45:17.448816304 +0000
+++ gcc/tree-ssanames.c	2013-11-27 18:45:46.705684598 +0000
@@ -182,19 +182,22 @@ make_ssa_name_fn (struct function *fn, t
 
 void
 set_range_info (tree name, enum value_range_type range_type,
-		const widest_int &min, const widest_int &max)
+		const wide_int_ref &min, const wide_int_ref &max)
 {
   gcc_assert (!POINTER_TYPE_P (TREE_TYPE (name)));
   gcc_assert (range_type == VR_RANGE || range_type == VR_ANTI_RANGE);
   range_info_def *ri = SSA_NAME_RANGE_INFO (name);
+  unsigned int precision = TYPE_PRECISION (TREE_TYPE (name));
 
   /* Allocate if not available.  */
   if (ri == NULL)
     {
-      ri = ggc_alloc_cleared_range_info_def ();
+      size_t size = (sizeof (range_info_def)
+		     + trailing_wide_ints <3>::extra_size (precision));
+      ri = ggc_alloc_range_info_def (size);
+      ri->ints.set_precision (precision);
       SSA_NAME_RANGE_INFO (name) = ri;
-      ri->nonzero_bits = wi::mask <widest_int> (TYPE_PRECISION (TREE_TYPE (name)),
-						false);
+      ri->set_nonzero_bits (wi::shwi (-1, precision));
     }
 
   /* Record the range type.  */
@@ -202,22 +205,16 @@ set_range_info (tree name, enum value_ra
     SSA_NAME_ANTI_RANGE_P (name) = (range_type == VR_ANTI_RANGE);
 
   /* Set the values.  */
-  ri->min = min;
-  ri->max = max;
+  ri->set_min (min);
+  ri->set_max (max);
 
   /* If it is a range, try to improve nonzero_bits from the min/max.  */
   if (range_type == VR_RANGE)
     {
-      int prec = TYPE_PRECISION (TREE_TYPE (name));
-
-      widest_int ext_min = wi::zext (min, prec);
-      widest_int ext_max = wi::zext (max, prec);
-      widest_int xorv = ext_min ^ ext_max;
+      wide_int xorv = ri->get_min () ^ ri->get_max ();
       if (xorv != 0)
-	xorv = wi::mask <widest_int> (MAX_BITSIZE_MODE_ANY_INT
-				      - wi::clz (xorv),
-				      false);
-      ri->nonzero_bits = ri->nonzero_bits & (ext_min | xorv);
+	xorv = wi::mask (precision - wi::clz (xorv), false, precision);
+      ri->set_nonzero_bits (ri->get_nonzero_bits () & (ri->get_min () | xorv));
     }
 }
 
@@ -227,7 +224,7 @@ set_range_info (tree name, enum value_ra
    is used to determine if MIN and MAX are valid values.  */
 
 enum value_range_type
-get_range_info (const_tree name, widest_int *min, widest_int *max)
+get_range_info (const_tree name, wide_int *min, wide_int *max)
 {
   gcc_assert (!POINTER_TYPE_P (TREE_TYPE (name)));
   gcc_assert (min && max);
@@ -239,52 +236,45 @@ get_range_info (const_tree name, widest_
 	      > 2 * HOST_BITS_PER_WIDE_INT))
     return VR_VARYING;
 
-  *min = ri->min;
-  *max = ri->max;
+  *min = ri->get_min ();
+  *max = ri->get_max ();
   return SSA_NAME_RANGE_TYPE (name);
 }
 
 /* Change non-zero bits bitmask of NAME.  */
 
 void
-set_nonzero_bits (tree name, const widest_int &mask)
+set_nonzero_bits (tree name, const wide_int_ref &mask)
 {
   gcc_assert (!POINTER_TYPE_P (TREE_TYPE (name)));
   if (SSA_NAME_RANGE_INFO (name) == NULL)
     set_range_info (name, VR_RANGE,
-		    wi::to_widest (TYPE_MIN_VALUE (TREE_TYPE (name))),
-		    wi::to_widest (TYPE_MAX_VALUE (TREE_TYPE (name))));
+		    TYPE_MIN_VALUE (TREE_TYPE (name)),
+		    TYPE_MAX_VALUE (TREE_TYPE (name)));
   range_info_def *ri = SSA_NAME_RANGE_INFO (name);
-  ri->nonzero_bits
-    = mask & wi::mask <widest_int> (TYPE_PRECISION (TREE_TYPE (name)),
-				    false);
+  ri->set_nonzero_bits (mask);
 }
 
 /* Return a widest_int with potentially non-zero bits in SSA_NAME
    NAME, or -1 if unknown.  */
 
-widest_int
+wide_int
 get_nonzero_bits (const_tree name)
 {
+  unsigned int precision = TYPE_PRECISION (TREE_TYPE (name));
   if (POINTER_TYPE_P (TREE_TYPE (name)))
     {
       struct ptr_info_def *pi = SSA_NAME_PTR_INFO (name);
       if (pi && pi->align)
-	{
-	  widest_int al = pi->align - 1;
-	  return ((wi::mask <widest_int> (TYPE_PRECISION (TREE_TYPE (name)),
-					  false) & ~al)
-		  | pi->misalign);
-	}
-      return -1;
+	return wi::shwi (-(int) pi->align | pi->misalign, precision);
+      return wi::shwi (-1, precision);
     }
 
   range_info_def *ri = SSA_NAME_RANGE_INFO (name);
-  if (!ri || (GET_MODE_PRECISION (TYPE_MODE (TREE_TYPE (name)))
-	      > 2 * HOST_BITS_PER_WIDE_INT))
-    return -1;
+  if (!ri)
+    return wi::shwi (-1, precision);
 
-  return ri->nonzero_bits;
+  return ri->get_nonzero_bits ();
 }
 
 /* We no longer need the SSA_NAME expression VAR, release it so that
@@ -497,8 +487,11 @@ duplicate_ssa_name_range_info (tree name
   if (!range_info)
     return;
 
-  new_range_info = ggc_alloc_range_info_def ();
-  *new_range_info = *range_info;
+  unsigned int precision = TYPE_PRECISION (TREE_TYPE (name));
+  size_t size = (sizeof (range_info_def)
+		 + trailing_wide_ints <3>::extra_size (precision));
+  new_range_info = ggc_alloc_range_info_def (size);
+  memcpy (new_range_info, range_info, size);
 
   gcc_assert (range_type == VR_RANGE || range_type == VR_ANTI_RANGE);
   SSA_NAME_ANTI_RANGE_P (name) = (range_type == VR_ANTI_RANGE);
Index: gcc/tree-ssanames.h
===================================================================
--- gcc/tree-ssanames.h	2013-11-27 18:45:17.448816304 +0000
+++ gcc/tree-ssanames.h	2013-11-28 11:37:35.998909487 +0000
@@ -47,13 +47,12 @@ struct GTY(()) ptr_info_def
 
 /* Value range information for SSA_NAMEs representing non-pointer variables.  */
 
-struct GTY (()) range_info_def {
-  /* Minimum for value range.  */
-  widest_int min;
-  /* Maximum for value range.  */
-  widest_int max;
-  /* Non-zero bits - bits not set are guaranteed to be always zero.  */
-  widest_int nonzero_bits;
+struct GTY ((variable_size)) range_info_def {
+  /* Minimum, maximum and nonzero bits.  */
+  TRAILING_WIDE_INT_ACCESSOR (min, ints, 0)
+  TRAILING_WIDE_INT_ACCESSOR (max, ints, 1)
+  TRAILING_WIDE_INT_ACCESSOR (nonzero_bits, ints, 2)
+  trailing_wide_ints <3> ints;
 };
 
 
@@ -70,13 +69,13 @@ #define ssa_name(i) ((*cfun->gimple_df->
 enum value_range_type { VR_UNDEFINED, VR_RANGE, VR_ANTI_RANGE, VR_VARYING };
 
 /* Sets the value range to SSA.  */
-extern void set_range_info (tree, enum value_range_type, const widest_int &,
-			    const widest_int &);
+extern void set_range_info (tree, enum value_range_type, const wide_int_ref &,
+			    const wide_int_ref &);
 /* Gets the value range from SSA.  */
-extern enum value_range_type get_range_info (const_tree, widest_int *,
-					     widest_int *);
-extern void set_nonzero_bits (tree, const widest_int &);
-extern widest_int get_nonzero_bits (const_tree);
+extern enum value_range_type get_range_info (const_tree, wide_int *,
+					     wide_int *);
+extern void set_nonzero_bits (tree, const wide_int_ref &);
+extern wide_int get_nonzero_bits (const_tree);
 extern void init_ssanames (struct function *, int);
 extern void fini_ssanames (void);
 extern void ssanames_print_statistics (void);
Index: gcc/tree-vect-patterns.c
===================================================================
--- gcc/tree-vect-patterns.c	2013-11-27 18:45:17.448816304 +0000
+++ gcc/tree-vect-patterns.c	2013-11-27 18:45:46.711684572 +0000
@@ -2261,13 +2261,13 @@ vect_recog_divmod_pattern (vec<gimple> *
       else
 	t3 = t2;
 
-      widest_int oprnd0_min, oprnd0_max;
+      wide_int oprnd0_min, oprnd0_max;
       int msb = 1;
       if (get_range_info (oprnd0, &oprnd0_min, &oprnd0_max) == VR_RANGE)
 	{
-	  if (!wi::neg_p (oprnd0_min))
+	  if (!wi::neg_p (oprnd0_min, TYPE_SIGN (itype)))
 	    msb = 0;
-	  else if (wi::neg_p (oprnd0_max))
+	  else if (wi::neg_p (oprnd0_max, TYPE_SIGN (itype)))
 	    msb = -1;
 	}
 
Index: gcc/tree-vrp.c
===================================================================
--- gcc/tree-vrp.c	2013-11-27 18:45:17.448816304 +0000
+++ gcc/tree-vrp.c	2013-11-28 11:32:48.572622303 +0000
@@ -6422,8 +6422,7 @@ maybe_set_nonzero_bits (basic_block bb,
 	return;
     }
   cst = gimple_assign_rhs2 (stmt);
-  set_nonzero_bits (var, (get_nonzero_bits (var)
-			  & ~wi::to_widest (cst)));
+  set_nonzero_bits (var, wi::bit_and_not (get_nonzero_bits (var), cst));
 }
 
 /* Convert range assertion expressions into the implied copies and
@@ -6508,8 +6507,8 @@ remove_range_assertions (void)
 							  single_pred (bb)))
 		  {
 		    set_range_info (var, SSA_NAME_RANGE_TYPE (lhs),
-				    SSA_NAME_RANGE_INFO (lhs)->min,
-				    SSA_NAME_RANGE_INFO (lhs)->max);
+				    SSA_NAME_RANGE_INFO (lhs)->get_min (),
+				    SSA_NAME_RANGE_INFO (lhs)->get_max ());
 		    maybe_set_nonzero_bits (bb, var);
 		  }
 	      }
@@ -9534,9 +9533,8 @@ vrp_finalize (void)
 	    && (TREE_CODE (vr_value[i]->max) == INTEGER_CST)
 	    && (vr_value[i]->type == VR_RANGE
 		|| vr_value[i]->type == VR_ANTI_RANGE))
-	  set_range_info (name, vr_value[i]->type,
-			  wi::to_widest (vr_value[i]->min),
-			  wi::to_widest (vr_value[i]->max));
+	  set_range_info (name, vr_value[i]->type, vr_value[i]->min,
+			  vr_value[i]->max);
       }
 
   /* Free allocated memory.  */
Index: gcc/wide-int.h
===================================================================
--- gcc/wide-int.h	2013-11-27 18:45:17.448816304 +0000
+++ gcc/wide-int.h	2013-11-28 11:44:39.041731636 +0000
@@ -653,6 +653,9 @@ class GTY(()) generic_wide_int : public
   HOST_WIDE_INT slow () const;
   HOST_WIDE_INT shigh () const;
 
+  template <typename T>
+  generic_wide_int &operator = (const T &);
+
 #define BINARY_PREDICATE(OP, F) \
   template <typename T> \
   bool OP (const T &c) const { return wi::F (*this, c); }
@@ -831,6 +834,15 @@ generic_wide_int <storage>::elt (unsigne
     return this->get_val ()[i];
 }
 
+template <typename storage>
+template <typename T>
+generic_wide_int <storage> &
+generic_wide_int <storage>::operator = (const T &x)
+{
+  storage::operator = (x);
+  return *this;
+}
+
 namespace wi
 {
   template <>
@@ -1188,6 +1200,159 @@ get_binary_result (const T1 &, const T2
   return FIXED_WIDE_INT (N) ();
 }
 
+/* A reference to one element of a trailing_wide_ints structure.  */
+class trailing_wide_int_storage
+{
+private:
+  /* The precision of the integer, which is a fixed property of the
+     parent trailing_wide_ints.  */
+  unsigned int m_precision;
+
+  /* A pointer to the length field.  */
+  unsigned char *m_len;
+
+  /* A pointer to the HWI array.  There are enough elements to hold all
+     values of precision M_PRECISION.  */
+  HOST_WIDE_INT *m_val;
+
+public:
+  trailing_wide_int_storage (unsigned int, unsigned char *, HOST_WIDE_INT *);
+
+  /* The standard generic_wide_int storage methods.  */
+  unsigned int get_len () const;
+  unsigned int get_precision () const;
+  const HOST_WIDE_INT *get_val () const;
+  HOST_WIDE_INT *write_val ();
+  void set_len (unsigned int, bool = false);
+
+  template <typename T>
+  trailing_wide_int_storage &operator = (const T &);
+};
+
+typedef generic_wide_int <trailing_wide_int_storage> trailing_wide_int;
+
+/* trailing_wide_int behaves like a wide_int.  */
+namespace wi
+{
+  template <>
+  struct int_traits <trailing_wide_int_storage>
+    : public int_traits <wide_int_storage> {};
+}
+
+/* An array of N wide_int-like objects that can be put at the end of
+   a variable-sized structure.  Use extra_size to calculate how many
+   bytes beyond the sizeof need to be allocated.  Use set_precision
+   to initialize the structure.  */
+template <int N>
+class GTY(()) trailing_wide_ints
+{
+private:
+  /* The shared precision of each number.  */
+  unsigned short m_precision;
+
+  /* The shared maximum length of each number.  */
+  unsigned char m_max_len;
+
+  /* The current length of each number.  */
+  unsigned char m_len[N];
+
+  /* The variable-length part of the structure, which always contains
+     at least one HWI.  Element I starts at index I * M_MAX_LEN.  */
+  HOST_WIDE_INT m_val[1];
+
+public:
+  void set_precision (unsigned int);
+  trailing_wide_int operator [] (unsigned int);
+  static size_t extra_size (unsigned int);
+};
+
+inline trailing_wide_int_storage::
+trailing_wide_int_storage (unsigned int precision, unsigned char *len,
+			   HOST_WIDE_INT *val)
+  : m_precision (precision), m_len (len), m_val (val)
+{
+}
+
+inline unsigned int
+trailing_wide_int_storage::get_len () const
+{
+  return *m_len;
+}
+
+inline unsigned int
+trailing_wide_int_storage::get_precision () const
+{
+  return m_precision;
+}
+
+inline const HOST_WIDE_INT *
+trailing_wide_int_storage::get_val () const
+{
+  return m_val;
+}
+
+inline HOST_WIDE_INT *
+trailing_wide_int_storage::write_val ()
+{
+  return m_val;
+}
+
+inline void
+trailing_wide_int_storage::set_len (unsigned int len, bool is_sign_extended)
+{
+  *m_len = len;
+  if (!is_sign_extended && len * HOST_BITS_PER_WIDE_INT > m_precision)
+    m_val[len - 1] = sext_hwi (m_val[len - 1],
+			       m_precision % HOST_BITS_PER_WIDE_INT);
+}
+
+template <typename T>
+inline trailing_wide_int_storage &
+trailing_wide_int_storage::operator = (const T &x)
+{
+  WIDE_INT_REF_FOR (T) xi (x, m_precision);
+  wi::copy (*this, xi);
+  return *this;
+}
+
+/* Initialize the structure and record that all elements have precision
+   PRECISION.  */
+template <int N>
+inline void
+trailing_wide_ints <N>::set_precision (unsigned int precision)
+{
+  m_precision = precision;
+  m_max_len = ((precision + HOST_BITS_PER_WIDE_INT - 1)
+	       / HOST_BITS_PER_WIDE_INT);
+}
+
+/* Return a reference to element INDEX.  */
+template <int N>
+inline trailing_wide_int
+trailing_wide_ints <N>::operator [] (unsigned int index)
+{
+  return trailing_wide_int_storage (m_precision, &m_len[index],
+				    &m_val[index * m_max_len]);
+}
+
+/* Return how many extra bytes need to be added to the end of the structure
+   in order to handle N wide_ints of precision PRECISION.  */
+template <int N>
+inline size_t
+trailing_wide_ints <N>::extra_size (unsigned int precision)
+{
+  unsigned int max_len = ((precision + HOST_BITS_PER_WIDE_INT - 1)
+			  / HOST_BITS_PER_WIDE_INT);
+  return (N * max_len - 1) * sizeof (HOST_WIDE_INT);
+}
+
+/* This macro is used in structures that end with a trailing_wide_ints field
+   called FIELD.  It declares get_NAME() and set_NAME() methods to access
+   element I of FIELD.  */
+#define TRAILING_WIDE_INT_ACCESSOR(NAME, FIELD, I) \
+  trailing_wide_int get_##NAME () { return FIELD[I]; } \
+  template <typename T> void set_##NAME (const T &x) { FIELD[I] = x; }
+
 namespace wi
 {
   /* Implementation of int_traits for primitive integer types like "int".  */
@@ -2726,6 +2891,24 @@ gt_pch_nx (generic_wide_int <T> *, void
 {
 }
 
+template<int N>
+void
+gt_ggc_mx (trailing_wide_ints <N> *)
+{
+}
+
+template<int N>
+void
+gt_pch_nx (trailing_wide_ints <N> *)
+{
+}
+
+template<int N>
+void
+gt_pch_nx (trailing_wide_ints <N> *, void (*) (void *, void *), void *)
+{
+}
+
 namespace wi
 {
   /* Used for overloaded functions in which the only other acceptable



More information about the Gcc-patches mailing list