2012-07-03 22 views
7

sự khác biệt lớn giữa một con trỏ toàn cầu và tham chiếu toàn cầu cho trình tối ưu hóa VS2010 là gì? tại sao tham chiếu không được giải quyết?con trỏ toàn cục được giải quyết bởi trình tối ưu hóa - nhưng tham chiếu không - tại sao?

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; 
} 

biên soạn trong phiên bản-Mode với hội Output sản xuất này quả

;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 

chưa sửa đổi tháo

.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 

Tôi đã thử nghiệm một vài biến thể (trở về từ chức năng vv) - không giải quyết nếu low_ref đang được sử dụng

  • là trình tối ưu hóa ngu ngốc?
  • trường hợp không phổ biến để tối ưu hóa?
  • một số hạn chế tiêu chuẩn c/C++?

CẬP NHẬT

Nó có vẻ là một trường hợp hiếm gặp để tối ưu hóa - thx Michael Burr

nó hoạt động nếu tham chiếu là trong một phạm vi chức năng - hoặc bên trong một lớp học hoặc struct thuyết minh trong phạm vi chức năng (nhưng nó vẫn còn lạ mà trình tối ưu hóa giải quyết ptr const nhưng không tham chiếu - 100% giống hệt nhau)

CẬP NHẬT 2

của nó thậm chí nhiều hơn lạ - nếu bạn chuyển từ byte_t để int cả resolvings hoạt động - ptr const và tài liệu tham khảo

  • ptr const toàn cầu để byte_t var toàn cầu: giải quyết
  • ptr const toàn cầu để int toàn cầu var: giải quyết
  • tham khảo toàn cầu để byte_t var toàn cầu: không được giải quyết
  • tham khảo toàn cầu ence để int var toàn cầu: giải quyết
  • tham khảo toàn cầu để byte_t var địa phương: giải quyết
  • tham khảo toàn cầu để địa phương int var: giải quyết

do đó là một sự khác biệt nhỏ trong tôi ưu hoa cho ptr const và tham chiếu, phạm vi tham chiếu ..... và loại được tham chiếu ... đôi khi :)

CẬP NHẬT 3

mã kiểm tra đơn giản - được kiểm tra với VS2010 và clang 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 tháo

.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 

kêu vang 3.1 tháo

.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 

mà không nops cả tối ưu có thể tạo ra mã tốt hơn - nhưng kêu vang vẫn là tốt hơn

VS2010 (mã hơn vì tham chiếu byte chưa được giải quyết)

.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 

kêu vang 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

Địa chỉ của low_ptr kết thúc bằng PTR như thế nào? có lẽ bạn có thể cho chúng tôi thấy việc tháo gỡ hoàn toàn? Không chỉ các dòng được chọn? – RedX

+0

ý của bạn là gì khi kết thúc bằng PTR? biến "? r16 @@ 3Tword_reg_t @@ A" là toàn cục "word_reg_t r16" - không có gì nhiều hơn để xem trong phần tháo gỡ - đây là mã duy nhất giữa các bước nhảy? – llm

+0

Oh sry, nghĩ rằng tôi đã nhìn thấy một ';' đó. Ok nó có ý nghĩa hơn bây giờ. – RedX

Trả lời

5

Đây là những gì tôi tin rằng đang xảy ra. Tham chiếu đang được xử lý tương tự như một con trỏ không phải toàn cầu const. Bạn có thể thấy điều này nếu bạn xóa const khỏi tuyên bố low_ptr.

Bạn cũng có thể thấy rằng nếu bạn di chuyển tham chiếu thành cục bộ đến hàm, trình biên dịch có thể tối ưu hóa quyền truy cập thông qua nó mà không gặp sự cố.

Tôi đoán rằng vì tài liệu tham khảo toàn cầu là khá hiếm (một 'thống kê' tôi sẽ thừa nhận tôi vừa tạo) rằng có rất ít nỗ lực để tối ưu hóa chúng.

+0

nó hoạt động cho cả hai nếu int là kiểu cơ sở :) - nếu sử dụng byte_t chỉ có ptr const được giải quyết – llm

Các vấn đề liên quan