diff options
author | Mark Shannon <mark@hotpy.org> | 2023-11-14 15:30:33 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-11-14 15:30:33 (GMT) |
commit | a519b87958da0b340caef48349d6e3c23c98e47e (patch) | |
tree | db7ddda2fae058c072c214bb3e8e58c11dc6bfa8 | |
parent | b11c443bb2ebfdd009e43ff208fa6324b658d15d (diff) | |
download | cpython-a519b87958da0b340caef48349d6e3c23c98e47e.zip cpython-a519b87958da0b340caef48349d6e3c23c98e47e.tar.gz cpython-a519b87958da0b340caef48349d6e3c23c98e47e.tar.bz2 |
GH-111848: Convert remaining jumps to deopts into tier 2 code. (GH-112045)
-rw-r--r-- | Include/internal/pycore_opcode_metadata.h | 142 | ||||
-rw-r--r-- | Lib/test/test_capi/test_misc.py | 10 | ||||
-rw-r--r-- | Python/abstract_interp_cases.c.h | 14 | ||||
-rw-r--r-- | Python/bytecodes.c | 35 | ||||
-rw-r--r-- | Python/executor_cases.c.h | 31 | ||||
-rw-r--r-- | Python/generated_cases.c.h | 16 | ||||
-rw-r--r-- | Python/optimizer.c | 65 |
7 files changed, 184 insertions, 129 deletions
diff --git a/Include/internal/pycore_opcode_metadata.h b/Include/internal/pycore_opcode_metadata.h index 2905641..69ac388 100644 --- a/Include/internal/pycore_opcode_metadata.h +++ b/Include/internal/pycore_opcode_metadata.h @@ -76,46 +76,50 @@ #define _STORE_ATTR_SLOT 348 #define _SPECIALIZE_COMPARE_OP 349 #define _COMPARE_OP 350 -#define _IS_NONE 351 -#define _SPECIALIZE_FOR_ITER 352 -#define _FOR_ITER 353 -#define _ITER_CHECK_LIST 354 -#define _ITER_JUMP_LIST 355 -#define _GUARD_NOT_EXHAUSTED_LIST 356 -#define _ITER_NEXT_LIST 357 -#define _ITER_CHECK_TUPLE 358 -#define _ITER_JUMP_TUPLE 359 -#define _GUARD_NOT_EXHAUSTED_TUPLE 360 -#define _ITER_NEXT_TUPLE 361 -#define _ITER_CHECK_RANGE 362 -#define _ITER_JUMP_RANGE 363 -#define _GUARD_NOT_EXHAUSTED_RANGE 364 -#define _ITER_NEXT_RANGE 365 -#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT 366 -#define _GUARD_KEYS_VERSION 367 -#define _LOAD_ATTR_METHOD_WITH_VALUES 368 -#define _LOAD_ATTR_METHOD_NO_DICT 369 -#define _LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES 370 -#define _LOAD_ATTR_NONDESCRIPTOR_NO_DICT 371 -#define _CHECK_ATTR_METHOD_LAZY_DICT 372 -#define _LOAD_ATTR_METHOD_LAZY_DICT 373 -#define _SPECIALIZE_CALL 374 -#define _CALL 375 -#define _CHECK_CALL_BOUND_METHOD_EXACT_ARGS 376 -#define _INIT_CALL_BOUND_METHOD_EXACT_ARGS 377 -#define _CHECK_PEP_523 378 -#define _CHECK_FUNCTION_EXACT_ARGS 379 -#define _CHECK_STACK_SPACE 380 -#define _INIT_CALL_PY_EXACT_ARGS 381 -#define _PUSH_FRAME 382 -#define _SPECIALIZE_BINARY_OP 383 -#define _BINARY_OP 384 -#define _POP_JUMP_IF_FALSE 385 -#define _POP_JUMP_IF_TRUE 386 -#define _JUMP_TO_TOP 387 -#define _SAVE_RETURN_OFFSET 388 -#define _INSERT 389 -#define _CHECK_VALIDITY 390 +#define _POP_JUMP_IF_FALSE 351 +#define _POP_JUMP_IF_TRUE 352 +#define _IS_NONE 353 +#define _SPECIALIZE_FOR_ITER 354 +#define _FOR_ITER 355 +#define _ITER_CHECK_LIST 356 +#define _ITER_JUMP_LIST 357 +#define _GUARD_NOT_EXHAUSTED_LIST 358 +#define _ITER_NEXT_LIST 359 +#define _ITER_CHECK_TUPLE 360 +#define _ITER_JUMP_TUPLE 361 +#define _GUARD_NOT_EXHAUSTED_TUPLE 362 +#define _ITER_NEXT_TUPLE 363 +#define _ITER_CHECK_RANGE 364 +#define _ITER_JUMP_RANGE 365 +#define _GUARD_NOT_EXHAUSTED_RANGE 366 +#define _ITER_NEXT_RANGE 367 +#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT 368 +#define _GUARD_KEYS_VERSION 369 +#define _LOAD_ATTR_METHOD_WITH_VALUES 370 +#define _LOAD_ATTR_METHOD_NO_DICT 371 +#define _LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES 372 +#define _LOAD_ATTR_NONDESCRIPTOR_NO_DICT 373 +#define _CHECK_ATTR_METHOD_LAZY_DICT 374 +#define _LOAD_ATTR_METHOD_LAZY_DICT 375 +#define _SPECIALIZE_CALL 376 +#define _CALL 377 +#define _CHECK_CALL_BOUND_METHOD_EXACT_ARGS 378 +#define _INIT_CALL_BOUND_METHOD_EXACT_ARGS 379 +#define _CHECK_PEP_523 380 +#define _CHECK_FUNCTION_EXACT_ARGS 381 +#define _CHECK_STACK_SPACE 382 +#define _INIT_CALL_PY_EXACT_ARGS 383 +#define _PUSH_FRAME 384 +#define _SPECIALIZE_BINARY_OP 385 +#define _BINARY_OP 386 +#define _GUARD_IS_TRUE_POP 387 +#define _GUARD_IS_FALSE_POP 388 +#define _GUARD_IS_NONE_POP 389 +#define _GUARD_IS_NOT_NONE_POP 390 +#define _JUMP_TO_TOP 391 +#define _SAVE_RETURN_OFFSET 392 +#define _INSERT 393 +#define _CHECK_VALIDITY 394 extern int _PyOpcode_num_popped(int opcode, int oparg, bool jump); #ifdef NEED_OPCODE_METADATA @@ -505,12 +509,16 @@ int _PyOpcode_num_popped(int opcode, int oparg, bool jump) { return 0; case ENTER_EXECUTOR: return 0; - case POP_JUMP_IF_FALSE: + case _POP_JUMP_IF_FALSE: return 1; - case POP_JUMP_IF_TRUE: + case _POP_JUMP_IF_TRUE: return 1; case _IS_NONE: return 1; + case POP_JUMP_IF_TRUE: + return 1; + case POP_JUMP_IF_FALSE: + return 1; case POP_JUMP_IF_NONE: return 1; case POP_JUMP_IF_NOT_NONE: @@ -725,9 +733,13 @@ int _PyOpcode_num_popped(int opcode, int oparg, bool jump) { return 0; case RESERVED: return 0; - case _POP_JUMP_IF_FALSE: + case _GUARD_IS_TRUE_POP: return 1; - case _POP_JUMP_IF_TRUE: + case _GUARD_IS_FALSE_POP: + return 1; + case _GUARD_IS_NONE_POP: + return 1; + case _GUARD_IS_NOT_NONE_POP: return 1; case _JUMP_TO_TOP: return 0; @@ -1135,12 +1147,16 @@ int _PyOpcode_num_pushed(int opcode, int oparg, bool jump) { return 0; case ENTER_EXECUTOR: return 0; - case POP_JUMP_IF_FALSE: + case _POP_JUMP_IF_FALSE: return 0; - case POP_JUMP_IF_TRUE: + case _POP_JUMP_IF_TRUE: return 0; case _IS_NONE: return 1; + case POP_JUMP_IF_TRUE: + return 0; + case POP_JUMP_IF_FALSE: + return 0; case POP_JUMP_IF_NONE: return 0; case POP_JUMP_IF_NOT_NONE: @@ -1355,9 +1371,13 @@ int _PyOpcode_num_pushed(int opcode, int oparg, bool jump) { return 0; case RESERVED: return 0; - case _POP_JUMP_IF_FALSE: + case _GUARD_IS_TRUE_POP: return 0; - case _POP_JUMP_IF_TRUE: + case _GUARD_IS_FALSE_POP: + return 0; + case _GUARD_IS_NONE_POP: + return 0; + case _GUARD_IS_NOT_NONE_POP: return 0; case _JUMP_TO_TOP: return 0; @@ -1639,9 +1659,11 @@ const struct opcode_metadata _PyOpcode_opcode_metadata[OPCODE_METADATA_SIZE] = { [JUMP] = { true, 0, HAS_ARG_FLAG | HAS_JUMP_FLAG }, [JUMP_NO_INTERRUPT] = { true, 0, HAS_ARG_FLAG | HAS_JUMP_FLAG }, [ENTER_EXECUTOR] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_JUMP_FLAG | HAS_EVAL_BREAK_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, - [POP_JUMP_IF_FALSE] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_JUMP_FLAG | HAS_ESCAPES_FLAG }, - [POP_JUMP_IF_TRUE] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_JUMP_FLAG | HAS_ESCAPES_FLAG }, + [_POP_JUMP_IF_FALSE] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_JUMP_FLAG | HAS_ESCAPES_FLAG }, + [_POP_JUMP_IF_TRUE] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_JUMP_FLAG | HAS_ESCAPES_FLAG }, [_IS_NONE] = { true, INSTR_FMT_IX, HAS_ESCAPES_FLAG }, + [POP_JUMP_IF_TRUE] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_JUMP_FLAG | HAS_ESCAPES_FLAG }, + [POP_JUMP_IF_FALSE] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_JUMP_FLAG | HAS_ESCAPES_FLAG }, [POP_JUMP_IF_NONE] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_JUMP_FLAG | HAS_ESCAPES_FLAG }, [POP_JUMP_IF_NOT_NONE] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_JUMP_FLAG | HAS_ESCAPES_FLAG }, [JUMP_BACKWARD_NO_INTERRUPT] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_JUMP_FLAG }, @@ -1749,8 +1771,10 @@ const struct opcode_metadata _PyOpcode_opcode_metadata[OPCODE_METADATA_SIZE] = { [EXTENDED_ARG] = { true, INSTR_FMT_IB, HAS_ARG_FLAG }, [CACHE] = { true, INSTR_FMT_IX, HAS_ESCAPES_FLAG }, [RESERVED] = { true, INSTR_FMT_IX, HAS_ESCAPES_FLAG }, - [_POP_JUMP_IF_FALSE] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ESCAPES_FLAG }, - [_POP_JUMP_IF_TRUE] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ESCAPES_FLAG }, + [_GUARD_IS_TRUE_POP] = { true, INSTR_FMT_IX, HAS_DEOPT_FLAG | HAS_ESCAPES_FLAG }, + [_GUARD_IS_FALSE_POP] = { true, INSTR_FMT_IX, HAS_DEOPT_FLAG | HAS_ESCAPES_FLAG }, + [_GUARD_IS_NONE_POP] = { true, INSTR_FMT_IX, HAS_DEOPT_FLAG | HAS_ESCAPES_FLAG }, + [_GUARD_IS_NOT_NONE_POP] = { true, INSTR_FMT_IX, HAS_DEOPT_FLAG | HAS_ESCAPES_FLAG }, [_JUMP_TO_TOP] = { true, INSTR_FMT_IX, HAS_EVAL_BREAK_FLAG }, [_SET_IP] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ESCAPES_FLAG }, [_SAVE_RETURN_OFFSET] = { true, INSTR_FMT_IB, HAS_ARG_FLAG }, @@ -1871,6 +1895,10 @@ const struct opcode_macro_expansion _PyOpcode_macro_expansion[OPCODE_MACRO_EXPAN [CONTAINS_OP] = { .nuops = 1, .uops = { { CONTAINS_OP, 0, 0 } } }, [CHECK_EG_MATCH] = { .nuops = 1, .uops = { { CHECK_EG_MATCH, 0, 0 } } }, [CHECK_EXC_MATCH] = { .nuops = 1, .uops = { { CHECK_EXC_MATCH, 0, 0 } } }, + [POP_JUMP_IF_TRUE] = { .nuops = 1, .uops = { { _POP_JUMP_IF_TRUE, 0, 0 } } }, + [POP_JUMP_IF_FALSE] = { .nuops = 1, .uops = { { _POP_JUMP_IF_FALSE, 0, 0 } } }, + [POP_JUMP_IF_NONE] = { .nuops = 2, .uops = { { _IS_NONE, 0, 0 }, { _POP_JUMP_IF_TRUE, 0, 0 } } }, + [POP_JUMP_IF_NOT_NONE] = { .nuops = 2, .uops = { { _IS_NONE, 0, 0 }, { _POP_JUMP_IF_FALSE, 0, 0 } } }, [GET_LEN] = { .nuops = 1, .uops = { { GET_LEN, 0, 0 } } }, [MATCH_CLASS] = { .nuops = 1, .uops = { { MATCH_CLASS, 0, 0 } } }, [MATCH_MAPPING] = { .nuops = 1, .uops = { { MATCH_MAPPING, 0, 0 } } }, @@ -1972,6 +2000,8 @@ const char * const _PyOpcode_uop_name[OPCODE_UOP_NAME_SIZE] = { [_STORE_ATTR_SLOT] = "_STORE_ATTR_SLOT", [_SPECIALIZE_COMPARE_OP] = "_SPECIALIZE_COMPARE_OP", [_COMPARE_OP] = "_COMPARE_OP", + [_POP_JUMP_IF_FALSE] = "_POP_JUMP_IF_FALSE", + [_POP_JUMP_IF_TRUE] = "_POP_JUMP_IF_TRUE", [_IS_NONE] = "_IS_NONE", [_SPECIALIZE_FOR_ITER] = "_SPECIALIZE_FOR_ITER", [_FOR_ITER] = "_FOR_ITER", @@ -2006,8 +2036,10 @@ const char * const _PyOpcode_uop_name[OPCODE_UOP_NAME_SIZE] = { [_PUSH_FRAME] = "_PUSH_FRAME", [_SPECIALIZE_BINARY_OP] = "_SPECIALIZE_BINARY_OP", [_BINARY_OP] = "_BINARY_OP", - [_POP_JUMP_IF_FALSE] = "_POP_JUMP_IF_FALSE", - [_POP_JUMP_IF_TRUE] = "_POP_JUMP_IF_TRUE", + [_GUARD_IS_TRUE_POP] = "_GUARD_IS_TRUE_POP", + [_GUARD_IS_FALSE_POP] = "_GUARD_IS_FALSE_POP", + [_GUARD_IS_NONE_POP] = "_GUARD_IS_NONE_POP", + [_GUARD_IS_NOT_NONE_POP] = "_GUARD_IS_NOT_NONE_POP", [_JUMP_TO_TOP] = "_JUMP_TO_TOP", [_SAVE_RETURN_OFFSET] = "_SAVE_RETURN_OFFSET", [_INSERT] = "_INSERT", @@ -2256,8 +2288,8 @@ const uint8_t _PyOpcode_Caches[256] = { [LOAD_ATTR] = 9, [COMPARE_OP] = 1, [JUMP_BACKWARD] = 1, - [POP_JUMP_IF_FALSE] = 1, [POP_JUMP_IF_TRUE] = 1, + [POP_JUMP_IF_FALSE] = 1, [POP_JUMP_IF_NONE] = 1, [POP_JUMP_IF_NOT_NONE] = 1, [FOR_ITER] = 1, diff --git a/Lib/test/test_capi/test_misc.py b/Lib/test/test_capi/test_misc.py index d526bbf..fe5c36c 100644 --- a/Lib/test/test_capi/test_misc.py +++ b/Lib/test/test_capi/test_misc.py @@ -2610,7 +2610,7 @@ class TestUops(unittest.TestCase): ex = get_first_executor(testfunc) self.assertIsNotNone(ex) uops = {opname for opname, _, _ in ex} - self.assertIn("_POP_JUMP_IF_FALSE", uops) + self.assertIn("_GUARD_IS_TRUE_POP", uops) def test_pop_jump_if_none(self): def testfunc(a): @@ -2625,7 +2625,7 @@ class TestUops(unittest.TestCase): ex = get_first_executor(testfunc) self.assertIsNotNone(ex) uops = {opname for opname, _, _ in ex} - self.assertIn("_POP_JUMP_IF_TRUE", uops) + self.assertIn("_GUARD_IS_NOT_NONE_POP", uops) def test_pop_jump_if_not_none(self): def testfunc(a): @@ -2641,7 +2641,7 @@ class TestUops(unittest.TestCase): ex = get_first_executor(testfunc) self.assertIsNotNone(ex) uops = {opname for opname, _, _ in ex} - self.assertIn("_POP_JUMP_IF_FALSE", uops) + self.assertIn("_GUARD_IS_NONE_POP", uops) def test_pop_jump_if_true(self): def testfunc(n): @@ -2656,7 +2656,7 @@ class TestUops(unittest.TestCase): ex = get_first_executor(testfunc) self.assertIsNotNone(ex) uops = {opname for opname, _, _ in ex} - self.assertIn("_POP_JUMP_IF_TRUE", uops) + self.assertIn("_GUARD_IS_FALSE_POP", uops) def test_jump_backward(self): def testfunc(n): @@ -2806,7 +2806,7 @@ class TestUops(unittest.TestCase): ex = get_first_executor(testfunc) self.assertIsNotNone(ex) uops = {opname for opname, _, _ in ex} - self.assertIn("_POP_JUMP_IF_TRUE", uops) + self.assertIn("_GUARD_IS_FALSE_POP", uops) if __name__ == "__main__": diff --git a/Python/abstract_interp_cases.c.h b/Python/abstract_interp_cases.c.h index 8892d26..a2f6aa8 100644 --- a/Python/abstract_interp_cases.c.h +++ b/Python/abstract_interp_cases.c.h @@ -914,12 +914,22 @@ break; } - case _POP_JUMP_IF_FALSE: { + case _GUARD_IS_TRUE_POP: { STACK_SHRINK(1); break; } - case _POP_JUMP_IF_TRUE: { + case _GUARD_IS_FALSE_POP: { + STACK_SHRINK(1); + break; + } + + case _GUARD_IS_NONE_POP: { + STACK_SHRINK(1); + break; + } + + case _GUARD_IS_NOT_NONE_POP: { STACK_SHRINK(1); break; } diff --git a/Python/bytecodes.c b/Python/bytecodes.c index bb8123e..8a7dcb8 100644 --- a/Python/bytecodes.c +++ b/Python/bytecodes.c @@ -2368,7 +2368,7 @@ dummy_func( goto enter_tier_one; } - inst(POP_JUMP_IF_FALSE, (unused/1, cond -- )) { + replaced op(_POP_JUMP_IF_FALSE, (unused/1, cond -- )) { assert(PyBool_Check(cond)); int flag = Py_IsFalse(cond); #if ENABLE_SPECIALIZATION @@ -2377,7 +2377,7 @@ dummy_func( JUMPBY(oparg * flag); } - inst(POP_JUMP_IF_TRUE, (unused/1, cond -- )) { + replaced op(_POP_JUMP_IF_TRUE, (unused/1, cond -- )) { assert(PyBool_Check(cond)); int flag = Py_IsTrue(cond); #if ENABLE_SPECIALIZATION @@ -2396,9 +2396,13 @@ dummy_func( } } - macro(POP_JUMP_IF_NONE) = _IS_NONE + POP_JUMP_IF_TRUE; + macro(POP_JUMP_IF_TRUE) = _POP_JUMP_IF_TRUE; - macro(POP_JUMP_IF_NOT_NONE) = _IS_NONE + POP_JUMP_IF_FALSE; + macro(POP_JUMP_IF_FALSE) = _POP_JUMP_IF_FALSE; + + macro(POP_JUMP_IF_NONE) = _IS_NONE + _POP_JUMP_IF_TRUE; + + macro(POP_JUMP_IF_NOT_NONE) = _IS_NONE + _POP_JUMP_IF_FALSE; inst(JUMP_BACKWARD_NO_INTERRUPT, (--)) { /* This bytecode is used in the `yield from` or `await` loop. @@ -3963,16 +3967,23 @@ dummy_func( ///////// Tier-2 only opcodes ///////// - op(_POP_JUMP_IF_FALSE, (flag -- )) { - if (Py_IsFalse(flag)) { - next_uop = current_executor->trace + oparg; - } + op (_GUARD_IS_TRUE_POP, (flag -- )) { + DEOPT_IF(Py_IsFalse(flag)); + assert(Py_IsTrue(flag)); } - op(_POP_JUMP_IF_TRUE, (flag -- )) { - if (Py_IsTrue(flag)) { - next_uop = current_executor->trace + oparg; - } + op (_GUARD_IS_FALSE_POP, (flag -- )) { + DEOPT_IF(Py_IsTrue(flag)); + assert(Py_IsFalse(flag)); + } + + op (_GUARD_IS_NONE_POP, (val -- )) { + DEOPT_IF(!Py_IsNone(val)); + } + + op (_GUARD_IS_NOT_NONE_POP, (val -- )) { + DEOPT_IF(Py_IsNone(val)); + Py_DECREF(val); } op(_JUMP_TO_TOP, (--)) { diff --git a/Python/executor_cases.c.h b/Python/executor_cases.c.h index ac542a5..4e29fb9 100644 --- a/Python/executor_cases.c.h +++ b/Python/executor_cases.c.h @@ -3185,22 +3185,37 @@ break; } - case _POP_JUMP_IF_FALSE: { + case _GUARD_IS_TRUE_POP: { PyObject *flag; flag = stack_pointer[-1]; - if (Py_IsFalse(flag)) { - next_uop = current_executor->trace + oparg; - } + DEOPT_IF(Py_IsFalse(flag), _GUARD_IS_TRUE_POP); + assert(Py_IsTrue(flag)); STACK_SHRINK(1); break; } - case _POP_JUMP_IF_TRUE: { + case _GUARD_IS_FALSE_POP: { PyObject *flag; flag = stack_pointer[-1]; - if (Py_IsTrue(flag)) { - next_uop = current_executor->trace + oparg; - } + DEOPT_IF(Py_IsTrue(flag), _GUARD_IS_FALSE_POP); + assert(Py_IsFalse(flag)); + STACK_SHRINK(1); + break; + } + + case _GUARD_IS_NONE_POP: { + PyObject *val; + val = stack_pointer[-1]; + DEOPT_IF(!Py_IsNone(val), _GUARD_IS_NONE_POP); + STACK_SHRINK(1); + break; + } + + case _GUARD_IS_NOT_NONE_POP: { + PyObject *val; + val = stack_pointer[-1]; + DEOPT_IF(Py_IsNone(val), _GUARD_IS_NOT_NONE_POP); + Py_DECREF(val); STACK_SHRINK(1); break; } diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h index 6cbc54c..fe0cbfe 100644 --- a/Python/generated_cases.c.h +++ b/Python/generated_cases.c.h @@ -3435,14 +3435,14 @@ goto enter_tier_one; } - TARGET(POP_JUMP_IF_FALSE) { + TARGET(POP_JUMP_IF_TRUE) { _Py_CODEUNIT *this_instr = frame->instr_ptr = next_instr; next_instr += 2; - INSTRUCTION_STATS(POP_JUMP_IF_FALSE); + INSTRUCTION_STATS(POP_JUMP_IF_TRUE); PyObject *cond; cond = stack_pointer[-1]; assert(PyBool_Check(cond)); - int flag = Py_IsFalse(cond); + int flag = Py_IsTrue(cond); #if ENABLE_SPECIALIZATION this_instr[1].cache = (this_instr[1].cache << 1) | flag; #endif @@ -3451,14 +3451,14 @@ DISPATCH(); } - TARGET(POP_JUMP_IF_TRUE) { + TARGET(POP_JUMP_IF_FALSE) { _Py_CODEUNIT *this_instr = frame->instr_ptr = next_instr; next_instr += 2; - INSTRUCTION_STATS(POP_JUMP_IF_TRUE); + INSTRUCTION_STATS(POP_JUMP_IF_FALSE); PyObject *cond; cond = stack_pointer[-1]; assert(PyBool_Check(cond)); - int flag = Py_IsTrue(cond); + int flag = Py_IsFalse(cond); #if ENABLE_SPECIALIZATION this_instr[1].cache = (this_instr[1].cache << 1) | flag; #endif @@ -3485,7 +3485,7 @@ Py_DECREF(value); } } - // POP_JUMP_IF_TRUE + // _POP_JUMP_IF_TRUE cond = b; { assert(PyBool_Check(cond)); @@ -3517,7 +3517,7 @@ Py_DECREF(value); } } - // POP_JUMP_IF_FALSE + // _POP_JUMP_IF_FALSE cond = b; { assert(PyBool_Check(cond)); diff --git a/Python/optimizer.c b/Python/optimizer.c index e142bd0..bc518d0 100644 --- a/Python/optimizer.c +++ b/Python/optimizer.c @@ -385,7 +385,7 @@ PyTypeObject _PyUOpExecutor_Type = { .tp_methods = executor_methods, }; -/* TO DO -- Generate this table */ +/* TO DO -- Generate these tables */ static const uint16_t _PyUop_Replacements[OPCODE_METADATA_SIZE] = { [_ITER_JUMP_RANGE] = _GUARD_NOT_EXHAUSTED_RANGE, @@ -393,6 +393,18 @@ _PyUop_Replacements[OPCODE_METADATA_SIZE] = { [_ITER_JUMP_TUPLE] = _GUARD_NOT_EXHAUSTED_TUPLE, }; +static const uint16_t +BRANCH_TO_GUARD[4][2] = { + [POP_JUMP_IF_FALSE - POP_JUMP_IF_FALSE][0] = _GUARD_IS_TRUE_POP, + [POP_JUMP_IF_FALSE - POP_JUMP_IF_FALSE][1] = _GUARD_IS_FALSE_POP, + [POP_JUMP_IF_TRUE - POP_JUMP_IF_FALSE][0] = _GUARD_IS_FALSE_POP, + [POP_JUMP_IF_TRUE - POP_JUMP_IF_FALSE][1] = _GUARD_IS_TRUE_POP, + [POP_JUMP_IF_NONE - POP_JUMP_IF_FALSE][0] = _GUARD_IS_NOT_NONE_POP, + [POP_JUMP_IF_NONE - POP_JUMP_IF_FALSE][1] = _GUARD_IS_NONE_POP, + [POP_JUMP_IF_NOT_NONE - POP_JUMP_IF_FALSE][0] = _GUARD_IS_NONE_POP, + [POP_JUMP_IF_NOT_NONE - POP_JUMP_IF_FALSE][1] = _GUARD_IS_NOT_NONE_POP, +}; + #define TRACE_STACK_SIZE 5 /* Returns 1 on success, @@ -528,45 +540,23 @@ top: // Jump here after _PUSH_FRAME or likely branches } switch (opcode) { - case POP_JUMP_IF_NONE: - { - RESERVE(2, 2); - ADD_TO_TRACE(_IS_NONE, 0, 0); - opcode = POP_JUMP_IF_TRUE; - goto pop_jump_if_bool; - } - case POP_JUMP_IF_NOT_NONE: - { - RESERVE(2, 2); - ADD_TO_TRACE(_IS_NONE, 0, 0); - opcode = POP_JUMP_IF_FALSE; - goto pop_jump_if_bool; - } - case POP_JUMP_IF_FALSE: case POP_JUMP_IF_TRUE: { -pop_jump_if_bool: - RESERVE(1, 2); - max_length -= 2; // Really the start of the stubs + RESERVE(1, 0); int counter = instr[1].cache; int bitcount = _Py_popcount32(counter); - bool jump_likely = bitcount > 8; - bool jump_sense = opcode == POP_JUMP_IF_TRUE; - uint32_t uopcode = jump_sense ^ jump_likely ? - _POP_JUMP_IF_TRUE : _POP_JUMP_IF_FALSE; + int jump_likely = bitcount > 8; + uint32_t uopcode = BRANCH_TO_GUARD[opcode - POP_JUMP_IF_FALSE][jump_likely]; _Py_CODEUNIT *next_instr = instr + 1 + _PyOpcode_Caches[_PyOpcode_Deopt[opcode]]; - _Py_CODEUNIT *target_instr = next_instr + oparg; - _Py_CODEUNIT *stub_target = jump_likely ? next_instr : target_instr; - DPRINTF(4, "%s(%d): counter=%x, bitcount=%d, likely=%d, sense=%d, uopcode=%s\n", + DPRINTF(4, "%s(%d): counter=%x, bitcount=%d, likely=%d, uopcode=%s\n", uop_name(opcode), oparg, - counter, bitcount, jump_likely, jump_sense, uop_name(uopcode)); + counter, bitcount, jump_likely, uop_name(uopcode)); ADD_TO_TRACE(uopcode, max_length, 0); - ADD_TO_STUB(max_length, _SET_IP, INSTR_IP(stub_target, code), 0); - ADD_TO_STUB(max_length + 1, _EXIT_TRACE, 0, 0); if (jump_likely) { + _Py_CODEUNIT *target_instr = next_instr + oparg; DPRINTF(2, "Jump likely (%x = %d bits), continue at byte offset %d\n", instr[1].cache, bitcount, 2 * INSTR_IP(target_instr, code)); instr = target_instr; @@ -797,16 +787,13 @@ compute_used(_PyUOpInstruction *buffer, uint32_t *used) } /* All other micro-ops fall through, so i+1 is reachable */ SET_BIT(used, i+1); - switch(opcode) { - case NOP: - /* Don't count NOPs as used */ - count--; - UNSET_BIT(used, i); - break; - case _POP_JUMP_IF_FALSE: - case _POP_JUMP_IF_TRUE: - /* Mark target as reachable */ - SET_BIT(used, buffer[i].oparg); + if (OPCODE_HAS_JUMP(opcode)) { + /* Mark target as reachable */ + SET_BIT(used, buffer[i].oparg); + } + if (opcode == NOP) { + count--; + UNSET_BIT(used, i); } } return count; |