diff options
author | chappedm@gmail.com <chappedm@gmail.com@6b5cf1ce-ec42-a296-1ba9-69fdba395a50> | 2012-12-22 20:06:47 +0000 |
---|---|---|
committer | chappedm@gmail.com <chappedm@gmail.com@6b5cf1ce-ec42-a296-1ba9-69fdba395a50> | 2012-12-22 20:06:47 +0000 |
commit | 84b983c8d43f43a3c7f71d45d51fc4adcc688cd9 (patch) | |
tree | 7976021f2984cb489d544634af4f45961299c8c2 | |
parent | a5dacccd6ae4cbfedb5263bfe0f325f03c7f0db8 (diff) | |
download | gperftools-84b983c8d43f43a3c7f71d45d51fc4adcc688cd9.tar.gz |
issue-465: Adding automagic support for __builtin_expect
Previously __builtin_ expect was based on a macro check against gcc version.
Now we perform the check via AM which is a cleaner approach. There are also
a number of code changes here to utilize LIKELY/UNLIKELY macros based on
__builtin_expect to improve performance.
git-svn-id: http://gperftools.googlecode.com/svn/trunk@189 6b5cf1ce-ec42-a296-1ba9-69fdba395a50
-rwxr-xr-x | configure | 27 | ||||
-rw-r--r-- | configure.ac | 8 | ||||
-rw-r--r-- | src/base/basictypes.h | 17 | ||||
-rw-r--r-- | src/common.h | 8 | ||||
-rw-r--r-- | src/config.h.in | 3 | ||||
-rw-r--r-- | src/tcmalloc.cc | 22 |
6 files changed, 57 insertions, 28 deletions
@@ -16233,6 +16233,33 @@ fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext +# Check for __builtin_expect() +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for __builtin_expect()" >&5 +$as_echo_n "checking for __builtin_expect()... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +return __builtin_expect(main != 0, 1) + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + +$as_echo "#define HAVE_BUILTIN_EXPECT 1" >>confdefs.h + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + # Check if __environ is available (for GetenvBeforeMain) { $as_echo "$as_me:${as_lineno-$LINENO}: checking for __environ" >&5 $as_echo_n "checking for __environ... " >&6; } diff --git a/configure.ac b/configure.ac index f4ca2de..efe3217 100644 --- a/configure.ac +++ b/configure.ac @@ -289,6 +289,14 @@ AC_LINK_IFELSE([AC_LANG_PROGRAM(, [void *sp = __builtin_stack_pointer()])], AC_MSG_RESULT([yes])], [AC_MSG_RESULT([no])]) +# Check for __builtin_expect() +AC_MSG_CHECKING([for __builtin_expect()]) +AC_LINK_IFELSE([AC_LANG_PROGRAM(, return __builtin_expect(main != 0, 1))], + [AC_DEFINE(HAVE_BUILTIN_EXPECT, 1, + Define to 1 if compiler supports __builtin_expect) + AC_MSG_RESULT([yes])], + [AC_MSG_RESULT([no])]) + # Check if __environ is available (for GetenvBeforeMain) AC_MSG_CHECKING([for __environ]) AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <unistd.h>], diff --git a/src/base/basictypes.h b/src/base/basictypes.h index a5f971e..b002aa5 100644 --- a/src/base/basictypes.h +++ b/src/base/basictypes.h @@ -360,21 +360,4 @@ namespace base { enum LinkerInitialized { LINKER_INITIALIZED }; } -// Macros for performing optimizations based on branch prediction. -#if defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 303) -#ifndef LIKELY -# define LIKELY(x) __builtin_expect(!!(x), 1) -#endif -#ifndef UNLIKELY -# define UNLIKELY(x) __builtin_expect(!!(x), 0) -#endif -#else // not !defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 303) -#ifndef LIKELY -# define LIKELY(x) (x) -#endif -#ifndef UNLIKELY -# define UNLIKELY(x) (x) -#endif -#endif // defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 303) - #endif // _BASICTYPES_H_ diff --git a/src/common.h b/src/common.h index 3e5cd19..b0c4877 100644 --- a/src/common.h +++ b/src/common.h @@ -43,6 +43,14 @@ #include "internal_logging.h" // for ASSERT, etc #include "base/basictypes.h" // for LIKELY, etc +#ifdef HAVE_BUILTIN_EXPECT +#define LIKELY(x) __builtin_expect(!!(x), 1) +#define UNLIKELY(x) __builtin_expect(!!(x), 0) +#else +#define LIKELY(x) (x) +#define UNLIKELY(x) (x) +#endif + // Type that can hold a page number typedef uintptr_t PageID; diff --git a/src/config.h.in b/src/config.h.in index 4eed17a..b13d0c8 100644 --- a/src/config.h.in +++ b/src/config.h.in @@ -5,6 +5,9 @@ #define GPERFTOOLS_CONFIG_H_ +/* Define to 1 if compiler supports __builtin_expect */ +#undef HAVE_BUILTIN_EXPECT + /* Define to 1 if compiler supports __builtin_stack_pointer */ #undef HAVE_BUILTIN_STACK_POINTER diff --git a/src/tcmalloc.cc b/src/tcmalloc.cc index af04e04..857da14 100644 --- a/src/tcmalloc.cc +++ b/src/tcmalloc.cc @@ -969,13 +969,13 @@ static void* DoSampledAllocation(size_t size) { SpinLockHolder h(Static::pageheap_lock()); // Allocate span Span *span = Static::pageheap()->New(tcmalloc::pages(size == 0 ? 1 : size)); - if (span == NULL) { + if (UNLIKELY(span == NULL)) { return NULL; } // Allocate stack trace StackTrace *stack = Static::stacktrace_allocator()->New(); - if (stack == NULL) { + if (UNLIKELY(stack == NULL)) { // Sampling failed because of lack of memory return span; } @@ -1064,7 +1064,7 @@ inline void* do_malloc_pages(ThreadCache* heap, size_t size) { } else { SpinLockHolder h(Static::pageheap_lock()); Span* span = Static::pageheap()->New(num_pages); - result = (span == NULL ? NULL : SpanToMallocResult(span)); + result = (UNLIKELY(span == NULL) ? NULL : SpanToMallocResult(span)); report_large = should_report_large(num_pages); } @@ -1231,7 +1231,7 @@ inline size_t GetSizeWithCallback(const void* ptr, return Static::sizemap()->ByteSizeForClass(cl); } else { const Span *span = Static::pageheap()->GetDescriptor(p); - if (span == NULL) { // means we do not own this memory + if (UNLIKELY(span == NULL)) { // means we do not own this memory return (*invalid_getsize_fn)(ptr); } else if (span->sizeclass != 0) { Static::pageheap()->CacheSizeClass(p, span->sizeclass); @@ -1270,7 +1270,7 @@ inline void* do_realloc_with_callback( // Either new_size is not a tiny increment, or last do_malloc failed. new_ptr = do_malloc_or_cpp_alloc(new_size); } - if (new_ptr == NULL) { + if (UNLIKELY(new_ptr == NULL)) { return NULL; } MallocHook::InvokeNewHook(new_ptr, new_size); @@ -1313,7 +1313,7 @@ void* do_memalign(size_t align, size_t size) { return p; } - if (Static::pageheap() == NULL) ThreadCache::InitModule(); + if (UNLIKELY(Static::pageheap() == NULL)) ThreadCache::InitModule(); // Allocate at least one byte to avoid boundary conditions below if (size == 0) size = 1; @@ -1345,13 +1345,13 @@ void* do_memalign(size_t align, size_t size) { // TODO: We could put the rest of this page in the appropriate // TODO: cache but it does not seem worth it. Span* span = Static::pageheap()->New(tcmalloc::pages(size)); - return span == NULL ? NULL : SpanToMallocResult(span); + return UNLIKELY(span == NULL) ? NULL : SpanToMallocResult(span); } // Allocate extra pages and carve off an aligned portion const Length alloc = tcmalloc::pages(size + align); Span* span = Static::pageheap()->New(alloc); - if (span == NULL) return NULL; + if (UNLIKELY(span == NULL)) return NULL; // Skip starting portion so that we end up aligned Length skip = 0; @@ -1421,7 +1421,7 @@ inline void* cpp_alloc(size_t size, bool nothrow) { #else for (;;) { void* p = do_malloc_no_errno(size); - if (p == NULL) { // allocation failed + if (UNLIKELY(p == NULL)) { // allocation failed // Get the current new handler. NB: this function is not // thread-safe. We make a feeble stab at making it so here, but // this lock only protects against tcmalloc interfering with @@ -1472,7 +1472,7 @@ void* cpp_memalign(size_t align, size_t size) { #ifdef PREANSINEW return p; #else - if (p == NULL) { // allocation failed + if (UNLIKELY(p == NULL)) { // allocation failed // Get the current new handler. NB: this function is not // thread-safe. We make a feeble stab at making it so here, but // this lock only protects against tcmalloc interfering with @@ -1672,7 +1672,7 @@ extern "C" PERFTOOLS_DLL_DECL int tc_posix_memalign( void* result = do_memalign_or_cpp_memalign(align, size); MallocHook::InvokeNewHook(result, size); - if (result == NULL) { + if (UNLIKELY(result == NULL)) { return ENOMEM; } else { *result_ptr = result; |