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]

A question about push_reload()


   I think push_reload() is doing something weird with this insn:

Breakpoint 1, find_reloads (insn=0xb7f7e348, replace=0, ind_levels=0, live_known=0, reload_reg_p=0x8878a7c) at ../../../cvssrc/gcc/gcc/reload.c:2535
2535    {
(gdb) call debug_rtx(insn)
(insn 12 10 16 2 /tmp/ashiftsi3_1.c:3 (parallel [
            (set (subreg:HI (reg:SI 2 a [orig:20 D.1497 ] [20]) 0)
                (ashift:HI (reg:HI 8 si [orig:26 x ] [26])
                    (const_int 1 [0x1])))
            (clobber (reg:CC 13 cc))
        ]) 353 {*ashlhi3} (nil)
    (expr_list:REG_DEAD (reg:HI 8 si [orig:26 x ] [26])
        (expr_list:REG_UNUSED (reg:CC 13 cc)
            (insn_list:REG_RETVAL 13 (nil)))))

   where operands 0 and 1 must match. The resulting reloads are:

Spilling for insn 12.
Using reg 8 for reload 0

Reloads for insn # 12
Reload order: 0
Reload 0: reload_in (HI) = (reg:HI 26 [ x ])
	reload_out (SI) = (reg:SI 2 a [orig:20 D.1497 ] [20])
	GENERAL_REGS, RELOAD_OTHER (opnum = 0)
	reload_in_reg: (reg:HI 26 [ x ])
	reload_out_reg: (reg:SI 2 a [orig:20 D.1497 ] [20])
	reload_reg_rtx: (reg:SI 8 si)
;; Register dispositions:
20 in 2  21 in 8  22 in 9  23 in 2  24 in 0  25 in 0  

   It seems unnecessary to create a SImode output reload here and worse, it
clobbers (reg:HI 4 d) which is live ((reg:SI 2 a) is four registers):

(insn 40 10 12 2 /tmp/ashiftsi3_1.c:3 (set (reg:HI 8 si)
        (mem/c:HI (plus:HI (reg/f:HI 10 bp)
                (const_int -2 [0xfffffffe])) [0 S2 A8])) 9 {*movhi} (nil)
    (nil))

(insn 12 40 41 2 /tmp/ashiftsi3_1.c:3 (parallel [
            (set (reg:HI 8 si)
                (ashift:HI (reg:HI 8 si)
                    (const_int 1 [0x1])))
            (clobber (reg:CC 13 cc))
        ]) 353 {*ashlhi3} (nil)
    (nil))

(insn 41 12 42 2 /tmp/ashiftsi3_1.c:3 (set (reg:HI 2 a [orig:20 D.1497 ] [20])
        (reg:HI 8 si)) 9 {*movhi} (nil)
    (nil))

(insn 42 41 14 2 /tmp/ashiftsi3_1.c:3 (set (reg:HI 4 d [ D.1497+2 ])
        (reg:HI 9 di [+2 ])) 9 {*movhi} (nil)
    (nil))

   Register di was dead at this point, btw. The call to push_reload() seems
OK:

push_reload (in=0xb7f833b0, out=0xb7f7578c, inloc=0xb7f758bc, outloc=0xb7f758c8, class=GENERAL_REGS, inmode=HImode, outmode=HImode, strict_low=0, optional=0,
    opnum=0, type=RELOAD_OTHER) at ../../../cvssrc/gcc/gcc/reload.c:929
(gdb) call debug_rtx(in)
(reg:HI 8 si [orig:26 x ] [26])
(gdb) call debug_rtx(out)
(subreg:HI (reg:SI 2 a [orig:20 D.1497 ] [20]) 0)

Starting at line 1097 of reload.c is the interesting part:

  /* Similarly for paradoxical and problematical SUBREGs on the output.
     Note that there is no reason we need worry about the previous value
     of SUBREG_REG (out); even if wider than out,
     storing in a subreg is entitled to clobber it all
     (except in the case of STRICT_LOW_PART,
     and in that case the constraint should label it input-output.)  */
[...]
      || (REG_P (SUBREG_REG (out))
          && REGNO (SUBREG_REG (out)) < FIRST_PSEUDO_REGISTER
          && ((GET_MODE_SIZE (outmode) <= UNITS_PER_WORD
               && (GET_MODE_SIZE (GET_MODE (SUBREG_REG (out)))
                   > UNITS_PER_WORD)
               && ((GET_MODE_SIZE (GET_MODE (SUBREG_REG (out)))
                    / UNITS_PER_WORD)
                   != (int) hard_regno_nregs[REGNO (SUBREG_REG (out))]
                                            [GET_MODE (SUBREG_REG (out))]))
              || ! HARD_REGNO_MODE_OK (subreg_regno (out), outmode)))
[...]
    {
      out_subreg_loc = outloc;
      outloc = &SUBREG_REG (out);
      out = *outloc;
#if ! defined (LOAD_EXTEND_OP) && ! defined (WORD_REGISTER_OPERATIONS)
      gcc_assert (!MEM_P (out)
                  || GET_MODE_SIZE (GET_MODE (out))
                     <= GET_MODE_SIZE (outmode));
#endif
      outmode = GET_MODE (out);
    }

   What is the condition with hard_regno_nregs[][] supposed to check?
In this particular case, we have:

GET_MODE_SIZE (GET_MODE (SUBREG_REG (out))) = 4
UNITS_PER_WORD = 2
hard_regno_nregs[2][SImode] = 4 (8-bit registers)

so the condition 4 / 2 != 4 is true and reload thinks the SUBREG is
problematical. I don't see what is problematical about it.

   I tried to "svn blame" someone, but ended with:
------------------------------------------------------------------------
r363 | kenner | 1992-02-28 11:23:25 +0100 (fre, 28 feb 1992) | 2 lines

Initial revision
------------------------------------------------------------------------

-- 
Rask Ingemann Lambertsen


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