This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
Re: [PATCH] Add new target-hook truncated_to_mode
- From: Richard Sandiford <richard at codesourcery dot com>
- To: Paolo Bonzini <paolo dot bonzini at lu dot unisi dot ch>
- Cc: Adam Nemet <anemet at sonic dot net>, GCC Development <gcc at gcc dot gnu dot org>
- Date: Mon, 13 Mar 2006 10:09:34 +0000
- Subject: Re: [PATCH] Add new target-hook truncated_to_mode
- References: <17427.34832.666999.793894@localhost.localdomain> <441524A5.5070205@lu.unisi.ch> <17429.10008.301002.4809@localhost.localdomain> <441530E0.6050408@lu.unisi.ch>
Paolo Bonzini <paolo.bonzini@lu.unisi.ch> writes:
>>> bool
>>> truncated_to_mode (enum machine_mode mode, rtx x)
>>> {
>>> if (REG_P (x) && rtl_hooks.reg_truncated_to_mode (mode, x))
>>> return true;
>>>
>>> gcc_assert (!TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (mode),
>>> GET_MODE_BITSIZE (GET_MODE (x)));
>>> return num_sign_bit_copies (x, GET_MODE (x)) >
>>> GET_MODE_BITSIZE (GET_MODE (x)) - GET_MODE_BITSIZE (mode);
>>> }
>>>
>>> In the MIPS case, you would have n_s_b_c (x, GET_MODE (x)) > 64 - 32.
>>>
>>
>> This wouldn't work for DI->HI truncation for example. There too only
>> the upper 33 bits have to match for the TRUNCATE to be unnecessary.
>> See comment around truncsdi in mips.md.
>>
> If this is so, SImode should be passed to reg_truncated_to_mode as well,
> instead of HImode, shouldn't it? What about this logic:
>
> int n = num_sign_bit_copies (x, GET_MODE (x));
> int dest_bits;
> enum machine_mode next_mode = mode;
> do
> {
> mode = next_mode;
> dest_bits = GET_MODE_BITSIZE (mode);
>
> /* If it is a no-op to truncate to MODE from a wider mode (e.g. to
> HI from SI on MIPS),
> we can check a weaker condition. */
> next_mode = GET_MODE_WIDER_MODE (mode);
> }
> while (next_mode != VOIDmode
> && TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (next_mode),
> dest_bits);
>
> return (REG_P (x) && rtl_hooks.reg_truncated_to_mode (mode, x))
> || n > GET_MODE_BITSIZE (GET_MODE (x)) - dest_bits);
It looks like you're introducing a new assumption here: that we can
ignore TRULY_NOOP_TRUNCATE (X, Y) if the upper X-Y bits are all filled
with sign bits. I realise that's true for both SH and MIPS, but the
current documentation of TRULY_NOOP_TRUNCATE doesn't guarantee it.
For example, I could imagine some future port wanting to preserve zero
extension instead of sign extension. That still fits TRLULY_NOOP_TRUNCATION
as currently defined, but the code above would then be wrong. And...
> On MIPS, we would not test HImode but SImode since TRULY_NOOP_TRUNCATION
> (32, 16) == true. To me, this is a clue that the TRULY_NOOP_TRUNCATION
> macro is insufficient and could be replaced by another one. For example
> (for MIPS -- SHmedia is the same with s/MIPS64/SHMEDIA/):
>
> /* Return the mode to which we should truncate an INMODE value before
> operating
> on it in OUTMODE. For example, on MIPS we should truncate a 64-bit value
> to 32-bits when operating on it in SImode or a narrower mode.
>
> We return INMODE if no such truncation is necessary and we can just
> pretend
> that the value is already truncated. */
> #define WIDEST_NECESSARY_TRUNCATION(outmode, inmode) \
> (TARGET_MIPS64 \
> && GET_MODE_BITSIZE (inmode) <= 32 \
> && GET_MODE_BITSIZE (outmode) > 32 ? SImode : inmode)
>
> Since all uses of TRULY_NOOP_TRUNCATION (except one in convert.c which
> could be changed to use TYPE_MODE) are of the form TRULY_NOOP_TRUNCATION
> (GET_MODE_BITSIZE (x), GET_MODE_BITSIZE (y)), you could change them to
>
> WIDEST_NECESSARY_TRUNCATION (x, y) != y
>
> We could also take the occasion to remove all the defines of
> TRULY_NOOP_TRUNCATION to 1, and put a default definition in defaults.h!
>
> You can then proceed to implement truncated_to_mode as
>
> mode = WIDEST_NECESSARY_TRUNCATION (mode, GET_MODE (x));
> gcc_assert (mode != GET_MODE (x));
> return (REG_P (x) && rtl_hooks.reg_truncated_to_mode (mode, x))
> || num_sign_bit_copies (x, GET_MODE (x)) >
> GET_MODE_BITSIZE (GET_MODE (x)) - GET_MODE_BITSIZE (mode);
>
> What do you think?
...I think the same applies to this macro too. That's one reason why I
prefer the alternative hook that I described: it makes the sign extension
explicit. The other reason is that it would allow the middle-end to remove
redundant sign extensions. (Note that WIDEST_NECESSARY_TRUNCATION(X, Y) == Z
does _not_ imply that sign-extension of a Z-bit value to X bits comes for free.
On MIPS, it isn't true for X==128, just X==64.)
Richard