어제 포스팅했던 xor교환에 대한 추가 포스팅입니다.
페북 타임라인에서 A ,B를 교환하는 C코드를 컴파일러는 어떻게 처리하느냐에 대한 주제가 나왔습니다.
댓글로 쓸 내용이지만 내용이 길어져서 워드프레스 한페이지 정도는 할애해도 될것같아 이쪽으로 옮겨적습니다.
김민장님이 제공해주신 아래 코드로 테스트 해봤습니다.
void xor_swap(int &a, int &b) {
a = a ^ b;
b = a ^ b;
a = a ^ b;
}
a = a ^ b;
b = a ^ b;
a = a ^ b;
}
void swap(int &a, int &b) {
int temp = a;
a = b;
b = temp;
}
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;
}
int a = atoi(argv[1]);
int b = atoi(argv[2]);
swap(a, b);
return a + b;
}
컴파일러:VS2015 최적화 옵션 : /O2
1. 코드 그대로일때
swap()함수 호출안함
a + b를 리턴
swap()함수 호출안함
a + b를 리턴
2. printf를 넣어서 a와 b를 출력하게 했더니…
swap()함수 호출 안함
a,b에 대해 atoi() 순서를 바꿔서 처리함.
swap()함수 호출 안함
a,b에 대해 atoi() 순서를 바꿔서 처리함.
3. main()함수 앞 뒤로
#pragma optimize( “gpsy”,off),#pragma optimize( “gpsy”,on)을 넣어서 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)
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레지스터 복원
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)
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
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
컴파일러:VS2015 최적화 옵션 : /O2
1. 코드 그대로일때
swap()함수 호출안함
a + b를 리턴
swap()함수 호출안함
a + b를 리턴
2. printf를 넣어서 a와 b를 출력하게 했더니…
swap()함수 호출 안함
a,b에 대해 atoi() 순서를 바꿔서 처리함.
swap()함수 호출 안함
a,b에 대해 atoi() 순서를 바꿔서 처리함.
3. main()함수 앞 뒤로
#pragma optimize( “gpsy”,off),#pragma optimize( “gpsy”,on)을 넣어서 main함수만 옵티마이즈를 끈 경우
#pragma optimize( “gpsy”,off),#pragma optimize( “gpsy”,on)을 넣어서 main함수만 옵티마이즈를 끈 경우
xor_swap()함수,swap()함수만의 최적화라면 VS2015의 경우는 각각 임시변수 사용, xor연산으로 처리하긴 하네요.