Neden gcc tüm diziyi yalnızca kalan 96 tam sayı yerine sıfırlarla dolduruyor? Sıfır olmayan başlatıcıların tümü dizinin başlangıcındadır.
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 ve gcc9.2'nin ikisi de bu şekilde ortaya çıkıyor ( Godbolt derleyici gezgini ).
# 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 etkinken, 4 başlangıç ayarının tümünü movdqa load / store ile kopyalar)
GCC neden sadece Clang gibi son 96 elementi yapmıyor lea edi, [esp+16]ve takmıyor rep stosd? Bu kaçırılmış bir optimizasyon mu, yoksa bu şekilde yapmak daha verimli mi? (Clang aslında memsetsatır içi yerine çağırır rep stos)
Editörün notu: Soru aslında aynı şekilde çalışan optimize edilmemiş derleyici çıktısına sahipti, ancak adresindeki verimsiz kod -O0hiçbir şey kanıtlamıyor. Ancak bu optimizasyonun GCC tarafından bile kaçırıldığı ortaya çıktı -O3.
Bir işaretçi geçen aolmayan bir satır içi işlevi gerçekleştirmek için derleyici zorlamak için başka bir yol olacaktır a[], fakat 32-bit kodu asm önemli yığılmayı sebep olduğu anlamına gelmektedir. (Yığın argümanları, diziyi başlatmak için yığına depolarla karışan itmelerle sonuçlanır.)
Kullanmak deli dizi volatile a[100]{1,2,3,4}oluşturmak ve daha sonra kopyalamak için GCC alır . Normalde volatilederleyicilerin yerel değişkenleri nasıl başlattıklarına veya yığına nasıl yerleştirdiklerine bakmak iyidir.
.rodata... 400 bayt kopyalamanın sıfırlamaktan ve 8 öğeyi ayarlamaktan daha hızlı olduğuna inanamıyorum.
-O3. godbolt.org/z/rh_TNF
missed-optimizationanahtar kelimesini bildirin .
a[0] = 0;ve sonraa[0] = 1;.