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 memset
satı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 -O0
hiçbir şey kanıtlamıyor. Ancak bu optimizasyonun GCC tarafından bile kaçırıldığı ortaya çıktı -O3
.
Bir işaretçi geçen a
olmayan 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 volatile
derleyicilerin 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-optimization
anahtar kelimesini bildirin .
a[0] = 0;
ve sonraa[0] = 1;
.