컴파일러가 일부 명령어를 복제하는 이유는 무엇입니까?
때때로 컴파일러는 안전하게 제거 할 수있는 이상한 명령어 중복으로 코드를 생성합니다. 다음 코드를 고려하십시오.
int gcd(unsigned x, unsigned y) {
return x == 0 ? y : gcd(y % x, x);
}
다음은 어셈블리 코드 ( 최적화가 활성화 된 clang 5.0 에서 생성됨 )입니다.
gcd(unsigned int, unsigned int): # @gcd(unsigned int, unsigned int)
mov eax, esi
mov edx, edi
test edx, edx
je .LBB0_1
.LBB0_2: # =>This Inner Loop Header: Depth=1
mov ecx, edx
xor edx, edx
div ecx
test edx, edx
mov eax, ecx
jne .LBB0_2
mov eax, ecx
ret
.LBB0_1:
ret
다음 스 니펫에서 :
mov eax, ecx
jne .LBB0_2
mov eax, ecx
점프가 발생하지 않으면 eax
명백한 이유없이 재 할당됩니다.
다른 예는 함수 끝에있는 두 개의 ret입니다. 하나는 완벽하게 작동합니다.
컴파일러가 충분히 지능적이지 않거나 중복을 제거하지 않을 이유가 있습니까?
컴파일러는 사람들에게 명확하지 않은 최적화를 수행 할 수 있으며 명령을 제거한다고해서 항상 작업 속도가 빨라지는 것은 아닙니다.
소량의 검색은 RET가 조건부 분기 바로 뒤에있을 때 다양한 AMD 프로세서에 분기 예측 문제가 있음을 보여줍니다. 해당 슬롯을 기본적으로 작동하지 않는 것으로 채우면 성능 문제가 방지됩니다.
최신 정보:
예제 참조, "AMD64 프로세서 용 소프트웨어 최적화 가이드"( http://support.amd.com/TechDocs/25112.PDF 참조 ) 섹션 6.2에서는 다음과 같이 말합니다.
특히 다음 두 가지 상황을 피하십시오.
단일 바이트 니어 리턴 RET 명령어를 대상으로하는 모든 종류의 분기 (조건부 또는 무조건 부). "예제"를 참조하십시오.
단일 바이트 니어 리턴 RET 명령어 바로 전에 코드에서 발생하는 조건부 분기입니다.
또한 점프 타겟이 정렬을 가져야하는 이유에 대해 자세히 설명합니다. 이는 함수 끝에서 중복 RET를 설명 할 가능성이 높습니다.
모든 컴파일러에는 레지스터 이름 변경, 풀기, 호이 스팅 등을위한 많은 변환이 있습니다. 출력을 결합하면 보여준 것과 같은 차선의 경우가 발생할 수 있습니다. Marc Glisse는 좋은 조언을 제공합니다. 버그보고의 가치가 있습니다. Peephole Optimizer가 다음 중 하나의 명령을 버릴 수있는 기회를 설명하고 있습니다.
- 레지스터 및 메모리 상태에 전혀 영향을주지 않습니다.
- 함수의 사후 조건에 중요한 상태에 영향을주지 않으며 공용 API에는 중요하지 않습니다.
상징적 인 실행 기법 의 기회처럼 들립니다 . 제약 솔버가 주어진 MOV에 대한 분기점을 찾지 못하면 실제로 NOP 일 수 있습니다.
참고 URL : https://stackoverflow.com/questions/48014076/why-do-compilers-duplicate-some-instructions
'program story' 카테고리의 다른 글
OSX : 시스템 전체의 keyDown 이벤트 감지? (0) | 2020.12.13 |
---|---|
YAML 스키마 유효성 검사? (0) | 2020.12.13 |
텍스트 영역의 커서 위치에 DIV 표시 (0) | 2020.12.13 |
최고의 WPF 오픈 소스 프로젝트 (0) | 2020.12.13 |
Eclipse 3.7과 Eclipse 4.1의 차이점은 무엇입니까? (0) | 2020.12.13 |