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