mirror of
https://github.com/python/cpython.git
synced 2025-08-31 05:58:33 +00:00
gh-133273: Keep instruction definitions in bytecodes.c
and optimizer_bytecodes.c
in sync (GH-133320)
This commit is contained in:
parent
5f3d3f2a6c
commit
3f2f59a91d
4 changed files with 372 additions and 134 deletions
|
@ -2069,6 +2069,189 @@ class TestGeneratedAbstractCases(unittest.TestCase):
|
||||||
with self.assertRaisesRegex(AssertionError, "All abstract uops"):
|
with self.assertRaisesRegex(AssertionError, "All abstract uops"):
|
||||||
self.run_cases_test(input, input2, output)
|
self.run_cases_test(input, input2, output)
|
||||||
|
|
||||||
|
def test_validate_uop_input_length_mismatch(self):
|
||||||
|
input = """
|
||||||
|
op(OP, (arg1 -- out)) {
|
||||||
|
SPAM();
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
input2 = """
|
||||||
|
op(OP, (arg1, arg2 -- out)) {
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
output = """
|
||||||
|
"""
|
||||||
|
with self.assertRaisesRegex(SyntaxError,
|
||||||
|
"Must have the same number of inputs"):
|
||||||
|
self.run_cases_test(input, input2, output)
|
||||||
|
|
||||||
|
def test_validate_uop_output_length_mismatch(self):
|
||||||
|
input = """
|
||||||
|
op(OP, (arg1 -- out)) {
|
||||||
|
SPAM();
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
input2 = """
|
||||||
|
op(OP, (arg1 -- out1, out2)) {
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
output = """
|
||||||
|
"""
|
||||||
|
with self.assertRaisesRegex(SyntaxError,
|
||||||
|
"Must have the same number of outputs"):
|
||||||
|
self.run_cases_test(input, input2, output)
|
||||||
|
|
||||||
|
def test_validate_uop_input_name_mismatch(self):
|
||||||
|
input = """
|
||||||
|
op(OP, (foo -- out)) {
|
||||||
|
SPAM();
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
input2 = """
|
||||||
|
op(OP, (bar -- out)) {
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
output = """
|
||||||
|
"""
|
||||||
|
with self.assertRaisesRegex(SyntaxError,
|
||||||
|
"Inputs must have equal names"):
|
||||||
|
self.run_cases_test(input, input2, output)
|
||||||
|
|
||||||
|
def test_validate_uop_output_name_mismatch(self):
|
||||||
|
input = """
|
||||||
|
op(OP, (arg1 -- foo)) {
|
||||||
|
SPAM();
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
input2 = """
|
||||||
|
op(OP, (arg1 -- bar)) {
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
output = """
|
||||||
|
"""
|
||||||
|
with self.assertRaisesRegex(SyntaxError,
|
||||||
|
"Outputs must have equal names"):
|
||||||
|
self.run_cases_test(input, input2, output)
|
||||||
|
|
||||||
|
def test_validate_uop_unused_input(self):
|
||||||
|
input = """
|
||||||
|
op(OP, (unused -- )) {
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
input2 = """
|
||||||
|
op(OP, (foo -- )) {
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
output = """
|
||||||
|
case OP: {
|
||||||
|
stack_pointer += -1;
|
||||||
|
assert(WITHIN_STACK_BOUNDS());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
self.run_cases_test(input, input2, output)
|
||||||
|
|
||||||
|
input = """
|
||||||
|
op(OP, (foo -- )) {
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
input2 = """
|
||||||
|
op(OP, (unused -- )) {
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
output = """
|
||||||
|
case OP: {
|
||||||
|
stack_pointer += -1;
|
||||||
|
assert(WITHIN_STACK_BOUNDS());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
self.run_cases_test(input, input2, output)
|
||||||
|
|
||||||
|
def test_validate_uop_unused_output(self):
|
||||||
|
input = """
|
||||||
|
op(OP, ( -- unused)) {
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
input2 = """
|
||||||
|
op(OP, ( -- foo)) {
|
||||||
|
foo = NULL;
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
output = """
|
||||||
|
case OP: {
|
||||||
|
JitOptSymbol *foo;
|
||||||
|
foo = NULL;
|
||||||
|
stack_pointer[0] = foo;
|
||||||
|
stack_pointer += 1;
|
||||||
|
assert(WITHIN_STACK_BOUNDS());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
self.run_cases_test(input, input2, output)
|
||||||
|
|
||||||
|
input = """
|
||||||
|
op(OP, ( -- foo)) {
|
||||||
|
foo = NULL;
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
input2 = """
|
||||||
|
op(OP, ( -- unused)) {
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
output = """
|
||||||
|
case OP: {
|
||||||
|
stack_pointer += 1;
|
||||||
|
assert(WITHIN_STACK_BOUNDS());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
self.run_cases_test(input, input2, output)
|
||||||
|
|
||||||
|
def test_validate_uop_input_size_mismatch(self):
|
||||||
|
input = """
|
||||||
|
op(OP, (arg1[2] -- )) {
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
input2 = """
|
||||||
|
op(OP, (arg1[4] -- )) {
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
output = """
|
||||||
|
"""
|
||||||
|
with self.assertRaisesRegex(SyntaxError,
|
||||||
|
"Inputs must have equal sizes"):
|
||||||
|
self.run_cases_test(input, input2, output)
|
||||||
|
|
||||||
|
def test_validate_uop_output_size_mismatch(self):
|
||||||
|
input = """
|
||||||
|
op(OP, ( -- out[2])) {
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
input2 = """
|
||||||
|
op(OP, ( -- out[4])) {
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
output = """
|
||||||
|
"""
|
||||||
|
with self.assertRaisesRegex(SyntaxError,
|
||||||
|
"Outputs must have equal sizes"):
|
||||||
|
self.run_cases_test(input, input2, output)
|
||||||
|
|
||||||
|
def test_validate_uop_unused_size_mismatch(self):
|
||||||
|
input = """
|
||||||
|
op(OP, (foo[2] -- )) {
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
input2 = """
|
||||||
|
op(OP, (unused[4] -- )) {
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
output = """
|
||||||
|
"""
|
||||||
|
with self.assertRaisesRegex(SyntaxError,
|
||||||
|
"Inputs must have equal sizes"):
|
||||||
|
self.run_cases_test(input, input2, output)
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|
|
@ -104,18 +104,18 @@ dummy_func(void) {
|
||||||
res = sym_new_null(ctx);
|
res = sym_new_null(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
op(_GUARD_TOS_INT, (tos -- tos)) {
|
op(_GUARD_TOS_INT, (value -- value)) {
|
||||||
if (sym_matches_type(tos, &PyLong_Type)) {
|
if (sym_matches_type(value, &PyLong_Type)) {
|
||||||
REPLACE_OP(this_instr, _NOP, 0, 0);
|
REPLACE_OP(this_instr, _NOP, 0, 0);
|
||||||
}
|
}
|
||||||
sym_set_type(tos, &PyLong_Type);
|
sym_set_type(value, &PyLong_Type);
|
||||||
}
|
}
|
||||||
|
|
||||||
op(_GUARD_NOS_INT, (nos, unused -- nos, unused)) {
|
op(_GUARD_NOS_INT, (left, unused -- left, unused)) {
|
||||||
if (sym_matches_type(nos, &PyLong_Type)) {
|
if (sym_matches_type(left, &PyLong_Type)) {
|
||||||
REPLACE_OP(this_instr, _NOP, 0, 0);
|
REPLACE_OP(this_instr, _NOP, 0, 0);
|
||||||
}
|
}
|
||||||
sym_set_type(nos, &PyLong_Type);
|
sym_set_type(left, &PyLong_Type);
|
||||||
}
|
}
|
||||||
|
|
||||||
op(_GUARD_TYPE_VERSION, (type_version/2, owner -- owner)) {
|
op(_GUARD_TYPE_VERSION, (type_version/2, owner -- owner)) {
|
||||||
|
@ -141,25 +141,25 @@ dummy_func(void) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
op(_GUARD_TOS_FLOAT, (tos -- tos)) {
|
op(_GUARD_TOS_FLOAT, (value -- value)) {
|
||||||
if (sym_matches_type(tos, &PyFloat_Type)) {
|
if (sym_matches_type(value, &PyFloat_Type)) {
|
||||||
REPLACE_OP(this_instr, _NOP, 0, 0);
|
REPLACE_OP(this_instr, _NOP, 0, 0);
|
||||||
}
|
}
|
||||||
sym_set_type(tos, &PyFloat_Type);
|
sym_set_type(value, &PyFloat_Type);
|
||||||
}
|
}
|
||||||
|
|
||||||
op(_GUARD_NOS_FLOAT, (nos, unused -- nos, unused)) {
|
op(_GUARD_NOS_FLOAT, (left, unused -- left, unused)) {
|
||||||
if (sym_matches_type(nos, &PyFloat_Type)) {
|
if (sym_matches_type(left, &PyFloat_Type)) {
|
||||||
REPLACE_OP(this_instr, _NOP, 0, 0);
|
REPLACE_OP(this_instr, _NOP, 0, 0);
|
||||||
}
|
}
|
||||||
sym_set_type(nos, &PyFloat_Type);
|
sym_set_type(left, &PyFloat_Type);
|
||||||
}
|
}
|
||||||
|
|
||||||
op(_BINARY_OP, (left, right -- res)) {
|
op(_BINARY_OP, (lhs, rhs -- res)) {
|
||||||
bool lhs_int = sym_matches_type(left, &PyLong_Type);
|
bool lhs_int = sym_matches_type(lhs, &PyLong_Type);
|
||||||
bool rhs_int = sym_matches_type(right, &PyLong_Type);
|
bool rhs_int = sym_matches_type(rhs, &PyLong_Type);
|
||||||
bool lhs_float = sym_matches_type(left, &PyFloat_Type);
|
bool lhs_float = sym_matches_type(lhs, &PyFloat_Type);
|
||||||
bool rhs_float = sym_matches_type(right, &PyFloat_Type);
|
bool rhs_float = sym_matches_type(rhs, &PyFloat_Type);
|
||||||
if (!((lhs_int || lhs_float) && (rhs_int || rhs_float))) {
|
if (!((lhs_int || lhs_float) && (rhs_int || rhs_float))) {
|
||||||
// There's something other than an int or float involved:
|
// There's something other than an int or float involved:
|
||||||
res = sym_new_unknown(ctx);
|
res = sym_new_unknown(ctx);
|
||||||
|
@ -185,11 +185,11 @@ dummy_func(void) {
|
||||||
// Case C:
|
// Case C:
|
||||||
res = sym_new_type(ctx, &PyFloat_Type);
|
res = sym_new_type(ctx, &PyFloat_Type);
|
||||||
}
|
}
|
||||||
else if (!sym_is_const(ctx, right)) {
|
else if (!sym_is_const(ctx, rhs)) {
|
||||||
// Case A or B... can't know without the sign of the RHS:
|
// Case A or B... can't know without the sign of the RHS:
|
||||||
res = sym_new_unknown(ctx);
|
res = sym_new_unknown(ctx);
|
||||||
}
|
}
|
||||||
else if (_PyLong_IsNegative((PyLongObject *)sym_get_const(ctx, right))) {
|
else if (_PyLong_IsNegative((PyLongObject *)sym_get_const(ctx, rhs))) {
|
||||||
// Case B:
|
// Case B:
|
||||||
res = sym_new_type(ctx, &PyFloat_Type);
|
res = sym_new_type(ctx, &PyFloat_Type);
|
||||||
}
|
}
|
||||||
|
@ -366,7 +366,7 @@ dummy_func(void) {
|
||||||
ctx->done = true;
|
ctx->done = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
op(_BINARY_OP_SUBSCR_STR_INT, (left, right -- res)) {
|
op(_BINARY_OP_SUBSCR_STR_INT, (str_st, sub_st -- res)) {
|
||||||
res = sym_new_type(ctx, &PyUnicode_Type);
|
res = sym_new_type(ctx, &PyUnicode_Type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -398,11 +398,11 @@ dummy_func(void) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
op(_TO_BOOL_BOOL, (value -- res)) {
|
op(_TO_BOOL_BOOL, (value -- value)) {
|
||||||
int already_bool = optimize_to_bool(this_instr, ctx, value, &res);
|
int already_bool = optimize_to_bool(this_instr, ctx, value, &value);
|
||||||
if (!already_bool) {
|
if (!already_bool) {
|
||||||
sym_set_type(value, &PyBool_Type);
|
sym_set_type(value, &PyBool_Type);
|
||||||
res = sym_new_truthiness(ctx, value, true);
|
value = sym_new_truthiness(ctx, value, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -493,20 +493,20 @@ dummy_func(void) {
|
||||||
res = sym_new_type(ctx, &PyBool_Type);
|
res = sym_new_type(ctx, &PyBool_Type);
|
||||||
}
|
}
|
||||||
|
|
||||||
op(_IS_OP, (left, right -- res)) {
|
op(_IS_OP, (left, right -- b)) {
|
||||||
res = sym_new_type(ctx, &PyBool_Type);
|
b = sym_new_type(ctx, &PyBool_Type);
|
||||||
}
|
}
|
||||||
|
|
||||||
op(_CONTAINS_OP, (left, right -- res)) {
|
op(_CONTAINS_OP, (left, right -- b)) {
|
||||||
res = sym_new_type(ctx, &PyBool_Type);
|
b = sym_new_type(ctx, &PyBool_Type);
|
||||||
}
|
}
|
||||||
|
|
||||||
op(_CONTAINS_OP_SET, (left, right -- res)) {
|
op(_CONTAINS_OP_SET, (left, right -- b)) {
|
||||||
res = sym_new_type(ctx, &PyBool_Type);
|
b = sym_new_type(ctx, &PyBool_Type);
|
||||||
}
|
}
|
||||||
|
|
||||||
op(_CONTAINS_OP_DICT, (left, right -- res)) {
|
op(_CONTAINS_OP_DICT, (left, right -- b)) {
|
||||||
res = sym_new_type(ctx, &PyBool_Type);
|
b = sym_new_type(ctx, &PyBool_Type);
|
||||||
}
|
}
|
||||||
|
|
||||||
op(_LOAD_CONST, (-- value)) {
|
op(_LOAD_CONST, (-- value)) {
|
||||||
|
@ -707,10 +707,10 @@ dummy_func(void) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
op(_MAYBE_EXPAND_METHOD, (callable, self_or_null, args[oparg] -- func, maybe_self, args[oparg])) {
|
op(_MAYBE_EXPAND_METHOD, (callable, self_or_null, args[oparg] -- callable, self_or_null, args[oparg])) {
|
||||||
(void)args;
|
(void)args;
|
||||||
func = sym_new_not_null(ctx);
|
callable = sym_new_not_null(ctx);
|
||||||
maybe_self = sym_new_not_null(ctx);
|
self_or_null = sym_new_not_null(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
op(_PY_FRAME_GENERAL, (callable, self_or_null, args[oparg] -- new_frame: _Py_UOpsAbstractFrame *)) {
|
op(_PY_FRAME_GENERAL, (callable, self_or_null, args[oparg] -- new_frame: _Py_UOpsAbstractFrame *)) {
|
||||||
|
@ -730,14 +730,14 @@ dummy_func(void) {
|
||||||
ctx->done = true;
|
ctx->done = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
op(_CHECK_AND_ALLOCATE_OBJECT, (type_version/2, callable, null, args[oparg] -- self, init, args[oparg])) {
|
op(_CHECK_AND_ALLOCATE_OBJECT, (type_version/2, callable, self_or_null, args[oparg] -- callable, self_or_null, args[oparg])) {
|
||||||
(void)type_version;
|
(void)type_version;
|
||||||
(void)args;
|
(void)args;
|
||||||
self = sym_new_not_null(ctx);
|
callable = sym_new_not_null(ctx);
|
||||||
init = sym_new_not_null(ctx);
|
self_or_null = sym_new_not_null(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
op(_CREATE_INIT_FRAME, (self, init, args[oparg] -- init_frame: _Py_UOpsAbstractFrame *)) {
|
op(_CREATE_INIT_FRAME, (init, self, args[oparg] -- init_frame: _Py_UOpsAbstractFrame *)) {
|
||||||
init_frame = NULL;
|
init_frame = NULL;
|
||||||
ctx->done = true;
|
ctx->done = true;
|
||||||
}
|
}
|
||||||
|
@ -789,21 +789,23 @@ dummy_func(void) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
op(_YIELD_VALUE, (unused -- res)) {
|
op(_YIELD_VALUE, (unused -- value)) {
|
||||||
res = sym_new_unknown(ctx);
|
value = sym_new_unknown(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
op(_FOR_ITER_GEN_FRAME, ( -- )) {
|
op(_FOR_ITER_GEN_FRAME, (unused -- unused, gen_frame: _Py_UOpsAbstractFrame*)) {
|
||||||
|
gen_frame = NULL;
|
||||||
/* We are about to hit the end of the trace */
|
/* We are about to hit the end of the trace */
|
||||||
ctx->done = true;
|
ctx->done = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
op(_SEND_GEN_FRAME, ( -- )) {
|
op(_SEND_GEN_FRAME, (unused, unused -- unused, gen_frame: _Py_UOpsAbstractFrame *)) {
|
||||||
|
gen_frame = NULL;
|
||||||
// We are about to hit the end of the trace:
|
// We are about to hit the end of the trace:
|
||||||
ctx->done = true;
|
ctx->done = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
op(_CHECK_STACK_SPACE, ( --)) {
|
op(_CHECK_STACK_SPACE, (unused, unused, unused[oparg] -- unused, unused, unused[oparg])) {
|
||||||
assert(corresponding_check_stack == NULL);
|
assert(corresponding_check_stack == NULL);
|
||||||
corresponding_check_stack = this_instr;
|
corresponding_check_stack = this_instr;
|
||||||
}
|
}
|
||||||
|
@ -848,14 +850,16 @@ dummy_func(void) {
|
||||||
corresponding_check_stack = NULL;
|
corresponding_check_stack = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
op(_UNPACK_SEQUENCE, (seq -- values[oparg])) {
|
op(_UNPACK_SEQUENCE, (seq -- values[oparg], top[0])) {
|
||||||
|
(void)top;
|
||||||
/* This has to be done manually */
|
/* This has to be done manually */
|
||||||
for (int i = 0; i < oparg; i++) {
|
for (int i = 0; i < oparg; i++) {
|
||||||
values[i] = sym_new_unknown(ctx);
|
values[i] = sym_new_unknown(ctx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
op(_UNPACK_EX, (seq -- values[oparg & 0xFF], unused, unused[oparg >> 8])) {
|
op(_UNPACK_EX, (seq -- values[oparg & 0xFF], unused, unused[oparg >> 8], top[0])) {
|
||||||
|
(void)top;
|
||||||
/* This has to be done manually */
|
/* This has to be done manually */
|
||||||
int totalargs = (oparg & 0xFF) + (oparg >> 8) + 1;
|
int totalargs = (oparg & 0xFF) + (oparg >> 8) + 1;
|
||||||
for (int i = 0; i < totalargs; i++) {
|
for (int i = 0; i < totalargs; i++) {
|
||||||
|
@ -904,27 +908,27 @@ dummy_func(void) {
|
||||||
sym_set_const(flag, Py_False);
|
sym_set_const(flag, Py_False);
|
||||||
}
|
}
|
||||||
|
|
||||||
op(_GUARD_IS_NONE_POP, (flag -- )) {
|
op(_GUARD_IS_NONE_POP, (val -- )) {
|
||||||
if (sym_is_const(ctx, flag)) {
|
if (sym_is_const(ctx, val)) {
|
||||||
PyObject *value = sym_get_const(ctx, flag);
|
PyObject *value = sym_get_const(ctx, val);
|
||||||
assert(value != NULL);
|
assert(value != NULL);
|
||||||
eliminate_pop_guard(this_instr, !Py_IsNone(value));
|
eliminate_pop_guard(this_instr, !Py_IsNone(value));
|
||||||
}
|
}
|
||||||
else if (sym_has_type(flag)) {
|
else if (sym_has_type(val)) {
|
||||||
assert(!sym_matches_type(flag, &_PyNone_Type));
|
assert(!sym_matches_type(val, &_PyNone_Type));
|
||||||
eliminate_pop_guard(this_instr, true);
|
eliminate_pop_guard(this_instr, true);
|
||||||
}
|
}
|
||||||
sym_set_const(flag, Py_None);
|
sym_set_const(val, Py_None);
|
||||||
}
|
}
|
||||||
|
|
||||||
op(_GUARD_IS_NOT_NONE_POP, (flag -- )) {
|
op(_GUARD_IS_NOT_NONE_POP, (val -- )) {
|
||||||
if (sym_is_const(ctx, flag)) {
|
if (sym_is_const(ctx, val)) {
|
||||||
PyObject *value = sym_get_const(ctx, flag);
|
PyObject *value = sym_get_const(ctx, val);
|
||||||
assert(value != NULL);
|
assert(value != NULL);
|
||||||
eliminate_pop_guard(this_instr, Py_IsNone(value));
|
eliminate_pop_guard(this_instr, Py_IsNone(value));
|
||||||
}
|
}
|
||||||
else if (sym_has_type(flag)) {
|
else if (sym_has_type(val)) {
|
||||||
assert(!sym_matches_type(flag, &_PyNone_Type));
|
assert(!sym_matches_type(val, &_PyNone_Type));
|
||||||
eliminate_pop_guard(this_instr, false);
|
eliminate_pop_guard(this_instr, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -969,7 +973,7 @@ dummy_func(void) {
|
||||||
list = sym_new_type(ctx, &PyList_Type);
|
list = sym_new_type(ctx, &PyList_Type);
|
||||||
}
|
}
|
||||||
|
|
||||||
op(_BUILD_SLICE, (values[oparg] -- slice)) {
|
op(_BUILD_SLICE, (args[oparg] -- slice)) {
|
||||||
slice = sym_new_type(ctx, &PySlice_Type);
|
slice = sym_new_type(ctx, &PySlice_Type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -977,7 +981,7 @@ dummy_func(void) {
|
||||||
map = sym_new_type(ctx, &PyDict_Type);
|
map = sym_new_type(ctx, &PyDict_Type);
|
||||||
}
|
}
|
||||||
|
|
||||||
op(_BUILD_STRING, (values[oparg] -- str)) {
|
op(_BUILD_STRING, (pieces[oparg] -- str)) {
|
||||||
str = sym_new_type(ctx, &PyUnicode_Type);
|
str = sym_new_type(ctx, &PyUnicode_Type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
159
Python/optimizer_cases.c.h
generated
159
Python/optimizer_cases.c.h
generated
|
@ -171,14 +171,13 @@
|
||||||
|
|
||||||
case _TO_BOOL_BOOL: {
|
case _TO_BOOL_BOOL: {
|
||||||
JitOptSymbol *value;
|
JitOptSymbol *value;
|
||||||
JitOptSymbol *res;
|
|
||||||
value = stack_pointer[-1];
|
value = stack_pointer[-1];
|
||||||
int already_bool = optimize_to_bool(this_instr, ctx, value, &res);
|
int already_bool = optimize_to_bool(this_instr, ctx, value, &value);
|
||||||
if (!already_bool) {
|
if (!already_bool) {
|
||||||
sym_set_type(value, &PyBool_Type);
|
sym_set_type(value, &PyBool_Type);
|
||||||
res = sym_new_truthiness(ctx, value, true);
|
value = sym_new_truthiness(ctx, value, true);
|
||||||
}
|
}
|
||||||
stack_pointer[-1] = res;
|
stack_pointer[-1] = value;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -292,22 +291,22 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
case _GUARD_NOS_INT: {
|
case _GUARD_NOS_INT: {
|
||||||
JitOptSymbol *nos;
|
JitOptSymbol *left;
|
||||||
nos = stack_pointer[-2];
|
left = stack_pointer[-2];
|
||||||
if (sym_matches_type(nos, &PyLong_Type)) {
|
if (sym_matches_type(left, &PyLong_Type)) {
|
||||||
REPLACE_OP(this_instr, _NOP, 0, 0);
|
REPLACE_OP(this_instr, _NOP, 0, 0);
|
||||||
}
|
}
|
||||||
sym_set_type(nos, &PyLong_Type);
|
sym_set_type(left, &PyLong_Type);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case _GUARD_TOS_INT: {
|
case _GUARD_TOS_INT: {
|
||||||
JitOptSymbol *tos;
|
JitOptSymbol *value;
|
||||||
tos = stack_pointer[-1];
|
value = stack_pointer[-1];
|
||||||
if (sym_matches_type(tos, &PyLong_Type)) {
|
if (sym_matches_type(value, &PyLong_Type)) {
|
||||||
REPLACE_OP(this_instr, _NOP, 0, 0);
|
REPLACE_OP(this_instr, _NOP, 0, 0);
|
||||||
}
|
}
|
||||||
sym_set_type(tos, &PyLong_Type);
|
sym_set_type(value, &PyLong_Type);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -396,22 +395,22 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
case _GUARD_NOS_FLOAT: {
|
case _GUARD_NOS_FLOAT: {
|
||||||
JitOptSymbol *nos;
|
JitOptSymbol *left;
|
||||||
nos = stack_pointer[-2];
|
left = stack_pointer[-2];
|
||||||
if (sym_matches_type(nos, &PyFloat_Type)) {
|
if (sym_matches_type(left, &PyFloat_Type)) {
|
||||||
REPLACE_OP(this_instr, _NOP, 0, 0);
|
REPLACE_OP(this_instr, _NOP, 0, 0);
|
||||||
}
|
}
|
||||||
sym_set_type(nos, &PyFloat_Type);
|
sym_set_type(left, &PyFloat_Type);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case _GUARD_TOS_FLOAT: {
|
case _GUARD_TOS_FLOAT: {
|
||||||
JitOptSymbol *tos;
|
JitOptSymbol *value;
|
||||||
tos = stack_pointer[-1];
|
value = stack_pointer[-1];
|
||||||
if (sym_matches_type(tos, &PyFloat_Type)) {
|
if (sym_matches_type(value, &PyFloat_Type)) {
|
||||||
REPLACE_OP(this_instr, _NOP, 0, 0);
|
REPLACE_OP(this_instr, _NOP, 0, 0);
|
||||||
}
|
}
|
||||||
sym_set_type(tos, &PyFloat_Type);
|
sym_set_type(value, &PyFloat_Type);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -811,14 +810,17 @@
|
||||||
/* _SEND is not a viable micro-op for tier 2 */
|
/* _SEND is not a viable micro-op for tier 2 */
|
||||||
|
|
||||||
case _SEND_GEN_FRAME: {
|
case _SEND_GEN_FRAME: {
|
||||||
|
_Py_UOpsAbstractFrame *gen_frame;
|
||||||
|
gen_frame = NULL;
|
||||||
ctx->done = true;
|
ctx->done = true;
|
||||||
|
stack_pointer[-1] = (JitOptSymbol *)gen_frame;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case _YIELD_VALUE: {
|
case _YIELD_VALUE: {
|
||||||
JitOptSymbol *res;
|
JitOptSymbol *value;
|
||||||
res = sym_new_unknown(ctx);
|
value = sym_new_unknown(ctx);
|
||||||
stack_pointer[-1] = res;
|
stack_pointer[-1] = value;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -858,7 +860,10 @@
|
||||||
|
|
||||||
case _UNPACK_SEQUENCE: {
|
case _UNPACK_SEQUENCE: {
|
||||||
JitOptSymbol **values;
|
JitOptSymbol **values;
|
||||||
|
JitOptSymbol **top;
|
||||||
values = &stack_pointer[-1];
|
values = &stack_pointer[-1];
|
||||||
|
top = &stack_pointer[-1 + oparg];
|
||||||
|
(void)top;
|
||||||
for (int i = 0; i < oparg; i++) {
|
for (int i = 0; i < oparg; i++) {
|
||||||
values[i] = sym_new_unknown(ctx);
|
values[i] = sym_new_unknown(ctx);
|
||||||
}
|
}
|
||||||
|
@ -907,7 +912,10 @@
|
||||||
|
|
||||||
case _UNPACK_EX: {
|
case _UNPACK_EX: {
|
||||||
JitOptSymbol **values;
|
JitOptSymbol **values;
|
||||||
|
JitOptSymbol **top;
|
||||||
values = &stack_pointer[-1];
|
values = &stack_pointer[-1];
|
||||||
|
top = &stack_pointer[(oparg & 0xFF) + (oparg >> 8)];
|
||||||
|
(void)top;
|
||||||
int totalargs = (oparg & 0xFF) + (oparg >> 8) + 1;
|
int totalargs = (oparg & 0xFF) + (oparg >> 8) + 1;
|
||||||
for (int i = 0; i < totalargs; i++) {
|
for (int i = 0; i < totalargs; i++) {
|
||||||
values[i] = sym_new_unknown(ctx);
|
values[i] = sym_new_unknown(ctx);
|
||||||
|
@ -1376,18 +1384,18 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
case _IS_OP: {
|
case _IS_OP: {
|
||||||
JitOptSymbol *res;
|
JitOptSymbol *b;
|
||||||
res = sym_new_type(ctx, &PyBool_Type);
|
b = sym_new_type(ctx, &PyBool_Type);
|
||||||
stack_pointer[-2] = res;
|
stack_pointer[-2] = b;
|
||||||
stack_pointer += -1;
|
stack_pointer += -1;
|
||||||
assert(WITHIN_STACK_BOUNDS());
|
assert(WITHIN_STACK_BOUNDS());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case _CONTAINS_OP: {
|
case _CONTAINS_OP: {
|
||||||
JitOptSymbol *res;
|
JitOptSymbol *b;
|
||||||
res = sym_new_type(ctx, &PyBool_Type);
|
b = sym_new_type(ctx, &PyBool_Type);
|
||||||
stack_pointer[-2] = res;
|
stack_pointer[-2] = b;
|
||||||
stack_pointer += -1;
|
stack_pointer += -1;
|
||||||
assert(WITHIN_STACK_BOUNDS());
|
assert(WITHIN_STACK_BOUNDS());
|
||||||
break;
|
break;
|
||||||
|
@ -1405,18 +1413,18 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
case _CONTAINS_OP_SET: {
|
case _CONTAINS_OP_SET: {
|
||||||
JitOptSymbol *res;
|
JitOptSymbol *b;
|
||||||
res = sym_new_type(ctx, &PyBool_Type);
|
b = sym_new_type(ctx, &PyBool_Type);
|
||||||
stack_pointer[-2] = res;
|
stack_pointer[-2] = b;
|
||||||
stack_pointer += -1;
|
stack_pointer += -1;
|
||||||
assert(WITHIN_STACK_BOUNDS());
|
assert(WITHIN_STACK_BOUNDS());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case _CONTAINS_OP_DICT: {
|
case _CONTAINS_OP_DICT: {
|
||||||
JitOptSymbol *res;
|
JitOptSymbol *b;
|
||||||
res = sym_new_type(ctx, &PyBool_Type);
|
b = sym_new_type(ctx, &PyBool_Type);
|
||||||
stack_pointer[-2] = res;
|
stack_pointer[-2] = b;
|
||||||
stack_pointer += -1;
|
stack_pointer += -1;
|
||||||
assert(WITHIN_STACK_BOUNDS());
|
assert(WITHIN_STACK_BOUNDS());
|
||||||
break;
|
break;
|
||||||
|
@ -1600,7 +1608,12 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
case _FOR_ITER_GEN_FRAME: {
|
case _FOR_ITER_GEN_FRAME: {
|
||||||
|
_Py_UOpsAbstractFrame *gen_frame;
|
||||||
|
gen_frame = NULL;
|
||||||
ctx->done = true;
|
ctx->done = true;
|
||||||
|
stack_pointer[0] = (JitOptSymbol *)gen_frame;
|
||||||
|
stack_pointer += 1;
|
||||||
|
assert(WITHIN_STACK_BOUNDS());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1721,15 +1734,16 @@
|
||||||
|
|
||||||
case _MAYBE_EXPAND_METHOD: {
|
case _MAYBE_EXPAND_METHOD: {
|
||||||
JitOptSymbol **args;
|
JitOptSymbol **args;
|
||||||
JitOptSymbol *func;
|
JitOptSymbol *self_or_null;
|
||||||
JitOptSymbol *maybe_self;
|
JitOptSymbol *callable;
|
||||||
args = &stack_pointer[-oparg];
|
|
||||||
args = &stack_pointer[-oparg];
|
args = &stack_pointer[-oparg];
|
||||||
|
self_or_null = stack_pointer[-1 - oparg];
|
||||||
|
callable = stack_pointer[-2 - oparg];
|
||||||
(void)args;
|
(void)args;
|
||||||
func = sym_new_not_null(ctx);
|
callable = sym_new_not_null(ctx);
|
||||||
maybe_self = sym_new_not_null(ctx);
|
self_or_null = sym_new_not_null(ctx);
|
||||||
stack_pointer[-2 - oparg] = func;
|
stack_pointer[-2 - oparg] = callable;
|
||||||
stack_pointer[-1 - oparg] = maybe_self;
|
stack_pointer[-1 - oparg] = self_or_null;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2001,17 +2015,18 @@
|
||||||
|
|
||||||
case _CHECK_AND_ALLOCATE_OBJECT: {
|
case _CHECK_AND_ALLOCATE_OBJECT: {
|
||||||
JitOptSymbol **args;
|
JitOptSymbol **args;
|
||||||
JitOptSymbol *self;
|
JitOptSymbol *self_or_null;
|
||||||
JitOptSymbol *init;
|
JitOptSymbol *callable;
|
||||||
args = &stack_pointer[-oparg];
|
|
||||||
args = &stack_pointer[-oparg];
|
args = &stack_pointer[-oparg];
|
||||||
|
self_or_null = stack_pointer[-1 - oparg];
|
||||||
|
callable = stack_pointer[-2 - oparg];
|
||||||
uint32_t type_version = (uint32_t)this_instr->operand0;
|
uint32_t type_version = (uint32_t)this_instr->operand0;
|
||||||
(void)type_version;
|
(void)type_version;
|
||||||
(void)args;
|
(void)args;
|
||||||
self = sym_new_not_null(ctx);
|
callable = sym_new_not_null(ctx);
|
||||||
init = sym_new_not_null(ctx);
|
self_or_null = sym_new_not_null(ctx);
|
||||||
stack_pointer[-2 - oparg] = self;
|
stack_pointer[-2 - oparg] = callable;
|
||||||
stack_pointer[-1 - oparg] = init;
|
stack_pointer[-1 - oparg] = self_or_null;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2270,15 +2285,15 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
case _BINARY_OP: {
|
case _BINARY_OP: {
|
||||||
JitOptSymbol *right;
|
JitOptSymbol *rhs;
|
||||||
JitOptSymbol *left;
|
JitOptSymbol *lhs;
|
||||||
JitOptSymbol *res;
|
JitOptSymbol *res;
|
||||||
right = stack_pointer[-1];
|
rhs = stack_pointer[-1];
|
||||||
left = stack_pointer[-2];
|
lhs = stack_pointer[-2];
|
||||||
bool lhs_int = sym_matches_type(left, &PyLong_Type);
|
bool lhs_int = sym_matches_type(lhs, &PyLong_Type);
|
||||||
bool rhs_int = sym_matches_type(right, &PyLong_Type);
|
bool rhs_int = sym_matches_type(rhs, &PyLong_Type);
|
||||||
bool lhs_float = sym_matches_type(left, &PyFloat_Type);
|
bool lhs_float = sym_matches_type(lhs, &PyFloat_Type);
|
||||||
bool rhs_float = sym_matches_type(right, &PyFloat_Type);
|
bool rhs_float = sym_matches_type(rhs, &PyFloat_Type);
|
||||||
if (!((lhs_int || lhs_float) && (rhs_int || rhs_float))) {
|
if (!((lhs_int || lhs_float) && (rhs_int || rhs_float))) {
|
||||||
res = sym_new_unknown(ctx);
|
res = sym_new_unknown(ctx);
|
||||||
}
|
}
|
||||||
|
@ -2289,10 +2304,10 @@
|
||||||
else if (lhs_float) {
|
else if (lhs_float) {
|
||||||
res = sym_new_type(ctx, &PyFloat_Type);
|
res = sym_new_type(ctx, &PyFloat_Type);
|
||||||
}
|
}
|
||||||
else if (!sym_is_const(ctx, right)) {
|
else if (!sym_is_const(ctx, rhs)) {
|
||||||
res = sym_new_unknown(ctx);
|
res = sym_new_unknown(ctx);
|
||||||
}
|
}
|
||||||
else if (_PyLong_IsNegative((PyLongObject *)sym_get_const(ctx, right))) {
|
else if (_PyLong_IsNegative((PyLongObject *)sym_get_const(ctx, rhs))) {
|
||||||
res = sym_new_type(ctx, &PyFloat_Type);
|
res = sym_new_type(ctx, &PyFloat_Type);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -2375,33 +2390,33 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
case _GUARD_IS_NONE_POP: {
|
case _GUARD_IS_NONE_POP: {
|
||||||
JitOptSymbol *flag;
|
JitOptSymbol *val;
|
||||||
flag = stack_pointer[-1];
|
val = stack_pointer[-1];
|
||||||
if (sym_is_const(ctx, flag)) {
|
if (sym_is_const(ctx, val)) {
|
||||||
PyObject *value = sym_get_const(ctx, flag);
|
PyObject *value = sym_get_const(ctx, val);
|
||||||
assert(value != NULL);
|
assert(value != NULL);
|
||||||
eliminate_pop_guard(this_instr, !Py_IsNone(value));
|
eliminate_pop_guard(this_instr, !Py_IsNone(value));
|
||||||
}
|
}
|
||||||
else if (sym_has_type(flag)) {
|
else if (sym_has_type(val)) {
|
||||||
assert(!sym_matches_type(flag, &_PyNone_Type));
|
assert(!sym_matches_type(val, &_PyNone_Type));
|
||||||
eliminate_pop_guard(this_instr, true);
|
eliminate_pop_guard(this_instr, true);
|
||||||
}
|
}
|
||||||
sym_set_const(flag, Py_None);
|
sym_set_const(val, Py_None);
|
||||||
stack_pointer += -1;
|
stack_pointer += -1;
|
||||||
assert(WITHIN_STACK_BOUNDS());
|
assert(WITHIN_STACK_BOUNDS());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case _GUARD_IS_NOT_NONE_POP: {
|
case _GUARD_IS_NOT_NONE_POP: {
|
||||||
JitOptSymbol *flag;
|
JitOptSymbol *val;
|
||||||
flag = stack_pointer[-1];
|
val = stack_pointer[-1];
|
||||||
if (sym_is_const(ctx, flag)) {
|
if (sym_is_const(ctx, val)) {
|
||||||
PyObject *value = sym_get_const(ctx, flag);
|
PyObject *value = sym_get_const(ctx, val);
|
||||||
assert(value != NULL);
|
assert(value != NULL);
|
||||||
eliminate_pop_guard(this_instr, Py_IsNone(value));
|
eliminate_pop_guard(this_instr, Py_IsNone(value));
|
||||||
}
|
}
|
||||||
else if (sym_has_type(flag)) {
|
else if (sym_has_type(val)) {
|
||||||
assert(!sym_matches_type(flag, &_PyNone_Type));
|
assert(!sym_matches_type(val, &_PyNone_Type));
|
||||||
eliminate_pop_guard(this_instr, false);
|
eliminate_pop_guard(this_instr, false);
|
||||||
}
|
}
|
||||||
stack_pointer += -1;
|
stack_pointer += -1;
|
||||||
|
|
|
@ -30,16 +30,52 @@ DEFAULT_ABSTRACT_INPUT = (ROOT / "Python/optimizer_bytecodes.c").absolute().as_p
|
||||||
|
|
||||||
|
|
||||||
def validate_uop(override: Uop, uop: Uop) -> None:
|
def validate_uop(override: Uop, uop: Uop) -> None:
|
||||||
# To do
|
"""
|
||||||
pass
|
Check that the overridden uop (defined in 'optimizer_bytecodes.c')
|
||||||
|
has the same stack effects as the original uop (defined in 'bytecodes.c').
|
||||||
|
|
||||||
|
Ensure that:
|
||||||
|
- The number of inputs and outputs is the same.
|
||||||
|
- The names of the inputs and outputs are the same
|
||||||
|
(except for 'unused' which is ignored).
|
||||||
|
- The sizes of the inputs and outputs are the same.
|
||||||
|
"""
|
||||||
|
for stack_effect in ('inputs', 'outputs'):
|
||||||
|
orig_effects = getattr(uop.stack, stack_effect)
|
||||||
|
new_effects = getattr(override.stack, stack_effect)
|
||||||
|
|
||||||
|
if len(orig_effects) != len(new_effects):
|
||||||
|
msg = (
|
||||||
|
f"{uop.name}: Must have the same number of {stack_effect} "
|
||||||
|
"in bytecodes.c and optimizer_bytecodes.c "
|
||||||
|
f"({len(orig_effects)} != {len(new_effects)})"
|
||||||
|
)
|
||||||
|
raise analysis_error(msg, override.body.open)
|
||||||
|
|
||||||
|
for orig, new in zip(orig_effects, new_effects, strict=True):
|
||||||
|
if orig.name != new.name and orig.name != "unused" and new.name != "unused":
|
||||||
|
msg = (
|
||||||
|
f"{uop.name}: {stack_effect.capitalize()} must have "
|
||||||
|
"equal names in bytecodes.c and optimizer_bytecodes.c "
|
||||||
|
f"({orig.name} != {new.name})"
|
||||||
|
)
|
||||||
|
raise analysis_error(msg, override.body.open)
|
||||||
|
|
||||||
|
if orig.size != new.size:
|
||||||
|
msg = (
|
||||||
|
f"{uop.name}: {stack_effect.capitalize()} must have "
|
||||||
|
"equal sizes in bytecodes.c and optimizer_bytecodes.c "
|
||||||
|
f"({orig.size!r} != {new.size!r})"
|
||||||
|
)
|
||||||
|
raise analysis_error(msg, override.body.open)
|
||||||
|
|
||||||
|
|
||||||
def type_name(var: StackItem) -> str:
|
def type_name(var: StackItem) -> str:
|
||||||
if var.is_array():
|
if var.is_array():
|
||||||
return f"JitOptSymbol **"
|
return "JitOptSymbol **"
|
||||||
if var.type:
|
if var.type:
|
||||||
return var.type
|
return var.type
|
||||||
return f"JitOptSymbol *"
|
return "JitOptSymbol *"
|
||||||
|
|
||||||
|
|
||||||
def declare_variables(uop: Uop, out: CWriter, skip_inputs: bool) -> None:
|
def declare_variables(uop: Uop, out: CWriter, skip_inputs: bool) -> None:
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue