I'm having a problem where choose_reload_regs() calls
subreg_regno_offset() with invalid parameters for my 16-bit ix86 port. It
starts out fine in emit_reload_insns():
Breakpoint 6, emit_reload_insns (chain=0x882b5a8) at reload1.c:7506
reg_last_reload_reg[nregno] = rld[r].reg_rtx;
piecemeal = (nregno < FIRST_PSEUDO_REGISTER
&& nr == nnr
&& inherit_piecemeal_p (r, nregno));
if (nregno < FIRST_PSEUDO_REGISTER)
for (k = 1; k < nnr; k++)
reg_last_reload_reg[nregno + k]
= (piecemeal
? regno_reg_rtx[REGNO (rld[r].reg_rtx) + k]
: 0);
(gdb) print nregno
$443 = 10
(gdb) call debug_rtx (rld[r].reg_rtx)
(reg:SI 8 si)
Registers are Himode: 8 = si, 9 = di, 10 = bp and 11 = es.
(gdb) call debug_rtx (chain->insn)
(insn:HI 35 159 36 4 (set (mem:SI (pre_dec:HI (reg/f:HI 12 sp)) [0 S4 A8])
(reg/v:SI 10 bp [orig:24 arg_a ] [24])) 32 {*pushsi1} (nil)
(insn_list:REG_LIBCALL 39 (nil)))
(gdb) call debug_reload ()
Reload order: 0
Reload 0: reload_in (SI) = (reg/v:SI 10 bp [orig:24 arg_a ] [24])
GENERAL_REGS, RELOAD_FOR_INPUT (opnum = 0)
reload_in_reg: (reg/v:SI 10 bp [orig:24 arg_a ] [24])
reload_reg_rtx: (reg:SI 8 si)
The piecemeal path is taken and works fine:
(gdb) call debug_rtx (reg_last_reload_reg[10])
(reg:SI 8 si)
(gdb) call debug_rtx (reg_last_reload_reg[11])
(reg:HI 9 di)
So far, so good. Later, this happens in choose_reload_regs at
reload1.c:5640:
else if (GET_CODE (rld[r].in_reg) == SUBREG
&& REG_P (SUBREG_REG (rld[r].in_reg)))
{
byte = SUBREG_BYTE (rld[r].in_reg);
regno = REGNO (SUBREG_REG (rld[r].in_reg));
if (regno < FIRST_PSEUDO_REGISTER)
regno = subreg_regno (rld[r].in_reg);
mode = GET_MODE (rld[r].in_reg);
}
(gdb) frame 2
#2 0x084ec860 in choose_reload_regs (chain=0x882bbc4) at reload1.c:5674
(gdb) call debug_rtx (rld[r].in_reg)
(subreg:HI (reg/v:SI 10 bp [orig:24 arg_a ] [24]) 2)
(gdb) print byte
$472 = 2
(gdb) print regno
$473 = 11
(gdb) print mode
$474 = HImode
if (regno >= 0 && reg_last_reload_reg[regno] != 0)
{
enum reg_class class = rld[r].class, last_class;
rtx last_reg = reg_last_reload_reg[regno];
enum machine_mode need_mode;
i = REGNO (last_reg);
i += subreg_regno_offset (i, GET_MODE (last_reg), byte, mode);
(gdb) call debug_rtx (last_reg)
(reg:HI 9 di)
Here something has gone wrong, and the parameters to
subreg_regno_offset() are invalid:
(gdb) frame 1
#1 0x08504786 in subreg_regno_offset (xregno=9, xmode=HImode, offset=2,
ymode=HImode) at rtlanal.c:3017
If I take out the lines 5643 and 5644
if (regno < FIRST_PSEUDO_REGISTER)
regno = subreg_regno (rld[r].in_reg);
it will instead get regno = 10, mode = SImode and last_reg = (reg:SI 8 si)
and call subreg_regno_offset (xregno=8, xmode=SImode, offset=2, ymode=HImode)
which is fine and returns 1.
--
Rask Ingemann Lambertsen