के रूप में संकलित करते समय जीसीसी कोड पीढ़ी में बड़े अंतर मैं x86-64 असेंबली के साथ कुछ अलग-अलग सिम एक्सटेंशन (एमएमएक्स, एसएसई, एवीएक्स) के बारे में अधिक जानने की कोशिश कर रहा हूं।सी ++ बनाम सी
यह देखने के लिए कि सीसीसी या सी ++ संरचनाओं का जीसीसी द्वारा मशीन कोड में कितना अलग अनुवाद किया गया है, मैं Compiler Explorer का उपयोग कर रहा हूं जो एक शानदार उपकरण है।
मेरे 'प्ले सत्र' में से एक के दौरान मैं देखना चाहता था कि जीसीसी एक पूर्णांक सरणी के सरल रन-टाइम प्रारंभिकरण को कैसे अनुकूलित कर सकता है। इस मामले में मैंने संख्या 20 से 2047 को 2048 हस्ताक्षरित पूर्णांकों की सरणी में लिखने की कोशिश की।
कोड इस प्रकार दिखता है:
unsigned int buffer[2048];
void setup()
{
for (unsigned int i = 0; i < 2048; ++i)
{
buffer[i] = i;
}
}
अगर मैं अनुकूलन और AVX-512 निर्देश सक्षम -O3 -mavx512f -mtune=intel
जीसीसी 6.3 वास्तव में कुछ चालाक कोड :)
setup():
mov eax, OFFSET FLAT:buffer
mov edx, OFFSET FLAT:buffer+8192
vmovdqa64 zmm0, ZMMWORD PTR .LC0[rip]
vmovdqa64 zmm1, ZMMWORD PTR .LC1[rip]
.L2:
vmovdqa64 ZMMWORD PTR [rax], zmm0
add rax, 64
cmp rdx, rax
vpaddd zmm0, zmm0, zmm1
jne .L2
ret
buffer:
.zero 8192
.LC0:
.long 0
.long 1
.long 2
.long 3
.long 4
.long 5
.long 6
.long 7
.long 8
.long 9
.long 10
.long 11
.long 12
.long 13
.long 14
.long 15
.LC1:
.long 16
.long 16
.long 16
.long 16
.long 16
.long 16
.long 16
.long 16
.long 16
.long 16
.long 16
.long 16
.long 16
.long 16
.long 16
.long 16
, जब मैं परीक्षण किया उत्पन्न करता है फिर भी क्या होगा अगर 0xझंडे जोड़कर जीसीसी सी-कंपाइलर का उपयोग करके उसी कोड को संकलित किया गया था तो मैं उत्पन्न हुआ था। मैं वास्तव में आश्चर्यचकित था।
मुझे समान उम्मीद है, अगर समान नहीं है, तो परिणामस्वरूप सी-कंपाइलर उत्पन्न करता है अधिक जटिल और संभवतः धीमे मशीन कोड भी। परिणामी असेंबली पूरी तरह से पेस्ट करने के लिए बहुत बड़ी है, लेकिन इसे this लिंक का पालन करके godbolt.org पर देखा जा सकता है।
उत्पन्न कोड का एक टुकड़ा, लाइनों 83 करने के लिए 58, नीचे देखा जा सकता है:
.L2:
vpbroadcastd zmm0, r8d
lea rsi, buffer[0+rcx*4]
vmovdqa64 zmm1, ZMMWORD PTR .LC1[rip]
vpaddd zmm0, zmm0, ZMMWORD PTR .LC0[rip]
xor ecx, ecx
.L4:
add ecx, 1
add rsi, 64
vmovdqa64 ZMMWORD PTR [rsi-64], zmm0
cmp ecx, edi
vpaddd zmm0, zmm0, zmm1
jb .L4
sub edx, r10d
cmp r9d, r10d
lea eax, [r8+r10]
je .L1
mov ecx, eax
cmp edx, 1
mov DWORD PTR buffer[0+rcx*4], eax
lea ecx, [rax+1]
je .L1
mov esi, ecx
cmp edx, 2
mov DWORD PTR buffer[0+rsi*4], ecx
lea ecx, [rax+2]
आप देख सकते हैं, इस कोड को जटिल चाल का एक बहुत कुछ है और कूदता है और एक बहुत ही तरह सामान्य महसूस करता में एक सरल सरणी प्रारंभ करने का जटिल तरीका।
जेनरेट कोड में इतना बड़ा अंतर क्यों है?
क्या जीसीसी सी ++ - सी-कंपाइलर की तुलना में सी और सी ++ दोनों में मान्य कोड को अनुकूलित करने में सामान्य रूप से बेहतर है?
अतिरिक्त डेटा बिंदु: 'स्थिर हस्ताक्षरित int बफर [2048] का उपयोग करके; 'सी कोड को भी समान बनाता है। आपको वास्तव में 'बफर' का उपयोग करना होगा ताकि यह पूरी तरह से समाप्त नहीं हो पाये।ऐसा लगता है कि यह एक संरेखण मुद्दा है, गलत कोड संभालने के लिए अतिरिक्त कोड है। – Jester
समान वाक्यविन्यास/व्याकरण समान अर्थशास्त्र का अर्थ नहीं है। आप ** अलग ** भाषाओं सी और सी ++ को एक ही कोड उत्पन्न करने की अपेक्षा क्यों करते हैं? यह सवाल एक जीसीसी मंच में बेहतर पूछा जाता है। – Olaf
@ ओलाफ शायद आप कोड के इस टुकड़े के लिए सी और सी ++ में सेमेन्टिक्स के बीच अंतर पर भर सकते हैं –