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: patch to canonize small wide-ints.


Kenneth Zadeck <zadeck@naturalbridge.com> writes:
> +  /* 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)
>  	{
> -	  /* 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);
> +	  /* 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);
> +	    }
>  	}
> -      /* Otherwise we can use the constant as-is when not extending.  */
> -      return wi::storage_ref (val, len, precision);
> +
> +      unsigned int xprecision = get_precision (x);
> +      len = wi::force_to_size (scratch, val, len, xprecision, precision, UNSIGNED);
> +      return wi::storage_ref (scratch, len, precision);
>      }
>  
> -  /* Widen the constant according to its sign.  */
> -  len = wi::force_to_size (scratch, val, len, xprecision, precision,
> -			   TYPE_SIGN (TREE_TYPE (x)));
> -  return wi::storage_ref (scratch, len, precision);
> +  /* Signed and the rest of the unsigned cases are easy.  */
> +  return wi::storage_ref (val, len, precision);

AFAICT, no unsigned cases fall through to the "rest of the unsigned cases"
statement.

Changing the representation of unsigned constants is only worthwhile
if we can avoid the force_to_size for some unsigned cases.  I think we can
avoid it for precision >= xprecision && !small_prec.  Either we should take
the hit of doing that comparison (but see below) or the change isn't
worthwhile.

I was thinking that we should always be able to use the constant as-is
for max_wide_int-based and addr_wide_int-based operations.  The small_prec
case will get optimised away (because precision is a compile-time constant)
and the force_to_size shouldn't be necessary (because "max" and "addr"
should always be wide enough).  Could we assert for precision >= xprecision
instead of the force_to_size?  Or are there cases in which we implicitly
truncate tree constants for (variable-precision) wide_int-based operations?

Thanks,
Richard


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