소스 파일 에이 작은 기능이 있다고 가정 해보십시오.
static void foo() {}
바이너리의 최적화 된 버전을 빌드하지만이 기능을 최적화하지 않기 위해 인라인하지 않으려 고합니다. 인라인을 방지하기 위해 소스 코드에 추가 할 수있는 매크로가 있습니까?
소스 파일 에이 작은 기능이 있다고 가정 해보십시오.
static void foo() {}
바이너리의 최적화 된 버전을 빌드하지만이 기능을 최적화하지 않기 위해 인라인하지 않으려 고합니다. 인라인을 방지하기 위해 소스 코드에 추가 할 수있는 매크로가 있습니까?
답변:
gcc
-특정 noinline
속성을 원합니다 .
이 함수 속성은 함수가 인라인으로 간주되지 않도록합니다. 함수에 부작용이없는 경우 함수 호출이 활성화되어 있지만 인라인 이외의 최적화를 통해 함수 호출을 최적화 할 수 있습니다. 이러한 통화가 최적화되지 않도록하려면
asm ("");
다음과 같이 사용하십시오.
void __attribute__ ((noinline)) foo()
{
...
}
GCC에는
-fno-inline-small-functions
gcc를 호출 할 때 사용하십시오. 그러나 부작용은 다른 모든 작은 함수들도 인라인되지 않는다는 것입니다.
-fno-inline
하고 전혀 작동하지 않습니다. gdb
여전히 스텝 오버시 메소드를 입력합니다. 무언가가 깨졌으며 의심 스럽다 gdb
.
이를 수행하는 휴대용 방법은 포인터를 통해 함수를 호출하는 것입니다.
void (*foo_ptr)() = foo;
foo_ptr();
이것은 분기마다 다른 지침을 생성하지만 목표가 아닐 수도 있습니다. 다음 중 좋은 점을 제시합니다. 여기서 목표 는 무엇 입니까?
질문은 GCC에 관한 것임을 알고 있지만 다른 컴파일러에도 컴파일러에 대한 정보가 있으면 도움이 될 것이라고 생각했습니다.
GCC의
noinline
함수 속성은 다른 컴파일러에서도 널리 사용됩니다. 최소한 다음에 의해 지원됩니다.
__has_attribute(noinline)
)__TI_GNU_ATTRIBUTE_SUPPORT__
)또한 MSVC는 __declspec(noinline)
Visual Studio 7.1로 다시 지원합니다
. 인텔은 아마도 그것을 지원할 것입니다 (GCC와 MSVC 모두와 호환하려고 시도하지만). 문법은 기본적으로 같습니다 :
__declspec(noinline)
static void foo(void) { }
PGI 10.2+ (및 이전 버전)는 noinline
다음 기능에 적용되는 pragma를 지원 합니다.
#pragma noinline
static void foo(void) { }
TI 6.0+는 FUNC_CANNOT_INLINE
C와 C ++에서 다르게 작동 하는 pragma를 지원합니다
. C ++에서는 PGI와 비슷합니다.
#pragma FUNC_CANNOT_INLINE;
static void foo(void) { }
그러나 C에서는 함수 이름이 필요합니다.
#pragma FUNC_CANNOT_INLINE(foo);
static void foo(void) { }
Cray 6.4+ (및 이전 버전)는 비슷한 접근 방식을 취하며 함수 이름이 필요합니다.
#pragma _CRI inline_never foo
static void foo(void) { }
Oracle Developer Studio는 또한 함수 이름을 사용 하여 적어도 Forte Developer 6 로 돌아가는 pragma를 지원 하지만 , 최신 버전에서도 선언 뒤에 와야 합니다.
static void foo(void);
#pragma no_inline(foo)
얼마나 헌신적인지에 따라 모든 곳에서 작동하는 매크로를 만들 수 있지만 함수 이름과 인수로 선언해야합니다.
OTOH, 대부분의 사람들에게 적합한 것이 있으면 괜찮을 것입니다. 이것이 Hedley 에 대해 취한 접근법입니다 . 현재 HEDLEY_NEVER_INLINE 버전은 다음과 같습니다.
#if \
HEDLEY_GNUC_HAS_ATTRIBUTE(noinline,4,0,0) || \
HEDLEY_INTEL_VERSION_CHECK(16,0,0) || \
HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
HEDLEY_TI_VERSION_CHECK(8,0,0) || \
(HEDLEY_TI_VERSION_CHECK(7,3,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__))
# define HEDLEY_NEVER_INLINE __attribute__((__noinline__))
#elif HEDLEY_MSVC_VERSION_CHECK(13,10,0)
# define HEDLEY_NEVER_INLINE __declspec(noinline)
#elif HEDLEY_PGI_VERSION_CHECK(10,2,0)
# define HEDLEY_NEVER_INLINE _Pragma("noinline")
#elif HEDLEY_TI_VERSION_CHECK(6,0,0)
# define HEDLEY_NEVER_INLINE _Pragma("FUNC_CANNOT_INLINE;")
#else
# define HEDLEY_NEVER_INLINE HEDLEY_INLINE
#endif
Hedley (단일 퍼블릭 도메인 / CC0 헤더)를 사용하지 않으려는 경우 너무 많은 노력없이 버전 확인 매크로를 변환 할 수 있지만 ☺에 넣을 수있는 것 이상입니다.
나는 gcc 7.2와 함께 일한다. 라이브러리에서 인스턴스화해야했기 때문에 인라인이 아닌 함수가 필요했습니다. 나는 __attribute__((noinline))
대답뿐만 아니라 대답을 시도했다 asm("")
. 어느 쪽도 문제를 해결하지 못했습니다.
마지막으로 함수 내에서 정적 변수를 정의하면 컴파일러가 정적 변수 블록에 공간을 할당하고 함수가 처음 호출 될 때 초기화를 발행해야한다고 생각했습니다.
이것은 더러운 속임수이지만 작동합니다.
inline void foo(void) { ... }
헤더에서 함수 를 정의 extern inline void foo(void);
하고 라이브러리 소스 파일에서 선언 할 수 있습니다. C99 의미에 따라 컴파일러는 라이브러리에서 객체 코드를 기쁘게하고 방출 할 때 함수를 인라인 할 수 있습니다. 페이지 는 "고정"또는 C99의 적 "통근"유용하지 않고 "인라인"? .