From 385eb1d99c1326db7b2ce1df551b8efbc90104c0 Mon Sep 17 00:00:00 2001 From: Sam Gross Date: Tue, 12 Oct 2021 13:44:19 -0700 Subject: [PATCH] pyport: add new macros This adds _PY_LIKELY, _PY_UNLIKELY, _Py_ALWAYS_INLINE, and macros to test for SSE2 and NEON support. --- Include/pyport.h | 65 ++++++++++++++++++++++++++++++++++++++++++++++ Objects/obmalloc.c | 34 ------------------------ 2 files changed, 65 insertions(+), 34 deletions(-) diff --git a/Include/pyport.h b/Include/pyport.h index b1b2a747796..2c52c67e21e 100644 --- a/Include/pyport.h +++ b/Include/pyport.h @@ -162,6 +162,14 @@ typedef Py_ssize_t Py_ssize_clean_t; # define PY_FORMAT_SIZE_T "z" #endif +#if defined(__SSE2__) +#define HAVE_SSE2 1 +#elif defined(_MSC_VER) && (defined(_M_X64) || (defined(_M_IX86) && _M_IX86_FP >= 2)) +#define HAVE_SSE2 1 +#elif defined(__ARM_NEON) || defined(__ARM_NEON__) +#define HAVE_NEON 1 +#endif + /* Py_LOCAL can be used instead of static to get the fastest possible calling * convention for functions that are local to a given module. * @@ -340,6 +348,20 @@ extern "C" { #define _Py_COMP_DIAG_POP #endif +/* _Py_LIKELY and _PY_UNLIKELY + * Provides the compiler with branch prediction information. + * + * Usage: + * if (_PY_UNLIKELY(x == NULL)) { ... } + */ +#if defined(__GNUC__) +# define _PY_LIKELY(x) __builtin_expect((x),1) +# define _PY_UNLIKELY(x) __builtin_expect((x),0) +#else +# define _PY_LIKELY(x) (x) +# define _PY_UNLIKELY(x) (x) +#endif + /* _Py_HOT_FUNCTION * The hot attribute on a function is used to inform the compiler that the * function is a hot spot of the compiled program. The function is optimized @@ -409,6 +431,14 @@ extern "C" { # define Py_NO_INLINE #endif +#if defined(_MSC_VER) +# define _Py_ALWAYS_INLINE __forceinline +#elif defined(__GNUC__) || defined(__clang__) +# define _Py_ALWAYS_INLINE inline __attribute__ ((always_inline)) +#else +# define _Py_ALWAYS_INLINE inline +#endif + /************************************************************************** Prototypes that are missing from the standard include files on some systems (and possibly only some versions of such systems.) @@ -602,6 +632,12 @@ extern char * _getpty(int *, int, mode_t, int); #define Py_ALIGNED(x) #endif +#ifdef _MSC_VER +#define Py_DECL_THREAD __declspec(thread) +#else +#define Py_DECL_THREAD __thread +#endif + /* Eliminate end-of-loop code not reached warnings from SunPro C * when using do{...}while(0) macros */ @@ -720,10 +756,39 @@ extern char * _getpty(int *, int, mode_t, int); # define _Py_ADDRESS_SANITIZER # endif # endif +# if __has_feature(thread_sanitizer) +# if !defined(_Py_THREAD_SANITIZER) +# define _Py_THREAD_SANITIZER +# endif +# endif #elif defined(__GNUC__) # if defined(__SANITIZE_ADDRESS__) # define _Py_ADDRESS_SANITIZER # endif +# if defined(__SANITIZE_THREAD__) +# define _Py_THREAD_SANITIZER +# endif +#endif + +#if defined(_Py_MEMORY_SANITIZER) +# define _Py_NO_SANITIZE_MEMORY __attribute__((no_sanitize_memory)) +#else +# define _Py_NO_SANITIZE_MEMORY #endif +#if defined(_Py_ADDRESS_SANITIZER) +# define _Py_NO_SANITIZE_ADDRESS __attribute__((no_sanitize("address"))) +#else +# define _Py_NO_SANITIZE_ADDRESS +#endif + +// TSAN is supported since GCC 5.1, but __SANITIZE_THREAD__ macro is provided +// only since GCC 7. +#if defined(_Py_THREAD_SANITIZER) || (__GNUC__ > 5 || (__GNUC__ == 5 && __GNUC_MINOR__ >= 1)) +# define _Py_NO_SANITIZE_THREAD __attribute__((no_sanitize_thread)) +#else +# define _Py_NO_SANITIZE_THREAD +#endif + + #endif /* Py_PYPORT_H */ diff --git a/Objects/obmalloc.c b/Objects/obmalloc.c index 276c5a276c0..c0f03cdc1d5 100644 --- a/Objects/obmalloc.c +++ b/Objects/obmalloc.c @@ -167,40 +167,6 @@ _PyMem_ArenaFree(void *Py_UNUSED(ctx), void *ptr, /*******************************************/ -#if defined(__has_feature) /* Clang */ -# if __has_feature(address_sanitizer) /* is ASAN enabled? */ -# define _Py_NO_SANITIZE_ADDRESS \ - __attribute__((no_sanitize("address"))) -# endif -# if __has_feature(thread_sanitizer) /* is TSAN enabled? */ -# define _Py_NO_SANITIZE_THREAD __attribute__((no_sanitize_thread)) -# endif -# if __has_feature(memory_sanitizer) /* is MSAN enabled? */ -# define _Py_NO_SANITIZE_MEMORY __attribute__((no_sanitize_memory)) -# endif -#elif defined(__GNUC__) -# if defined(__SANITIZE_ADDRESS__) /* GCC 4.8+, is ASAN enabled? */ -# define _Py_NO_SANITIZE_ADDRESS \ - __attribute__((no_sanitize_address)) -# endif - // TSAN is supported since GCC 5.1, but __SANITIZE_THREAD__ macro - // is provided only since GCC 7. -# if __GNUC__ > 5 || (__GNUC__ == 5 && __GNUC_MINOR__ >= 1) -# define _Py_NO_SANITIZE_THREAD __attribute__((no_sanitize_thread)) -# endif -#endif - -#ifndef _Py_NO_SANITIZE_ADDRESS -# define _Py_NO_SANITIZE_ADDRESS -#endif -#ifndef _Py_NO_SANITIZE_THREAD -# define _Py_NO_SANITIZE_THREAD -#endif -#ifndef _Py_NO_SANITIZE_MEMORY -# define _Py_NO_SANITIZE_MEMORY -#endif - - #define _PyMem_Raw (_PyRuntime.allocators.standard.raw) #define _PyMem (_PyRuntime.allocators.standard.mem) #define _PyObject (_PyRuntime.allocators.standard.obj)