On Thu, Nov 28, 2013 at 12:58 PM, Richard Sandiford
<rdsandif...@googlemail.com> wrote:
> Jakub Jelinek <ja...@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 <mikest...@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.

Looks good to me.

Thanks,
Richard.

> 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

Reply via email to