summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGuido van Rossum <guido@python.org>2022-12-08 23:54:07 (GMT)
committerGitHub <noreply@github.com>2022-12-08 23:54:07 (GMT)
commit1cfa704f64193701e400a77d2287f3526ff026f8 (patch)
tree5aa37f510556e544604ede6a558953992aac5a7e
parent8a3f06c54b52e5e7490a131b261384baac9d6090 (diff)
downloadcpython-1cfa704f64193701e400a77d2287f3526ff026f8.zip
cpython-1cfa704f64193701e400a77d2287f3526ff026f8.tar.gz
cpython-1cfa704f64193701e400a77d2287f3526ff026f8.tar.bz2
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.
-rw-r--r--Python/generated_cases.c.h474
-rw-r--r--Tools/cases_generator/generate_cases.py56
2 files changed, 269 insertions, 261 deletions
diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h
index 510b6c4..76eb608 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 8442722..5930c79 100644
--- a/Tools/cases_generator/generate_cases.py
+++ b/Tools/cases_generator/generate_cases.py
@@ -311,6 +311,7 @@ class Analyzer:
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 @@ class Analyzer:
# Parse from start
psr.setpos(start)
+ self.everything = []
self.instrs = {}
self.supers = {}
self.macros = {}
@@ -352,10 +354,13 @@ class Analyzer:
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 @@ class Analyzer:
# 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 @@ class Analyzer:
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):