mirror of
https://github.com/python/cpython.git
synced 2025-09-26 10:19:53 +00:00
gh-106529: Support JUMP_BACKWARD in Tier 2 (uops) (#106543)
During superblock generation, a JUMP_BACKWARD instruction is translated to either a JUMP_TO_TOP micro-op (when the target of the jump is exactly the beginning of the superblock, closing the loop), or a SAVE_IP + EXIT_TRACE pair, when the jump goes elsewhere. The new JUMP_TO_TOP instruction includes a CHECK_EVAL_BREAKER() call, so a closed loop can still be interrupted.
This commit is contained in:
parent
292ac4bfe9
commit
cabd6e8a10
5 changed files with 63 additions and 30 deletions
|
@ -2525,7 +2525,6 @@ class TestUops(unittest.TestCase):
|
||||||
i += 1
|
i += 1
|
||||||
|
|
||||||
opt = _testinternalcapi.get_uop_optimizer()
|
opt = _testinternalcapi.get_uop_optimizer()
|
||||||
|
|
||||||
with temporary_optimizer(opt):
|
with temporary_optimizer(opt):
|
||||||
testfunc(10)
|
testfunc(10)
|
||||||
|
|
||||||
|
@ -2541,7 +2540,6 @@ class TestUops(unittest.TestCase):
|
||||||
i += 1
|
i += 1
|
||||||
|
|
||||||
opt = _testinternalcapi.get_uop_optimizer()
|
opt = _testinternalcapi.get_uop_optimizer()
|
||||||
|
|
||||||
with temporary_optimizer(opt):
|
with temporary_optimizer(opt):
|
||||||
testfunc(10)
|
testfunc(10)
|
||||||
|
|
||||||
|
@ -2550,6 +2548,20 @@ class TestUops(unittest.TestCase):
|
||||||
uops = {opname for opname, _ in ex}
|
uops = {opname for opname, _ in ex}
|
||||||
self.assertIn("_POP_JUMP_IF_TRUE", uops)
|
self.assertIn("_POP_JUMP_IF_TRUE", uops)
|
||||||
|
|
||||||
|
def test_jump_backward(self):
|
||||||
|
def testfunc(n):
|
||||||
|
i = 0
|
||||||
|
while i < n:
|
||||||
|
i += 1
|
||||||
|
opt = _testinternalcapi.get_uop_optimizer()
|
||||||
|
with temporary_optimizer(opt):
|
||||||
|
testfunc(10)
|
||||||
|
|
||||||
|
ex = get_first_executor(testfunc)
|
||||||
|
self.assertIsNotNone(ex)
|
||||||
|
uops = {opname for opname, _ in ex}
|
||||||
|
self.assertIn("JUMP_TO_TOP", uops)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|
|
@ -2783,6 +2783,13 @@ _PyUopExecute(_PyExecutorObject *executor, _PyInterpreterFrame *frame, PyObject
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case JUMP_TO_TOP:
|
||||||
|
{
|
||||||
|
pc = 0;
|
||||||
|
CHECK_EVAL_BREAKER();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case SAVE_IP:
|
case SAVE_IP:
|
||||||
{
|
{
|
||||||
frame->prev_instr = ip_offset + oparg;
|
frame->prev_instr = ip_offset + oparg;
|
||||||
|
|
54
Python/opcode_metadata.h
generated
54
Python/opcode_metadata.h
generated
|
@ -23,19 +23,20 @@
|
||||||
#define SAVE_IP 301
|
#define SAVE_IP 301
|
||||||
#define _POP_JUMP_IF_FALSE 302
|
#define _POP_JUMP_IF_FALSE 302
|
||||||
#define _POP_JUMP_IF_TRUE 303
|
#define _POP_JUMP_IF_TRUE 303
|
||||||
#define _GUARD_BOTH_INT 304
|
#define JUMP_TO_TOP 304
|
||||||
#define _BINARY_OP_MULTIPLY_INT 305
|
#define _GUARD_BOTH_INT 305
|
||||||
#define _BINARY_OP_ADD_INT 306
|
#define _BINARY_OP_MULTIPLY_INT 306
|
||||||
#define _BINARY_OP_SUBTRACT_INT 307
|
#define _BINARY_OP_ADD_INT 307
|
||||||
#define _GUARD_BOTH_FLOAT 308
|
#define _BINARY_OP_SUBTRACT_INT 308
|
||||||
#define _BINARY_OP_MULTIPLY_FLOAT 309
|
#define _GUARD_BOTH_FLOAT 309
|
||||||
#define _BINARY_OP_ADD_FLOAT 310
|
#define _BINARY_OP_MULTIPLY_FLOAT 310
|
||||||
#define _BINARY_OP_SUBTRACT_FLOAT 311
|
#define _BINARY_OP_ADD_FLOAT 311
|
||||||
#define _GUARD_BOTH_UNICODE 312
|
#define _BINARY_OP_SUBTRACT_FLOAT 312
|
||||||
#define _BINARY_OP_ADD_UNICODE 313
|
#define _GUARD_BOTH_UNICODE 313
|
||||||
#define _LOAD_LOCALS 314
|
#define _BINARY_OP_ADD_UNICODE 314
|
||||||
#define _LOAD_FROM_DICT_OR_GLOBALS 315
|
#define _LOAD_LOCALS 315
|
||||||
#define IS_NONE 316
|
#define _LOAD_FROM_DICT_OR_GLOBALS 316
|
||||||
|
#define IS_NONE 317
|
||||||
|
|
||||||
#ifndef NEED_OPCODE_METADATA
|
#ifndef NEED_OPCODE_METADATA
|
||||||
extern int _PyOpcode_num_popped(int opcode, int oparg, bool jump);
|
extern int _PyOpcode_num_popped(int opcode, int oparg, bool jump);
|
||||||
|
@ -1298,18 +1299,19 @@ const char * const _PyOpcode_uop_name[512] = {
|
||||||
[301] = "SAVE_IP",
|
[301] = "SAVE_IP",
|
||||||
[302] = "_POP_JUMP_IF_FALSE",
|
[302] = "_POP_JUMP_IF_FALSE",
|
||||||
[303] = "_POP_JUMP_IF_TRUE",
|
[303] = "_POP_JUMP_IF_TRUE",
|
||||||
[304] = "_GUARD_BOTH_INT",
|
[304] = "JUMP_TO_TOP",
|
||||||
[305] = "_BINARY_OP_MULTIPLY_INT",
|
[305] = "_GUARD_BOTH_INT",
|
||||||
[306] = "_BINARY_OP_ADD_INT",
|
[306] = "_BINARY_OP_MULTIPLY_INT",
|
||||||
[307] = "_BINARY_OP_SUBTRACT_INT",
|
[307] = "_BINARY_OP_ADD_INT",
|
||||||
[308] = "_GUARD_BOTH_FLOAT",
|
[308] = "_BINARY_OP_SUBTRACT_INT",
|
||||||
[309] = "_BINARY_OP_MULTIPLY_FLOAT",
|
[309] = "_GUARD_BOTH_FLOAT",
|
||||||
[310] = "_BINARY_OP_ADD_FLOAT",
|
[310] = "_BINARY_OP_MULTIPLY_FLOAT",
|
||||||
[311] = "_BINARY_OP_SUBTRACT_FLOAT",
|
[311] = "_BINARY_OP_ADD_FLOAT",
|
||||||
[312] = "_GUARD_BOTH_UNICODE",
|
[312] = "_BINARY_OP_SUBTRACT_FLOAT",
|
||||||
[313] = "_BINARY_OP_ADD_UNICODE",
|
[313] = "_GUARD_BOTH_UNICODE",
|
||||||
[314] = "_LOAD_LOCALS",
|
[314] = "_BINARY_OP_ADD_UNICODE",
|
||||||
[315] = "_LOAD_FROM_DICT_OR_GLOBALS",
|
[315] = "_LOAD_LOCALS",
|
||||||
[316] = "IS_NONE",
|
[316] = "_LOAD_FROM_DICT_OR_GLOBALS",
|
||||||
|
[317] = "IS_NONE",
|
||||||
};
|
};
|
||||||
#endif // NEED_OPCODE_METADATA
|
#endif // NEED_OPCODE_METADATA
|
||||||
|
|
|
@ -372,9 +372,7 @@ translate_bytecode_to_trace(
|
||||||
_PyUOpInstruction *trace,
|
_PyUOpInstruction *trace,
|
||||||
int buffer_size)
|
int buffer_size)
|
||||||
{
|
{
|
||||||
#ifdef Py_DEBUG
|
|
||||||
_Py_CODEUNIT *initial_instr = instr;
|
_Py_CODEUNIT *initial_instr = instr;
|
||||||
#endif
|
|
||||||
int trace_length = 0;
|
int trace_length = 0;
|
||||||
int max_length = buffer_size;
|
int max_length = buffer_size;
|
||||||
|
|
||||||
|
@ -456,6 +454,19 @@ translate_bytecode_to_trace(
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case JUMP_BACKWARD:
|
||||||
|
{
|
||||||
|
if (instr + 2 - oparg == initial_instr
|
||||||
|
&& trace_length + 3 <= max_length)
|
||||||
|
{
|
||||||
|
ADD_TO_TRACE(JUMP_TO_TOP, 0);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
DPRINTF(2, "JUMP_BACKWARD not to top ends trace\n");
|
||||||
|
}
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
const struct opcode_macro_expansion *expansion = &_PyOpcode_macro_expansion[opcode];
|
const struct opcode_macro_expansion *expansion = &_PyOpcode_macro_expansion[opcode];
|
||||||
|
|
|
@ -1346,6 +1346,7 @@ class Analyzer:
|
||||||
add("SAVE_IP")
|
add("SAVE_IP")
|
||||||
add("_POP_JUMP_IF_FALSE")
|
add("_POP_JUMP_IF_FALSE")
|
||||||
add("_POP_JUMP_IF_TRUE")
|
add("_POP_JUMP_IF_TRUE")
|
||||||
|
add("JUMP_TO_TOP")
|
||||||
|
|
||||||
for instr in self.instrs.values():
|
for instr in self.instrs.values():
|
||||||
if instr.kind == "op" and instr.is_viable_uop():
|
if instr.kind == "op" and instr.is_viable_uop():
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue