변수의 값(임시변수,xor) 교환을 컴파일러는 어떻게 처리하는지에 대한 테스트

어제 포스팅했던 xor교환에 대한 추가 포스팅입니다.
페북 타임라인에서 A ,B를 교환하는 C코드를 컴파일러는 어떻게 처리하느냐에 대한 주제가 나왔습니다.
댓글로 쓸 내용이지만 내용이 길어져서 워드프레스 한페이지 정도는 할애해도 될것같아 이쪽으로 옮겨적습니다.
김민장님이 제공해주신 아래 코드로 테스트 해봤습니다.
void xor_swap(int &a, int &b) {
a = a ^ b;
b = a ^ b;
a = a ^ b;
}
void swap(int &a, int &b) {
int temp = a;
a = b;
b = temp;
}
int main(int argc, char *argv[]) {
int a = atoi(argv[1]);
int b = atoi(argv[2]);
swap(a, b);
return a + b;
}
컴파일러:VS2015 최적화 옵션 : /O2
1. 코드 그대로일때
swap()함수 호출안함
a + b를 리턴
2. printf를 넣어서 a와 b를 출력하게 했더니…
swap()함수 호출 안함
a,b에 대해 atoi() 순서를 바꿔서 처리함.
3. main()함수 앞 뒤로
#pragma optimize( “gpsy”,off),#pragma optimize( “gpsy”,on)을 넣어서 main함수만 옵티마이즈를 끈 경우
fastcall로 xor_swap(), swap()각각 진입.
;swap()호출
00A21065  lea         edx,[b]
00A21068  lea         ecx,[a]
00A2106B  call        swap (0A21010h)
;swap(int &a, int &b)
001D1010  mov         eax,dword ptr [edx]   ; b
001D1012  push        esi     ; esi레지스터 보호를 위해 push
001D1013  mov         esi,dword ptr [ecx]   ; a
001D1015  mov         dword ptr [ecx],eax   ; a = b
001D1017  mov         dword ptr [edx],esi   ; b = a
001D1019  pop         esi   ;- esi레지스터 복원
;xor_swap()호출
00FC1055  lea         edx,[b]
00FC1058  lea         ecx,[a]
00FC105B  call        xor_swap (0FC1000h)
;xor_swap(int &a, int &b)
00FC1000  mov         eax,dword ptr [edx]   ; eax = b
00FC1002  xor         dword ptr [ecx],eax   ; a = a^b
00FC1004  mov         eax,dword ptr [ecx]   ; eax = a^b (xor mask)
00FC1006  xor         dword ptr [edx],eax   ; b = b^(xor mask) , b = a
00FC1008  mov         eax,dword ptr [edx]   ; eax = a
00FC100A  xor         dword ptr [ecx],eax   ; a = (xor mask) ^ a , a = b
올려주신 소스코드를 VS2015에서 컴파일 해봤습니다.
컴파일러:VS2015 최적화 옵션 : /O2
1. 코드 그대로일때
swap()함수 호출안함
a + b를 리턴
2. printf를 넣어서 a와 b를 출력하게 했더니…
swap()함수 호출 안함
a,b에 대해 atoi() 순서를 바꿔서 처리함.
3. main()함수 앞 뒤로
#pragma optimize( “gpsy”,off),#pragma optimize( “gpsy”,on)을 넣어서 main함수만 옵티마이즈를 끈 경우
xor_swap()함수,swap()함수만의 최적화라면 VS2015의 경우는 각각 임시변수 사용, xor연산으로 처리하긴 하네요.

답글 남기기

댓글을 게시하려면 다음의 방법 중 하나를 사용하여 로그인 하세요:

WordPress.com 로고

WordPress.com의 계정을 사용하여 댓글을 남깁니다. 로그아웃 /  변경 )

Facebook 사진

Facebook의 계정을 사용하여 댓글을 남깁니다. 로그아웃 /  변경 )

%s에 연결하는 중