> 백엔드 개발 > C++ > 컴파일러 최적화가 이 64비트 스왑 기능을 중단하는 이유는 무엇입니까?

컴파일러 최적화가 이 64비트 스왑 기능을 중단하는 이유는 무엇입니까?

DDD
풀어 주다: 2024-11-28 08:34:12
원래의
584명이 탐색했습니다.

Why Does Compiler Optimization Break This 64-bit Swap Function?

왜 최적화가 이 기능을 저하시키는가

대학 프로그래밍 전문 강의에서 한 강사가 학생들을 당황하게 하는 기능을 제시했습니다.

inline u64 Swap_64(u64 x)
{
    u64 tmp;
    (*(u32*)&tmp)       = Swap_32(*(((u32*)&x)+1));
    (*(((u32*)&tmp)+1)) = Swap_32(*(u32*) &x);

    return tmp;
}
로그인 후 복사

처음에는 기능이 원활하게 작동했지만, 높은 최적화 수준을 활성화하면 비활성화되었습니다. 이 동작의 원인은 엄격한 앨리어싱 규칙 개념에 있습니다.

엄격한 앨리어싱 위반

제공된 코드는 엄격한 앨리어싱 규칙을 위반합니다. 호환되는 포인터 유형을 통해 액세스됩니다. 이 경우 u32 및 u64 포인터는 잠재적으로 중복되는 메모리를 가리키지만 컴파일러는 두 포인터가 서로 다른 개체를 나타내는 것으로 가정합니다. 이러한 가정을 통해 임시 변수 tmp에 대한 할당을 최적화하여 함수를 무효화할 수 있습니다.

최적화가 발생하는 이유

컴파일러는 가정을 기반으로 코드를 최적화할 수 있습니다. 포인터 동작에 대해 u32와 u64는 서로 다른 유형이므로 컴파일러는 이들이 동일한 메모리를 가리키지 않으며 u32 포인터를 통해 이루어진 변경 사항이 tmp 값에 영향을 미치지 않는다고 가정합니다. 이러한 최적화는 관찰된 동작으로 이어집니다.

함수 동작을 보존하기 위한 솔루션

코드가 최적화되는 것을 방지하려면 포인터 유형이 액세스된 데이터 유형과 일치해야 합니다. 한 가지 접근 방식은 Union을 사용하여 비트에 직접 액세스하는 것입니다.

typedef union
{
  uint32_t u32;
  uint16_t u16[2];
} U32;

uint32_t swap_words(uint32_t arg)
{
  U32 in;
  uint16_t lo;
  uint16_t hi;

  in.u32    = arg;
  hi        = in.u16[0];
  lo        = in.u16[1];
  in.u16[0] = lo;
  in.u16[1] = hi;

  return (in.u32);
}
로그인 후 복사

Union을 사용하면 포인터와 데이터 유형이 호환되도록 보장하여 컴파일러가 의도한 변경 사항을 최적화하지 못하게 합니다.

위 내용은 컴파일러 최적화가 이 64비트 스왑 기능을 중단하는 이유는 무엇입니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

원천:php.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿