This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: patch to fix constant math -5th patch, rtl


Richard Biener <richard.guenther@gmail.com> writes:
> On Wed, Apr 24, 2013 at 5:00 PM, Richard Sandiford
> <rdsandiford@googlemail.com> wrote:
>> Richard Biener <richard.guenther@gmail.com> writes:
>>> On Wed, Apr 24, 2013 at 4:29 PM, Richard Sandiford
>>> <rdsandiford@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.

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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]