]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
GH-113464: Speed up JIT builds (GH-122839)
authorBrandt Bucher <brandtbucher@microsoft.com>
Wed, 14 Aug 2024 14:53:46 +0000 (07:53 -0700)
committerGitHub <noreply@github.com>
Wed, 14 Aug 2024 14:53:46 +0000 (07:53 -0700)
Tools/jit/_targets.py
Tools/jit/template.c

index 73d10a128756eb1cb52fead6a528d1ef91d835e8..e37ee94399978536b129e8fe5a5d12a9fed60762 100644 (file)
@@ -182,15 +182,27 @@ class _Target(typing.Generic[_S, _R]):
 
     async def _build_stencils(self) -> dict[str, _stencils.StencilGroup]:
         generated_cases = PYTHON_EXECUTOR_CASES_C_H.read_text()
-        opnames = sorted(re.findall(r"\n {8}case (\w+): \{\n", generated_cases))
+        cases_and_opnames = sorted(
+            re.findall(
+                r"\n {8}(case (\w+): \{\n.*?\n {8}\})", generated_cases, flags=re.DOTALL
+            )
+        )
         tasks = []
         with tempfile.TemporaryDirectory() as tempdir:
             work = pathlib.Path(tempdir).resolve()
             async with asyncio.TaskGroup() as group:
                 coro = self._compile("trampoline", TOOLS_JIT / "trampoline.c", work)
                 tasks.append(group.create_task(coro, name="trampoline"))
-                for opname in opnames:
-                    coro = self._compile(opname, TOOLS_JIT_TEMPLATE_C, work)
+                template = TOOLS_JIT_TEMPLATE_C.read_text()
+                for case, opname in cases_and_opnames:
+                    # Write out a copy of the template with *only* this case
+                    # inserted. This is about twice as fast as #include'ing all
+                    # of executor_cases.c.h each time we compile (since the C
+                    # compiler wastes a bunch of time parsing the dead code for
+                    # all of the other cases):
+                    c = work / f"{opname}.c"
+                    c.write_text(template.replace("CASE", case))
+                    coro = self._compile(opname, c, work)
                     tasks.append(group.create_task(coro, name=opname))
         return {task.get_name(): task.result() for task in tasks}
 
index ec7d033e89deff5a1f7a3cfe843d66edc26c3b9b..6cf15085f79933d0f4c697d7b791c16d8178a99c 100644 (file)
@@ -84,6 +84,8 @@ do {                                                         \
 #undef WITHIN_STACK_BOUNDS
 #define WITHIN_STACK_BOUNDS() 1
 
+#define TIER_TWO 2
+
 _Py_CODEUNIT *
 _JIT_ENTRY(_PyInterpreterFrame *frame, _PyStackRef *stack_pointer, PyThreadState *tstate)
 {
@@ -107,9 +109,9 @@ _JIT_ENTRY(_PyInterpreterFrame *frame, _PyStackRef *stack_pointer, PyThreadState
     OPT_STAT_INC(uops_executed);
     UOP_STAT_INC(uopcode, execution_count);
 
-    // The actual instruction definitions (only one will be used):
     switch (uopcode) {
-#include "executor_cases.c.h"
+        // The actual instruction definition gets inserted here:
+        CASE
         default:
             Py_UNREACHABLE();
     }