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.

Reply via email to