2012-07-03 11 views
7

वैश्विक सूचक और वीएस -2010 अनुकूलक के लिए वैश्विक संदर्भ के बीच बड़ा अंतर क्या है? संदर्भ का समाधान क्यों नहीं किया गया है?वैश्विक पॉइंटर्स को ऑप्टिमाइज़र द्वारा हल किया जाता है - लेकिन संदर्भ नहीं - क्यों?

typedef unsigned char byte_t; 
typedef unsigned short word_t; 

struct byte_reg_t 
{ 
    byte_t low; 
    byte_t high; 
}; 

union word_reg_t 
{ 
    word_t value; 
    byte_reg_t part; 
}; 

word_reg_t r16; 

byte_t& low_ref = r16.part.low; 
byte_t* const low_ptr = &r16.part.low; 

#define SPLIT() _asm nop; 

int main() 
{ 
    low_ref = 4; 
    SPLIT() 

    byte_t a = r16.part.low; 
    SPLIT() 

    byte_t b = low_ref; 
    SPLIT() 

    byte_t c = *low_ptr; 
    SPLIT() 

    return a+b+c; 
} 

विधानसभा आउटपुट के साथ रिलीज-मोड में संकलित का उत्पादन इस परिणाम

;byte_t a = r16.part.low; 
mov cl, BYTE PTR [email protected]@[email protected]@A 

;byte_t b = low_ref; 
mov edx, DWORD PTR [email protected]@3AAEA ; low_ref 
mov dl, BYTE PTR [edx] 

;byte_t c = *low_ptr; 
mov al, BYTE PTR [email protected]@[email protected]@A 

असंशोधित disassembly

.text:00401000 _main   proc near    ; CODE XREF: __tmainCRTStartup+11D 
.text:00401000     mov  eax, [email protected]@3AAEA ; uchar & low_ref 
.text:00401005     mov  byte ptr [eax], 4 
.text:00401008     nop 
.text:00401009     mov  cl, [email protected]@[email protected]@A ; word_reg_t r16 
.text:0040100F     nop 
.text:00401010     mov  edx, [email protected]@3AAEA ; uchar & low_ref 
.text:00401016     mov  dl, [edx] 
.text:00401018     nop 
.text:00401019     mov  al, [email protected]@[email protected]@A ; word_reg_t r16 
.text:0040101E     nop 
.text:0040101F     movzx eax, al 
.text:00401022     movzx edx, dl 
.text:00401025     movzx ecx, cl 
.text:00401028     add  eax, edx 
.text:0040102A     add  eax, ecx 
.text:0040102C     retn 
.text:0040102C _main   endp 

.data:00403374 [email protected]@[email protected]@A db ?    ; DATA XREF: _main+9 
.data:00403374           ; _main+19 
.data:00403375     align 4 

.data:00403018 ; unsigned char & low_ref 
.data:00403018 [email protected]@3AAEA dd offset [email protected]@[email protected]@A ; DATA XREF: _main 
.data:00403018           ; _main+10 
.data:00403018           ; word_reg_t r16 

मैं कई वेरिएंट (समारोह आदि से लौटने) का परीक्षण किया - कोई अगर हल करने low_ref उपयोग में है

  • अनुकूलक बेवकूफ है?
  • अनुकूलन के लिए एक असामान्य मामला?
  • कुछ सी/सी ++ मानक प्रतिबंध?

अद्यतन

यह के लिए अनुकूलन एक असामान्य मामला प्रतीत हो रहा है - THX माइकल बर

यह काम करता है, तो संदर्भ एक समारोह दायरे में है - या अंदर एक वर्ग की या में instantiated struct समारोह गुंजाइश (लेकिन इसकी अभी भी अजीब है कि अनुकूलक का समाधान करता है ptr स्थिरांक नहीं बल्कि संदर्भ - जो 100% समान हैं)

अद्यतन 2

इसके और भी अधिक अजीब - अगर आप दोनों resolvings int करने के लिए byte_t से स्विच काम करता है - स्थिरांक ptr और संदर्भ

  • वैश्विक ptr स्थिरांक वैश्विक byte_t वर के लिए: संकल्प लिया
  • वैश्विक ptr स्थिरांक वैश्विक पूर्णांक के लिए var: संकल्प लिया
  • वैश्विक byte_t वर के लिए वैश्विक संदर्भ: हल नहीं
  • वैश्विक संदर्भ लें वैश्विक पूर्णांक वर के लिए खिलाडि़यों: संकल्प लिया
  • स्थानीय byte_t वर के लिए वैश्विक संदर्भ: संकल्प लिया
  • स्थानीय पूर्णांक वर के लिए वैश्विक संदर्भ: संकल्प लिया

तो वहाँ अनुकूलक में एक छोटा सा फर्क है पीआरटी कॉन्स और संदर्भों के लिए, संदर्भ क्षेत्र ..... और प्रस्तुत प्रकार ... कभी-कभी :)

अद्यतन 3

सरल टेस्टकोड - वीएस -2010 और क्लैंग 3 के साथ चेक किया गया।1

typedef unsigned char byte_t; 
typedef unsigned int dword_t; 

//for msvc 
#define SPLIT() _asm nop _asm nop; 
//for clang 
//#define SPLIT() asm("nop"); asm("nop"); 

byte_t byte; 
dword_t dword; 

byte_t& global_ref_byte = byte; 
dword_t& global_ref_dword = dword; 

byte_t* const global_ptrc_byte = &byte; 
dword_t* const global_ptrc_dword = &dword; 

int main(int argc, char** argv) 
{ 
    byte_t& local_ref_byte = byte; 
    dword_t& local_ref_dword = dword; 

    dword_t random = (dword_t)argv; 

    byte = (byte_t)random; 
    dword = (dword_t)random; 
    SPLIT() 

    byte_t a = global_ref_byte; 
    SPLIT() 

    dword_t b = global_ref_dword; 
    SPLIT() 

    byte_t c = *global_ptrc_byte; 
    SPLIT() 

    dword_t d = *global_ptrc_dword; 
    SPLIT() 

    byte_t e = local_ref_byte; 
    SPLIT() 

    dword_t f = local_ref_dword; 
    SPLIT() 

    dword_t result = a+b+c+d+e+f; 

    return result; 
} 

VS2010 disassembly

.text:00401000 ; int __cdecl main(int argc, const char **argv, const char **envp) 
.text:00401000 _main   proc near    ; CODE XREF: ___tmainCRTStartup+11D 
.text:00401000 
.text:00401000 argc   = dword ptr 8 
.text:00401000 argv   = dword ptr 0Ch 
.text:00401000 envp   = dword ptr 10h 
.text:00401000 
.text:00401000     push ebp 
.text:00401001     mov  ebp, esp 
.text:00401003     mov  eax, [ebp+argv] 
.text:00401006     push ebx 
.text:00401007     push esi 
.text:00401008     push edi 
.text:00401009     mov  byte_403374, al 
.text:0040100E     mov  dword_403378, eax 
.text:00401013     nop 
.text:00401014     nop 
.text:00401015     mov  eax, off_40301C 
.text:0040101A     mov  al, [eax] 
.text:0040101C     nop 
.text:0040101D     nop 
.text:0040101E     mov  ecx, dword_403378 
.text:00401024     nop 
.text:00401025     nop 
.text:00401026     mov  dl, byte_403374 
.text:0040102C     nop 
.text:0040102D     nop 
.text:0040102E     mov  esi, dword_403378 
.text:00401034     nop 
.text:00401035     nop 
.text:00401036     mov  bl, byte_403374 
.text:0040103C     nop 
.text:0040103D     nop 
.text:0040103E     mov  edi, dword_403378 
.text:00401044     nop 
.text:00401045     nop 
.text:00401046     movzx edx, dl 
.text:00401049     movzx ebx, bl 
.text:0040104C     add  edx, edi 
.text:0040104E     movzx eax, al 
.text:00401051     add  edx, ebx 
.text:00401053     add  eax, edx 
.text:00401055     pop  edi 
.text:00401056     add  eax, esi 
.text:00401058     pop  esi 
.text:00401059     add  eax, ecx 
.text:0040105B     pop  ebx 
.text:0040105C     pop  ebp 
.text:0040105D     retn 
.text:0040105D _main   endp 

बजना 3.1 disassembly

.text:004012E0 sub_4012E0  proc near    ; CODE XREF: sub_401020+91 
.text:004012E0 
.text:004012E0 arg_4   = dword ptr 0Ch 
.text:004012E0 
.text:004012E0     push ebp 
.text:004012E1     mov  ebp, esp 
.text:004012E3     call sub_4014F0 
.text:004012E8     mov  eax, [ebp+arg_4] 
.text:004012EB     mov  byte_402000, al 
.text:004012F0     mov  dword_402004, eax 
.text:004012F5     nop 
.text:004012F6     nop 
.text:004012F7     movzx eax, byte_402000 
.text:004012FE     nop 
.text:004012FF     nop 
.text:00401300     add  eax, dword_402004 
.text:00401306     nop 
.text:00401307     nop 
.text:00401308     movzx ecx, byte_402000 
.text:0040130F     add  ecx, eax 
.text:00401311     nop 
.text:00401312     nop 
.text:00401313     add  ecx, dword_402004 
.text:00401319     nop 
.text:0040131A     nop 
.text:0040131B     movzx eax, byte_402000 
.text:00401322     add  eax, ecx 
.text:00401324     nop 
.text:00401325     nop 
.text:00401326     add  eax, dword_402004 
.text:0040132C     nop 
.text:0040132D     nop 
.text:0040132E     pop  ebp 
.text:0040132F     retn 
.text:0040132F sub_4012E0  endp 
nops बिना

दोनों optimizers बेहतर कोड का उत्पादन कर सकते हैं - लेकिन बजना अभी भी बेहतर

VS2010 (अधिक कोड है अनसुलझा बाइट संदर्भ के कारण)

.text:00401003     mov  eax, [ebp+argv] 
.text:00401006     movzx ecx, al 
.text:00401009     lea  edx, [eax+eax*2] 
.text:0040100C     mov  byte_403374, al 
.text:00401011     mov  dword_403378, eax 
.text:00401016     lea  eax, [edx+ecx*2] 
.text:00401019     mov  ecx, off_40301C 
.text:0040101F     movzx edx, byte ptr [ecx] 
.text:00401022     add  eax, edx 

बजना 3.1:

.text:004012E8     mov  eax, [ebp+arg_4] 
.text:004012EB     mov  byte_402000, al 
.text:004012F0     mov  dword_402004, eax 
.text:004012F5     movzx ecx, al 
.text:004012F8     add  ecx, eax 
.text:004012FA     lea  eax, [ecx+ecx*2] 
+0

पीटीआर में low_ptr का पता कैसे समाप्त हुआ? शायद आप हमें पूरी तरह से अलग-अलग सामान दिखा सकते हैं? सिर्फ लाइनों का चयन नहीं किया? – RedX

+0

पीटीआर में अंत में आपका क्या मतलब है? परिवर्तनीय "? r16 @@ 3Tword_reg_t @@ ए" वैश्विक है "word_reg_t r16" - disassembly में देखने के लिए और कुछ नहीं - यह nops के बीच एकमात्र कोड है? – llm

+0

ओह, मैंने सोचा कि मैंने एक ';' देखा था क्या आप वहां मौजूद हैं। ठीक है अब यह और अधिक समझ में आता है। – RedX

उत्तर

5

यहाँ मैं क्या मानना ​​है कि क्या हो रहा है है। संदर्भ को गैर-कॉन्स ग्लोबल पॉइंटर के समान माना जा रहा है। यदि आप low_ptr घोषणा से const हटाते हैं तो आप इसे देख सकते हैं।

आप यह भी देख सकते हैं कि यदि आप संदर्भ में स्थानीय होने के संदर्भ को संदर्भित करते हैं तो संकलक बिना किसी समस्या के पहुंच को अनुकूलित कर सकता है।

मुझे लगता है कि वैश्विक संदर्भ काफी दुर्लभ हैं (एक 'सांख्यिकी' मैं स्वीकार करूंगा कि मैंने अभी बनाया है) कि उन्हें अनुकूलित करने में बहुत कम प्रयास किया गया है।

+0

यह दोनों के लिए काम करता है यदि int मूल प्रकार है :) - यदि बाइट_टी का उपयोग केवल पीआरटी कॉन्स को हल किया गया है – llm

 संबंधित मुद्दे

  • कोई संबंधित समस्या नहीं^_^