On 04/24/2013 11:13 AM, Richard Biener wrote:
On Wed, Apr 24, 2013 at 5:00 PM, Richard Sandiford
<rdsandif...@googlemail.com> wrote:
Richard Biener<richard.guent...@gmail.com> writes:
On Wed, Apr 24, 2013 at 4:29 PM, Richard Sandiford
<rdsandif...@googlemail.com> wrote:
In other words, one of the reasons wide_int can't be exactly 1:1
in practice is because it is clearing out these mistakes (GEN_INT
rather than gen_int_mode) and missing features (non-power-of-2 widths).
Note that the argument should be about CONST_WIDE_INT here,
not wide-int. Indeed CONST_WIDE_INT has the desired feature
and can be properly truncated/extended according to mode at the time we build it
via immed_wide_int_cst (w, mode). I don't see the requirement that
wide-int itself is automagically providing that truncation/extension
(though it is a possibility, one that does not match existing behavior of
HWI for CONST_INT or double-int for CONST_DOUBLE).
I agree it doesn't match the existing behaviour of HWI for CONST_INT or
double-int for CONST_DOUBLE, but I think that's very much a good thing.
The model for HWIs at the moment is that you have to truncate results
to the canonical form after every operation where it matters. As you
proved in your earlier message about the plus_constant bug, that's easily
forgotten. I don't think the rtl code is doing all CONST_INT arithmetic
on full HWIs because it wants to: it's doing it because that's the way
C/C++ arithmetic on primitive types works. In other words, the current
CONST_INT code is trying to emulate N-bit arithmetic (for gcc runtime N)
using a single primitive integer type. wide_int gives us N-bit arithmetic
directly; no emulation is needed.
Ok, so what wide-int provides is integer values encoded in 'len' HWI
words that fit in 'precision' or more bits (and often in less). wide-int
also provides N-bit arithmetic operations. IMHO both are tied
too closely together. A give constant doesn't really have a precision.
Associating one with it to give a precision to an arithmetic operation
looks wrong to me and are a source of mismatches.
What RTL currently has looks better to me - operations have
explicitely specified precisions.
I have tried very hard to make wide-int work very efficiently with both
tree and rtl without biasing the rep towards either representation.
Both rtl and trees constants have a precision. In tree, constants are
done better than in rtl because the tree really does have a field that
is filled in that points to a type. However, that does not mean that rtl
constants do not have a precision: currently you have to look around at
the context to find the mode of a constant that is in your hand, but it
is in fact always there. At the rtl level, you can see the entire
patch - we always find an appropriate mode.
In the future, this may change. Wide-int moves one step closer in that
ports that support it will not expect that double-ints never have a
mode. But that is a long way from having the mode attached.
What is not stored with the constant is a indication of the signedness.
Unlike a desire to add modes to rtl constants, there is no one even
thinking about the sign. The sign is implicit in the operator, just as
it is at the tree level.
So when i designed wide-int, i assumed that i could get precisions from
the variables or at least "close to" them.
As far as the question of infinite precision, 99% of the uses of
double-int today are "get in, do a single operation and get out". If
this is all that we plan to do, then it does not really matter if it is
infinite precision or not, because at both the rtl and tree level, we
truncate on the way out. However, the use of double-int accounts for
only a small percentage of the math done in the compiler. My wide-int
port converts a substantial portion of the math from inline code that is
guarded by checks to the precision against HOST_WIDE_BITS_PER_INT or
calls to host_integerp. The conversion of this code has substantial
potential to expose the differences between the fixed precision and
infinite precision representations.
The only justification that you have ever given for wanting to use
infinite precision is that it is cleaner. You have never directly
addressed my point that it gives surprising answers except to say that
the user would have to put in explicit intermediate truncations. It
is hard for me to imaging buggering up something as bad as having to put
in explicit intermediate truncations. When i write a * b / c, it
should really look something like the expression.
If your point is that an arbitrary-precision wide_int could be used by
other (non-rtl, and probably non-tree) clients, then I don't really
see the need. We already have mpz_t for that. What we don't have,
and what we IMO need, is something that performs N-bit arithmetic
for runtime N. It seems better to have a single class that does
that for us (wide_int), rather than scatter N-bit emulation throughout
the codebase, which is what we do now.
mpz_t is not suitable here - it's way too expensive. double-int
was the "suitable" bit for now, but given it's host dependency and
inability to handle larger ints (VRP ...) the ability to use wide-ints
for this looks appealing.
and it is expensive why? Because it is not tightly integrated into
tree and rtl as you have fought me tooth and nail about? Because the
people who did mpz were idiots and you feel that i am god's gift to
programming and will do a better job? Or because infinite precision
arithmetic might just be more expensive.
I vote for the last option. Being able to exit out inline for the
math that can be done in a HWI is actually a big win!!!!
Richard.
Richard