On 10/03/2013 10:29 AM, Richard Sandiford wrote:
Kenneth Zadeck <zad...@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.
You are seeing the result of me being corner cased to death.
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 think that it is something closer to precision >= xprecision +
HOST_BITS_PER_WIDE_INT && ...
The problem is that the tree cst may have one extra block beyond the
precision.
for my example say HBPWI is 8, not 64. The uint16 constant 0xffff must
be represented by 3 hwi's in the tree-cst as 00 ff ff. This is why the
patch came out today rather than yesterday.
I can fire up a run with this, if you want.
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
again, you can get edge cased to death here. i think it would work
for max because that really is bigger than anything else, but it is
possible (though unlikely) to have something big converted to an address
by truncation.
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?
again the max is safe by definition. The addr is inherently unsafe
because i believe that some of the places where the values are converted
to addr-wide-int come from tree-csts where the type comes from the
source program.
Thanks,
Richard