This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH][m68k] Partially fix PR target/28181 (movqi from mem to address register)
- From: Rask Ingemann Lambertsen <rask at sygehus dot dk>
- To: gcc-patches at gcc dot gnu dot org
- Date: Mon, 11 Dec 2006 18:46:01 +0100
- Subject: [PATCH][m68k] Partially fix PR target/28181 (movqi from mem to address register)
Hi.
This one looked to me like a fairly obvious misspecification of the
CANNOT_CHANGE_MODE_CLASS macro, so I built a cross compiler from
i686-pc-linux-gnu to m68k-elf (with no binutils, just asm output) to see if
I could fix the ICE. I used the second of the two mini.c testcases.
During reload, the insn
(insn 49 48 50 4 (set (reg:SI 67)
(minus:SI (subreg:SI (mem/s:QI (plus:SI (reg/f:SI 14 %a6)
(const_int -128 [0xffffff80])) [0 name+0 S1 A16]) 0)
(subreg:SI (mem/s:QI (plus:SI (reg/f:SI 14 %a6)
(const_int -127 [0xffffff81])) [0 name+1 S1 A8]) 0))) 162 {subsi3} (nil)
(nil))
produces two reloads
Reloads for insn # 49
Reload 0: reload_in (QI) = (mem/s:QI (plus:SI (reg/f:SI 14 %a6)
(const_int -128 [0xffffff80])) [0 name+0 S1 A16])
reload_out (SI) = (reg:SI 8 %a0 [67])
ADDR_REGS, RELOAD_OTHER (opnum = 0)
reload_in_reg: (mem/s:QI (plus:SI (reg/f:SI 14 %a6)
(const_int -128 [0xffffff80])) [0 name+0 S1 A16])
reload_out_reg: (reg:SI 8 %a0 [67])
reload_reg_rtx: (reg:SI 8 %a0 [67])
Reload 1: reload_in (QI) = (mem/s:QI (plus:SI (reg/f:SI 14 %a6)
(const_int -127 [0xffffff81])) [0 name+1 S1 A8])
DATA_REGS, RELOAD_FOR_INPUT (opnum = 2)
reload_in_reg: (mem/s:QI (plus:SI (reg/f:SI 14 %a6)
(const_int -127 [0xffffff81])) [0 name+1 S1 A8])
reload_reg_rtx: (reg:QI 0 %d0)
which results in these three insns, including the one which needed
reloading:
(insn 183 48 184 4 (set (reg:QI 8 %a0)
(mem/s:QI (plus:SI (reg/f:SI 14 %a6)
(const_int -128 [0xffffff80])) [0 name+0 S1 A16])) 41 {*m68k.md:748} (nil)
(nil))
(insn 184 183 49 4 (set (reg:QI 0 %d0)
(mem/s:QI (plus:SI (reg/f:SI 14 %a6)
(const_int -127 [0xffffff81])) [0 name+1 S1 A8])) 41 {*m68k.md:748} (nil)
(nil))
(insn 49 184 185 4 (set (reg:SI 8 %a0 [67])
(minus:SI (reg:SI 8 %a0 [+-3 ])
(reg:SI 0 %d0 [+-3 ]))) 162 {subsi3} (nil)
(nil))
Insn 183 doesn't satisfy its constraints, because QImode values can only
be copied into an address register from an immediate or a register. I assume
this is faked with a HImode copy.
The patch below fixes the ICE, but the resulting code will not work on
68000 and 68010 CPUs because of the unaligned longword access (insn 183):
.L20:
move.l -131(%fp),%a0 | 183 *m68k.md:671/1
move.b -127(%fp),%d0 | 184 *m68k.md:748/1
sub.l %d0,%a0 | 49 subsi3/3
I think it is enough of an improvement to post here, though. I might get
around to run a simulator test this week, but feel free to beat me to it. I
have no idea how to fix the alignment problem.
I do wonder how the m68k back end managed to produce code for so long
without CANNOT_CHANGE_MODE_CLASS defined.
ChangeLog:
2006-12-11 Rask Ingemann Lambertsen <rask@sygehus.dk>
PR target/28181
* config/m68k/m68k.h (CANNOT_CHANGE_MODE_CLASS): New. Forbid
address registers from changing mode to/from an 8-bit mode.
Index: config/m68k/m68k.h
===================================================================
--- config/m68k/m68k.h (revision 119451)
+++ config/m68k/m68k.h (working copy)
@@ -436,6 +436,13 @@ extern enum reg_class regno_reg_class[];
? DATA_REGS \
: (CLASS))
+/* Classes containing address registers can not change mode to or from a mode
+ which is 8 bits wide. */
+#define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS) \
+ ((GET_MODE_SIZE (TO) == 1 || GET_MODE_SIZE (FROM) == 1) \
+ && ((CLASS) == ADDR_REGS || (CLASS) == ADDR_OR_FP_REGS \
+ || (CLASS) == GENERAL_REGS || (CLASS) == ALL_REGS))
+
/* On the m68k, this is the size of MODE in words,
except in the FP regs, where a single reg is always enough. */
#define CLASS_MAX_NREGS(CLASS, MODE) \
--
Rask Ingemann Lambertsen