[gcc] gcc 확장 __builtin_constant_p(exp)

Documentation/CodingStyle에서 inline disease 에 언급된 (slab 기준) kmalloc 구현을 살펴보다가 눈에 띄어서 정리해 둔다.
__builtin_constant_p(exp) 는 컴파일 타임에 상수로 정해질 수 있는 경우에 1을, 아닌 경우에는 0을 리턴한다. 따라서 이 조건에 따라 다른 코드를 사용함으로 써 최적화할 수 있도록 할 수 있다.

(이 글을 쓰는 시점인 v3.3-rc6 기준)kmalloc 의 경우 다음과 같이 구현되어 있다.

include/linux/slab_def.h

static __always_inline void *kmalloc(size_t size, gfp_t flags)

{
	struct kmem_cache *cachep;
	void *ret;

	if (__builtin_constant_p(size)) {
		int i = 0;

		if (!size)
			return ZERO_SIZE_PTR;

#define CACHE(x) \
		if (size <= x) \
			goto found; \
		else \
			i++;
#include <linux/kmalloc_sizes.h>
#undef CACHE
		return NULL;
found:
#ifdef CONFIG_ZONE_DMA
		if (flags & GFP_DMA)
			cachep = malloc_sizes[i].cs_dmacachep;
		else
#endif
			cachep = malloc_sizes[i].cs_cachep;

		ret = kmem_cache_alloc_trace(size, cachep, flags);

		return ret;
	}
	return __kmalloc(size, flags);
}

이외에도 __always_inline 사용, CACHE(x) 매크로를 상황에 따라 define하고 linux/kmalloc_sizes.h 헤더를 include 하여 사용하는 부분은 매우 흥미롭다. __always_inline 은 gcc의 function attribute 를 이용한다.

이 글의 라이센스는 GPL 을 따른다(This document is released under the GPL licence.).

참고 : 
http://gcc.gnu.org/onlinedocs/gcc-4.6.3/gcc/Other-Builtins.html