Thanks for doing this.

Kenneth Zadeck <zad...@naturalbridge.com> writes:
> @@ -1204,11 +1204,11 @@ wide_int_to_tree (tree type, const wide_
>      }
>  
>    wide_int cst = wide_int::from (pcst, prec, sgn);
> -  int len = int (cst.get_len ());
> -  int small_prec = prec & (HOST_BITS_PER_WIDE_INT - 1);
> +  unsigned int len = int (cst.get_len ());

The cast to int is redundant now (get_len () is unsigned int).

> @@ -5172,39 +5173,48 @@ wi::int_traits <const_tree>::get_precisi
>    return TYPE_PRECISION (TREE_TYPE (tcst));
>  }
>  
> -/* Convert the tree_cst X into a wide_int.  */
> +/* Convert the tree_cst X into a wide_int of PRECISION.  */
>  inline wi::storage_ref
>  wi::int_traits <const_tree>::decompose (HOST_WIDE_INT *scratch,
>                                       unsigned int precision, const_tree x)
>  {
> -  unsigned int xprecision = get_precision (x);
>    unsigned int len = TREE_INT_CST_NUNITS (x);
>    const HOST_WIDE_INT *val = (const HOST_WIDE_INT *) &TREE_INT_CST_ELT (x, 
> 0);
>    unsigned int max_len = ((precision + HOST_BITS_PER_WIDE_INT - 1)
>                         / HOST_BITS_PER_WIDE_INT);
> -  /* Truncate the constant if necessary.  */
> -  if (len > max_len)
> -    return wi::storage_ref (val, max_len, precision);
> +  unsigned int xprecision = get_precision (x);
> +
> +  gcc_assert (precision >= xprecision);
>  
> -  if (precision <= xprecision)
> +  /* Got to be careful of precision 0 values.  */
> +  if (precision)
> +    len = MIN (len, max_len);
> +  if (TYPE_SIGN (TREE_TYPE (x)) == UNSIGNED)
>      {
> -      if (precision < HOST_BITS_PER_WIDE_INT 
> -       && TYPE_SIGN (TREE_TYPE (x)) == UNSIGNED)
> +      unsigned int small_prec = precision & (HOST_BITS_PER_WIDE_INT - 1);
> +      if (small_prec)
> +     {
> +       /* We have to futz with this because the canonization for
> +          short unsigned numbers in wide-int is different from the
> +          canonized short unsigned numbers in the tree-cst.  */
> +       if (len == max_len) 
> +         {
> +           for (unsigned int i = 0; i < len - 1; i++)
> +             scratch[i] = val[i];
> +           scratch[len - 1] = sext_hwi (val[len - 1], precision);
> +           return wi::storage_ref (scratch, len, precision);
> +         }
> +     }
> +
> +      if (precision < xprecision + HOST_BITS_PER_WIDE_INT)
>       {
> -       /* The rep of wide-int is signed, so if the value comes from
> -          an unsigned int_cst, we have to sign extend it to make it
> -          correct.  */
> -       scratch[0] = sext_hwi (val[0], precision);
> -       return wi::storage_ref (scratch, 1, precision);
> +       len = wi::force_to_size (scratch, val, len, xprecision, precision, 
> UNSIGNED);
> +       return wi::storage_ref (scratch, len, precision);
>       }

AFAICT, with the assert, this last case is only needed when
!small_prec && precision == xprecision, and the only situation it
handles is where the top bit is set.  Is that right?  If so,
we can use the original val as-is and just trim the length.  I.e.

      if (small_prec)
        ;
      else if (precision == xprecision)
        while (len >= 0 && val[len - 1] == -1)
          len--;

Sorry if I've got that wrong -- it's taking a while to page the
wide-int stuff back in.

Thanks,
Richard

Reply via email to