From f419d4ffd5c653a7fcb85449ed2ba8296c147d18 Mon Sep 17 00:00:00 2001 From: Andrey Semashev Date: Fri, 7 Jun 2013 20:05:18 +0000 Subject: [PATCH] Added BOOST_NOINLINE, BOOST_LIKELY and BOOST_UNLIKELY macros. [SVN r84679] --- doc/macro_reference.qbk | 28 +++++++++++++++++++++++ include/boost/config/compiler/clang.hpp | 8 +++++++ include/boost/config/compiler/gcc.hpp | 8 +++++-- include/boost/config/compiler/intel.hpp | 8 +++++++ include/boost/config/suffix.hpp | 30 ++++++++++++++++++++++++- 5 files changed, 79 insertions(+), 3 deletions(-) diff --git a/doc/macro_reference.qbk b/doc/macro_reference.qbk index 31f5f92e..acc36d54 100644 --- a/doc/macro_reference.qbk +++ b/doc/macro_reference.qbk @@ -1003,6 +1003,34 @@ Note that use of this macro can lead to cryptic error messages with some compile Consider defining it to `inline` before including the Boost.Config header in order to be able to debug errors more easily. ]] +[[`BOOST_NOINLINE`][ +This macro can be used in place of the `inline` keyword to instruct the compiler +that a function should never be inlined. One should typically use this macro +to mark functions that are unlikely to be called, such as error handling routines. + +Usage example: +`` + BOOST_NOINLINE void handle_error(const char* descr) + { + // ... + } +`` +]] +[[`BOOST_LIKELY(X)` + `BOOST_UNLIKELY(X)`][ +These macros communicate to the compiler that the conditional expression `X` is likely +or unlikely to yield a positive result. The expression should result in a boolean value. +The result of the macro is an integer or boolean value equivalent to the result of `X`. + +The macros are intended to be used in branching statements. The additional hint they provide +can be used by the compiler to arrange the compiled code of the branches more effectively. + +Usage example: +`` + if (BOOST_UNLIKELY(ptr == NULL)) + handle_error("ptr is NULL"); +`` +]] ] [endsect] diff --git a/include/boost/config/compiler/clang.hpp b/include/boost/config/compiler/clang.hpp index 8e38821b..89975737 100644 --- a/include/boost/config/compiler/clang.hpp +++ b/include/boost/config/compiler/clang.hpp @@ -26,6 +26,14 @@ #define BOOST_HAS_NRVO +// Branch prediction hints +#if defined(__has_builtin) +#if __has_builtin(__builtin_expect) +#define BOOST_LIKELY(x) __builtin_expect(x, 1) +#define BOOST_UNLIKELY(x) __builtin_expect(x, 0) +#endif +#endif + // Clang supports "long long" in all compilation modes. #define BOOST_HAS_LONG_LONG diff --git a/include/boost/config/compiler/gcc.hpp b/include/boost/config/compiler/gcc.hpp index b3d12ec6..0b86dd3f 100644 --- a/include/boost/config/compiler/gcc.hpp +++ b/include/boost/config/compiler/gcc.hpp @@ -118,6 +118,10 @@ #define BOOST_HAS_NRVO #endif +// Branch prediction hints +#define BOOST_LIKELY(x) __builtin_expect(x, 1) +#define BOOST_UNLIKELY(x) __builtin_expect(x, 0) + // // Dynamic shared object (DSO) and dynamic-link library (DLL) support // @@ -135,7 +139,7 @@ # endif # define BOOST_SYMBOL_VISIBLE __attribute__((visibility("default"))) #else -// config/platform/win32.hpp will define BOOST_SYMBOL_EXPORT, etc., unless already defined +// config/platform/win32.hpp will define BOOST_SYMBOL_EXPORT, etc., unless already defined # define BOOST_SYMBOL_EXPORT #endif @@ -158,7 +162,7 @@ // // We disable this if the compiler is really nvcc as it // doesn't actually support __int128 as of CUDA_VERSION=5000 -// even though it defines __SIZEOF_INT128__. +// even though it defines __SIZEOF_INT128__. // See https://svn.boost.org/trac/boost/ticket/8048 // Only re-enable this for nvcc if you're absolutely sure // of the circumstances under which it's supported: diff --git a/include/boost/config/compiler/intel.hpp b/include/boost/config/compiler/intel.hpp index e94540a5..243397c4 100644 --- a/include/boost/config/compiler/intel.hpp +++ b/include/boost/config/compiler/intel.hpp @@ -154,6 +154,14 @@ template<> struct assert_intrinsic_wchar_t {}; # define BOOST_HAS_NRVO #endif +// Branch prediction hints +// I'm not sure 8.0 was the first version to support these builtins, +// update the condition if the version is not accurate. (Andrey Semashev) +#if defined(__GNUC__) && BOOST_INTEL_CXX_VERSION >= 800 +#define BOOST_LIKELY(x) __builtin_expect(x, 1) +#define BOOST_UNLIKELY(x) __builtin_expect(x, 0) +#endif + // // versions check: // we don't support Intel prior to version 5.0: diff --git a/include/boost/config/suffix.hpp b/include/boost/config/suffix.hpp index 21591c9e..654284d2 100644 --- a/include/boost/config/suffix.hpp +++ b/include/boost/config/suffix.hpp @@ -632,7 +632,7 @@ namespace std{ using ::type_info; } // Set some default values GPU support // # ifndef BOOST_GPU_ENABLED -# define BOOST_GPU_ENABLED +# define BOOST_GPU_ENABLED # endif // BOOST_FORCEINLINE ---------------------------------------------// @@ -648,6 +648,34 @@ namespace std{ using ::type_info; } # endif #endif +// BOOST_NOINLINE ---------------------------------------------// +// Macro to use in place of 'inline' to prevent a function to be inlined +#if !defined(BOOST_NOINLINE) +# if defined(_MSC_VER) +# define BOOST_NOINLINE __declspec(noinline) +# elif defined(__GNUC__) && __GNUC__ > 3 + // Clang also defines __GNUC__ (as 4) +# define BOOST_NOINLINE __attribute__ ((__noinline__)) +# else +# define BOOST_NOINLINE +# endif +#endif + +// Branch prediction hints +// These macros are intended to wrap conditional expressions that yield true or false +// +// if (BOOST_LIKELY(var == 10)) +// { +// // the most probable code here +// } +// +#if !defined(BOOST_LIKELY) +# define BOOST_LIKELY(x) x +#endif +#if !defined(BOOST_UNLIKELY) +# define BOOST_UNLIKELY(x) x +#endif + // // Set BOOST_NO_DECLTYPE_N3276 when BOOST_NO_DECLTYPE is defined //