[Python-checkins] GH-98831: Generate things in the input order (#100123)

gvanrossum webhook-mailer at python.org
Thu Dec 8 18:54:14 EST 2022


https://github.com/python/cpython/commit/1cfa704f64193701e400a77d2287f3526ff026f8
commit: 1cfa704f64193701e400a77d2287f3526ff026f8
branch: main
author: Guido van Rossum <guido at python.org>
committer: gvanrossum <gvanrossum at gmail.com>
date: 2022-12-08T15:54:07-08:00
summary:

GH-98831: Generate things in the input order (#100123)

This makes it easier to see what changed in the generated code
when converting an instruction to super or macro.

files:
M Python/generated_cases.c.h
M Tools/cases_generator/generate_cases.py

diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h
index 510b6c4a75b8..76eb6085ec57 100644
--- a/Python/generated_cases.c.h
+++ b/Python/generated_cases.c.h
@@ -63,6 +63,115 @@
             DISPATCH();
         }
 
+        TARGET(LOAD_FAST__LOAD_FAST) {
+            PyObject *_tmp_1;
+            PyObject *_tmp_2;
+            {
+                PyObject *value;
+                value = GETLOCAL(oparg);
+                assert(value != NULL);
+                Py_INCREF(value);
+                _tmp_2 = value;
+            }
+            NEXTOPARG();
+            JUMPBY(1);
+            {
+                PyObject *value;
+                value = GETLOCAL(oparg);
+                assert(value != NULL);
+                Py_INCREF(value);
+                _tmp_1 = value;
+            }
+            STACK_GROW(2);
+            POKE(1, _tmp_1);
+            POKE(2, _tmp_2);
+            DISPATCH();
+        }
+
+        TARGET(LOAD_FAST__LOAD_CONST) {
+            PyObject *_tmp_1;
+            PyObject *_tmp_2;
+            {
+                PyObject *value;
+                value = GETLOCAL(oparg);
+                assert(value != NULL);
+                Py_INCREF(value);
+                _tmp_2 = value;
+            }
+            NEXTOPARG();
+            JUMPBY(1);
+            {
+                PyObject *value;
+                value = GETITEM(consts, oparg);
+                Py_INCREF(value);
+                _tmp_1 = value;
+            }
+            STACK_GROW(2);
+            POKE(1, _tmp_1);
+            POKE(2, _tmp_2);
+            DISPATCH();
+        }
+
+        TARGET(STORE_FAST__LOAD_FAST) {
+            PyObject *_tmp_1 = PEEK(1);
+            {
+                PyObject *value = _tmp_1;
+                SETLOCAL(oparg, value);
+            }
+            NEXTOPARG();
+            JUMPBY(1);
+            {
+                PyObject *value;
+                value = GETLOCAL(oparg);
+                assert(value != NULL);
+                Py_INCREF(value);
+                _tmp_1 = value;
+            }
+            POKE(1, _tmp_1);
+            DISPATCH();
+        }
+
+        TARGET(STORE_FAST__STORE_FAST) {
+            PyObject *_tmp_1 = PEEK(1);
+            PyObject *_tmp_2 = PEEK(2);
+            {
+                PyObject *value = _tmp_1;
+                SETLOCAL(oparg, value);
+            }
+            NEXTOPARG();
+            JUMPBY(1);
+            {
+                PyObject *value = _tmp_2;
+                SETLOCAL(oparg, value);
+            }
+            STACK_SHRINK(2);
+            DISPATCH();
+        }
+
+        TARGET(LOAD_CONST__LOAD_FAST) {
+            PyObject *_tmp_1;
+            PyObject *_tmp_2;
+            {
+                PyObject *value;
+                value = GETITEM(consts, oparg);
+                Py_INCREF(value);
+                _tmp_2 = value;
+            }
+            NEXTOPARG();
+            JUMPBY(1);
+            {
+                PyObject *value;
+                value = GETLOCAL(oparg);
+                assert(value != NULL);
+                Py_INCREF(value);
+                _tmp_1 = value;
+            }
+            STACK_GROW(2);
+            POKE(1, _tmp_1);
+            POKE(2, _tmp_2);
+            DISPATCH();
+        }
+
         TARGET(POP_TOP) {
             PyObject *value = PEEK(1);
             Py_DECREF(value);
@@ -78,6 +187,21 @@
             DISPATCH();
         }
 
+        TARGET(END_FOR) {
+            PyObject *_tmp_1 = PEEK(1);
+            PyObject *_tmp_2 = PEEK(2);
+            {
+                PyObject *value = _tmp_1;
+                Py_DECREF(value);
+            }
+            {
+                PyObject *value = _tmp_2;
+                Py_DECREF(value);
+            }
+            STACK_SHRINK(2);
+            DISPATCH();
+        }
+
         TARGET(UNARY_POSITIVE) {
             PyObject *value = PEEK(1);
             PyObject *res;
@@ -2078,6 +2202,119 @@
             DISPATCH();
         }
 
+        TARGET(COMPARE_OP_FLOAT_JUMP) {
+            PyObject *_tmp_1 = PEEK(1);
+            PyObject *_tmp_2 = PEEK(2);
+            {
+                PyObject *right = _tmp_1;
+                PyObject *left = _tmp_2;
+                size_t jump;
+                uint16_t when_to_jump_mask = read_u16(next_instr + 1);
+                assert(cframe.use_tracing == 0);
+                // Combined: COMPARE_OP (float ? float) + POP_JUMP_IF_(true/false)
+                DEOPT_IF(!PyFloat_CheckExact(left), COMPARE_OP);
+                DEOPT_IF(!PyFloat_CheckExact(right), COMPARE_OP);
+                double dleft = PyFloat_AS_DOUBLE(left);
+                double dright = PyFloat_AS_DOUBLE(right);
+                // 1 if <, 2 if ==, 4 if >; this matches when _to_jump_mask
+                int sign_ish = 2*(dleft > dright) + 2 - (dleft < dright);
+                DEOPT_IF(isnan(dleft), COMPARE_OP);
+                DEOPT_IF(isnan(dright), COMPARE_OP);
+                STAT_INC(COMPARE_OP, hit);
+                _Py_DECREF_SPECIALIZED(left, _PyFloat_ExactDealloc);
+                _Py_DECREF_SPECIALIZED(right, _PyFloat_ExactDealloc);
+                jump = sign_ish & when_to_jump_mask;
+                _tmp_2 = (PyObject *)jump;
+            }
+            JUMPBY(2);
+            NEXTOPARG();
+            JUMPBY(1);
+            {
+                size_t jump = (size_t)_tmp_2;
+                assert(opcode == POP_JUMP_IF_FALSE || opcode == POP_JUMP_IF_TRUE);
+                if (jump) {
+                    JUMPBY(oparg);
+                }
+            }
+            STACK_SHRINK(2);
+            DISPATCH();
+        }
+
+        TARGET(COMPARE_OP_INT_JUMP) {
+            PyObject *_tmp_1 = PEEK(1);
+            PyObject *_tmp_2 = PEEK(2);
+            {
+                PyObject *right = _tmp_1;
+                PyObject *left = _tmp_2;
+                size_t jump;
+                uint16_t when_to_jump_mask = read_u16(next_instr + 1);
+                assert(cframe.use_tracing == 0);
+                // Combined: COMPARE_OP (int ? int) + POP_JUMP_IF_(true/false)
+                DEOPT_IF(!PyLong_CheckExact(left), COMPARE_OP);
+                DEOPT_IF(!PyLong_CheckExact(right), COMPARE_OP);
+                DEOPT_IF((size_t)(Py_SIZE(left) + 1) > 2, COMPARE_OP);
+                DEOPT_IF((size_t)(Py_SIZE(right) + 1) > 2, COMPARE_OP);
+                STAT_INC(COMPARE_OP, hit);
+                assert(Py_ABS(Py_SIZE(left)) <= 1 && Py_ABS(Py_SIZE(right)) <= 1);
+                Py_ssize_t ileft = Py_SIZE(left) * ((PyLongObject *)left)->ob_digit[0];
+                Py_ssize_t iright = Py_SIZE(right) * ((PyLongObject *)right)->ob_digit[0];
+                // 1 if <, 2 if ==, 4 if >; this matches when _to_jump_mask
+                int sign_ish = 2*(ileft > iright) + 2 - (ileft < iright);
+                _Py_DECREF_SPECIALIZED(left, (destructor)PyObject_Free);
+                _Py_DECREF_SPECIALIZED(right, (destructor)PyObject_Free);
+                jump = sign_ish & when_to_jump_mask;
+                _tmp_2 = (PyObject *)jump;
+            }
+            JUMPBY(2);
+            NEXTOPARG();
+            JUMPBY(1);
+            {
+                size_t jump = (size_t)_tmp_2;
+                assert(opcode == POP_JUMP_IF_FALSE || opcode == POP_JUMP_IF_TRUE);
+                if (jump) {
+                    JUMPBY(oparg);
+                }
+            }
+            STACK_SHRINK(2);
+            DISPATCH();
+        }
+
+        TARGET(COMPARE_OP_STR_JUMP) {
+            PyObject *_tmp_1 = PEEK(1);
+            PyObject *_tmp_2 = PEEK(2);
+            {
+                PyObject *right = _tmp_1;
+                PyObject *left = _tmp_2;
+                size_t jump;
+                uint16_t invert = read_u16(next_instr + 1);
+                assert(cframe.use_tracing == 0);
+                // Combined: COMPARE_OP (str == str or str != str) + POP_JUMP_IF_(true/false)
+                DEOPT_IF(!PyUnicode_CheckExact(left), COMPARE_OP);
+                DEOPT_IF(!PyUnicode_CheckExact(right), COMPARE_OP);
+                STAT_INC(COMPARE_OP, hit);
+                int res = _PyUnicode_Equal(left, right);
+                assert(oparg == Py_EQ || oparg == Py_NE);
+                _Py_DECREF_SPECIALIZED(left, _PyUnicode_ExactDealloc);
+                _Py_DECREF_SPECIALIZED(right, _PyUnicode_ExactDealloc);
+                assert(res == 0 || res == 1);
+                assert(invert == 0 || invert == 1);
+                jump = res ^ invert;
+                _tmp_2 = (PyObject *)jump;
+            }
+            JUMPBY(2);
+            NEXTOPARG();
+            JUMPBY(1);
+            {
+                size_t jump = (size_t)_tmp_2;
+                assert(opcode == POP_JUMP_IF_FALSE || opcode == POP_JUMP_IF_TRUE);
+                if (jump) {
+                    JUMPBY(oparg);
+                }
+            }
+            STACK_SHRINK(2);
+            DISPATCH();
+        }
+
         TARGET(IS_OP) {
             PyObject *right = POP();
             PyObject *left = TOP();
@@ -3593,240 +3830,3 @@
         TARGET(CACHE) {
             Py_UNREACHABLE();
         }
-
-        TARGET(LOAD_FAST__LOAD_FAST) {
-            PyObject *_tmp_1;
-            PyObject *_tmp_2;
-            {
-                PyObject *value;
-                value = GETLOCAL(oparg);
-                assert(value != NULL);
-                Py_INCREF(value);
-                _tmp_2 = value;
-            }
-            NEXTOPARG();
-            JUMPBY(1);
-            {
-                PyObject *value;
-                value = GETLOCAL(oparg);
-                assert(value != NULL);
-                Py_INCREF(value);
-                _tmp_1 = value;
-            }
-            STACK_GROW(2);
-            POKE(1, _tmp_1);
-            POKE(2, _tmp_2);
-            DISPATCH();
-        }
-
-        TARGET(LOAD_FAST__LOAD_CONST) {
-            PyObject *_tmp_1;
-            PyObject *_tmp_2;
-            {
-                PyObject *value;
-                value = GETLOCAL(oparg);
-                assert(value != NULL);
-                Py_INCREF(value);
-                _tmp_2 = value;
-            }
-            NEXTOPARG();
-            JUMPBY(1);
-            {
-                PyObject *value;
-                value = GETITEM(consts, oparg);
-                Py_INCREF(value);
-                _tmp_1 = value;
-            }
-            STACK_GROW(2);
-            POKE(1, _tmp_1);
-            POKE(2, _tmp_2);
-            DISPATCH();
-        }
-
-        TARGET(STORE_FAST__LOAD_FAST) {
-            PyObject *_tmp_1 = PEEK(1);
-            {
-                PyObject *value = _tmp_1;
-                SETLOCAL(oparg, value);
-            }
-            NEXTOPARG();
-            JUMPBY(1);
-            {
-                PyObject *value;
-                value = GETLOCAL(oparg);
-                assert(value != NULL);
-                Py_INCREF(value);
-                _tmp_1 = value;
-            }
-            POKE(1, _tmp_1);
-            DISPATCH();
-        }
-
-        TARGET(STORE_FAST__STORE_FAST) {
-            PyObject *_tmp_1 = PEEK(1);
-            PyObject *_tmp_2 = PEEK(2);
-            {
-                PyObject *value = _tmp_1;
-                SETLOCAL(oparg, value);
-            }
-            NEXTOPARG();
-            JUMPBY(1);
-            {
-                PyObject *value = _tmp_2;
-                SETLOCAL(oparg, value);
-            }
-            STACK_SHRINK(2);
-            DISPATCH();
-        }
-
-        TARGET(LOAD_CONST__LOAD_FAST) {
-            PyObject *_tmp_1;
-            PyObject *_tmp_2;
-            {
-                PyObject *value;
-                value = GETITEM(consts, oparg);
-                Py_INCREF(value);
-                _tmp_2 = value;
-            }
-            NEXTOPARG();
-            JUMPBY(1);
-            {
-                PyObject *value;
-                value = GETLOCAL(oparg);
-                assert(value != NULL);
-                Py_INCREF(value);
-                _tmp_1 = value;
-            }
-            STACK_GROW(2);
-            POKE(1, _tmp_1);
-            POKE(2, _tmp_2);
-            DISPATCH();
-        }
-
-        TARGET(COMPARE_OP_FLOAT_JUMP) {
-            PyObject *_tmp_1 = PEEK(1);
-            PyObject *_tmp_2 = PEEK(2);
-            {
-                PyObject *right = _tmp_1;
-                PyObject *left = _tmp_2;
-                size_t jump;
-                uint16_t when_to_jump_mask = read_u16(next_instr + 1);
-                assert(cframe.use_tracing == 0);
-                // Combined: COMPARE_OP (float ? float) + POP_JUMP_IF_(true/false)
-                DEOPT_IF(!PyFloat_CheckExact(left), COMPARE_OP);
-                DEOPT_IF(!PyFloat_CheckExact(right), COMPARE_OP);
-                double dleft = PyFloat_AS_DOUBLE(left);
-                double dright = PyFloat_AS_DOUBLE(right);
-                // 1 if <, 2 if ==, 4 if >; this matches when _to_jump_mask
-                int sign_ish = 2*(dleft > dright) + 2 - (dleft < dright);
-                DEOPT_IF(isnan(dleft), COMPARE_OP);
-                DEOPT_IF(isnan(dright), COMPARE_OP);
-                STAT_INC(COMPARE_OP, hit);
-                _Py_DECREF_SPECIALIZED(left, _PyFloat_ExactDealloc);
-                _Py_DECREF_SPECIALIZED(right, _PyFloat_ExactDealloc);
-                jump = sign_ish & when_to_jump_mask;
-                _tmp_2 = (PyObject *)jump;
-            }
-            JUMPBY(2);
-            NEXTOPARG();
-            JUMPBY(1);
-            {
-                size_t jump = (size_t)_tmp_2;
-                assert(opcode == POP_JUMP_IF_FALSE || opcode == POP_JUMP_IF_TRUE);
-                if (jump) {
-                    JUMPBY(oparg);
-                }
-            }
-            STACK_SHRINK(2);
-            DISPATCH();
-        }
-
-        TARGET(COMPARE_OP_INT_JUMP) {
-            PyObject *_tmp_1 = PEEK(1);
-            PyObject *_tmp_2 = PEEK(2);
-            {
-                PyObject *right = _tmp_1;
-                PyObject *left = _tmp_2;
-                size_t jump;
-                uint16_t when_to_jump_mask = read_u16(next_instr + 1);
-                assert(cframe.use_tracing == 0);
-                // Combined: COMPARE_OP (int ? int) + POP_JUMP_IF_(true/false)
-                DEOPT_IF(!PyLong_CheckExact(left), COMPARE_OP);
-                DEOPT_IF(!PyLong_CheckExact(right), COMPARE_OP);
-                DEOPT_IF((size_t)(Py_SIZE(left) + 1) > 2, COMPARE_OP);
-                DEOPT_IF((size_t)(Py_SIZE(right) + 1) > 2, COMPARE_OP);
-                STAT_INC(COMPARE_OP, hit);
-                assert(Py_ABS(Py_SIZE(left)) <= 1 && Py_ABS(Py_SIZE(right)) <= 1);
-                Py_ssize_t ileft = Py_SIZE(left) * ((PyLongObject *)left)->ob_digit[0];
-                Py_ssize_t iright = Py_SIZE(right) * ((PyLongObject *)right)->ob_digit[0];
-                // 1 if <, 2 if ==, 4 if >; this matches when _to_jump_mask
-                int sign_ish = 2*(ileft > iright) + 2 - (ileft < iright);
-                _Py_DECREF_SPECIALIZED(left, (destructor)PyObject_Free);
-                _Py_DECREF_SPECIALIZED(right, (destructor)PyObject_Free);
-                jump = sign_ish & when_to_jump_mask;
-                _tmp_2 = (PyObject *)jump;
-            }
-            JUMPBY(2);
-            NEXTOPARG();
-            JUMPBY(1);
-            {
-                size_t jump = (size_t)_tmp_2;
-                assert(opcode == POP_JUMP_IF_FALSE || opcode == POP_JUMP_IF_TRUE);
-                if (jump) {
-                    JUMPBY(oparg);
-                }
-            }
-            STACK_SHRINK(2);
-            DISPATCH();
-        }
-
-        TARGET(COMPARE_OP_STR_JUMP) {
-            PyObject *_tmp_1 = PEEK(1);
-            PyObject *_tmp_2 = PEEK(2);
-            {
-                PyObject *right = _tmp_1;
-                PyObject *left = _tmp_2;
-                size_t jump;
-                uint16_t invert = read_u16(next_instr + 1);
-                assert(cframe.use_tracing == 0);
-                // Combined: COMPARE_OP (str == str or str != str) + POP_JUMP_IF_(true/false)
-                DEOPT_IF(!PyUnicode_CheckExact(left), COMPARE_OP);
-                DEOPT_IF(!PyUnicode_CheckExact(right), COMPARE_OP);
-                STAT_INC(COMPARE_OP, hit);
-                int res = _PyUnicode_Equal(left, right);
-                assert(oparg == Py_EQ || oparg == Py_NE);
-                _Py_DECREF_SPECIALIZED(left, _PyUnicode_ExactDealloc);
-                _Py_DECREF_SPECIALIZED(right, _PyUnicode_ExactDealloc);
-                assert(res == 0 || res == 1);
-                assert(invert == 0 || invert == 1);
-                jump = res ^ invert;
-                _tmp_2 = (PyObject *)jump;
-            }
-            JUMPBY(2);
-            NEXTOPARG();
-            JUMPBY(1);
-            {
-                size_t jump = (size_t)_tmp_2;
-                assert(opcode == POP_JUMP_IF_FALSE || opcode == POP_JUMP_IF_TRUE);
-                if (jump) {
-                    JUMPBY(oparg);
-                }
-            }
-            STACK_SHRINK(2);
-            DISPATCH();
-        }
-
-        TARGET(END_FOR) {
-            PyObject *_tmp_1 = PEEK(1);
-            PyObject *_tmp_2 = PEEK(2);
-            {
-                PyObject *value = _tmp_1;
-                Py_DECREF(value);
-            }
-            {
-                PyObject *value = _tmp_2;
-                Py_DECREF(value);
-            }
-            STACK_SHRINK(2);
-            DISPATCH();
-        }
diff --git a/Tools/cases_generator/generate_cases.py b/Tools/cases_generator/generate_cases.py
index 844272291245..5930c797b8a4 100644
--- a/Tools/cases_generator/generate_cases.py
+++ b/Tools/cases_generator/generate_cases.py
@@ -311,6 +311,7 @@ def error(self, msg: str, node: parser.Node) -> None:
         print(f"{self.filename}:{lineno}: {msg}", file=sys.stderr)
         self.errors += 1
 
+    everything: list[parser.InstDef | parser.Super | parser.Macro]
     instrs: dict[str, Instruction]  # Includes ops
     supers: dict[str, parser.Super]
     super_instrs: dict[str, SuperInstruction]
@@ -344,6 +345,7 @@ def parse(self) -> None:
 
         # Parse from start
         psr.setpos(start)
+        self.everything = []
         self.instrs = {}
         self.supers = {}
         self.macros = {}
@@ -352,10 +354,13 @@ def parse(self) -> None:
             match thing:
                 case parser.InstDef(name=name):
                     self.instrs[name] = Instruction(thing)
+                    self.everything.append(thing)
                 case parser.Super(name):
                     self.supers[name] = thing
+                    self.everything.append(thing)
                 case parser.Macro(name):
                     self.macros[name] = thing
+                    self.everything.append(thing)
                 case parser.Family(name):
                     self.families[name] = thing
                 case _:
@@ -560,33 +565,24 @@ def write_instructions(self) -> None:
             # Create formatter; the rest of the code uses this.
             self.out = Formatter(f, 8)
 
-            # Write and count regular instructions
+            # Write and count instructions of all kinds
             n_instrs = 0
-            for name, instr in self.instrs.items():
-                if instr.kind != "inst":
-                    continue  # ops are not real instructions
-                n_instrs += 1
-                self.out.emit("")
-                with self.out.block(f"TARGET({name})"):
-                    if instr.predicted:
-                        self.out.emit(f"PREDICTED({name});")
-                    instr.write(self.out)
-                    if not instr.always_exits:
-                        for prediction in instr.predictions:
-                            self.out.emit(f"PREDICT({prediction});")
-                        self.out.emit(f"DISPATCH();")
-
-            # Write and count super-instructions
             n_supers = 0
-            for sup in self.super_instrs.values():
-                n_supers += 1
-                self.write_super(sup)
-
-            # Write and count macro instructions
             n_macros = 0
-            for macro in self.macro_instrs.values():
-                n_macros += 1
-                self.write_macro(macro)
+            for thing in self.everything:
+                match thing:
+                    case parser.InstDef():
+                        if thing.kind == "inst":
+                            n_instrs += 1
+                            self.write_instr(self.instrs[thing.name])
+                    case parser.Super():
+                        n_supers += 1
+                        self.write_super(self.super_instrs[thing.name])
+                    case parser.Macro():
+                        n_macros += 1
+                        self.write_macro(self.macro_instrs[thing.name])
+                    case _:
+                        typing.assert_never(thing)
 
         print(
             f"Wrote {n_instrs} instructions, {n_supers} supers, "
@@ -594,6 +590,18 @@ def write_instructions(self) -> None:
             file=sys.stderr,
         )
 
+    def write_instr(self, instr: Instruction) -> None:
+        name = instr.name
+        self.out.emit("")
+        with self.out.block(f"TARGET({name})"):
+            if instr.predicted:
+                self.out.emit(f"PREDICTED({name});")
+            instr.write(self.out)
+            if not instr.always_exits:
+                for prediction in instr.predictions:
+                    self.out.emit(f"PREDICT({prediction});")
+                self.out.emit(f"DISPATCH();")
+
     def write_super(self, sup: SuperInstruction) -> None:
         """Write code for a super-instruction."""
         with self.wrap_super_or_macro(sup):



More information about the Python-checkins mailing list