2016-12-23 5 views
-2

대부분의 컴파일러는 인라인 어셈블리 코드 (VS2015, gcc)를 최적화하지 않으므로 지원하지 않는 새로운 지침을 작성할 수 있습니다.컴파일러는 언제 C/C++ 소스에서 어셈블리 코드를 최적화합니까?

그러나 C/C++ 컴파일러는 언제 인라인 어셈블리 최적화를 구현해야합니까?

+0

전역 최적화를 요청할 때 그렇게 할 수 있습니다. g ++ 및 MSVC 모두 전역 최적화를 지원합니다. –

+4

나는 결코 바랄 수 없다! 인라인 어셈블리를 충분히 신경 쓰면 아마도 엉망이되고 싶지 않을 것입니다. 컴파일러는 0xbeefface에 겉보기 쓸모없는 쓰기가 일부 임베디드 장치에 중요하지 않다는 것을 어떻게 알 수 있습니까? – John3136

+3

인라인 어셈블리를 사용하면 기본적으로 컴파일러에게 자신이 수행하고있는 작업을 알 수 있으며 컴파일러는 수행 할 수있는 작업보다 뛰어나다 고 말합니다. 컴파일러가 왜 최적화를 시도해야합니까? 컴파일러가 코드를 최적화하기를 원한다면, 컴파일러는 IMO를위한 실제 언어로 작성합니다. –

답변

6

일반적으로 컴파일러는 인라인 어셈블리의내용을 최적화하지 않습니다. 즉, 어셈블리 블록에서 명령을 제거하거나 변경하지 않습니다. 특히 gcc은 인라인 어셈블리의 본문을 그대로 기본 어셈블러 (이 경우 gas)로 전달합니다.

그러나 좋은 컴파일러는 주위에 인라인 어셈블리를 최적화 할 수 있으며 경우에 따라 실행 인라인 어셈블리 코드를 완전히 생략 할 수도 있습니다. 예를 들어, GCC는 어셈블리의 선언 된 출력이 작동하지 않는다고 판단하면이 작업을 수행 할 수 있습니다. 어셈블리 블록을 루프 밖으로 끌어 올리거나 여러 호출을 하나로 결합 할 수도 있습니다. 따라서 블록 내부의 명령어는 절대로 혼란에 빠지지 않지만 블록을 실행할 횟수를 변경하는 것이 합리적입니다. 물론 블록에 다른 중요한 부작용이있는 경우이 동작을 비활성화 할 수도 있습니다.

확장 된 asm 구문의 gcc 문서에는이 모든 내용 중 일부가 good examples 있습니다.

6

그것은 인라인 어셈블리의 목적을 무너 뜨릴 것입니다. 인라인 어셈블리는 여러분이 요구하는 것을 정확히 얻는 것입니다.

대상의 CPU의 명령의 모든 기능을 사용하려면

컴파일러가 이해하고 최적화, 당신이 내장 함수가 아닌 인라인 ASM를 사용해야 수있는 방식으로을 설정합니다.

popcnt의 인라인 asm 대신 int count = __builtin_popcount(x); (-mpopcnt으로 컴파일 된 GNU C)을 사용하십시오. Inline-asm은 컴파일러마다 다르므로 intrinsics가 더 이식성이있는 경우 특히 x86을 대상으로 할 수있는 모든 주요 컴파일러에서 지원되는 Intel x86 내장 함수를 사용하는 경우 특히 그렇습니다. #include <x86intrin.h>을 사용하고 int _popcnt32 (int a)을 사용하면 popcnt x86 명령어를 안정적으로 얻을 수 있습니다. 및 태그 위키의 다른 링크를 참조하십시오.

mov  eax, 4 
    ret 

clang 3.9 with an inline-asm definition of popc, on the Godbolt compiler explorer : 당신은 왜 shouldn

xor  eax, eax 
    popcnt eax, eax 
    mov  ecx, 1 
    popcnt ecx, ecx 
    add  ecx, eax 
    mov  edx, 2 
    popcnt edx, edx 
    add  edx, ecx 
    mov  eax, 3 
    popcnt eax, eax 
    add  eax, edx 
    ret 

이것은 인라인 어셈블리의 전형적인 예 일정한 전파를 격파하고 gcc6.3에 의해 #define popc _popcnt32 컴파일


int count(){ 
    int total = 0; 
    for(int i=0 ; i<4 ; ++i) 
    total += popc(i); 
    return total; 
} 

그것을 피할 수 있다면 성능을 위해 사용하지 마십시오 : https://gcc.gnu.org/wiki/DontUseInlineAsm.


내가이 시험에 사용되는 인라인 ASM 정의했다 :

int popc_asm(int x) { 
    // force use of the same register because popcnt has a false dependency on its output, on Intel hardware 
    // this is just a toy example, though, and also demonstrates how non-optimal constraints can lead to worse code 
    asm("popcnt %0,%0" : "+r"(x)); 
    return x; 
} 

당신이, 즉 가능한 컴파일러에게 맡겨해야하는 또 다른 이유가있어 popcnt has a false dependency on its output register on Intel hardware 것을 알고하지 않은 경우.인라인 어셈블리에 대해 하나의 사용 사례이지만, 컴파일러는 그것에 대해 알고하지 않는 경우, 그것은 확실히 최적화 할 수에 대해 컴파일러가 모르는 특별한 지침을 사용


. 컴파일러가 내장 함수를 최적화하기 전에 (예 : SIMD 명령어의 경우) 인라인 asm이 더 일반적이었습니다. 하지만 지금은 그 이상입니다. 컴파일러는 일반적으로 ARM과 같은 비 x86 아키텍처의 경우에도 내장 함수를 사용하는 것이 일반적입니다.

+0

x86 용 (Google이 [https://github.com/hundt98847/mao]를 만들었지 만) 알 수는 없지만 실제로 "최적화 된 어셈블러"와 같은 것을 들었습니다.). 대부분은 임베디드 시스템 또는 RISC 스타일의 아키텍처로, 모든 레지스터와 명령어 스케줄링의 미묘한 차이로 인해 어셈블리 프로그래밍이 지루한 작업입니다. 그래서 이론적으로 C 컴파일러의 인라인 어셈블리에 그러한 것을 통합하는 것이 가능할 것입니다. 나는 인라인 asm이 실제로 잘 작동한다고 가정 할 때 이것이 목적을 이길 것이라고 동의하지 않는다! –

+0

예를 들어, [지침 번들 및 슬롯] (https://blogs.msdn.microsoft.com/oldnewthing/20150728-00/?p)에주의해야하기 때문에 Itanium 용 어셈블리에서 작성하는 것은 뒤쪽에 큰 고통입니다. = 90811), 그리고 이상한 규칙들. ISA는 C/C++ 컴파일러 용으로 많이 설계 되었기 때문에 너무 복잡하여 옵티마이 저가 사실상 절반의 목적 코드를 얻으려는 의도가 필요합니다. 최적화 어셈블러는 다소 멋지다. 비록 asm의 구문이 구현하기 어렵게 만들 것이라고 생각합니다. 재정렬 할 수있는 지침을 어떻게 알 수 있습니까? –

+0

컴파일러가 그것을 grok하고 다른 지시를 내리려 고한다면 * inline * -asm을 (intrinsics 대신) 처음 사용하는 이유는 무엇입니까? 내가 생각할 수있는 유일한 이유는 C가 이식 가능하게 표현할 수 없다는 것입니다. 산술 권리 이동 및 기타 여러 가지 결함이 있습니다. Intrinsics는이 OP가 실제로 가지고 있다고 생각하는 문제에 대한 해결책이며, 컴파일러 최적화 된 인라인 - asm에서 X-Y 문제에 빠져 있습니다. –