This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
Reload using a live register to reload into
- From: "Pranav Bhandarkar" <pranav dot bhandarkar at gmail dot com>
- To: gcc at gcc dot gnu dot org
- Date: Tue, 6 Nov 2007 18:12:57 +0530
- Subject: Reload using a live register to reload into
Hi,
Working on a private port I am seeing a problem with reload clobbering
a live register and thus causing havoc.
Consider the following snippet of the code dump.
(note:HI 85 84 86 5 [bb 5] NOTE_INSN_BASIC_BLOCK)
(note:HI 86 85 89 5 NOTE_INSN_DELETED)
(insn:HI 89 86 87 5 cor_h.c:129 (set (reg:SI 3 $c3 [ ivtmp.103 ])
(sign_extend:SI (subreg:HI (reg:SI 206 [ ivtmp.103 ]) 0))) 86
{extendhisi2} (nil))
(insn:HI 87 89 88 5 cor_h.c:129 (set (reg:SI 1 $c1 [ ivtmp.101 ])
(reg:SI 208 [ ivtmp.101 ])) 45 {*movsi} (nil))
(insn:HI 88 87 270 5 cor_h.c:129 (set (reg:SI 2 $c2 [ h ])
(reg/v/f:SI 236 [ h ])) 45 {*movsi} (nil))
(insn:HI 270 88 91 5 cor_h.c:129 (set (reg:SI 4 $c4)
(const_int 0 [0x0])) 45 {*movsi} (nil))
(call_insn:HI 91 270 92 5 cor_h.c:129 (parallel [
(set (reg:SI 1 $c1)
(call (mem:SI (symbol_ref:SI
("DotProductWithoutShift") [flags 0x41] <function_decl 0x401f7d00
DotProductWithoutShift>) [0 S4 A32])
(const_int 0 [0x0])))
(use (const_int 0 [0x0]))
(clobber (reg:SI 31 $link))
]) 42 {*call_value_direct} (expr_list:REG_DEAD (reg:SI 4 $c4)
(expr_list:REG_DEAD (reg:SI 3 $c3 [ ivtmp.103 ])
(expr_list:REG_DEAD (reg:SI 2 $c2 [ h ])
(nil))))
(expr_list:REG_DEP_TRUE (use (reg:SI 4 $c4))
(expr_list:REG_DEP_TRUE (use (reg:SI 3 $c3 [ ivtmp.103 ]))
(expr_list:REG_DEP_TRUE (use (reg:SI 2 $c2 [ h ]))
(expr_list:REG_DEP_TRUE (use (reg:SI 1 $c1 [ ivtmp.101 ]))
(nil))))))
(insn:HI 92 91 285 5 cor_h.c:129 (set (reg/v:SI 230 [ s ])
(reg:SI 1 $c1)) 45 {*movsi} (expr_list:REG_DEAD (reg:SI 1 $c1)
(nil)))
(jump_insn:HI 285 92 286 5 (set (pc)
(label_ref 118)) 8 {jump} (nil))
;; End of basic block 5 -> ( 10)
The register $c1 is used to pass the first argument to the function
DotProductWithoutShift
On encountering the call_insn ( insn no 91) global.c inserts a store
to save the register $c16 (which contains a variable 'tot' and $c16
is a caller save register ).
Hence the following insn is inserted just before the call to
DotProductWithoutShift.
(insn 309 270 91 5 cor_h.c:129 (set (mem/c:SI (plus:SI (reg/f:SI 29 $sp)
(const_int 176 [0xb0])) [11 S4 A32])
(reg:SI 16 $c16)) 45 {*movsi} (nil))
However the index 176 is too large and
(plus:SI (reg/f:SI 29 $sp)
(const_int 176 [0xb0])) needs to be reloaded.
$c1 gets chosen for this reload and now the dump snippet looks like
(note:HI 85 84 86 5 [bb 5] NOTE_INSN_BASIC_BLOCK)
(note:HI 86 85 89 5 NOTE_INSN_DELETED)
(insn:HI 89 86 87 5 cor_h.c:129 (set (reg:SI 3 $c3 [ ivtmp.103 ])
(sign_extend:SI (reg:HI 14 $c14 [orig:206 ivtmp.103 ] [206])))
86 {extendhisi2} (nil))
(insn:HI 87 89 88 5 cor_h.c:129 (set (reg:SI 1 $c1 [ ivtmp.101 ])
(reg:SI 8 $c8 [orig:208 ivtmp.101 ] [208])) 45 {*movsi} (nil))
(insn:HI 88 87 270 5 cor_h.c:129 (set (reg:SI 2 $c2 [ h ])
(reg/v/f:SI 22 $c22 [orig:236 h ] [236])) 45 {*movsi} (nil))
(insn:HI 270 88 329 5 cor_h.c:129 (set (reg:SI 4 $c4)
(const_int 0 [0x0])) 45 {*movsi} (nil))
(insn 329 270 330 5 cor_h.c:129 (set (reg:SI 1 $c1)
(const_int 176 [0xb0])) 45 {*movsi} (nil))
(insn 330 329 309 5 cor_h.c:129 (set (reg:SI 1 $c1)
(plus:SI (reg:SI 1 $c1)
(reg/f:SI 29 $sp))) 65 {*addsi3} (expr_list:REG_EQUIV
(plus:SI (reg/f:SI 29 $sp)
(const_int 176 [0xb0]))
(nil)))
(insn 309 330 91 5 cor_h.c:129 (set (mem/c:SI (reg:SI 1 $c1) [11 S4 A32])
(reg:SI 16 $c16)) 45 {*movsi} (nil))
(call_insn:HI 91 309 332 5 cor_h.c:129 (parallel [
(set (reg:SI 1 $c1)
(call (mem:SI (symbol_ref:SI
("DotProductWithoutShift") [flags 0x41] <function_decl 0x401f7d00
DotProductWithoutShift>) [0 S4 A32])
(const_int 0 [0x0])))
(use (const_int 0 [0x0]))
(clobber (reg:SI 31 $link))
]) 42 {*call_value_direct} (nil)
(expr_list:REG_DEP_TRUE (use (reg:SI 4 $c4))
(expr_list:REG_DEP_TRUE (use (reg:SI 3 $c3 [ ivtmp.103 ]))
(expr_list:REG_DEP_TRUE (use (reg:SI 2 $c2 [ h ]))
(expr_list:REG_DEP_TRUE (use (reg:SI 1 $c1 [ ivtmp.101 ]))
(nil))))))
(insn 332 91 333 5 (set (reg:SI 4 $c4)
(const_int 176 [0xb0])) 45 {*movsi} (nil))
(insn 333 332 310 5 (set (reg:SI 4 $c4)
(plus:SI (reg:SI 4 $c4)
(reg/f:SI 29 $sp))) 65 {*addsi3} (expr_list:REG_EQUIV
(plus:SI (reg/f:SI 29 $sp)
(const_int 176 [0xb0]))
(nil)))
(insn 310 333 285 5 (set (reg:SI 16 $c16)
(mem/c:SI (reg:SI 4 $c4) [11 S4 A32])) 45 {*movsi} (nil))
(jump_insn:HI 285 310 286 5 (set (pc)
(label_ref 118)) 8 {jump} (nil))
;; End of basic block 5 -> ( 10)
clearly the register $c1 which after insn 87 has the first argument of
the function DotProductWithoutShift is overwritten.
The file.c.176r.greg for insn 309 says
"Spilling for insn 309.
Using reg 6 for reload 0"
and indeed rld[0].regno is 6 and rld[0].in is
(plus:SI (reg/f:SI 29 $sp)
(const_int 176 [0xb0]))
However the function choose_reload_regs chooses $c1 for this reload
and sets rld[0].reg_rtx to the rtl expression for $c1.
Looking at struct reload in reload.h I am a little confused about the
use of regno and reg_rtx. While the comment for reg_rtx is quite
clear, for
regno it reads,
/* Used in find_reload_regs to record the allocated register. */
and for reg_rtx it reads,
/* This is the register to reload into. If it is zero when `find_reloads'
returns, you must find a suitable register in the class specified by
reload_reg_class, and store here an rtx for that register with mode from
reload_inmode or reload_outmode. */
I am confused whether reg_rtx should always be the rtl expression for
regno ? or am I missing something here.
Anyways shouldnt reload be checking for live registers before
reloading into them ?
TIA,
Pranav