man gcc
....
-fstrict-aliasing
Allows the compiler to assume the strictest aliasing rules applicable to the language being
compiled. For C (and C++), this activates optimizations based on the type of expressions. In
particular, an object of one type is assumed never to reside at the same address as an object
of a different type, unless the types are almost the same. For example, an "unsigned int" can
alias an "int", but not a "void*" or a "double". A character type may alias any other type.
Pay special attention to code like this:
union a_union {
int i;
double d;
};
int f() {
a_union t;
t.d = 3.0;
return t.i;
}
The practice of reading from a different union member than the one most recently written to
(called ‘‘type-punning’’) is common. Even with -fstrict-aliasing, type-punning is allowed,
provided the memory is accessed through the union type. So, the code above will work as
expected. However, this code might not:
int f() {
a_union t;
int* ip;
t.d = 3.0;
ip = &t.i;
return *ip;
}
Every language that wishes to perform language-specific alias analysis should define a function
that computes, given an "tree" node, an alias set for the node. Nodes in different alias sets
are not allowed to alias. For an example, see the C front-end function "c_get_alias_set".
Enabled at levels -O2, -O3, -Os.
....
---------------------
C 언어 표준에 anti-aliasing rule (혹은 lvalue access rule) 이라는
규칙이 있습니다. 이 규칙은 일반적인 프로그램에서 잘못된 구조가 될
가능성이 큰 프로그램에 대해 컴파일러가 마음 놓고 "type 에 기반한
최적화"를 가할 수 있도록 허락해주는 규칙으로, 다음과 같은 예로
대강 설명할 수 있습니다.
이때 foo(*b); 를 foo(3.0); 으로 최적화가 가능할까요? 이는 아래와
같은 함수 호출이 올바른 것이냐 그렇지 않느냐에 따라 달라집니다.
double c;
func((int *)&c, &c);
만약, 이와 같은 구조가 올바른 구조로 인정된다면 위에서 말한
컴파일러의 최적화는 허용될 수 없으며, 그렇지 않다면 자유롭게
최적화를 수행할 수 있게 됩니다.
C 표준의 입장은 double 형 대상체와 int 형 대상체를 aliasing 해서
사용하는 것이 이식성도 없을 뿐더러 잘못된 프로그램으로 본다는
것입니다. 따라서 컴파일러는 func() 를 호출하는 문맥을 살펴볼 필요도
없이 오로지 지역적인 type 정보에만 의존해 앞서 말씀드린 것같은
최적화를 수행할 수 있습니다.
보통의 C 프로그램은 특정 환경에 의존하면서 포인터를 사용해 다양한
type punnig 을 수행하기 때문에 위와 같은 표준이 허락해준 "면허"가
있어도 실제 그러한 최적화를 "항상" 수행하는 컴파일러는 없습니다.
대부분의 경우 그와 같은 최적화를 켜고, 끌 수 있는 옵션을 제공해
(비록 표준 관점에서는 잘못된 구조이지만) 그와 같은 aliasing 을 필요로
하는 프로그램이 "적법한" 최적화로 인해 오작동할 걱정 없이 컴파일할 수
있게 해주는 것입니다.
커널을 컴파일 할 때 -fno-... 옵션을 주어야 한다는 이야기는 커널이
바로 그와 같은 (표준 관점에서 불법적인) aliasing 에 의존한다는 이야기
입니다. 따라서 anti-aliasing rule 에 기반해 최적화를 하도록 옵션을
잘못 줄 경우 커널 이곳 저곳에서 의도하지 않은 결과가 생겨 오작동이
가능함을 뜻합니다.
man page 에 나온 union 과 관련된 내용은 다소 복잡한 이야기에 해당
됩니다. union 은 그 자체가 aliasing 을 위해 존재합니다 - 원하든
그렇지 않든 union 의 멤버는 모두 aliasing 됩니다. 따라서 컴파일러
입장에서 union 을 통한 접근이 명백하게 보이는 경우에는 이를 의도적인
aliasing 으로 인정해 결과를 망칠 수 있는 최적화를 적용하지 않는다는
것입니다. 실제로 모 컴파일러의 경우 특정 type 이 union 멤버로
나왔다는 사실만으로 해당 type 에 대한 anti-aliasing rule 에 기반한
지역적인 최적화를 모두 끄기도 합니다.
하지만, anti-aliasing rule 를 사용한 union 의 최적화 문제의 경우
아직도 표준에서 제대로 정리가 되지 않은 상태입니다. C99 이후 정리가
되었다고 생각했으나 실제로는 그렇지 않음이 밝혀졌고 (이 Defect
Report 를 제가 제기했습니다! ^^V) 현재 다른 다양한 문제(예를 들면
동적으로 할당된 메모리 공간에 대한 anti-aliasing rule 적용)와 함께
해결하기 까다로운 문제로 남아 있습니다. 따라서 각 컴파일러는 관례에
의존하면서 가능한 프로그램을 깨뜨리지 않는 방향으로 최적화 구현을
하고 있습니다.
man gcc ....
man gcc
....
-fstrict-aliasing
Allows the compiler to assume the strictest aliasing rules applicable to the language being
compiled. For C (and C++), this activates optimizations based on the type of expressions. In
particular, an object of one type is assumed never to reside at the same address as an object
of a different type, unless the types are almost the same. For example, an "unsigned int" can
alias an "int", but not a "void*" or a "double". A character type may alias any other type.
Pay special attention to code like this:
union a_union {
int i;
double d;
};
int f() {
a_union t;
t.d = 3.0;
return t.i;
}
The practice of reading from a different union member than the one most recently written to
(called ‘‘type-punning’’) is common. Even with -fstrict-aliasing, type-punning is allowed,
provided the memory is accessed through the union type. So, the code above will work as
expected. However, this code might not:
int f() {
a_union t;
int* ip;
t.d = 3.0;
ip = &t.i;
return *ip;
}
Every language that wishes to perform language-specific alias analysis should define a function
that computes, given an "tree" node, an alias set for the node. Nodes in different alias sets
are not allowed to alias. For an example, see the C front-end function "c_get_alias_set".
Enabled at levels -O2, -O3, -Os.
....
---------------------
C 언어 표준에
C 언어 표준에 anti-aliasing rule (혹은 lvalue access rule) 이라는
규칙이 있습니다. 이 규칙은 일반적인 프로그램에서 잘못된 구조가 될
가능성이 큰 프로그램에 대해 컴파일러가 마음 놓고 "type 에 기반한
최적화"를 가할 수 있도록 허락해주는 규칙으로, 다음과 같은 예로
대강 설명할 수 있습니다.
이때 foo(*b); 를 foo(3.0); 으로 최적화가 가능할까요? 이는 아래와
같은 함수 호출이 올바른 것이냐 그렇지 않느냐에 따라 달라집니다.
만약, 이와 같은 구조가 올바른 구조로 인정된다면 위에서 말한
컴파일러의 최적화는 허용될 수 없으며, 그렇지 않다면 자유롭게
최적화를 수행할 수 있게 됩니다.
C 표준의 입장은 double 형 대상체와 int 형 대상체를 aliasing 해서
사용하는 것이 이식성도 없을 뿐더러 잘못된 프로그램으로 본다는
것입니다. 따라서 컴파일러는 func() 를 호출하는 문맥을 살펴볼 필요도
없이 오로지 지역적인 type 정보에만 의존해 앞서 말씀드린 것같은
최적화를 수행할 수 있습니다.
보통의 C 프로그램은 특정 환경에 의존하면서 포인터를 사용해 다양한
type punnig 을 수행하기 때문에 위와 같은 표준이 허락해준 "면허"가
있어도 실제 그러한 최적화를 "항상" 수행하는 컴파일러는 없습니다.
대부분의 경우 그와 같은 최적화를 켜고, 끌 수 있는 옵션을 제공해
(비록 표준 관점에서는 잘못된 구조이지만) 그와 같은 aliasing 을 필요로
하는 프로그램이 "적법한" 최적화로 인해 오작동할 걱정 없이 컴파일할 수
있게 해주는 것입니다.
커널을 컴파일 할 때 -fno-... 옵션을 주어야 한다는 이야기는 커널이
바로 그와 같은 (표준 관점에서 불법적인) aliasing 에 의존한다는 이야기
입니다. 따라서 anti-aliasing rule 에 기반해 최적화를 하도록 옵션을
잘못 줄 경우 커널 이곳 저곳에서 의도하지 않은 결과가 생겨 오작동이
가능함을 뜻합니다.
man page 에 나온 union 과 관련된 내용은 다소 복잡한 이야기에 해당
됩니다. union 은 그 자체가 aliasing 을 위해 존재합니다 - 원하든
그렇지 않든 union 의 멤버는 모두 aliasing 됩니다. 따라서 컴파일러
입장에서 union 을 통한 접근이 명백하게 보이는 경우에는 이를 의도적인
aliasing 으로 인정해 결과를 망칠 수 있는 최적화를 적용하지 않는다는
것입니다. 실제로 모 컴파일러의 경우 특정 type 이 union 멤버로
나왔다는 사실만으로 해당 type 에 대한 anti-aliasing rule 에 기반한
지역적인 최적화를 모두 끄기도 합니다.
하지만, anti-aliasing rule 를 사용한 union 의 최적화 문제의 경우
아직도 표준에서 제대로 정리가 되지 않은 상태입니다. C99 이후 정리가
되었다고 생각했으나 실제로는 그렇지 않음이 밝혀졌고 (이 Defect
Report 를 제가 제기했습니다! ^^V) 현재 다른 다양한 문제(예를 들면
동적으로 할당된 메모리 공간에 대한 anti-aliasing rule 적용)와 함께
해결하기 까다로운 문제로 남아 있습니다. 따라서 각 컴파일러는 관례에
의존하면서 가능한 프로그램을 깨뜨리지 않는 방향으로 최적화 구현을
하고 있습니다.
--
Jun, Woong (woong at icu.ac.kr)
Web: http://www.woong.org (서버 공사중)
--
Jun, Woong (woong at gmail.com)
http://www.woong.org
댓글 달기