This is the mail archive of the gcc@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]

Bug in multiple register reload inheritance?


   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


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