This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]