Различная сборка gcc при использовании назначенных инициализаторов - PullRequest
0 голосов
/ 26 ноября 2018

Я проверял некоторые сгенерированные gcc сборки для ARM и заметил, что получаю странные результаты, если использую обозначенные инициализаторы:

Например, если у меня есть этот код:

struct test 
{
    int x;
    int y;
};

__attribute__((noinline))
struct test get_struct_1(void)
{
    struct test x;
    x.x = 123456780;
    x.y = 123456781;
    return x;
}

__attribute__((noinline))
struct test get_struct_2(void)
{
    return (struct test){ .x = 123456780, .y = 123456781 };
}

Я получаю следующий вывод с gcc -O2 -std = C11 для ARM (ARM GCC 6.3.0):

get_struct_1:
    ldr r1, .L2
    ldr r2, .L2+4
    stm r0, {r1, r2}
    bx lr
.L2:
    .word 123456780
    .word 123456781


get_struct_2:     // <--- what is happening here
    mov r3, r0
    ldr r2, .L5
    ldm r2, {r0, r1}
    stm r3, {r0, r1}
    mov r0, r3
    bx lr
.L5:
    .word .LANCHOR0

Я вижу константы для первой функции, но я не вижупонять, как работает get_struct_2.

Если я скомпилирую для x86, обе функции просто загружают одно и то же 64-разрядное значение в одной инструкции.

get_struct_1:
    movabs rax, 530242836987890956
    ret

get_struct_2:
    movabs rax, 530242836987890956
    ret

Я провоцирую какое-то неопределенное поведение или это .LANCHOR0как-то связано с этими константами?

1 Ответ

0 голосов
/ 26 ноября 2018

Похоже, что gcc стреляет себе в ногу с дополнительным уровнем косвенности после объединения нагрузок констант в ldm.

Не знаю почему, но, очевидно, пропущенная ошибка оптимизации.

x86-64 легко оптимизировать;вся 8-байтовая константа может быть введена сразу.Но ARM часто использует относительные нагрузки ПК для констант, которые слишком велики для одного немедленного.

...