This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [wide-int] int_traits <tree>
- From: Richard Biener <rguenther at suse dot de>
- To: Kenneth Zadeck <zadeck at naturalbridge dot com>
- Cc: Richard Sandiford <rsandifo at linux dot vnet dot ibm dot com>, gcc-patches at gcc dot gnu dot org, Mike Stump <mikestump at comcast dot net>
- Date: Fri, 18 Oct 2013 10:58:12 +0200 (CEST)
- Subject: Re: [wide-int] int_traits <tree>
- Authentication-results: sourceware.org; auth=none
- References: <alpine dot LNX dot 2 dot 00 dot 1310161537220 dot 11149 at zhemvz dot fhfr dot qr> <525EB50F dot 2090003 at naturalbridge dot com> <87ppr56on1 dot fsf at talisman dot default> <525EFC33 dot 4010304 at naturalbridge dot com> <87hacg720z dot fsf at talisman dot default> <alpine dot LNX dot 2 dot 00 dot 1310171015000 dot 11149 at zhemvz dot fhfr dot qr> <87k3hc9n9w dot fsf at sandifor-thinkpad dot stglab dot manchester dot uk dot ibm dot com> <alpine dot LNX dot 2 dot 00 dot 1310171309390 dot 11149 at zhemvz dot fhfr dot qr> <87bo2o9kow dot fsf at sandifor-thinkpad dot stglab dot manchester dot uk dot ibm dot com> <alpine dot LNX dot 2 dot 00 dot 1310171406490 dot 11149 at zhemvz dot fhfr dot qr> <877gdc9fxb dot fsf at sandifor-thinkpad dot stglab dot manchester dot uk dot ibm dot com> <alpine dot LNX dot 2 dot 00 dot 1310171542090 dot 11149 at zhemvz dot fhfr dot qr> <52601509 dot 3070801 at naturalbridge dot com>
On Thu, 17 Oct 2013, Kenneth Zadeck wrote:
> On 10/17/2013 09:48 AM, Richard Biener wrote:
> > On Thu, 17 Oct 2013, Richard Sandiford wrote:
> >
> > > Richard Biener <rguenther@suse.de> writes:
> > > > On Thu, 17 Oct 2013, Richard Sandiford wrote:
> > > >
> > > > > Richard Biener <rguenther@suse.de> writes:
> > > > > > > The new tree representation can have a length greater than max_len
> > > > > > > for an unsigned tree constant that occupies a whole number of
> > > > > > > HWIs.
> > > > > > > The tree representation of an unsigned 0x8000 is 0x00 0x80 0x00.
> > > > > > > When extended to max_wide_int the representation is the same.
> > > > > > > But a 2-HWI addr_wide_int would be 0x80 0x00, without the leading
> > > > > > > zero.
> > > > > > > The MIN trims the length from 3 to 2 in the last case.
> > > > > > Oh, so it was the tree rep that changed? _Why_ was it changed?
> > > > > > We still cannot use it directly from wide-int and the extra
> > > > > > word is redundant because we have access to TYPE_UNSIGNED (TREE_TYPE
> > > > > > ()).
> > > > > It means that we can now use the tree's HWI array directly, without
> > > > > any
> > > > > copying, for addr_wide_int and max_wide_int. The only part of
> > > > > decompose ()
> > > > > that does a copy is the small_prec case, which is trivially compiled
> > > > > out
> > > > > for addr_wide_int and max_wide_int.
> > > > " 2) addr_wide_int. This is a fixed size representation that is
> > > > guaranteed to be large enough to compute any bit or byte sized
> > > > address calculation on the target. Currently the value is 64 + 4
> > > > bits rounded up to the next number even multiple of
> > > > HOST_BITS_PER_WIDE_INT (but this can be changed when the first
> > > > port needs more than 64 bits for the size of a pointer).
> > > >
> > > > This flavor can be used for all address math on the target. In
> > > > this representation, the values are sign or zero extended based
> > > > on their input types to the internal precision. All math is done
> > > > in this precision and then the values are truncated to fit in the
> > > > result type. Unlike most gimple or rtl intermediate code, it is
> > > > not useful to perform the address arithmetic at the same
> > > > precision in which the operands are represented because there has
> > > > been no effort by the front ends to convert most addressing
> > > > arithmetic to canonical types.
> > > >
> > > > In the addr_wide_int, all numbers are represented as signed
> > > > numbers. There are enough bits in the internal representation so
> > > > that no infomation is lost by representing them this way."
> > > >
> > > > so I guess from that that addr_wide_int.get_precision is always
> > > > that "64 + 4 rounded up". Thus decompose gets that constant precision
> > > > input and the extra zeros make the necessary extension always a no-op.
> > > > Aha.
> > > >
> > > > For max_wide_int the same rules apply, just its size is larger.
> > > >
> > > > Ok. So the reps are only canonical wide-int because we only
> > > > ever use them with precision > xprecision (maybe we should assert
> > > > that).
> > > No, we allow precision == xprecision for addr_wide_int and max_wide_int
> > > too.
> > > But all we do in that case is trim the length.
> > >
> > > Requiring precision > xprecision was option (5) from my message.
> > >
> > > > Btw, we are not using them directly, but every time we actually
> > > > build a addr_wide_int / max_wide_int we copy them anyway:
> > > >
> > > > /* Initialize the storage from integer X, in precision N. */
> > > > template <int N>
> > > > template <typename T>
> > > > inline fixed_wide_int_storage <N>::fixed_wide_int_storage (const T &x)
> > > > {
> > > > /* Check for type compatibility. We don't want to initialize a
> > > > fixed-width integer from something like a wide_int. */
> > > > WI_BINARY_RESULT (T, FIXED_WIDE_INT (N)) *assertion ATTRIBUTE_UNUSED;
> > > > wide_int_ref xi (x, N);
> > > > len = xi.len;
> > > > for (unsigned int i = 0; i < len; ++i)
> > > > val[i] = xi.val[i];
> > > > }
> > > Are you saying that:
> > >
> > > max_wide_int x = (tree) y;
> > >
> > > should just copy a pointer? Then what about:
> > No, it should do a copy. But only one - which it does now with
> > the append-extra-zeros-in-tree-rep, I was just thinking how to
> > avoid it when not doing that which means adjusting the rep in
> > the copy we need to do anyway. If fixed_wide_int_storage is
> > really the only reason to enlarge the tree rep.
> >
> > > max_wide_int z = x;
> > >
> > > Should that just copy a pointer too, or is it OK for the second
> > > constructor
> > > to do a copy?
> > >
> > > In most cases we only use the fixed_wide_int to store the result of the
> > > computation. We don't use the above constructor for things like:
> > >
> > > max_wide_int x = wi::add ((tree) y, (int) z);
> > >
> > > wi::add uses y and z without going through max_wide_int.
> > Yes, I am aware of that.
> >
> > > > What's the reason again to not use my original proposed encoding
> > > > of the MSB being the sign bit? RTL constants simply are all signed
> > > > then. Just you have to also sign-extend in functions like lts_p
> > > > as not all constants are sign-extended. But we can use both tree
> > > > (with the now appended zero) and RTL constants representation
> > > > unchanged.
> > > The answer's the same as always. RTL constants don't have a sign.
> > > Any time we extend an RTL constant, we need to say whether the extension
> > > should be sign extension or zero extension. So the natural model for
> > > RTL is that an SImode addition is done to SImode width, not some
> > > arbitrary wider width.
> > RTL constants are sign-extended (whether you call them then "signed"
> > is up to you). They have a precision. This is how they are
> > valid reps for wide-ints, and that doesn't change.
> >
> > I was saying that if we make not _all_ wide-ints sign-extended
> > then we can use the tree rep as-is. We'd then have the wide-int
> > rep being either zero or sign extended but not arbitrary random
> > bits outside of the precision (same as the tree rep).
> >
> > As nearly 100% of all compile-time constant math is done on
> > the tree level pessimizing that just because we can invent sth
> > that only fits RTX and not tree looks wrong. At least if we
> > can invent sth that fits _both_, which I think we can (see above).
> This would be a disaster. the wide int rep is the same as the double-int
> rep. both do not have an explicit bit that says that this came from a
> signed or unsigned value. Once you go down that road then you have to start
> saying what you mean for every binary operation if the signedness does not
> match. And you have to say for every comparison what it means to compare
> unsigned numbers in a signed way......
Signedness only matters for operations where we already specify it.
A plus or a minus doesn't care about the upper bits (twos complement
to the rescue), so the only question is how do you extend the result?
Obvious: the wide-int way (sign-extend).
But I suppose you are right. The only way to make it work reasonably
efficient would be for infinite precision wide-ints.
Bah.
Now I'm thinking of having the storage rep say if it is reliably
sign-extended,
static const bool is_sign_extended = ...;
which would be true for wide-int and RTX but not for tree. In
'signed' function variants you then can no longer rely on all
values being sign-extended but you have to do sth like
if (!x::is_sign_extended)
sext (x);
which should be decidable at compile-time. Note that all this
dances are to avoid ::decompose of trees of making a copy and
thus introducing possibly escaped local (large) storage.
That said, even the _large workers can just get this flag as
input and do the sign-extension on-the-fly?
Richard.