Richard Biener <[email protected]> writes:
> On Wed, Apr 24, 2013 at 5:00 PM, Richard Sandiford
> <[email protected]> wrote:
>> Richard Biener <[email protected]> writes:
>>> On Wed, Apr 24, 2013 at 4:29 PM, Richard Sandiford
>>> <[email protected]> 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.
I disagree. All rtl objects have a precision. REGs, MEMs, SYMBOL_REFs,
LABEL_REFs and CONSTs all have precisions, and the last three are
run-time constants. Why should CONST_INT and CONST_DOUBLE be different?
See e.g. the hoops that cselib has to jump through:
/* We need to pass down the mode of constants through the hash table
functions. For that purpose, wrap them in a CONST of the appropriate
mode. */
static rtx
wrap_constant (enum machine_mode mode, rtx x)
{
if ((!CONST_SCALAR_INT_P (x)) && GET_CODE (x) != CONST_FIXED)
return x;
gcc_assert (mode != VOIDmode);
return gen_rtx_CONST (mode, x);
}
That is, cselib locally converts (const_int X) into (const:M (const_int X)),
purely so that it doesn't lose track of the CONST_INT's mode.
(const:M (const_int ...)) is invalid rtl elsewhere, but a necessary
hack here all the same.
> What RTL currently has looks better to me - operations have
> explicitely specified precisions.
But that isn't enough to determine the precision of all operands.
A classic case is ZERO_EXTEND. Something like:
(zero_extend:DI (reg:SI X))
is unambiguous. But if you substitute (reg:SI X) with a CONST_INT,
the result becomes ambiguous. E.g. we could end up with:
(zero_extend:DI (const_int -1))
The ZERO_EXTEND operand still has SImode, but that fact is not explicit
in the rtl, and is certainly not explicit in the ZERO_EXTEND operation.
So if we just see the result above, we no longer know whether the result
should be (const_int 0xff), (const_int 0xffff), or what. The same goes for:
(zero_extend:DI (const_int 256))
where (const_int 0) and (const_int 256) are both potential results.
It's not just ZERO_EXTEND. E.g.:
(zero_extract:SI ...)
tells you that an SImode value is being extracted, but it doesn't tell
you what precision you're extracting from. So for:
(zero_extract:SI (const_int -1) (const_int X) (const_int 3))
how many 1 bits should be the result have? Because of the sign-extension
canonicalisation, the answer depends on the precision of the (const_int -1),
which has now been lost. If instead CONST_INTs were stored in zero-extended
form, the same ambiguity would apply to SIGN_EXTRACT.
This sort of thing has been a constant headache in rtl. I can't stress
how much I feel it is _not_ better than recording the precision of
the constant :-)
Richard