I've run into a case where reload clobbers a register which it had
decided to use for reload inheritance. Reload is given this:

(insn 623 430 431 35 ../../.././gcc/dp-bit.c:734 (set (reg:HI 162 [+6 ])
        (mem/c/i:HI (plus:HI (reg/f:HI 10 bp)
                (const_int -2 [0xfffffffe])) [0 S2 A16])) 9 {*movhi} (nil)
    (expr_list:REG_EQUIV (mem/c/i:HI (plus:HI (reg/f:HI 10 bp)
                (const_int -2 [0xfffffffe])) [0 S2 A16])
        (nil)))

(insn 431 623 432 35 ../../.././gcc/dp-bit.c:734 (set (mem/s/j:HI (plus:HI 
(reg/v/f:HI 37 [ tmp ])
                (const_int 10 [0xa])) [0 <variable>.fraction.ll+6 S2 A16])
        (reg:HI 162 [+6 ])) 9 {*movhi} (insn_list:REG_DEP_TRUE 421 (nil))
    (expr_list:REG_DEAD (reg:HI 162 [+6 ])
        (nil)))

(note 432 431 433 35)

(note 433 432 434 35)

(insn 434 433 435 35 ../../.././gcc/dp-bit.c:735 (parallel [
            (set (mem/s/j:HI (plus:HI (reg/v/f:HI 37 [ tmp ])
                        (const_int 2 [0x2])) [0 <variable>.normal_exp+0 S2 A16])
                (plus:HI (mem/s/j:HI (plus:HI (reg/v/f:HI 37 [ tmp ])
                            (const_int 2 [0x2])) [0 <variable>.normal_exp+0 S2 
A16])
                    (const_int 1 [0x1])))
            (clobber (reg:CC 13 cc))
        ]) 44 {*addhi3} (nil)
    (expr_list:REG_UNUSED (reg:CC 13 cc)
        (nil)))

   Reload faces two problems here:
1) Eliminating %bp to %sp where %sp can not be used as a base register.
2) Register 37 didn't get a hard reg, so it is on the stack.

   Reload handles insns 623 and 431 fine and correctly records that register
37 has been loaded into %bx (reg:HI 6 b) as a result. Unfortunately, reload
clobbers %bx in insn 897 before using %bx in insn 434.

        movw    %sp,    %bx     ;# 895  *movhi/1
        movw    74(%bx),%ax     ;# 623  *movhi/1

        movw    94(%bx),%bx     ;# 896  *movhi/1
        movw    %ax,    10(%bx) ;# 431  *movhi/2

        movw    %sp,    %bx     ;# 897  *movhi/1
        incw    2(%bx)          ;# 434  *addhi3/1

   Everything looks fine early in choose_reload_regs():

(gdb) call debug_rtx (chain->insn)
(insn 434 433 435 35 ../../.././gcc/dp-bit.c:735 (parallel [
            (set (mem/s/j:HI (plus:HI (reg/v/f:HI 37 [ tmp ])
                        (const_int 2 [0x2])) [0 <variable>.normal_exp+0 S2 A16])
                (plus:HI (mem/s/j:HI (plus:HI (reg/v/f:HI 37 [ tmp ])
                            (const_int 2 [0x2])) [0 <variable>.normal_exp+0 S2 
A16])
                    (const_int 1 [0x1])))
            (clobber (reg:CC 13 cc))
        ]) 44 {*addhi3} (nil)
    (expr_list:REG_UNUSED (reg:CC 13 cc)
        (nil)))

   The *addhi3 pattern is nothing unusual. We're using the first
alternative of adding one to a memory operand:

(define_insn "*addhi3"
  [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,rm,qm,qm,r,m,!r,!r")
     (plus:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0,0,0,0,0,*w,*B")
              (match_operand:HI 2 "general_operand" "P1,M1,Um,Uo,g,ri,*x,i")))
   (clobber (reg:CC CC_REG))]

(gdb) call debug_reload()
Reload order: 0 1 2 3 4
Reload 0: reload_in (HI) = (reg/f:HI 12 sp)
        BASE_REGS, RELOAD_FOR_OPADDR_ADDR (opnum = 0)
        reload_in_reg: (reg/f:HI 12 sp)
Reload 1: reload_in (HI) = (mem/f/c/i:HI (plus:HI (reg/f:HI 12 sp)
                                                        (const_int 94 [0x5e])) 
[0 tmp+0 S2 A16])
        BASE_REGS, RELOAD_FOR_OPERAND_ADDRESS (opnum = 0), can't combine
        reload_in_reg: (reg/v/f:HI 37 [ tmp ])
Reload 2: BASE_REGS, RELOAD_FOR_OPERAND_ADDRESS (opnum = 0)
        reload_in_reg: (reg/f:HI 12 sp)
Reload 3: BASE_REGS, RELOAD_FOR_OPERAND_ADDRESS (opnum = 0), can't combine
        reload_in_reg: (reg/v/f:HI 37 [ tmp ])
Reload 4: reload_in (HI) = (mem/s/j:HI (plus:HI (reg/v/f:HI 37 [ tmp ])
                                                        (const_int 2 [0x2])) [0 
<variable>.normal_exp+0 S2 A16])
        reload_out (HI) = (mem/s/j:HI (plus:HI (reg/v/f:HI 37 [ tmp ])
                                                        (const_int 2 [0x2])) [0 
<variable>.normal_exp+0 S2 A16])
        GENERAL_REGS, RELOAD_OTHER (opnum = 0), optional
        reload_in_reg: (mem/s/j:HI (plus:HI (reg/v/f:HI 37 [ tmp ])
                                                        (const_int 2 [0x2])) [0 
<variable>.normal_exp+0 S2 A16])
        reload_out_reg: (mem/s/j:HI (plus:HI (reg/v/f:HI 37 [ tmp ])
                                                        (const_int 2 [0x2])) [0 
<variable>.normal_exp+0 S2 A16])

reload 0:
(gdb) print regno
$61 = 12
(gdb) call debug_rtx(reg_last_reload_reg[regno])
(reg:HI 6 b)
(gdb) print /x reg_reloaded_valid
$67 = 0xc0
(gdb) print reg_reloaded_contents[6]
$64 = 37
(gdb) print reg_reloaded_contents[7]
$65 = 37
(gdb) print [EMAIL PROTECTED]
$70 = "\000\000\000\000"

   I.e. reload looks at register 6 for reload inheritance, but the contents
aren't right, so no reload inheritance for reload 0.

reload 1:
(gdb) print regno
$77 = 37
(gdb) print mode
$78 = HImode
(gdb) call debug_rtx(reg_last_reload_reg[regno])
(reg:HI 6 b)

(gdb) s
free_for_value_p (regno=6, mode=HImode, opnum=0, 
type=RELOAD_FOR_OPERAND_ADDRESS, value=0xb7d58f18, out=0xb7e72210, reloadnum=1, 
ignore_address_reloads=1)
    at ../../../cvssrc/gcc/gcc/reload1.c:5294
(gdb) fin
Run till exit from #0  free_for_value_p (regno=6, mode=HImode, opnum=0, 
type=RELOAD_FOR_OPERAND_ADDRESS, value=0xb7d58f18, out=0xb7e72210, reloadnum=1,
    ignore_address_reloads=1) at ../../../cvssrc/gcc/gcc/reload1.c:5300
0x083cd89e in choose_reload_regs (chain=0x90e4fe8) at 
../../../cvssrc/gcc/gcc/reload1.c:5792
Value returned is $85 = 1

   So reload decides to use hard reg 6 (%bx) for reg 37 because the previous
reload can be inherited:

(gdb) s
mark_reload_reg_in_use (regno=6, opnum=0, type=RELOAD_FOR_OPERAND_ADDRESS, 
mode=HImode) at ../../../cvssrc/gcc/gcc/reload1.c:4449
(gdb) print /x reload_reg_used_in_op_addr
$90 = 0xc0
(gdb) print /x reload_reg_used_at_all
$91 = 0xc0

   Additionally, it is recorded that this reload uses inheritance:

                              rld[r].reg_rtx = last_reg;
                              reload_inherited[r] = 1;
                              reload_inheritance_insn[r]
                                = reg_reloaded_insn[i];
                              reload_spill_index[r] = i;
                              for (k = 0; k < nr; k++)
                                SET_HARD_REG_BIT (reload_reg_used_for_inherit,
                                                  i + k);

   For reload 0, choose_reload_regs() needs to allocate a register:

(gdb) s
allocate_reload_reg (chain=0x90e4fe8, r=0, last_reload=0) at 
../../../cvssrc/gcc/gcc/reload1.c:5439

We have

(gdb) print /x reload_reg_used_in_op_addr_reload
$102 = 0x0
(gdb) print /x reload_reg_used_at_all
$110 = 0xc0
(gdb) print /x reload_reg_used_for_inherit
$111 = 0xc0

   allocate_reload_reg() checks reload_reg_free_p(), where we have:

    case RELOAD_FOR_OPADDR_ADDR:
      for (i = 0; i < reload_n_operands; i++)
        if (TEST_HARD_REG_BIT (reload_reg_used_in_input[i], regno))
          return 0;
      return (!TEST_HARD_REG_BIT (reload_reg_used_in_op_addr_reload, regno));

   but no check for reload_reg_used_for_inherit. In fact, the only place where
reload_reg_used_for_inherit is checked is in allocate_reload_reg()

              /* Look first for regs to share, then for unshared.  But
                 don't share regs used for inherited reloads; they are
                 the ones we want to preserve.  */
              && (pass
                  || (TEST_HARD_REG_BIT (reload_reg_used_at_all,
                                         regnum)
                      && ! TEST_HARD_REG_BIT (reload_reg_used_for_inherit,
                                              regnum))))

and I'm wondering if perhaps the parentheses have become misplaced. I
mean, the code would better match the comment if written as

              && (pass
                  || TEST_HARD_REG_BIT (reload_reg_used_at_all,
                                         regnum))
              && ! TEST_HARD_REG_BIT (reload_reg_used_for_inherit,
                                              regnum)))

but the code seems to match the log entry:

----------
r3991 | kenner | 1993-04-03 01:43:16 +0200 (l, 03 apr 1993) | 8 lines

(reload_reg_used_for_inherit): New variable.
(clear_reload_reg_in_use): New function.
(allocate_reload_reg): Don't consider an inherited register as one that we
should share in the first pass.
Don't mark a register in use until we are sure it will fit.
(choose_reload_regs): Mark spill regs used for inheriting.
When we decide we can no longer use a register, show it isn't being used.
----------

   I.e. we're deliberately clobbering inherited registers the second time
around.

   So when the time comes to actually emit the reload insns, we emit insn
897 for reload 0, clobbering %bx (reg:HI 6 b):

(gdb) fin
Run till exit from #0  gen_reload (out=0xb7d7e460, in=0xb7ea6000, opnum=0, 
type=RELOAD_FOR_OPADDR_ADDR) at ../../../cvssrc/gcc/gcc/reload1.c:8047
emit_input_reload_insns (chain=0x99b1000, rl=0x88ed780, old=0xb7ea6000, j=0) at 
../../../cvssrc/gcc/gcc/reload1.c:6978
Value returned is $10 = (struct rtx_def *) 0xb7d8c3e8
(gdb) call debug_rtx($10)
(insn 897 0 0 (set (reg:HI 6 b)
        (reg/f:HI 12 sp)) -1 (nil)
    (nil))

   On to reload 1:

(gdb) s
do_input_reload (chain=0x99b1000, rl=0x88ed7cc, j=1) at 
../../../cvssrc/gcc/gcc/reload1.c:7221
(gdb) print *rl
$16 = {in = 0xb7d8bf18, out = 0x0, class = BASE_REGS, inmode = HImode, outmode 
= VOIDmode, mode = HImode, nregs = 4, inc = 0, in_reg = 0xb7f98e20,
  out_reg = 0x0, regno = -1, reg_rtx = 0xb7d7e460, opnum = 0, 
secondary_in_reload = -1, secondary_out_reload = -1, secondary_in_icode = 
CODE_FOR_nothing,
  secondary_out_icode = CODE_FOR_nothing, when_needed = 
RELOAD_FOR_OPERAND_ADDRESS, optional = 0, nocombine = 1, secondary_p = 0, 
nongroup = 0}
(gdb) print [EMAIL PROTECTED]
$19 = "\000\001\000\000"

   Because reload_inherited[1] = 1, do_input_reload() doesn't call
emit_input_reload_insns(). There is no check that the reload register still
contains the correct value, and besides, reg_reloaded_valid and
reg_reloaded_contents aren't updated until later anyway.

-- 
Rask Ingemann Lambertsen

Reply via email to