При создании кода для arm64, почему gcc + clang использует adrp + add вместо adr для адресации соседних переменных? - PullRequest
1 голос
/ 10 марта 2019

С помощью arm64 литерал для соседнего адреса можно загрузить в регистр с помощью инструкции adr . Согласно Справочному руководству по архитектуре ARM-V8 инструкция adr :

ADR <Xd>, <label>   Address of label at a PC-relative offset

может ссылаться на метки в пределах +/- 1 МБ. Существует версия страницы с установленным битом 31 adrp для создания больших смещений.

Я не понимаю, почему ни gcc 8.2 , ни clang 7.0 для ARM64 не используют adr вместо adrp и добавить пару для соседних переменных. Уровни оптимизации не меняют этого.

int write(int fd, const void *buf, int count);

void xyz(void)
{
    write(2, "abc", 4);
}

xyz(): // @xyz()
  adrp x1, .L.str
  add x1, x1, :lo12:.L.str
  orr w0, wzr, #0x2
  orr w2, wzr, #0x4
  b write(int, void const*, int)
.L.str:
  .asciz "abc"

Неужели они не считают, что этот строковый литерал находится в пределах +/- 1 МБ? Есть ли атрибут компилятора / ключ, чтобы сказать им это?

1 Ответ

1 голос
/ 10 марта 2019

GCC сгенерирует такой код с -mcmodel=tiny:

    .global xyz
    .type   xyz, %function
xyz:
.LFB0:
    .cfi_startproc
    mov w2, 4
    adr x1, .LC0
    mov w0, 2
    b   write
    .cfi_endproc
.LFE0:
    .size   xyz, .-xyz
    .section    .rodata.str1.8,"aMS",@progbits,1
    .align  3
.LC0:
    .string "abc"
...