जीसीसी केवल शेष 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 दोनों इस तरह से ( गॉडबोल्ट कंपाइलर एक्सप्लोरर ) बनाते हैं ।
# 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 load / store के साथ कॉपी करेगा)
जीसीसी केवल अंतिम 96 तत्वों को क्यों नहीं करता है lea edi, [esp+16]
और क्यों नहीं rep stosd
करता है? यह एक चूक अनुकूलन है, या यह किसी भी तरह से इसे इस तरह से अधिक कुशल है? (क्लैंग वास्तव memset
में इनलाइनिंग के बजाय कॉल करता है rep stos
)
संपादक का ध्यान दें: प्रश्न में मूल रूप से संयुक्त राष्ट्र के अनुकूलित आउटपुट आउटपुट थे जो उसी तरह से काम करते थे, लेकिन अक्षम कोड -O0
कुछ भी साबित नहीं करता है। लेकिन यह पता चला है कि यह अनुकूलन जीसीसी द्वारा भी याद किया जाता है -O3
।
एक इनलाइनर को a
नॉन-इनलाइन फ़ंक्शन के लिए पास करना कंपाइलर को भौतिक बनाने के लिए मजबूर करने का एक और तरीका होगा a[]
, लेकिन 32-बिट कोड में जो एएसएम के महत्वपूर्ण अव्यवस्था की ओर जाता है। (स्टैक आर्गेज का परिणाम धक्का होता है, जो स्टोर में स्टोर हो जाता है और सरणी को टॉयलेट करने के लिए मिलाया जाता है।)
उपयोग करने volatile a[100]{1,2,3,4}
से जीसीसी बन जाता है और फिर सरणी को कॉपी करता है, जो पागल है। आम तौर पर volatile
यह देखने के लिए अच्छा है कि स्थानीय चर कैसे संकलित करते हैं या स्टैक पर उन्हें बिछाते हैं।
.rodata
... मैं विश्वास नहीं कर सकता कि 400 बाइट्स की नकल करना शून्य करने और 8 आइटम सेट करने से अधिक तेज़ है।
-O3
(जो यह करता है)। godbolt.org/z/rh_TNF
missed-optimization
कीवर्ड के साथ बगज़िला पर रिपोर्ट करें ।
a[0] = 0;
और फिरa[0] = 1;
।