글 목록 보기

Lyn
조회 수 1259 추천 수 0 댓글 0
Atachment
첨부 '2'
?

단축키

Prev이전 문서

Next다음 문서

크게 작게 위로 아래로 댓글로 가기 인쇄
?

단축키

Prev이전 문서

Next다음 문서

크게 작게 위로 아래로 댓글로 가기 인쇄

정말 오랫만에 로우레벨 관련 질문을 받았습니다...

바로 아래 코드에서

 

#include <smmintrin.h>

int main()
{
    __m128i m_128i;
    m_128i.m128i_i16[0] = 0;

    for (int i = 0; i < 15; i++)
    {
        auto a = _mm_extract_epi8(m_128i, i); // <-- 컴파일 에러
    }
}

 

error C2057: expected constant expression 에러가 발생 한다는 얘기입니다.

 

_mm_extract_epi8 의 prototype 을 확인 해 보면 extern int   _mm_extract_epi8 (__m128i /* src */, const int /* index */); 입니다. 일반적으론 변수 -> const 로의 변환은 자유로우므로 문제가 없어야 하는데... 오류가 나죠.

 

원인은 간단한데 _mm_extract_epi8 는 C++의 "함수" 가 아니라, 기계어와 매칭되는 Intrinsics 입니다. 저게 선언되어있는 헤더가 smminstrin.h 라는 것에서도 알 수 있지요. 해당명령어는 intel 명령어이니 intel 사이트에서 한번 해당 내용을 검색 해 봅시다

 

inst01.PNG

 

 

몇가지 정보가 나오네요. 해당 Intrinsics 에 대응되는 어셈블리는 pextrb r32, xmm, imm 이고, SSE4.1 지원이 필요하며, Latency 는 CPU 종류에 따라 2~3 클럭이네요.

 

여기는 Visual Studio 에 들어있는 헤더와 달리 각 파라메터에 이름이 붙어있습니다. a, 와 imm8 이네요.
그럼 imm8 은 뭐냐가 중요해지는데, 이 imm은 이름만 보면 무슨 레지스터 비슷한걸로 착각 할 수도 있는데, 실제로는 Immediate value 의 약자입니다.
한자로는 즉치값(즉시 계산되는 값) 이라고도 하는 것 같은데 C++ 프로그래머 입장에서 보자면 컴파일타임에 계산하여 결정이 가능한 상수(const) 를 이야기 합니다. 8은 뭐냐구요? 걍 bit 수 입니다. 저 값은 8bit 범위에서 작동한다는 거죠. 즉 imm8 을 풀어서 써보면 8-bit immediate value 라고 할 수 있겠습니다.

 

그럼 결론을 내보자면. Intrinsics 를 호출 할때는, C++의 호출/캐스팅 규칙 보다 CPU 명령어의 제약사항이 우선하며, _mm_extract_epi8 의 2번째 argument는  Immediate value 일 것을 요구하므로 변수를 사용할 수 없습니다.

 

기왕 하는김에 하나 더 해보자면, imm8 이라고 되어있긴 하지만, 128bit 변수를 8bit 단위로 쪼개서 값을 읽는 명령이므로, 실제 imm8의 사용 범위는 0~15 일 것입니다. 그런데 만약 그 이상의 값(ex : 16) 을 넣으면 어떻게 될까요?

 

 inst02.PNG

 

다행히도 컴파일러는 해당 명령어의 허용 범위를 알고 있으므로 

warning C4556: value of intrinsic immediate argument '16' is out of range '0 - 15' warning 을 띄워 줍니다.

 

TAG •
?