From 6183cbdc92d6648fa9997cdc8fc44971b3fc4983 Mon Sep 17 00:00:00 2001 From: Brandt Bucher Date: Thu, 23 Mar 2023 15:25:09 -0700 Subject: [PATCH] GH-100982: Break up COMPARE_AND_BRANCH (GH-102801) --- Doc/library/dis.rst | 9 -- Include/internal/pycore_code.h | 2 +- Include/internal/pycore_opcode.h | 27 +++-- Include/opcode.h | 107 +++++++++-------- Lib/importlib/_bootstrap_external.py | 4 +- Lib/opcode.py | 13 +-- Lib/test/test_compile.py | 2 +- Lib/test/test_dis.py | 16 +-- ...-03-17-12-09-45.gh-issue-100982.Pf_BI6.rst | 1 + Objects/frameobject.c | 8 -- Python/bytecodes.c | 93 ++++++--------- Python/compile.c | 11 +- Python/generated_cases.c.h | 109 +++++++----------- Python/opcode_metadata.h | 31 +++-- Python/opcode_targets.h | 16 +-- Python/specialize.c | 92 +++++---------- Python/tier2_typepropagator.c.h | 20 ++-- Tools/c-analyzer/cpython/ignored.tsv | 1 - Tools/scripts/summarize_stats.py | 2 - 19 files changed, 232 insertions(+), 332 deletions(-) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2023-03-17-12-09-45.gh-issue-100982.Pf_BI6.rst diff --git a/Doc/library/dis.rst b/Doc/library/dis.rst index b06fe67a983aa1..8703cddb3448cc 100644 --- a/Doc/library/dis.rst +++ b/Doc/library/dis.rst @@ -1042,15 +1042,6 @@ iterations of the loop. ``cmp_op[opname]``. -.. opcode:: COMPARE_AND_BRANCH (opname) - - Compares the top two values on the stack, popping them, then branches. - The direction and offset of the jump is embedded as a ``POP_JUMP_IF_TRUE`` - or ``POP_JUMP_IF_FALSE`` instruction immediately following the cache. - - .. versionadded:: 3.12 - - .. opcode:: IS_OP (invert) Performs ``is`` comparison, or ``is not`` if ``invert`` is 1. diff --git a/Include/internal/pycore_code.h b/Include/internal/pycore_code.h index bfda105c61d4dc..3586c292117459 100644 --- a/Include/internal/pycore_code.h +++ b/Include/internal/pycore_code.h @@ -244,7 +244,7 @@ extern void _Py_Specialize_Call(PyObject *callable, _Py_CODEUNIT *instr, int nargs, PyObject *kwnames); extern void _Py_Specialize_BinaryOp(PyObject *lhs, PyObject *rhs, _Py_CODEUNIT *instr, int oparg, PyObject **locals); -extern void _Py_Specialize_CompareAndBranch(PyObject *lhs, PyObject *rhs, +extern void _Py_Specialize_CompareOp(PyObject *lhs, PyObject *rhs, _Py_CODEUNIT *instr, int oparg); extern void _Py_Specialize_UnpackSequence(PyObject *seq, _Py_CODEUNIT *instr, int oparg); diff --git a/Include/internal/pycore_opcode.h b/Include/internal/pycore_opcode.h index 4a3270dd11b2de..9884184df4d3d8 100644 --- a/Include/internal/pycore_opcode.h +++ b/Include/internal/pycore_opcode.h @@ -51,7 +51,6 @@ const uint8_t _PyOpcode_Caches[256] = { [LOAD_GLOBAL] = 4, [BINARY_OP] = 1, [SEND] = 1, - [COMPARE_AND_BRANCH] = 1, [CALL] = 4, }; @@ -109,11 +108,10 @@ const uint8_t _PyOpcode_Deopt[256] = { [CHECK_EG_MATCH] = CHECK_EG_MATCH, [CHECK_EXC_MATCH] = CHECK_EXC_MATCH, [CLEANUP_THROW] = CLEANUP_THROW, - [COMPARE_AND_BRANCH] = COMPARE_AND_BRANCH, - [COMPARE_AND_BRANCH_FLOAT] = COMPARE_AND_BRANCH, - [COMPARE_AND_BRANCH_INT] = COMPARE_AND_BRANCH, - [COMPARE_AND_BRANCH_STR] = COMPARE_AND_BRANCH, [COMPARE_OP] = COMPARE_OP, + [COMPARE_OP_FLOAT] = COMPARE_OP, + [COMPARE_OP_INT] = COMPARE_OP, + [COMPARE_OP_STR] = COMPARE_OP, [CONTAINS_OP] = CONTAINS_OP, [COPY] = COPY, [COPY_FREE_VARS] = COPY_FREE_VARS, @@ -292,9 +290,9 @@ static const char *const _PyOpcode_OpName[263] = { [END_ASYNC_FOR] = "END_ASYNC_FOR", [CLEANUP_THROW] = "CLEANUP_THROW", [CALL_NO_KW_TYPE_1] = "CALL_NO_KW_TYPE_1", - [COMPARE_AND_BRANCH_FLOAT] = "COMPARE_AND_BRANCH_FLOAT", - [COMPARE_AND_BRANCH_INT] = "COMPARE_AND_BRANCH_INT", - [COMPARE_AND_BRANCH_STR] = "COMPARE_AND_BRANCH_STR", + [COMPARE_OP_FLOAT] = "COMPARE_OP_FLOAT", + [COMPARE_OP_INT] = "COMPARE_OP_INT", + [COMPARE_OP_STR] = "COMPARE_OP_STR", [STORE_SUBSCR] = "STORE_SUBSCR", [DELETE_SUBSCR] = "DELETE_SUBSCR", [FOR_ITER_LIST] = "FOR_ITER_LIST", @@ -376,9 +374,9 @@ static const char *const _PyOpcode_OpName[263] = { [STORE_DEREF] = "STORE_DEREF", [DELETE_DEREF] = "DELETE_DEREF", [JUMP_BACKWARD] = "JUMP_BACKWARD", - [COMPARE_AND_BRANCH] = "COMPARE_AND_BRANCH", - [CALL_FUNCTION_EX] = "CALL_FUNCTION_EX", [STORE_ATTR_INSTANCE_VALUE] = "STORE_ATTR_INSTANCE_VALUE", + [CALL_FUNCTION_EX] = "CALL_FUNCTION_EX", + [STORE_ATTR_SLOT] = "STORE_ATTR_SLOT", [EXTENDED_ARG] = "EXTENDED_ARG", [LIST_APPEND] = "LIST_APPEND", [SET_ADD] = "SET_ADD", @@ -388,29 +386,28 @@ static const char *const _PyOpcode_OpName[263] = { [YIELD_VALUE] = "YIELD_VALUE", [RESUME] = "RESUME", [MATCH_CLASS] = "MATCH_CLASS", - [STORE_ATTR_SLOT] = "STORE_ATTR_SLOT", [STORE_ATTR_WITH_HINT] = "STORE_ATTR_WITH_HINT", + [STORE_FAST__LOAD_FAST] = "STORE_FAST__LOAD_FAST", [FORMAT_VALUE] = "FORMAT_VALUE", [BUILD_CONST_KEY_MAP] = "BUILD_CONST_KEY_MAP", [BUILD_STRING] = "BUILD_STRING", - [STORE_FAST__LOAD_FAST] = "STORE_FAST__LOAD_FAST", [STORE_FAST__STORE_FAST] = "STORE_FAST__STORE_FAST", [STORE_SUBSCR_DICT] = "STORE_SUBSCR_DICT", [STORE_SUBSCR_LIST_INT] = "STORE_SUBSCR_LIST_INT", + [UNPACK_SEQUENCE_LIST] = "UNPACK_SEQUENCE_LIST", [LIST_EXTEND] = "LIST_EXTEND", [SET_UPDATE] = "SET_UPDATE", [DICT_MERGE] = "DICT_MERGE", [DICT_UPDATE] = "DICT_UPDATE", - [UNPACK_SEQUENCE_LIST] = "UNPACK_SEQUENCE_LIST", [UNPACK_SEQUENCE_TUPLE] = "UNPACK_SEQUENCE_TUPLE", [UNPACK_SEQUENCE_TWO_TUPLE] = "UNPACK_SEQUENCE_TWO_TUPLE", [SEND_GEN] = "SEND_GEN", [BB_BRANCH] = "BB_BRANCH", + [BB_BRANCH_IF_FLAG_UNSET] = "BB_BRANCH_IF_FLAG_UNSET", [CALL] = "CALL", [KW_NAMES] = "KW_NAMES", [CALL_INTRINSIC_1] = "CALL_INTRINSIC_1", [CALL_INTRINSIC_2] = "CALL_INTRINSIC_2", - [BB_BRANCH_IF_FLAG_UNSET] = "BB_BRANCH_IF_FLAG_UNSET", [BB_BRANCH_IF_FLAG_SET] = "BB_BRANCH_IF_FLAG_SET", [BB_JUMP_IF_FLAG_UNSET] = "BB_JUMP_IF_FLAG_UNSET", [BB_JUMP_IF_FLAG_SET] = "BB_JUMP_IF_FLAG_SET", @@ -434,6 +431,7 @@ static const char *const _PyOpcode_OpName[263] = { [STORE_FAST_BOXED_UNBOXED] = "STORE_FAST_BOXED_UNBOXED", [STORE_FAST_UNBOXED_BOXED] = "STORE_FAST_UNBOXED_BOXED", [STORE_FAST_UNBOXED_UNBOXED] = "STORE_FAST_UNBOXED_UNBOXED", + [198] = "<198>", [199] = "<199>", [200] = "<200>", [201] = "<201>", @@ -503,6 +501,7 @@ static const char *const _PyOpcode_OpName[263] = { #define EXTRA_CASES \ + case 198: \ case 199: \ case 200: \ case 201: \ diff --git a/Include/opcode.h b/Include/opcode.h index 6f02501b835718..ae70a273f41573 100644 --- a/Include/opcode.h +++ b/Include/opcode.h @@ -93,7 +93,6 @@ extern "C" { #define STORE_DEREF 138 #define DELETE_DEREF 139 #define JUMP_BACKWARD 140 -#define COMPARE_AND_BRANCH 141 #define CALL_FUNCTION_EX 142 #define EXTENDED_ARG 144 #define LIST_APPEND 145 @@ -155,9 +154,9 @@ extern "C" { #define CALL_NO_KW_STR_1 47 #define CALL_NO_KW_TUPLE_1 48 #define CALL_NO_KW_TYPE_1 56 -#define COMPARE_AND_BRANCH_FLOAT 57 -#define COMPARE_AND_BRANCH_INT 58 -#define COMPARE_AND_BRANCH_STR 59 +#define COMPARE_OP_FLOAT 57 +#define COMPARE_OP_INT 58 +#define COMPARE_OP_STR 59 #define FOR_ITER_LIST 62 #define FOR_ITER_TUPLE 63 #define FOR_ITER_RANGE 64 @@ -181,17 +180,17 @@ extern "C" { #define LOAD_FAST__LOAD_FAST 111 #define LOAD_GLOBAL_BUILTIN 112 #define LOAD_GLOBAL_MODULE 113 -#define STORE_ATTR_INSTANCE_VALUE 143 -#define STORE_ATTR_SLOT 153 -#define STORE_ATTR_WITH_HINT 154 -#define STORE_FAST__LOAD_FAST 158 -#define STORE_FAST__STORE_FAST 159 -#define STORE_SUBSCR_DICT 160 -#define STORE_SUBSCR_LIST_INT 161 -#define UNPACK_SEQUENCE_LIST 166 -#define UNPACK_SEQUENCE_TUPLE 167 -#define UNPACK_SEQUENCE_TWO_TUPLE 168 -#define SEND_GEN 169 +#define STORE_ATTR_INSTANCE_VALUE 141 +#define STORE_ATTR_SLOT 143 +#define STORE_ATTR_WITH_HINT 153 +#define STORE_FAST__LOAD_FAST 154 +#define STORE_FAST__STORE_FAST 158 +#define STORE_SUBSCR_DICT 159 +#define STORE_SUBSCR_LIST_INT 160 +#define UNPACK_SEQUENCE_LIST 161 +#define UNPACK_SEQUENCE_TUPLE 166 +#define UNPACK_SEQUENCE_TWO_TUPLE 167 +#define SEND_GEN 168 #define DO_TRACING 255 // Tier 2 interpreter ops #define RESUME_QUICK 5 @@ -225,9 +224,9 @@ extern "C" { #define CALL_NO_KW_STR_1 47 #define CALL_NO_KW_TUPLE_1 48 #define CALL_NO_KW_TYPE_1 56 -#define COMPARE_AND_BRANCH_FLOAT 57 -#define COMPARE_AND_BRANCH_INT 58 -#define COMPARE_AND_BRANCH_STR 59 +#define COMPARE_OP_FLOAT 57 +#define COMPARE_OP_INT 58 +#define COMPARE_OP_STR 59 #define FOR_ITER_LIST 62 #define FOR_ITER_TUPLE 63 #define FOR_ITER_RANGE 64 @@ -251,43 +250,43 @@ extern "C" { #define LOAD_FAST__LOAD_FAST 111 #define LOAD_GLOBAL_BUILTIN 112 #define LOAD_GLOBAL_MODULE 113 -#define STORE_ATTR_INSTANCE_VALUE 143 -#define STORE_ATTR_SLOT 153 -#define STORE_ATTR_WITH_HINT 154 -#define STORE_FAST__LOAD_FAST 158 -#define STORE_FAST__STORE_FAST 159 -#define STORE_SUBSCR_DICT 160 -#define STORE_SUBSCR_LIST_INT 161 -#define UNPACK_SEQUENCE_LIST 166 -#define UNPACK_SEQUENCE_TUPLE 167 -#define UNPACK_SEQUENCE_TWO_TUPLE 168 -#define SEND_GEN 169 +#define STORE_ATTR_INSTANCE_VALUE 141 +#define STORE_ATTR_SLOT 143 +#define STORE_ATTR_WITH_HINT 153 +#define STORE_FAST__LOAD_FAST 154 +#define STORE_FAST__STORE_FAST 158 +#define STORE_SUBSCR_DICT 159 +#define STORE_SUBSCR_LIST_INT 160 +#define UNPACK_SEQUENCE_LIST 161 +#define UNPACK_SEQUENCE_TUPLE 166 +#define UNPACK_SEQUENCE_TWO_TUPLE 167 +#define SEND_GEN 168 #define DO_TRACING 255 -#define BB_BRANCH 170 -#define BB_BRANCH_IF_FLAG_UNSET 175 -#define BB_BRANCH_IF_FLAG_SET 176 -#define BB_JUMP_IF_FLAG_UNSET 177 -#define BB_JUMP_IF_FLAG_SET 178 -#define BB_TEST_ITER 179 -#define BB_TEST_IF_FALSE_OR_POP 180 -#define BB_TEST_IF_TRUE_OR_POP 181 -#define BB_TEST_POP_IF_FALSE 182 -#define BB_TEST_POP_IF_TRUE 183 -#define BB_TEST_POP_IF_NOT_NONE 184 -#define BB_TEST_POP_IF_NONE 185 -#define BB_JUMP_BACKWARD_LAZY 186 -#define BINARY_CHECK_INT 187 -#define BINARY_CHECK_FLOAT 188 -#define UNARY_CHECK_FLOAT 189 -#define BINARY_OP_ADD_INT_REST 190 -#define BINARY_OP_ADD_FLOAT_UNBOXED 191 -#define POP_TOP_NO_DECREF 192 -#define UNBOX_FLOAT 193 -#define BOX_FLOAT 194 -#define LOAD_FAST_NO_INCREF 195 -#define STORE_FAST_BOXED_UNBOXED 196 -#define STORE_FAST_UNBOXED_BOXED 197 -#define STORE_FAST_UNBOXED_UNBOXED 198 +#define BB_BRANCH 169 +#define BB_BRANCH_IF_FLAG_UNSET 170 +#define BB_BRANCH_IF_FLAG_SET 175 +#define BB_JUMP_IF_FLAG_UNSET 176 +#define BB_JUMP_IF_FLAG_SET 177 +#define BB_TEST_ITER 178 +#define BB_TEST_IF_FALSE_OR_POP 179 +#define BB_TEST_IF_TRUE_OR_POP 180 +#define BB_TEST_POP_IF_FALSE 181 +#define BB_TEST_POP_IF_TRUE 182 +#define BB_TEST_POP_IF_NOT_NONE 183 +#define BB_TEST_POP_IF_NONE 184 +#define BB_JUMP_BACKWARD_LAZY 185 +#define BINARY_CHECK_INT 186 +#define BINARY_CHECK_FLOAT 187 +#define UNARY_CHECK_FLOAT 188 +#define BINARY_OP_ADD_INT_REST 189 +#define BINARY_OP_ADD_FLOAT_UNBOXED 190 +#define POP_TOP_NO_DECREF 191 +#define UNBOX_FLOAT 192 +#define BOX_FLOAT 193 +#define LOAD_FAST_NO_INCREF 194 +#define STORE_FAST_BOXED_UNBOXED 195 +#define STORE_FAST_UNBOXED_BOXED 196 +#define STORE_FAST_UNBOXED_UNBOXED 197 #define HAS_ARG(op) ((((op) >= HAVE_ARGUMENT) && (!IS_PSEUDO_OPCODE(op)))\ || ((op) == JUMP) \ diff --git a/Lib/importlib/_bootstrap_external.py b/Lib/importlib/_bootstrap_external.py index 3f78300c226345..28e55fdc8b7d10 100644 --- a/Lib/importlib/_bootstrap_external.py +++ b/Lib/importlib/_bootstrap_external.py @@ -435,7 +435,7 @@ def _write_atomic(path, data, mode=0o666): # Python 3.12a6 3519 (Modify SEND instruction) # Python 3.12a6 3520 (Remove PREP_RERAISE_STAR, add CALL_INTRINSIC_2) # Python 3.12a7 3521 (Shrink the LOAD_GLOBAL caches) -# Python 3.12a7 3522 (Removed JUMP_IF_FALSE_OR_POP/JUMP_IF_TRUE_OR_POP) +# Python 3.12a7 3523 (Convert COMPARE_AND_BRANCH back to COMPARE_OP) # Python 3.13 will start with 3550 @@ -452,7 +452,7 @@ def _write_atomic(path, data, mode=0o666): # Whenever MAGIC_NUMBER is changed, the ranges in the magic_values array # in PC/launcher.c must also be updated. -MAGIC_NUMBER = (3522).to_bytes(2, 'little') + b'\r\n' +MAGIC_NUMBER = (3523).to_bytes(2, 'little') + b'\r\n' _RAW_MAGIC_NUMBER = int.from_bytes(MAGIC_NUMBER, 'little') # For import.c diff --git a/Lib/opcode.py b/Lib/opcode.py index cacbdaf575039f..fba7f76cc279b7 100644 --- a/Lib/opcode.py +++ b/Lib/opcode.py @@ -191,8 +191,6 @@ def pseudo_op(name, op, real_ops): def_op('DELETE_DEREF', 139) hasfree.append(139) jrel_op('JUMP_BACKWARD', 140) # Number of words to skip (backwards) -def_op('COMPARE_AND_BRANCH', 141) # Comparison and jump -hascompare.append(141) def_op('CALL_FUNCTION_EX', 142) # Flags @@ -320,10 +318,10 @@ def pseudo_op(name, op, real_ops): "CALL_NO_KW_TUPLE_1", "CALL_NO_KW_TYPE_1", ], - "COMPARE_AND_BRANCH": [ - "COMPARE_AND_BRANCH_FLOAT", - "COMPARE_AND_BRANCH_INT", - "COMPARE_AND_BRANCH_STR", + "COMPARE_OP": [ + "COMPARE_OP_FLOAT", + "COMPARE_OP_INT", + "COMPARE_OP_STR", ], "FOR_ITER": [ "FOR_ITER_LIST", @@ -404,9 +402,6 @@ def pseudo_op(name, op, real_ops): "COMPARE_OP": { "counter": 1, }, - "COMPARE_AND_BRANCH": { - "counter": 1, - }, "BINARY_SUBSCR": { "counter": 1, "type_version": 2, diff --git a/Lib/test/test_compile.py b/Lib/test/test_compile.py index fe775779c50f50..dca38418935b76 100644 --- a/Lib/test/test_compile.py +++ b/Lib/test/test_compile.py @@ -1283,7 +1283,7 @@ def test_multiline_boolean_expression(self): self.assertOpcodeSourcePositionIs(compiled_code, 'POP_JUMP_IF_FALSE', line=2, end_line=2, column=15, end_column=16, occurrence=2) # compare d and 0 - self.assertOpcodeSourcePositionIs(compiled_code, 'COMPARE_AND_BRANCH', + self.assertOpcodeSourcePositionIs(compiled_code, 'COMPARE_OP', line=4, end_line=4, column=8, end_column=13, occurrence=1) # jump if comparison it True self.assertOpcodeSourcePositionIs(compiled_code, 'POP_JUMP_IF_TRUE', diff --git a/Lib/test/test_dis.py b/Lib/test/test_dis.py index fa1de1c7ded1b3..ed66b362b08080 100644 --- a/Lib/test/test_dis.py +++ b/Lib/test/test_dis.py @@ -46,7 +46,7 @@ def cm(cls, x): %3d LOAD_FAST 1 (x) LOAD_CONST 1 (1) - COMPARE_OP 32 (==) + COMPARE_OP 40 (==) LOAD_FAST 0 (self) STORE_ATTR 0 (x) RETURN_CONST 0 (None) @@ -56,7 +56,7 @@ def cm(cls, x): RESUME 0 LOAD_FAST 1 LOAD_CONST 1 - COMPARE_OP 32 (==) + COMPARE_OP 40 (==) LOAD_FAST 0 STORE_ATTR 0 RETURN_CONST 0 @@ -67,7 +67,7 @@ def cm(cls, x): %3d LOAD_FAST 1 (x) LOAD_CONST 1 (1) - COMPARE_OP 32 (==) + COMPARE_OP 40 (==) LOAD_FAST 0 (cls) STORE_ATTR 0 (x) RETURN_CONST 0 (None) @@ -78,7 +78,7 @@ def cm(cls, x): %3d LOAD_FAST 0 (x) LOAD_CONST 1 (1) - COMPARE_OP 32 (==) + COMPARE_OP 40 (==) STORE_FAST 0 (x) RETURN_CONST 0 (None) """ % (_C.sm.__code__.co_firstlineno, _C.sm.__code__.co_firstlineno + 2,) @@ -1554,12 +1554,12 @@ def _prepare_test_cases(): Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=54, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=56, starts_line=5, is_jump_target=False, positions=None), Instruction(opname='LOAD_CONST', opcode=100, arg=2, argval=4, argrepr='4', offset=58, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='COMPARE_AND_BRANCH', opcode=141, arg=13, argval='<', argrepr='<', offset=60, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='COMPARE_OP', opcode=107, arg=2, argval='<', argrepr='<', offset=60, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='POP_JUMP_IF_FALSE', opcode=114, arg=1, argval=68, argrepr='to 68', offset=64, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='JUMP_BACKWARD', opcode=140, arg=21, argval=26, argrepr='to 26', offset=66, starts_line=6, is_jump_target=False, positions=None), Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=68, starts_line=7, is_jump_target=True, positions=None), Instruction(opname='LOAD_CONST', opcode=100, arg=3, argval=6, argrepr='6', offset=70, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='COMPARE_AND_BRANCH', opcode=141, arg=68, argval='>', argrepr='>', offset=72, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='COMPARE_OP', opcode=107, arg=68, argval='>', argrepr='>', offset=72, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='POP_JUMP_IF_TRUE', opcode=115, arg=1, argval=80, argrepr='to 80', offset=76, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='JUMP_BACKWARD', opcode=140, arg=27, argval=26, argrepr='to 26', offset=78, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=80, starts_line=8, is_jump_target=True, positions=None), @@ -1581,12 +1581,12 @@ def _prepare_test_cases(): Instruction(opname='STORE_FAST', opcode=125, arg=0, argval='i', argrepr='i', offset=146, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=148, starts_line=14, is_jump_target=False, positions=None), Instruction(opname='LOAD_CONST', opcode=100, arg=3, argval=6, argrepr='6', offset=150, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='COMPARE_AND_BRANCH', opcode=141, arg=75, argval='>', argrepr='>', offset=152, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='COMPARE_OP', opcode=107, arg=68, argval='>', argrepr='>', offset=152, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='POP_JUMP_IF_FALSE', opcode=114, arg=1, argval=160, argrepr='to 160', offset=156, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='JUMP_BACKWARD', opcode=140, arg=25, argval=110, argrepr='to 110', offset=158, starts_line=15, is_jump_target=False, positions=None), Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=160, starts_line=16, is_jump_target=True, positions=None), Instruction(opname='LOAD_CONST', opcode=100, arg=2, argval=4, argrepr='4', offset=162, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='COMPARE_AND_BRANCH', opcode=141, arg=13, argval='<', argrepr='<', offset=164, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='COMPARE_OP', opcode=107, arg=2, argval='<', argrepr='<', offset=164, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='POP_JUMP_IF_FALSE', opcode=114, arg=1, argval=172, argrepr='to 172', offset=168, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='JUMP_FORWARD', opcode=110, arg=15, argval=202, argrepr='to 202', offset=170, starts_line=17, is_jump_target=False, positions=None), Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=172, starts_line=11, is_jump_target=True, positions=None), diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-03-17-12-09-45.gh-issue-100982.Pf_BI6.rst b/Misc/NEWS.d/next/Core and Builtins/2023-03-17-12-09-45.gh-issue-100982.Pf_BI6.rst new file mode 100644 index 00000000000000..31a8660836c759 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2023-03-17-12-09-45.gh-issue-100982.Pf_BI6.rst @@ -0,0 +1 @@ +Replace all occurrences of ``COMPARE_AND_BRANCH`` with :opcode:`COMPARE_OP`. diff --git a/Objects/frameobject.c b/Objects/frameobject.c index 19bd4b10780b91..63590d58809e3e 100644 --- a/Objects/frameobject.c +++ b/Objects/frameobject.c @@ -347,14 +347,6 @@ mark_stacks(PyCodeObject *code_obj, int len) assert(stacks[j] == UNINITIALIZED || stacks[j] == next_stack); stacks[j] = next_stack; break; - case COMPARE_AND_BRANCH: - next_stack = pop_value(pop_value(next_stack)); - i++; - j = get_arg(code, i) + i + 1; - assert(j < len); - assert(stacks[j] == UNINITIALIZED || stacks[j] == next_stack); - stacks[j] = next_stack; - break; case GET_ITER: case GET_AITER: next_stack = push_value(pop_value(next_stack), Iterator); diff --git a/Python/bytecodes.c b/Python/bytecodes.c index b9a6a9e2b61208..55ef034c9a9ff8 100644 --- a/Python/bytecodes.c +++ b/Python/bytecodes.c @@ -1760,75 +1760,54 @@ dummy_func( Py_DECREF(owner); } - inst(COMPARE_OP, (unused/1, left, right -- res)) { - STAT_INC(COMPARE_OP, deferred); - assert((oparg >> 4) <= Py_GE); - res = PyObject_RichCompare(left, right, oparg>>4); - DECREF_INPUTS(); - ERROR_IF(res == NULL, error); - } - - // No cache size here, since this is a family of super-instructions. - family(compare_and_branch) = { - COMPARE_AND_BRANCH, - COMPARE_AND_BRANCH_FLOAT, - COMPARE_AND_BRANCH_INT, - COMPARE_AND_BRANCH_STR, + family(compare_op, INLINE_CACHE_ENTRIES_COMPARE_OP) = { + COMPARE_OP, + COMPARE_OP_FLOAT, + COMPARE_OP_INT, + COMPARE_OP_STR, }; - inst(COMPARE_AND_BRANCH, (unused/2, left, right -- )) { + inst(COMPARE_OP, (unused/1, left, right -- res)) { #if ENABLE_SPECIALIZATION _PyCompareOpCache *cache = (_PyCompareOpCache *)next_instr; if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) { assert(cframe.use_tracing == 0); next_instr--; - _Py_Specialize_CompareAndBranch(left, right, next_instr, oparg); + _Py_Specialize_CompareOp(left, right, next_instr, oparg); DISPATCH_SAME_OPARG(); } - STAT_INC(COMPARE_AND_BRANCH, deferred); + STAT_INC(COMPARE_OP, deferred); DECREMENT_ADAPTIVE_COUNTER(cache->counter); #endif /* ENABLE_SPECIALIZATION */ assert((oparg >> 4) <= Py_GE); - PyObject *cond = PyObject_RichCompare(left, right, oparg>>4); + res = PyObject_RichCompare(left, right, oparg>>4); DECREF_INPUTS(); - ERROR_IF(cond == NULL, error); - assert(next_instr[1].op.code == POP_JUMP_IF_FALSE || - next_instr[1].op.code == POP_JUMP_IF_TRUE); - bool jump_on_true = next_instr[1].op.code == POP_JUMP_IF_TRUE; - int offset = next_instr[1].op.arg; - int err = PyObject_IsTrue(cond); - Py_DECREF(cond); - ERROR_IF(err < 0, error); - if (jump_on_true == (err != 0)) { - JUMPBY(offset); - } + ERROR_IF(res == NULL, error); } - inst(COMPARE_AND_BRANCH_FLOAT, (unused/2, left, right -- )) { + inst(COMPARE_OP_FLOAT, (unused/1, left, right -- res)) { assert(cframe.use_tracing == 0); - DEOPT_IF(!PyFloat_CheckExact(left), COMPARE_AND_BRANCH); - DEOPT_IF(!PyFloat_CheckExact(right), COMPARE_AND_BRANCH); - STAT_INC(COMPARE_AND_BRANCH, hit); + DEOPT_IF(!PyFloat_CheckExact(left), COMPARE_OP); + DEOPT_IF(!PyFloat_CheckExact(right), COMPARE_OP); + STAT_INC(COMPARE_OP, hit); double dleft = PyFloat_AS_DOUBLE(left); double dright = PyFloat_AS_DOUBLE(right); // 1 if NaN, 2 if <, 4 if >, 8 if ==; this matches low four bits of the oparg int sign_ish = COMPARISON_BIT(dleft, dright); _Py_DECREF_SPECIALIZED(left, _PyFloat_ExactDealloc); _Py_DECREF_SPECIALIZED(right, _PyFloat_ExactDealloc); - if (sign_ish & oparg) { - int offset = next_instr[1].op.arg; - JUMPBY(offset); - } + res = (sign_ish & oparg) ? Py_True : Py_False; + Py_INCREF(res); } - // Similar to COMPARE_AND_BRANCH_FLOAT - inst(COMPARE_AND_BRANCH_INT, (unused/2, left, right -- )) { + // Similar to COMPARE_OP_FLOAT + inst(COMPARE_OP_INT, (unused/1, left, right -- res)) { assert(cframe.use_tracing == 0); - DEOPT_IF(!PyLong_CheckExact(left), COMPARE_AND_BRANCH); - DEOPT_IF(!PyLong_CheckExact(right), COMPARE_AND_BRANCH); - DEOPT_IF(!_PyLong_IsCompact((PyLongObject *)left), COMPARE_AND_BRANCH); - DEOPT_IF(!_PyLong_IsCompact((PyLongObject *)right), COMPARE_AND_BRANCH); - STAT_INC(COMPARE_AND_BRANCH, hit); + DEOPT_IF(!PyLong_CheckExact(left), COMPARE_OP); + DEOPT_IF(!PyLong_CheckExact(right), COMPARE_OP); + DEOPT_IF(!_PyLong_IsCompact((PyLongObject *)left), COMPARE_OP); + DEOPT_IF(!_PyLong_IsCompact((PyLongObject *)right), COMPARE_OP); + STAT_INC(COMPARE_OP, hit); assert(_PyLong_DigitCount((PyLongObject *)left) <= 1 && _PyLong_DigitCount((PyLongObject *)right) <= 1); Py_ssize_t ileft = _PyLong_CompactValue((PyLongObject *)left); @@ -1837,29 +1816,25 @@ dummy_func( int sign_ish = COMPARISON_BIT(ileft, iright); _Py_DECREF_SPECIALIZED(left, (destructor)PyObject_Free); _Py_DECREF_SPECIALIZED(right, (destructor)PyObject_Free); - if (sign_ish & oparg) { - int offset = next_instr[1].op.arg; - JUMPBY(offset); - } + res = (sign_ish & oparg) ? Py_True : Py_False; + Py_INCREF(res); } - // Similar to COMPARE_AND_BRANCH_FLOAT, but for ==, != only - inst(COMPARE_AND_BRANCH_STR, (unused/2, left, right -- )) { + // Similar to COMPARE_OP_FLOAT, but for ==, != only + inst(COMPARE_OP_STR, (unused/1, left, right -- res)) { assert(cframe.use_tracing == 0); - DEOPT_IF(!PyUnicode_CheckExact(left), COMPARE_AND_BRANCH); - DEOPT_IF(!PyUnicode_CheckExact(right), COMPARE_AND_BRANCH); - STAT_INC(COMPARE_AND_BRANCH, hit); - int res = _PyUnicode_Equal(left, right); + DEOPT_IF(!PyUnicode_CheckExact(left), COMPARE_OP); + DEOPT_IF(!PyUnicode_CheckExact(right), COMPARE_OP); + STAT_INC(COMPARE_OP, hit); + int eq = _PyUnicode_Equal(left, right); assert((oparg >>4) == Py_EQ || (oparg >>4) == Py_NE); _Py_DECREF_SPECIALIZED(left, _PyUnicode_ExactDealloc); _Py_DECREF_SPECIALIZED(right, _PyUnicode_ExactDealloc); - assert(res == 0 || res == 1); + assert(eq == 0 || eq == 1); assert((oparg & 0xf) == COMPARISON_NOT_EQUALS || (oparg & 0xf) == COMPARISON_EQUALS); assert(COMPARISON_NOT_EQUALS + 1 == COMPARISON_EQUALS); - if ((res + COMPARISON_NOT_EQUALS) & oparg) { - int offset = next_instr[1].op.arg; - JUMPBY(offset); - } + res = ((COMPARISON_NOT_EQUALS + eq) & oparg) ? Py_True : Py_False; + Py_INCREF(res); } inst(IS_OP, (left, right -- b: PyBool_Type)) { diff --git a/Python/compile.c b/Python/compile.c index 33cd6ca07d3bb6..192deaa4b35f4d 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -2800,6 +2800,15 @@ check_compare(struct compiler *c, expr_ty e) return SUCCESS; } +static const int compare_masks[] = { + [Py_LT] = COMPARISON_LESS_THAN, + [Py_LE] = COMPARISON_LESS_THAN | COMPARISON_EQUALS, + [Py_EQ] = COMPARISON_EQUALS, + [Py_NE] = COMPARISON_NOT_EQUALS, + [Py_GT] = COMPARISON_GREATER_THAN, + [Py_GE] = COMPARISON_GREATER_THAN | COMPARISON_EQUALS, +}; + static int compiler_addcompare(struct compiler *c, location loc, cmpop_ty op) { @@ -2840,7 +2849,7 @@ static int compiler_addcompare(struct compiler *c, location loc, } /* cmp goes in top bits of the oparg, while the low bits are used by quickened * versions of this opcode to store the comparison mask. */ - ADDOP_I(c, loc, COMPARE_OP, cmp << 4); + ADDOP_I(c, loc, COMPARE_OP, (cmp << 4) | compare_masks[cmp]); return SUCCESS; } diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h index e74ef78c3b0aeb..158116daaaddc4 100644 --- a/Python/generated_cases.c.h +++ b/Python/generated_cases.c.h @@ -2271,87 +2271,65 @@ } TARGET(COMPARE_OP) { + PREDICTED(COMPARE_OP); + static_assert(INLINE_CACHE_ENTRIES_COMPARE_OP == 1, "incorrect cache size"); PyObject *right = stack_pointer[-1]; PyObject *left = stack_pointer[-2]; PyObject *res; - STAT_INC(COMPARE_OP, deferred); - assert((oparg >> 4) <= Py_GE); - res = PyObject_RichCompare(left, right, oparg>>4); - Py_DECREF(left); - Py_DECREF(right); - if (res == NULL) goto pop_2_error; - STACK_SHRINK(1); - stack_pointer[-1] = res; - next_instr += 1; - DISPATCH(); - } - - TARGET(COMPARE_AND_BRANCH) { - PREDICTED(COMPARE_AND_BRANCH); - PyObject *right = stack_pointer[-1]; - PyObject *left = stack_pointer[-2]; #if ENABLE_SPECIALIZATION _PyCompareOpCache *cache = (_PyCompareOpCache *)next_instr; if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) { assert(cframe.use_tracing == 0); next_instr--; - _Py_Specialize_CompareAndBranch(left, right, next_instr, oparg); + _Py_Specialize_CompareOp(left, right, next_instr, oparg); DISPATCH_SAME_OPARG(); } - STAT_INC(COMPARE_AND_BRANCH, deferred); + STAT_INC(COMPARE_OP, deferred); DECREMENT_ADAPTIVE_COUNTER(cache->counter); #endif /* ENABLE_SPECIALIZATION */ assert((oparg >> 4) <= Py_GE); - PyObject *cond = PyObject_RichCompare(left, right, oparg>>4); + res = PyObject_RichCompare(left, right, oparg>>4); Py_DECREF(left); Py_DECREF(right); - if (cond == NULL) goto pop_2_error; - assert(next_instr[1].op.code == POP_JUMP_IF_FALSE || - next_instr[1].op.code == POP_JUMP_IF_TRUE); - bool jump_on_true = next_instr[1].op.code == POP_JUMP_IF_TRUE; - int offset = next_instr[1].op.arg; - int err = PyObject_IsTrue(cond); - Py_DECREF(cond); - if (err < 0) goto pop_2_error; - if (jump_on_true == (err != 0)) { - JUMPBY(offset); - } - STACK_SHRINK(2); - next_instr += 2; + if (res == NULL) goto pop_2_error; + STACK_SHRINK(1); + stack_pointer[-1] = res; + next_instr += 1; DISPATCH(); } - TARGET(COMPARE_AND_BRANCH_FLOAT) { + TARGET(COMPARE_OP_FLOAT) { PyObject *right = stack_pointer[-1]; PyObject *left = stack_pointer[-2]; + PyObject *res; assert(cframe.use_tracing == 0); - DEOPT_IF(!PyFloat_CheckExact(left), COMPARE_AND_BRANCH); - DEOPT_IF(!PyFloat_CheckExact(right), COMPARE_AND_BRANCH); - STAT_INC(COMPARE_AND_BRANCH, hit); + DEOPT_IF(!PyFloat_CheckExact(left), COMPARE_OP); + DEOPT_IF(!PyFloat_CheckExact(right), COMPARE_OP); + STAT_INC(COMPARE_OP, hit); double dleft = PyFloat_AS_DOUBLE(left); double dright = PyFloat_AS_DOUBLE(right); // 1 if NaN, 2 if <, 4 if >, 8 if ==; this matches low four bits of the oparg int sign_ish = COMPARISON_BIT(dleft, dright); _Py_DECREF_SPECIALIZED(left, _PyFloat_ExactDealloc); _Py_DECREF_SPECIALIZED(right, _PyFloat_ExactDealloc); - if (sign_ish & oparg) { - int offset = next_instr[1].op.arg; - JUMPBY(offset); - } - STACK_SHRINK(2); - next_instr += 2; + res = (sign_ish & oparg) ? Py_True : Py_False; + Py_INCREF(res); + STACK_SHRINK(1); + stack_pointer[-1] = res; + next_instr += 1; DISPATCH(); } - TARGET(COMPARE_AND_BRANCH_INT) { + TARGET(COMPARE_OP_INT) { PyObject *right = stack_pointer[-1]; PyObject *left = stack_pointer[-2]; + PyObject *res; assert(cframe.use_tracing == 0); - DEOPT_IF(!PyLong_CheckExact(left), COMPARE_AND_BRANCH); - DEOPT_IF(!PyLong_CheckExact(right), COMPARE_AND_BRANCH); - DEOPT_IF(!_PyLong_IsCompact((PyLongObject *)left), COMPARE_AND_BRANCH); - DEOPT_IF(!_PyLong_IsCompact((PyLongObject *)right), COMPARE_AND_BRANCH); - STAT_INC(COMPARE_AND_BRANCH, hit); + DEOPT_IF(!PyLong_CheckExact(left), COMPARE_OP); + DEOPT_IF(!PyLong_CheckExact(right), COMPARE_OP); + DEOPT_IF(!_PyLong_IsCompact((PyLongObject *)left), COMPARE_OP); + DEOPT_IF(!_PyLong_IsCompact((PyLongObject *)right), COMPARE_OP); + STAT_INC(COMPARE_OP, hit); assert(_PyLong_DigitCount((PyLongObject *)left) <= 1 && _PyLong_DigitCount((PyLongObject *)right) <= 1); Py_ssize_t ileft = _PyLong_CompactValue((PyLongObject *)left); @@ -2360,35 +2338,34 @@ int sign_ish = COMPARISON_BIT(ileft, iright); _Py_DECREF_SPECIALIZED(left, (destructor)PyObject_Free); _Py_DECREF_SPECIALIZED(right, (destructor)PyObject_Free); - if (sign_ish & oparg) { - int offset = next_instr[1].op.arg; - JUMPBY(offset); - } - STACK_SHRINK(2); - next_instr += 2; + res = (sign_ish & oparg) ? Py_True : Py_False; + Py_INCREF(res); + STACK_SHRINK(1); + stack_pointer[-1] = res; + next_instr += 1; DISPATCH(); } - TARGET(COMPARE_AND_BRANCH_STR) { + TARGET(COMPARE_OP_STR) { PyObject *right = stack_pointer[-1]; PyObject *left = stack_pointer[-2]; + PyObject *res; assert(cframe.use_tracing == 0); - DEOPT_IF(!PyUnicode_CheckExact(left), COMPARE_AND_BRANCH); - DEOPT_IF(!PyUnicode_CheckExact(right), COMPARE_AND_BRANCH); - STAT_INC(COMPARE_AND_BRANCH, hit); - int res = _PyUnicode_Equal(left, right); + DEOPT_IF(!PyUnicode_CheckExact(left), COMPARE_OP); + DEOPT_IF(!PyUnicode_CheckExact(right), COMPARE_OP); + STAT_INC(COMPARE_OP, hit); + int eq = _PyUnicode_Equal(left, right); assert((oparg >>4) == Py_EQ || (oparg >>4) == Py_NE); _Py_DECREF_SPECIALIZED(left, _PyUnicode_ExactDealloc); _Py_DECREF_SPECIALIZED(right, _PyUnicode_ExactDealloc); - assert(res == 0 || res == 1); + assert(eq == 0 || eq == 1); assert((oparg & 0xf) == COMPARISON_NOT_EQUALS || (oparg & 0xf) == COMPARISON_EQUALS); assert(COMPARISON_NOT_EQUALS + 1 == COMPARISON_EQUALS); - if ((res + COMPARISON_NOT_EQUALS) & oparg) { - int offset = next_instr[1].op.arg; - JUMPBY(offset); - } - STACK_SHRINK(2); - next_instr += 2; + res = ((COMPARISON_NOT_EQUALS + eq) & oparg) ? Py_True : Py_False; + Py_INCREF(res); + STACK_SHRINK(1); + stack_pointer[-1] = res; + next_instr += 1; DISPATCH(); } diff --git a/Python/opcode_metadata.h b/Python/opcode_metadata.h index 25463ced32d5d4..bc3aeba527d13b 100644 --- a/Python/opcode_metadata.h +++ b/Python/opcode_metadata.h @@ -241,13 +241,11 @@ _PyOpcode_num_popped(int opcode, int oparg, bool jump) { return 2; case COMPARE_OP: return 2; - case COMPARE_AND_BRANCH: + case COMPARE_OP_FLOAT: return 2; - case COMPARE_AND_BRANCH_FLOAT: + case COMPARE_OP_INT: return 2; - case COMPARE_AND_BRANCH_INT: - return 2; - case COMPARE_AND_BRANCH_STR: + case COMPARE_OP_STR: return 2; case IS_OP: return 2; @@ -637,14 +635,12 @@ _PyOpcode_num_pushed(int opcode, int oparg, bool jump) { return 0; case COMPARE_OP: return 1; - case COMPARE_AND_BRANCH: - return 0; - case COMPARE_AND_BRANCH_FLOAT: - return 0; - case COMPARE_AND_BRANCH_INT: - return 0; - case COMPARE_AND_BRANCH_STR: - return 0; + case COMPARE_OP_FLOAT: + return 1; + case COMPARE_OP_INT: + return 1; + case COMPARE_OP_STR: + return 1; case IS_OP: return 1; case CONTAINS_OP: @@ -795,7 +791,7 @@ _PyOpcode_num_pushed(int opcode, int oparg, bool jump) { } #endif -enum InstructionFormat { INSTR_FMT_IB, INSTR_FMT_IBC, INSTR_FMT_IBC0, INSTR_FMT_IBC000, INSTR_FMT_IBC00000000, INSTR_FMT_IBIB, INSTR_FMT_IX, INSTR_FMT_IXC, INSTR_FMT_IXC000 }; +enum InstructionFormat { INSTR_FMT_IB, INSTR_FMT_IBC, INSTR_FMT_IBC000, INSTR_FMT_IBC00000000, INSTR_FMT_IBIB, INSTR_FMT_IX, INSTR_FMT_IXC, INSTR_FMT_IXC000 }; struct opcode_metadata { bool valid_entry; enum InstructionFormat instr_format; @@ -921,10 +917,9 @@ const struct opcode_metadata _PyOpcode_opcode_metadata[256] = { [STORE_ATTR_WITH_HINT] = { true, INSTR_FMT_IBC000 }, [STORE_ATTR_SLOT] = { true, INSTR_FMT_IXC000 }, [COMPARE_OP] = { true, INSTR_FMT_IBC }, - [COMPARE_AND_BRANCH] = { true, INSTR_FMT_IBC0 }, - [COMPARE_AND_BRANCH_FLOAT] = { true, INSTR_FMT_IBC0 }, - [COMPARE_AND_BRANCH_INT] = { true, INSTR_FMT_IBC0 }, - [COMPARE_AND_BRANCH_STR] = { true, INSTR_FMT_IBC0 }, + [COMPARE_OP_FLOAT] = { true, INSTR_FMT_IBC }, + [COMPARE_OP_INT] = { true, INSTR_FMT_IBC }, + [COMPARE_OP_STR] = { true, INSTR_FMT_IBC }, [IS_OP] = { true, INSTR_FMT_IB }, [CONTAINS_OP] = { true, INSTR_FMT_IB }, [CHECK_EG_MATCH] = { true, INSTR_FMT_IX }, diff --git a/Python/opcode_targets.h b/Python/opcode_targets.h index 38217d9e8f2ba9..48c858e0cd2d00 100644 --- a/Python/opcode_targets.h +++ b/Python/opcode_targets.h @@ -56,9 +56,9 @@ static void *opcode_targets[256] = { &&TARGET_END_ASYNC_FOR, &&TARGET_CLEANUP_THROW, &&TARGET_CALL_NO_KW_TYPE_1, - &&TARGET_COMPARE_AND_BRANCH_FLOAT, - &&TARGET_COMPARE_AND_BRANCH_INT, - &&TARGET_COMPARE_AND_BRANCH_STR, + &&TARGET_COMPARE_OP_FLOAT, + &&TARGET_COMPARE_OP_INT, + &&TARGET_COMPARE_OP_STR, &&TARGET_STORE_SUBSCR, &&TARGET_DELETE_SUBSCR, &&TARGET_FOR_ITER_LIST, @@ -140,9 +140,9 @@ static void *opcode_targets[256] = { &&TARGET_STORE_DEREF, &&TARGET_DELETE_DEREF, &&TARGET_JUMP_BACKWARD, - &&TARGET_COMPARE_AND_BRANCH, - &&TARGET_CALL_FUNCTION_EX, &&TARGET_STORE_ATTR_INSTANCE_VALUE, + &&TARGET_CALL_FUNCTION_EX, + &&TARGET_STORE_ATTR_SLOT, &&TARGET_EXTENDED_ARG, &&TARGET_LIST_APPEND, &&TARGET_SET_ADD, @@ -152,24 +152,24 @@ static void *opcode_targets[256] = { &&TARGET_YIELD_VALUE, &&TARGET_RESUME, &&TARGET_MATCH_CLASS, - &&TARGET_STORE_ATTR_SLOT, &&TARGET_STORE_ATTR_WITH_HINT, + &&TARGET_STORE_FAST__LOAD_FAST, &&TARGET_FORMAT_VALUE, &&TARGET_BUILD_CONST_KEY_MAP, &&TARGET_BUILD_STRING, - &&TARGET_STORE_FAST__LOAD_FAST, &&TARGET_STORE_FAST__STORE_FAST, &&TARGET_STORE_SUBSCR_DICT, &&TARGET_STORE_SUBSCR_LIST_INT, + &&TARGET_UNPACK_SEQUENCE_LIST, &&TARGET_LIST_EXTEND, &&TARGET_SET_UPDATE, &&TARGET_DICT_MERGE, &&TARGET_DICT_UPDATE, - &&TARGET_UNPACK_SEQUENCE_LIST, &&TARGET_UNPACK_SEQUENCE_TUPLE, &&TARGET_UNPACK_SEQUENCE_TWO_TUPLE, &&TARGET_SEND_GEN, &&_unknown_opcode, + &&_unknown_opcode, &&TARGET_CALL, &&TARGET_KW_NAMES, &&TARGET_CALL_INTRINSIC_1, diff --git a/Python/specialize.c b/Python/specialize.c index 2e93ab193990a1..dd5b22dd2346c5 100644 --- a/Python/specialize.c +++ b/Python/specialize.c @@ -264,15 +264,6 @@ do { \ #define SPECIALIZATION_FAIL(opcode, kind) ((void)0) #endif -static int compare_masks[] = { - [Py_LT] = COMPARISON_LESS_THAN, - [Py_LE] = COMPARISON_LESS_THAN | COMPARISON_EQUALS, - [Py_EQ] = COMPARISON_EQUALS, - [Py_NE] = COMPARISON_NOT_EQUALS, - [Py_GT] = COMPARISON_GREATER_THAN, - [Py_GE] = COMPARISON_GREATER_THAN | COMPARISON_EQUALS, -}; - // Initialize warmup counters and insert superinstructions. This cannot fail. void _PyCode_Quicken(PyCodeObject *code) @@ -305,19 +296,6 @@ _PyCode_Quicken(PyCodeObject *code) case STORE_FAST << 8 | STORE_FAST: instructions[i - 1].op.code = STORE_FAST__STORE_FAST; break; - case COMPARE_OP << 8 | POP_JUMP_IF_TRUE: - case COMPARE_OP << 8 | POP_JUMP_IF_FALSE: - { - int oparg = instructions[i - 1 - INLINE_CACHE_ENTRIES_COMPARE_OP].op.arg; - assert((oparg >> 4) <= Py_GE); - int mask = compare_masks[oparg >> 4]; - if (opcode == POP_JUMP_IF_FALSE) { - mask = mask ^ 0xf; - } - instructions[i - 1 - INLINE_CACHE_ENTRIES_COMPARE_OP].op.code = COMPARE_AND_BRANCH; - instructions[i - 1 - INLINE_CACHE_ENTRIES_COMPARE_OP].op.arg = (oparg & 0xf0) | mask; - break; - } } } #endif /* ENABLE_SPECIALIZATION */ @@ -436,19 +414,17 @@ _PyCode_Quicken(PyCodeObject *code) #define SPEC_FAIL_CALL_OPERATOR_WRAPPER 29 /* COMPARE_OP */ -#define SPEC_FAIL_COMPARE_DIFFERENT_TYPES 12 -#define SPEC_FAIL_COMPARE_STRING 13 -#define SPEC_FAIL_COMPARE_NOT_FOLLOWED_BY_COND_JUMP 14 -#define SPEC_FAIL_COMPARE_BIG_INT 15 -#define SPEC_FAIL_COMPARE_BYTES 16 -#define SPEC_FAIL_COMPARE_TUPLE 17 -#define SPEC_FAIL_COMPARE_LIST 18 -#define SPEC_FAIL_COMPARE_SET 19 -#define SPEC_FAIL_COMPARE_BOOL 20 -#define SPEC_FAIL_COMPARE_BASEOBJECT 21 -#define SPEC_FAIL_COMPARE_FLOAT_LONG 22 -#define SPEC_FAIL_COMPARE_LONG_FLOAT 23 -#define SPEC_FAIL_COMPARE_EXTENDED_ARG 24 +#define SPEC_FAIL_COMPARE_OP_DIFFERENT_TYPES 12 +#define SPEC_FAIL_COMPARE_OP_STRING 13 +#define SPEC_FAIL_COMPARE_OP_BIG_INT 14 +#define SPEC_FAIL_COMPARE_OP_BYTES 15 +#define SPEC_FAIL_COMPARE_OP_TUPLE 16 +#define SPEC_FAIL_COMPARE_OP_LIST 17 +#define SPEC_FAIL_COMPARE_OP_SET 18 +#define SPEC_FAIL_COMPARE_OP_BOOL 19 +#define SPEC_FAIL_COMPARE_OP_BASEOBJECT 20 +#define SPEC_FAIL_COMPARE_OP_FLOAT_LONG 21 +#define SPEC_FAIL_COMPARE_OP_LONG_FLOAT 22 /* FOR_ITER */ #define SPEC_FAIL_FOR_ITER_GENERATOR 10 @@ -1958,83 +1934,79 @@ compare_op_fail_kind(PyObject *lhs, PyObject *rhs) { if (Py_TYPE(lhs) != Py_TYPE(rhs)) { if (PyFloat_CheckExact(lhs) && PyLong_CheckExact(rhs)) { - return SPEC_FAIL_COMPARE_FLOAT_LONG; + return SPEC_FAIL_COMPARE_OP_FLOAT_LONG; } if (PyLong_CheckExact(lhs) && PyFloat_CheckExact(rhs)) { - return SPEC_FAIL_COMPARE_LONG_FLOAT; + return SPEC_FAIL_COMPARE_OP_LONG_FLOAT; } - return SPEC_FAIL_COMPARE_DIFFERENT_TYPES; + return SPEC_FAIL_COMPARE_OP_DIFFERENT_TYPES; } if (PyBytes_CheckExact(lhs)) { - return SPEC_FAIL_COMPARE_BYTES; + return SPEC_FAIL_COMPARE_OP_BYTES; } if (PyTuple_CheckExact(lhs)) { - return SPEC_FAIL_COMPARE_TUPLE; + return SPEC_FAIL_COMPARE_OP_TUPLE; } if (PyList_CheckExact(lhs)) { - return SPEC_FAIL_COMPARE_LIST; + return SPEC_FAIL_COMPARE_OP_LIST; } if (PySet_CheckExact(lhs) || PyFrozenSet_CheckExact(lhs)) { - return SPEC_FAIL_COMPARE_SET; + return SPEC_FAIL_COMPARE_OP_SET; } if (PyBool_Check(lhs)) { - return SPEC_FAIL_COMPARE_BOOL; + return SPEC_FAIL_COMPARE_OP_BOOL; } if (Py_TYPE(lhs)->tp_richcompare == PyBaseObject_Type.tp_richcompare) { - return SPEC_FAIL_COMPARE_BASEOBJECT; + return SPEC_FAIL_COMPARE_OP_BASEOBJECT; } return SPEC_FAIL_OTHER; } #endif void -_Py_Specialize_CompareAndBranch(PyObject *lhs, PyObject *rhs, _Py_CODEUNIT *instr, +_Py_Specialize_CompareOp(PyObject *lhs, PyObject *rhs, _Py_CODEUNIT *instr, int oparg) { assert(ENABLE_SPECIALIZATION); - assert(_PyOpcode_Caches[COMPARE_AND_BRANCH] == INLINE_CACHE_ENTRIES_COMPARE_OP); + assert(_PyOpcode_Caches[COMPARE_OP] == INLINE_CACHE_ENTRIES_COMPARE_OP); _PyCompareOpCache *cache = (_PyCompareOpCache *)(instr + 1); -#ifndef NDEBUG - int next_opcode = instr[INLINE_CACHE_ENTRIES_COMPARE_OP + 1].op.code; - assert(next_opcode == POP_JUMP_IF_FALSE || next_opcode == POP_JUMP_IF_TRUE); -#endif if (Py_TYPE(lhs) != Py_TYPE(rhs)) { - SPECIALIZATION_FAIL(COMPARE_AND_BRANCH, compare_op_fail_kind(lhs, rhs)); + SPECIALIZATION_FAIL(COMPARE_OP, compare_op_fail_kind(lhs, rhs)); goto failure; } if (PyFloat_CheckExact(lhs)) { - instr->op.code = COMPARE_AND_BRANCH_FLOAT; + instr->op.code = COMPARE_OP_FLOAT; goto success; } if (PyLong_CheckExact(lhs)) { if (_PyLong_IsCompact((PyLongObject *)lhs) && _PyLong_IsCompact((PyLongObject *)rhs)) { - instr->op.code = COMPARE_AND_BRANCH_INT; + instr->op.code = COMPARE_OP_INT; goto success; } else { - SPECIALIZATION_FAIL(COMPARE_AND_BRANCH, SPEC_FAIL_COMPARE_BIG_INT); + SPECIALIZATION_FAIL(COMPARE_OP, SPEC_FAIL_COMPARE_OP_BIG_INT); goto failure; } } if (PyUnicode_CheckExact(lhs)) { int cmp = oparg >> 4; if (cmp != Py_EQ && cmp != Py_NE) { - SPECIALIZATION_FAIL(COMPARE_AND_BRANCH, SPEC_FAIL_COMPARE_STRING); + SPECIALIZATION_FAIL(COMPARE_OP, SPEC_FAIL_COMPARE_OP_STRING); goto failure; } else { - instr->op.code = COMPARE_AND_BRANCH_STR; + instr->op.code = COMPARE_OP_STR; goto success; } } - SPECIALIZATION_FAIL(COMPARE_AND_BRANCH, compare_op_fail_kind(lhs, rhs)); + SPECIALIZATION_FAIL(COMPARE_OP, compare_op_fail_kind(lhs, rhs)); failure: - STAT_INC(COMPARE_AND_BRANCH, failure); - instr->op.code = COMPARE_AND_BRANCH; + STAT_INC(COMPARE_OP, failure); + instr->op.code = COMPARE_OP; cache->counter = adaptive_counter_backoff(cache->counter); return; success: - STAT_INC(COMPARE_AND_BRANCH, success); + STAT_INC(COMPARE_OP, success); cache->counter = adaptive_counter_cooldown(); } diff --git a/Python/tier2_typepropagator.c.h b/Python/tier2_typepropagator.c.h index c50ae42092bfd5..46987cc6a07ed2 100644 --- a/Python/tier2_typepropagator.c.h +++ b/Python/tier2_typepropagator.c.h @@ -645,23 +645,21 @@ break; } - TARGET(COMPARE_AND_BRANCH) { - STACK_SHRINK(2); - break; - } - - TARGET(COMPARE_AND_BRANCH_FLOAT) { - STACK_SHRINK(2); + TARGET(COMPARE_OP_FLOAT) { + STACK_SHRINK(1); + TYPE_OVERWRITE((_Py_TYPENODE_t *)_Py_TYPENODE_NULLROOT, TYPESTACK_PEEK(1), true); break; } - TARGET(COMPARE_AND_BRANCH_INT) { - STACK_SHRINK(2); + TARGET(COMPARE_OP_INT) { + STACK_SHRINK(1); + TYPE_OVERWRITE((_Py_TYPENODE_t *)_Py_TYPENODE_NULLROOT, TYPESTACK_PEEK(1), true); break; } - TARGET(COMPARE_AND_BRANCH_STR) { - STACK_SHRINK(2); + TARGET(COMPARE_OP_STR) { + STACK_SHRINK(1); + TYPE_OVERWRITE((_Py_TYPENODE_t *)_Py_TYPENODE_NULLROOT, TYPESTACK_PEEK(1), true); break; } diff --git a/Tools/c-analyzer/cpython/ignored.tsv b/Tools/c-analyzer/cpython/ignored.tsv index 14fc32a07b4309..9203c1888149fb 100644 --- a/Tools/c-analyzer/cpython/ignored.tsv +++ b/Tools/c-analyzer/cpython/ignored.tsv @@ -350,7 +350,6 @@ Python/pylifecycle.c - INTERPRETER_TRAMPOLINE_CODEDEF - Python/pystate.c - initial - Python/specialize.c - adaptive_opcodes - Python/specialize.c - cache_requirements - -Python/specialize.c - compare_masks - Python/stdlib_module_names.h - _Py_stdlib_module_names - Python/sysmodule.c - _PySys_ImplCacheTag - Python/sysmodule.c - _PySys_ImplName - diff --git a/Tools/scripts/summarize_stats.py b/Tools/scripts/summarize_stats.py index 7789c4d3a17d38..ce25374f3a9a52 100644 --- a/Tools/scripts/summarize_stats.py +++ b/Tools/scripts/summarize_stats.py @@ -228,8 +228,6 @@ def kind_to_text(kind, defines, opname): return pretty(defines[kind][0]) if opname.endswith("ATTR"): opname = "ATTR" - if opname in ("COMPARE_OP", "COMPARE_AND_BRANCH"): - opname = "COMPARE" if opname.endswith("SUBSCR"): opname = "SUBSCR" for name in defines[kind]: