From dd42fc2722b5d21bca602727e98af56c717e9b26 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Thu, 16 Sep 2021 18:03:16 +0200 Subject: [PATCH 1/3] bpo-45116: Add the Py_ALWAYS_INLINE macro Add the Py_ALWAYS_INLINE macro to ask the compiler to always inline a static inline function. The compiler can ignore it and decides to not inline the function. --- Doc/c-api/intro.rst | 22 ++++++++++++++++ Include/pyport.h | 25 +++++++++++++++++++ .../2021-09-16-18-05-20.bpo-45116.WxXewl.rst | 3 +++ 3 files changed, 50 insertions(+) create mode 100644 Misc/NEWS.d/next/C API/2021-09-16-18-05-20.bpo-45116.WxXewl.rst diff --git a/Doc/c-api/intro.rst b/Doc/c-api/intro.rst index 83824bb474fbd8..f5d0702e93d7a6 100644 --- a/Doc/c-api/intro.rst +++ b/Doc/c-api/intro.rst @@ -111,6 +111,28 @@ complete listing. .. versionadded:: 3.3 +.. c:macro:: Py_ALWAYS_INLINE + + Ask the compiler to always inline a static inline function. The compiler can + ignore it and decides to not inline the function. + + This attribute can be used to avoid increasing the stack memory usage when + building Python in debug mode with function inlining disabled. For example, + MSC disables function inlining when building in debug mode. It should be + used on the most commonly used static inline functions. + + Marking blindly a static inline function with Py_ALWAYS_INLINE can result in + worse performances (due to increased code size for example). The compiler is + usually smarter than the developer for the cost/benefit analysis. + + It must be specified before the function return type. + + Usage:: + + static inline Py_ALWAYS_INLINE int random(void) { return 4; } + + .. versionadded:: 3.11 + .. c:macro:: Py_CHARMASK(c) Argument must be a character or an integer in the range [-128, 127] or [0, diff --git a/Include/pyport.h b/Include/pyport.h index 0aaa4eedd31a1c..cf8539b2ee26cb 100644 --- a/Include/pyport.h +++ b/Include/pyport.h @@ -557,6 +557,31 @@ extern "C" { #define _Py_HOT_FUNCTION #endif +// Ask the compiler to always inline a static inline function. The compiler can +// ignore it and decides to not inline the function. +// +// This attribute can be used to avoid increasing the stack memory usage when +// building Python in debug mode with function inlining disabled. For example, +// MSC disables function inlining when building in debug mode. It should be +// used on the most commonly used static inline functions. +// +// Marking blindly a static inline function with Py_ALWAYS_INLINE can result in +// worse performances (due to increased code size for example). The compiler is +// usually smarter than the developer for the cost/benefit analysis. +// +// It must be specified before the function return type. +// +// Usage: +// +// static inline Py_ALWAYS_INLINE int random(void) { return 4; } +#if defined(__GNUC__) || defined(__clang__) || defined(__INTEL_COMPILER) +# define Py_ALWAYS_INLINE __attribute__((always_inline)) +#elif defined(_MSC_VER) +# define Py_ALWAYS_INLINE __forceinline +#else +# define Py_ALWAYS_INLINE +#endif + // Py_NO_INLINE // Disable inlining on a function. For example, it reduces the C stack // consumption: useful on LTO+PGO builds which heavily inline code (see diff --git a/Misc/NEWS.d/next/C API/2021-09-16-18-05-20.bpo-45116.WxXewl.rst b/Misc/NEWS.d/next/C API/2021-09-16-18-05-20.bpo-45116.WxXewl.rst new file mode 100644 index 00000000000000..cf3db5ca2a0236 --- /dev/null +++ b/Misc/NEWS.d/next/C API/2021-09-16-18-05-20.bpo-45116.WxXewl.rst @@ -0,0 +1,3 @@ +Add the :c:macro:`Py_ALWAYS_INLINE` macro to ask the compiler to always +inline a static inline function. The compiler can ignore it and decides to +not inline the function. Patch by Victor Stinner. From fa020c890a68c142bdfda1f4824ce697e4124fb1 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Thu, 16 Sep 2021 18:11:39 +0200 Subject: [PATCH 2/3] Rephrase the doc --- Doc/c-api/intro.rst | 5 ++--- Include/pyport.h | 5 ++--- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/Doc/c-api/intro.rst b/Doc/c-api/intro.rst index f5d0702e93d7a6..e21aa207b20d0a 100644 --- a/Doc/c-api/intro.rst +++ b/Doc/c-api/intro.rst @@ -116,10 +116,9 @@ complete listing. Ask the compiler to always inline a static inline function. The compiler can ignore it and decides to not inline the function. - This attribute can be used to avoid increasing the stack memory usage when + It can be used to inline performance critical static inline functions when building Python in debug mode with function inlining disabled. For example, - MSC disables function inlining when building in debug mode. It should be - used on the most commonly used static inline functions. + MSC disables function inlining when building in debug mode. Marking blindly a static inline function with Py_ALWAYS_INLINE can result in worse performances (due to increased code size for example). The compiler is diff --git a/Include/pyport.h b/Include/pyport.h index cf8539b2ee26cb..f8c6267a88db25 100644 --- a/Include/pyport.h +++ b/Include/pyport.h @@ -560,10 +560,9 @@ extern "C" { // Ask the compiler to always inline a static inline function. The compiler can // ignore it and decides to not inline the function. // -// This attribute can be used to avoid increasing the stack memory usage when +// It can be used to inline performance critical static inline functions when // building Python in debug mode with function inlining disabled. For example, -// MSC disables function inlining when building in debug mode. It should be -// used on the most commonly used static inline functions. +// MSC disables function inlining when building in debug mode. // // Marking blindly a static inline function with Py_ALWAYS_INLINE can result in // worse performances (due to increased code size for example). The compiler is From 73e5d10ac6e5f642ddfed2eb6b1cb68e8675adc5 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Thu, 16 Sep 2021 18:13:40 +0200 Subject: [PATCH 3/3] Reformat the doc --- Doc/c-api/intro.rst | 4 +--- Include/pyport.h | 4 +--- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/Doc/c-api/intro.rst b/Doc/c-api/intro.rst index e21aa207b20d0a..aac28b1e77561a 100644 --- a/Doc/c-api/intro.rst +++ b/Doc/c-api/intro.rst @@ -124,9 +124,7 @@ complete listing. worse performances (due to increased code size for example). The compiler is usually smarter than the developer for the cost/benefit analysis. - It must be specified before the function return type. - - Usage:: + It must be specified before the function return type. Usage:: static inline Py_ALWAYS_INLINE int random(void) { return 4; } diff --git a/Include/pyport.h b/Include/pyport.h index f8c6267a88db25..af7fbe7fc71954 100644 --- a/Include/pyport.h +++ b/Include/pyport.h @@ -568,9 +568,7 @@ extern "C" { // worse performances (due to increased code size for example). The compiler is // usually smarter than the developer for the cost/benefit analysis. // -// It must be specified before the function return type. -// -// Usage: +// It must be specified before the function return type. Usage: // // static inline Py_ALWAYS_INLINE int random(void) { return 4; } #if defined(__GNUC__) || defined(__clang__) || defined(__INTEL_COMPILER)