[Python-checkins] bpo-45094: Add Py_NO_INLINE macro (GH-28140)

vstinner webhook-mailer at python.org
Fri Sep 3 10:45:17 EDT 2021


https://github.com/python/cpython/commit/7974c30b9fd84fa56ea1515ed2c08b38edf1a383
commit: 7974c30b9fd84fa56ea1515ed2c08b38edf1a383
branch: main
author: Victor Stinner <vstinner at python.org>
committer: vstinner <vstinner at python.org>
date: 2021-09-03T16:44:02+02:00
summary:

bpo-45094: Add Py_NO_INLINE macro (GH-28140)

* Rename _Py_NO_INLINE macro to Py_NO_INLINE: make it public and
  document it.
* Sort macros in the C API documentation.

files:
A Misc/NEWS.d/next/C API/2021-09-03-15-53-43.bpo-45094.tinXwL.rst
M Doc/c-api/intro.rst
M Include/pymath.h
M Include/pyport.h
M Modules/_functoolsmodule.c
M Modules/_io/bytesio.c
M Modules/_posixsubprocess.c
M Python/marshal.c

diff --git a/Doc/c-api/intro.rst b/Doc/c-api/intro.rst
index 2d85d30702df9..83824bb474fbd 100644
--- a/Doc/c-api/intro.rst
+++ b/Doc/c-api/intro.rst
@@ -105,45 +105,63 @@ defined closer to where they are useful (e.g. :c:macro:`Py_RETURN_NONE`).
 Others of a more general utility are defined here.  This is not necessarily a
 complete listing.
 
-.. c:macro:: Py_UNREACHABLE()
+.. c:macro:: Py_ABS(x)
 
-   Use this when you have a code path that cannot be reached by design.
-   For example, in the ``default:`` clause in a ``switch`` statement for which
-   all possible values are covered in ``case`` statements.  Use this in places
-   where you might be tempted to put an ``assert(0)`` or ``abort()`` call.
+   Return the absolute value of ``x``.
 
-   In release mode, the macro helps the compiler to optimize the code, and
-   avoids a warning about unreachable code.  For example, the macro is
-   implemented with ``__builtin_unreachable()`` on GCC in release mode.
+   .. versionadded:: 3.3
 
-   A use for ``Py_UNREACHABLE()`` is following a call a function that
-   never returns but that is not declared :c:macro:`_Py_NO_RETURN`.
+.. c:macro:: Py_CHARMASK(c)
 
-   If a code path is very unlikely code but can be reached under exceptional
-   case, this macro must not be used.  For example, under low memory condition
-   or if a system call returns a value out of the expected range.  In this
-   case, it's better to report the error to the caller.  If the error cannot
-   be reported to caller, :c:func:`Py_FatalError` can be used.
+   Argument must be a character or an integer in the range [-128, 127] or [0,
+   255].  This macro returns ``c`` cast to an ``unsigned char``.
 
-   .. versionadded:: 3.7
+.. c:macro:: Py_DEPRECATED(version)
 
-.. c:macro:: Py_ABS(x)
+   Use this for deprecated declarations.  The macro must be placed before the
+   symbol name.
 
-   Return the absolute value of ``x``.
+   Example::
+
+      Py_DEPRECATED(3.8) PyAPI_FUNC(int) Py_OldFunction(void);
+
+   .. versionchanged:: 3.8
+      MSVC support was added.
+
+.. c:macro:: Py_GETENV(s)
+
+   Like ``getenv(s)``, but returns ``NULL`` if :option:`-E` was passed on the
+   command line (i.e. if ``Py_IgnoreEnvironmentFlag`` is set).
+
+.. c:macro:: Py_MAX(x, y)
+
+   Return the maximum value between ``x`` and ``y``.
 
    .. versionadded:: 3.3
 
+.. c:macro:: Py_MEMBER_SIZE(type, member)
+
+   Return the size of a structure (``type``) ``member`` in bytes.
+
+   .. versionadded:: 3.6
+
 .. c:macro:: Py_MIN(x, y)
 
    Return the minimum value between ``x`` and ``y``.
 
    .. versionadded:: 3.3
 
-.. c:macro:: Py_MAX(x, y)
+.. c:macro:: Py_NO_INLINE
 
-   Return the maximum value between ``x`` and ``y``.
+   Disable inlining on a function. For example, it reduces the C stack
+   consumption: useful on LTO+PGO builds which heavily inline code (see
+   :issue:`33720`).
 
-   .. versionadded:: 3.3
+   Usage::
+
+       Py_NO_INLINE static int random(void) { return 4; }
+
+   .. versionadded:: 3.11
 
 .. c:macro:: Py_STRINGIFY(x)
 
@@ -152,21 +170,27 @@ complete listing.
 
    .. versionadded:: 3.4
 
-.. c:macro:: Py_MEMBER_SIZE(type, member)
-
-   Return the size of a structure (``type``) ``member`` in bytes.
+.. c:macro:: Py_UNREACHABLE()
 
-   .. versionadded:: 3.6
+   Use this when you have a code path that cannot be reached by design.
+   For example, in the ``default:`` clause in a ``switch`` statement for which
+   all possible values are covered in ``case`` statements.  Use this in places
+   where you might be tempted to put an ``assert(0)`` or ``abort()`` call.
 
-.. c:macro:: Py_CHARMASK(c)
+   In release mode, the macro helps the compiler to optimize the code, and
+   avoids a warning about unreachable code.  For example, the macro is
+   implemented with ``__builtin_unreachable()`` on GCC in release mode.
 
-   Argument must be a character or an integer in the range [-128, 127] or [0,
-   255].  This macro returns ``c`` cast to an ``unsigned char``.
+   A use for ``Py_UNREACHABLE()`` is following a call a function that
+   never returns but that is not declared :c:macro:`_Py_NO_RETURN`.
 
-.. c:macro:: Py_GETENV(s)
+   If a code path is very unlikely code but can be reached under exceptional
+   case, this macro must not be used.  For example, under low memory condition
+   or if a system call returns a value out of the expected range.  In this
+   case, it's better to report the error to the caller.  If the error cannot
+   be reported to caller, :c:func:`Py_FatalError` can be used.
 
-   Like ``getenv(s)``, but returns ``NULL`` if :option:`-E` was passed on the
-   command line (i.e. if ``Py_IgnoreEnvironmentFlag`` is set).
+   .. versionadded:: 3.7
 
 .. c:macro:: Py_UNUSED(arg)
 
@@ -175,18 +199,6 @@ complete listing.
 
    .. versionadded:: 3.4
 
-.. c:macro:: Py_DEPRECATED(version)
-
-   Use this for deprecated declarations.  The macro must be placed before the
-   symbol name.
-
-   Example::
-
-      Py_DEPRECATED(3.8) PyAPI_FUNC(int) Py_OldFunction(void);
-
-   .. versionchanged:: 3.8
-      MSVC support was added.
-
 .. c:macro:: PyDoc_STRVAR(name, str)
 
    Creates a variable with name ``name`` that can be used in docstrings.
@@ -221,6 +233,7 @@ complete listing.
           {NULL, NULL}
       };
 
+
 .. _api-objects:
 
 Objects, Types and Reference Counts
diff --git a/Include/pymath.h b/Include/pymath.h
index f869724334a4c..ebb3b05f1b53c 100644
--- a/Include/pymath.h
+++ b/Include/pymath.h
@@ -163,12 +163,7 @@ PyAPI_FUNC(void) _Py_set_387controlword(unsigned short);
         #pragma float_control(push)
         #pragma float_control(precise, on)
         #pragma float_control(except,  on)
-        #if defined(_MSC_VER)
-            __declspec(noinline)
-        #else /* Linux */
-            __attribute__((noinline))
-        #endif /* _MSC_VER */
-        static double __icc_nan()
+        Py_NO_INLINE static double __icc_nan()
         {
             return sqrt(-1.0);
         }
diff --git a/Include/pyport.h b/Include/pyport.h
index b2b53dd2f771b..0aaa4eedd31a1 100644
--- a/Include/pyport.h
+++ b/Include/pyport.h
@@ -557,19 +557,20 @@ extern "C" {
 #define _Py_HOT_FUNCTION
 #endif
 
-/* _Py_NO_INLINE
- * Disable inlining on a function. For example, it helps to reduce the C stack
- * consumption.
- *
- * Usage:
- *    int _Py_NO_INLINE x(void) { return 3; }
- */
-#if defined(_MSC_VER)
-#  define _Py_NO_INLINE __declspec(noinline)
-#elif defined(__GNUC__) || defined(__clang__)
-#  define _Py_NO_INLINE __attribute__ ((noinline))
+// 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
+// bpo-33720).
+//
+// Usage:
+//
+//    Py_NO_INLINE static int random(void) { return 4; }
+#if defined(__GNUC__) || defined(__clang__) || defined(__INTEL_COMPILER)
+#  define Py_NO_INLINE __attribute__ ((noinline))
+#elif defined(_MSC_VER)
+#  define Py_NO_INLINE __declspec(noinline)
 #else
-#  define _Py_NO_INLINE
+#  define Py_NO_INLINE
 #endif
 
 /**************************************************************************
diff --git a/Misc/NEWS.d/next/C API/2021-09-03-15-53-43.bpo-45094.tinXwL.rst b/Misc/NEWS.d/next/C API/2021-09-03-15-53-43.bpo-45094.tinXwL.rst
new file mode 100644
index 0000000000000..84b01b23b435f
--- /dev/null
+++ b/Misc/NEWS.d/next/C API/2021-09-03-15-53-43.bpo-45094.tinXwL.rst	
@@ -0,0 +1,2 @@
+Add the :c:macro:`Py_NO_INLINE` macro to disable inlining on a function.
+Patch by Victor Stinner.
diff --git a/Modules/_functoolsmodule.c b/Modules/_functoolsmodule.c
index fa1452168094b..a93c0be6a149a 100644
--- a/Modules/_functoolsmodule.c
+++ b/Modules/_functoolsmodule.c
@@ -186,7 +186,7 @@ partial_dealloc(partialobject *pto)
 /* Merging keyword arguments using the vectorcall convention is messy, so
  * if we would need to do that, we stop using vectorcall and fall back
  * to using partial_call() instead. */
-_Py_NO_INLINE static PyObject *
+Py_NO_INLINE static PyObject *
 partial_vectorcall_fallback(PyThreadState *tstate, partialobject *pto,
                             PyObject *const *args, size_t nargsf,
                             PyObject *kwnames)
diff --git a/Modules/_io/bytesio.c b/Modules/_io/bytesio.c
index 2468f45f941e2..930ef7e29dbcf 100644
--- a/Modules/_io/bytesio.c
+++ b/Modules/_io/bytesio.c
@@ -176,7 +176,7 @@ resize_buffer(bytesio *self, size_t size)
    object. Returns the number of bytes written, or -1 on error.
    Inlining is disabled because it's significantly decreases performance
    of writelines() in PGO build. */
-_Py_NO_INLINE static Py_ssize_t
+Py_NO_INLINE static Py_ssize_t
 write_bytes(bytesio *self, PyObject *b)
 {
     if (check_closed(self)) {
diff --git a/Modules/_posixsubprocess.c b/Modules/_posixsubprocess.c
index a58159a277bea..63207de8b9137 100644
--- a/Modules/_posixsubprocess.c
+++ b/Modules/_posixsubprocess.c
@@ -451,7 +451,7 @@ reset_signal_handlers(const sigset_t *child_sigmask)
  * If vfork-unsafe functionality is desired after vfork(), consider using
  * syscall() to obtain it.
  */
-_Py_NO_INLINE static void
+Py_NO_INLINE static void
 child_exec(char *const exec_array[],
            char *const argv[],
            char *const envp[],
@@ -650,7 +650,7 @@ child_exec(char *const exec_array[],
  * child_exec() should not be inlined to avoid spurious -Wclobber warnings from
  * GCC (see bpo-35823).
  */
-_Py_NO_INLINE static pid_t
+Py_NO_INLINE static pid_t
 do_fork_exec(char *const exec_array[],
              char *const argv[],
              char *const envp[],
diff --git a/Python/marshal.c b/Python/marshal.c
index 60b818f0dda4a..346384edea618 100644
--- a/Python/marshal.c
+++ b/Python/marshal.c
@@ -891,7 +891,7 @@ r_float_bin(RFILE *p)
 
 /* Issue #33720: Disable inlining for reducing the C stack consumption
    on PGO builds. */
-_Py_NO_INLINE static double
+Py_NO_INLINE static double
 r_float_str(RFILE *p)
 {
     int n;



More information about the Python-checkins mailing list