This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] FR30: fix bad code generated in fr30_move_double
- From: Thomas Kleffel <tk at maintech dot de>
- To: gcc-patches at gcc dot gnu dot org
- Date: Mon, 18 Jun 2007 02:02:39 +0200
- Subject: [PATCH] FR30: fix bad code generated in fr30_move_double
Hi,
in fr30_move_double in fr30.c, if the move goes from MEM to REG, the
following code is executed:
---8<---
int reverse = (refers_to_regno_p (dregno, dregno + 1, addr, 0) != 0);
dest0 = operand_subword (dest, reverse, TRUE, mode);
dest1 = operand_subword (dest, !reverse, TRUE, mode);
if (reverse)
{
emit_insn (gen_rtx_SET (VOIDmode, dest1,
adjust_address (src, SImode, 0)));
emit_insn (gen_rtx_SET (SImode, dest0,
gen_rtx_REG (SImode, REGNO (addr))));
emit_insn (gen_rtx_SET (SImode, dest0,
plus_constant (dest0, UNITS_PER_WORD)));
new_mem = gen_rtx_MEM (SImode, dest0);
MEM_COPY_ATTRIBUTES (new_mem, src);
emit_insn (gen_rtx_SET (VOIDmode, dest0, new_mem));
}
else
{
emit_insn (gen_rtx_SET (VOIDmode, dest0,
adjust_address (src, SImode, 0)));
emit_insn (gen_rtx_SET (SImode, dest1,
gen_rtx_REG (SImode, REGNO (addr))));
emit_insn (gen_rtx_SET (SImode, dest1,
plus_constant (dest1, UNITS_PER_WORD)));
new_mem = gen_rtx_MEM (SImode, dest1);
MEM_COPY_ATTRIBUTES (new_mem, src);
emit_insn (gen_rtx_SET (VOIDmode, dest1, new_mem));
}
--->8---
If you examine the case where reverse is true, you'll find that it
generates exactly the same code as the case where reverse if false
(dest0 and dest1 are swapped twice).
But even if this is fixed, there are still cases where the generated
code is wrong. Therefore I suggest to replace this code by a simpler
version that uses the fixed scratch register (zero) and works for all
combinations of src/dest registers.
Best regards,
Thomas
Index: fr30.c
===================================================================
--- fr30.c (revision 125771)
+++ fr30.c (working copy)
@@ -830,45 +830,27 @@
int dregno = REGNO (dest);
rtx dest0;
rtx dest1;
+ rtx scratch;
rtx new_mem;
- /* If the high-address word is used in the address, we
- must load it last. Otherwise, load it first. */
- int reverse = (refers_to_regno_p (dregno, dregno + 1, addr, 0) != 0);
-
gcc_assert (GET_CODE (addr) == REG);
- dest0 = operand_subword (dest, reverse, TRUE, mode);
- dest1 = operand_subword (dest, !reverse, TRUE, mode);
+ dest0 = operand_subword (dest, 0, TRUE, mode);
+ dest1 = operand_subword (dest, 1, TRUE, mode);
+ scratch = gen_rtx_REG (SImode, 0);
- if (reverse)
- {
- emit_insn (gen_rtx_SET (VOIDmode, dest1,
- adjust_address (src, SImode, 0)));
- emit_insn (gen_rtx_SET (SImode, dest0,
- gen_rtx_REG (SImode, REGNO (addr))));
- emit_insn (gen_rtx_SET (SImode, dest0,
- plus_constant (dest0, UNITS_PER_WORD)));
- new_mem = gen_rtx_MEM (SImode, dest0);
- MEM_COPY_ATTRIBUTES (new_mem, src);
-
- emit_insn (gen_rtx_SET (VOIDmode, dest0, new_mem));
- }
- else
- {
- emit_insn (gen_rtx_SET (VOIDmode, dest0,
- adjust_address (src, SImode, 0)));
- emit_insn (gen_rtx_SET (SImode, dest1,
- gen_rtx_REG (SImode, REGNO (addr))));
- emit_insn (gen_rtx_SET (SImode, dest1,
- plus_constant (dest1, UNITS_PER_WORD)));
+ emit_insn (gen_rtx_SET (SImode, scratch,
+ gen_rtx_REG (SImode, REGNO (addr))));
+ emit_insn (gen_rtx_SET (VOIDmode, dest0,
+ adjust_address (src, SImode, 0)));
+ emit_insn (gen_rtx_SET (SImode, scratch,
+ plus_constant (scratch, UNITS_PER_WORD)));
+
+ new_mem = gen_rtx_MEM (SImode, scratch);
+ MEM_COPY_ATTRIBUTES (new_mem, src);
- new_mem = gen_rtx_MEM (SImode, dest1);
- MEM_COPY_ATTRIBUTES (new_mem, src);
-
- emit_insn (gen_rtx_SET (VOIDmode, dest1, new_mem));
- }
+ emit_insn (gen_rtx_SET (VOIDmode, dest1, new_mem));
}
else if (src_code == CONST_INT || src_code == CONST_DOUBLE)
{