https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90553
Bug ID: 90553
Summary: Register allocation allocates post-incremented
address-load of call to call-clobbered register
Product: gcc
Version: 9.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: middle-end
Assignee: unassigned at gcc dot gnu.org
Reporter: hp at gcc dot gnu.org
Target Milestone: ---
Target: cris-elf
For this code, similar to the newlib newlib/libc/misc/init.c:__init_array
function, IRA is responsible for allocating a call-clobbered register for the
address to the array of functions to call. To wit, that register is then
clobbered by the called function:
extern void (*p []) (void);
void f(int x)
{
int i;
for (i = 0; i < x; i++)
p[i]();
}
The generated code for cris-elf with -O2 for r271317 (leading ELF-assembly
sugar elided):
_f:
subq 4,$sp
move $srp,[$sp]
subq 8,$sp
movem $r1,[$sp]
cmpq 1,$r10
blt .L1
move.d $r10,$r1
move.d _p,$r9
clear.d $r0
.L3:
jsr [$r9+]
addq 1,$r0
cmp.d $r0,$r1
bne .L3
nop
.L1:
movem [$sp+],$r1
jump [$sp+]
To all those not fluent in CRIS assembly, in gcc-rtl, the call instruction is
(from the 312r.final dump):
(call_insn 16 14 17 (parallel [
(call (mem:QI (mem/f:SI (post_inc:SI (reg:SI 9 r9 [orig:27 ivtmp.7
] [27])) [1 MEM[base: _8, offset: 0B]+0 S4 A8]) [0 *_1 S1 A8])
(const_int 0 [0]))
(clobber (reg:SI 16 srp))
]) "t.c":7:5 220 {*expanded_call_non_v32}
(expr_list:REG_UNUSED (reg:SI 9 r9 [orig:27 ivtmp.7 ] [27])
(expr_list:REG_INC (reg:SI 9 r9 [orig:27 ivtmp.7 ] [27])
(expr_list:REG_CALL_DECL (nil)
(nil))))
(nil))
That is, the address to call is loaded from the pointer in R9, which is
post-incremented. The register R9 is call-clobbered and mentioned as such in
CALL_USED_REGISTERS.
In the IRA dump in 276r.ira, pseudo-register 27 is is allocated to register R9.
Following ira-lives.c:process_bb_node_lives it's apparent that the
post-increment addressing is handled as the register being read at the
beginning of the call, and the updated value happening *after* the call.
It's open whether gcc *should* be able to handle this construct (a trivial
patch to ira-lives.c) or whether this should be deemed outside what gcc
currently can handle regarding register-allocation (the post-incrementing to be
disabled until post-reload and the documentation updated). I'l marking this
middle-end for moment. There's a tested patch, to be posted.