Ping ~
On 11/12/17 15:27, Renlin Li wrote:
Hi all,
In aarch64 backend, ip0/ip1 register will be used in the prologue/epilogue as
temporary register.
When the compiler is performing sibcall optimization. It has the chance to use
ip0/ip1 register for indirect function call to hold the address. However, those
two register might
be clobbered by the epilogue code which makes the last sibcall instruction
invalid.
The following is an extreme example:
When built with -O2 -ffixed-x0 -ffixed-x1 -ffixed-x2 -ffixed-x3 -ffixed-x4
-ffixed-x5 -ffixed-x6 -ffixed-x7
-ffixed-x8 -ffixed-x9 -ffixed-x10 -ffixed-x11 -ffixed-x12 -ffixed-x13
-ffixed-x14 -ffixed-x15 -ffixed-x17 -ffixed-x18
void (*f)();
int xx;
void tailcall (int i)
{
int arr[5000];
xx = arr[i];
f();
}
tailcall:
mov x16, 20016
sub sp, sp, x16
adrp x16, .LANCHOR0
stp x19, x30, [sp]
add x19, sp, 16
ldr s0, [x19, w0, sxtw 2]
ldp x19, x30, [sp]
str s0, [x16, #:lo12:.LANCHOR0]
mov x16, 20016
add sp, sp, x16
br x16 // oops
As we can see, x16 is used in the indirect sibcall instruction. It is used as
a temporary in the epilogue code as well. The register allocation is invalid.
With the change, the register allocator is only allowed to use r0-r15, r18 for
indirect sibcall instruction.
For this particular case above, the compiler will ICE as there is not register
could be used for this sibcall instruction.
And I think it is better to fail instead of wrong code-generation.
test.c:10:1: error: unable to generate reloads for:
}
^
(call_insn/j 16 12 17 2 (parallel [
(call (mem:DI (reg/f:DI 84 [ f ]) [0 *f.0_2 S8 A8])
(const_int 0 [0]))
(return)
]) "test.c":9 42 {*sibcall_insn}
(expr_list:REG_DEAD (reg/f:DI 84 [ f ])
(expr_list:REG_CALL_DECL (nil)
(nil)))
(expr_list (clobber (reg:DI 17 x17))
(expr_list (clobber (reg:DI 16 x16))
(nil))))
aarch64-none-elf test without regressions. Okay to commit?
The same issue affects gcc-6, gcc-7 as well. Backport are needed for those
branches.
Regards,
Renlin
gcc/ChangeLog:
2017-12-11 Renlin Li <renlin...@arm.com>
PR target/83370
* config/aarch64/aarch64.c (aarch64_class_max_nregs): Handle
TAILCALL_ADDR_REGS.
(aarch64_register_move_cost): Likewise.
* config/aarch64/aarch64.h (reg_class): Rename CALLER_SAVE_REGS to
TAILCALL_ADDR_REGS.
* config/aarch64/constraints.md (Ucs): Update register constraint.