Mat Hostetter writes:
> Adam Nemet <[email protected]> writes:
>
> > Ian Lance Taylor <[email protected]> writes:
> > > Mat Hostetter <[email protected]> writes:
> > >
> > >> Since the high bits are already zero, that would be less efficient on
> > >> most platforms, so guarding it with something like this would probably
> > >> be smarter:
> > >>
> > >> if (targetm.mode_rep_extended (mode, GET_MODE(x)) == SIGN_EXTEND)
> > >> return simplify_gen_unary (TRUNCATE, mode, x, GET_MODE (x));
> > >>
> > >> I'm happy to believe I'm doing something wrong in my back end, but I'm
> > >> not sure what that would be. I could also believe these are obscure
> > >> edge cases no one cared about before. Any tips would be appreciated.
> > >
> > > Interesting. I think you are in obscure edge case territory. Your
> > > suggestion makes sense to me, and in fact it should probably be put
> > > into gen_lowpart_common.
> >
> > FWIW, I disagree. Firstly, mode_rep_extended is a special case of
> > !TRULY_NOOP_TRUNCATION so the above check should use that. Secondly, in
> > MIPS we call gen_lowpart to convert DI to SI when we know it's safe. In
> > this case we always want a subreg not a truncate for better code. So I
> > don't think gen_lowpart_common is the right place to fix this.
> >
> > I think the right fix is to call convert_to_mode or convert_move in the
> > expansion code which ensure the proper truncation.
>
> That would yield correct code, but wouldn't it throw away the fact
> that the high bits are already known to be zero, and yield redundant
> zero-extension on some platforms? I'm guessing that's why the code was
> originally written to call convert_lowpart rather than convert_to_mode.
convert_to_mode uses gen_lowpart for truncation if TRULY_NOOP_TRUNCATION.
> And just to add a minor wrinkle: for the widen_bswap case, which
> produces (bswap64 (x) >> 32), the optimal thing is actually to use
> ashiftrt instead of lshiftrt when targetm.mode_rep_extended says
> SIGN_EXTEND, and then call convert_lowpart as now.
Agreed but we sort of do this due to this pattern in mips.md:
(define_insn "*lshr32_trunc<mode>"
[(set (match_operand:SUBDI 0 "register_operand" "=d")
(truncate:SUBDI
(lshiftrt:DI (match_operand:DI 1 "register_operand" "d")
(const_int 32))))]
"TARGET_64BIT && !TARGET_MIPS16"
"dsra\t%0,%1,32"
[(set_attr "type" "shift")
(set_attr "mode" "<MODE>")])
That said with mode_rep_extended this optimization could now be performed by
the middle-end in simplify-rtx.c:
(truncate:SI (lshiftrt:DI .. 32))
->
(subreg:SI (ashiftrt:DI .. 32) <lowpart>)
if targetm.mode_rep_extended (SImod, DImode) == SIGN_EXTEND.
Adam