Kenneth Zadeck<email@example.com> writes:
I have figured out what the root cause of pr52543, but i need some
advise as to how to fix it.
The bug only happens if the source or destination of the move is a
hard register. lower-subreg never breaks up pseudo to pseudo moves
that are larger than word mode. According to richard sandiford, this
bug also appears on the neon, but i do not know if there is a bugzilla
for it. It also appears on my private port, which is why i am
interested in it.
in the particular case of pr52543 and my port, this happens because
the input arguments are hard regs.
The offending code is in can_decompose_p. The problem is that if the
reg is a hard reg, it completely blows off all of the information that
it accumulated during the first pass and unconditionally splits the
register (assuming it is legal to do so).
My question for the list, what is the predicate that we want to
replace the code that always decomposes hardregs (assuming it is
legal). In the case of the neon and my port, decomposing costs 4x
more than using a wide move. I assume the avr is similar.
I don't think can_decompose_p would be the right thing to change. If
that function returns false, resolve_simple_move is still going to split
up the move. You need to change resolve_simple_move. In fact, looking
at resolve_simple_move, I don't think it will break up the register
unless it has already decided to do so:
/* If we didn't have any big SUBREGS of decomposed registers, and
neither side of the move is a register we are decomposing, then
we don't have to do anything here. */
if (src == SET_SRC (set)
&& dest == SET_DEST (set)
&& !resolve_reg_p (src)
&& !resolve_subreg_p (src)
&& !resolve_reg_p (dest)
&& !resolve_subreg_p (dest))
So I think you need to analyze this a bit more. I don't think that is
the offending code.