This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: patch to canonize small wide-ints.
- From: Richard Sandiford <rdsandiford at googlemail dot com>
- To: Kenneth Zadeck <zadeck at naturalbridge dot com>
- Cc: Richard Biener <rguenther at suse dot de>, gcc-patches <gcc-patches at gcc dot gnu dot org>, Mike Stump <mikestump at comcast dot net>
- Date: Thu, 03 Oct 2013 15:29:28 +0100
- Subject: Re: patch to canonize small wide-ints.
- Authentication-results: sourceware.org; auth=none
- References: <5238B585 dot 2020703 at naturalbridge dot com> <alpine dot LNX dot 2 dot 00 dot 1309241539100 dot 29411 at zhemvz dot fhfr dot qr> <5241986B dot 7040306 at naturalbridge dot com> <alpine dot LNX dot 2 dot 00 dot 1309241550270 dot 29411 at zhemvz dot fhfr dot qr> <524D7A13 dot 6060303 at naturalbridge dot com>
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