Paolo Bonzini <[EMAIL PROTECTED]> 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