Почему gcc заполняет весь массив нулями вместо оставшихся 96 целых чисел? Все ненулевые инициализаторы находятся в начале массива.
void *sink;
void bar() {
int a[100]{1,2,3,4};
sink = a; // a escapes the function
asm("":::"memory"); // and compiler memory barrier
// forces the compiler to materialize a[] in memory instead of optimizing away
}
MinGW8.1 и gcc9.2 оба создают asm вот так ( проводник компилятора Godbolt ).
# gcc9.2 -O3 -m32 -mno-sse
bar():
push edi # save call-preserved EDI which rep stos uses
xor eax, eax # eax=0
mov ecx, 100 # repeat-count = 100
sub esp, 400 # reserve 400 bytes on the stack
mov edi, esp # dst for rep stos
mov DWORD PTR sink, esp # sink = a
rep stosd # memset(a, 0, 400)
mov DWORD PTR [esp], 1 # then store the non-zero initializers
mov DWORD PTR [esp+4], 2 # over the zeroed part of the array
mov DWORD PTR [esp+8], 3
mov DWORD PTR [esp+12], 4
# memory barrier empty asm statement is here.
add esp, 400 # cleanup the stack
pop edi # and restore caller's EDI
ret
(с включенным SSE он скопирует все 4 инициализатора с загрузкой / хранением movdqa)
Почему GCC не делает lea edi, [esp+16]и устанавливает (с rep stosd) только последние 96 элементов, как это делает Кланг? Это пропущенная оптимизация или так эффективнее? (На самом деле звонит Clang memsetвместо того, чтобы вставлять rep stos)
Примечание редактора: изначально вопрос содержал неоптимизированный вывод компилятора, который работал таким же образом, но неэффективный код -O0ничего не доказывает. Но оказывается, что эта оптимизация пропущена GCC даже в -O3.
Передача указателя на aне встроенную функцию была бы другим способом заставить компилятор материализоваться a[], но в 32-битном коде, который приводит к значительному загромождению asm. (Аргументы стека приводят к толчкам, которые смешиваются с хранилищами в стеке для инициализации массива.)
Использование volatile a[100]{1,2,3,4}получает GCC для создания, а затем скопировать массив, что безумие. Обычно volatileполезно посмотреть, как компиляторы инициируют локальные переменные или размещают их в стеке.
.rodata... Я не могу поверить, что копирование 400 байтов происходит быстрее, чем обнуление и установка 8 элементов.
-O3(что и происходит). godbolt.org/z/rh_TNF
missed-optimizationключевым словом.
a[0] = 0;и тогдаa[0] = 1;.