diff options
| author | Mark Shannon <mark@hotpy.org> | 2024-01-24 12:08:31 (GMT) |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-01-24 12:08:31 (GMT) |
| commit | 384429d1c0cf011dcf88d4043e0328de8b063c24 (patch) | |
| tree | d3b325f08d9359bce60065b162ddec3572b08662 /Python | |
| parent | 1e4f00ebd8db44a031b61eed0803b4c3d731aed7 (diff) | |
| download | cpython-384429d1c0cf011dcf88d4043e0328de8b063c24.zip cpython-384429d1c0cf011dcf88d4043e0328de8b063c24.tar.gz cpython-384429d1c0cf011dcf88d4043e0328de8b063c24.tar.bz2 | |
GH-113710: Add a tier 2 peephole optimization pass. (GH-114487)
* Convert _LOAD_CONST to inline versions
* Remove PEP 523 checks
Diffstat (limited to 'Python')
| -rw-r--r-- | Python/bytecodes.c | 4 | ||||
| -rw-r--r-- | Python/executor_cases.c.h | 9 | ||||
| -rw-r--r-- | Python/optimizer.c | 6 | ||||
| -rw-r--r-- | Python/optimizer_analysis.c | 34 | ||||
| -rw-r--r-- | Python/pystate.c | 10 |
5 files changed, 60 insertions, 3 deletions
diff --git a/Python/bytecodes.c b/Python/bytecodes.c index 7674ff8..18749ce 100644 --- a/Python/bytecodes.c +++ b/Python/bytecodes.c @@ -4070,6 +4070,10 @@ dummy_func( DEOPT_IF(!current_executor->vm_data.valid); } + op(_LOAD_CONST_INLINE, (ptr/4 -- value)) { + value = Py_NewRef(ptr); + } + op(_LOAD_CONST_INLINE_BORROW, (ptr/4 -- value)) { value = ptr; } diff --git a/Python/executor_cases.c.h b/Python/executor_cases.c.h index 2b4399b..241b905 100644 --- a/Python/executor_cases.c.h +++ b/Python/executor_cases.c.h @@ -3390,6 +3390,15 @@ break; } + case _LOAD_CONST_INLINE: { + PyObject *value; + PyObject *ptr = (PyObject *)CURRENT_OPERAND(); + value = Py_NewRef(ptr); + stack_pointer[0] = value; + stack_pointer += 1; + break; + } + case _LOAD_CONST_INLINE_BORROW: { PyObject *value; PyObject *ptr = (PyObject *)CURRENT_OPERAND(); diff --git a/Python/optimizer.c b/Python/optimizer.c index 1551a5e..4b6ed17 100644 --- a/Python/optimizer.c +++ b/Python/optimizer.c @@ -588,6 +588,9 @@ top: // Jump here after _PUSH_FRAME or likely branches ADD_TO_TRACE(uop, oparg, operand, target); if (uop == _POP_FRAME) { TRACE_STACK_POP(); + /* Set the operand to the code object returned to, + * to assist optimization passes */ + trace[trace_length-1].operand = (uintptr_t)code; DPRINTF(2, "Returning to %s (%s:%d) at byte offset %d\n", PyUnicode_AsUTF8(code->co_qualname), @@ -629,6 +632,9 @@ top: // Jump here after _PUSH_FRAME or likely branches instr += _PyOpcode_Caches[_PyOpcode_Deopt[opcode]] + 1; TRACE_STACK_PUSH(); _Py_BloomFilter_Add(dependencies, new_code); + /* Set the operand to the callee's code object, + * to assist optimization passes */ + trace[trace_length-1].operand = (uintptr_t)new_code; code = new_code; instr = _PyCode_CODE(code); DPRINTF(2, diff --git a/Python/optimizer_analysis.c b/Python/optimizer_analysis.c index 7db51f0..d122599 100644 --- a/Python/optimizer_analysis.c +++ b/Python/optimizer_analysis.c @@ -13,6 +13,39 @@ #include "pycore_optimizer.h" static void +peephole_opt(PyCodeObject *co, _PyUOpInstruction *buffer, int buffer_size) +{ + for (int pc = 0; pc < buffer_size; pc++) { + int opcode = buffer[pc].opcode; + switch(opcode) { + case _LOAD_CONST: { + assert(co != NULL); + PyObject *val = PyTuple_GET_ITEM(co->co_consts, buffer[pc].oparg); + buffer[pc].opcode = _Py_IsImmortal(val) ? _LOAD_CONST_INLINE_BORROW : _LOAD_CONST_INLINE; + buffer[pc].operand = (uintptr_t)val; + break; + } + case _CHECK_PEP_523: + { + /* Setting the eval frame function invalidates + * all executors, so no need to check dynamically */ + if (_PyInterpreterState_GET()->eval_frame == NULL) { + buffer[pc].opcode = _NOP; + } + break; + } + case _PUSH_FRAME: + case _POP_FRAME: + co = (PyCodeObject *)buffer[pc].operand; + break; + case _JUMP_TO_TOP: + case _EXIT_TRACE: + return; + } + } +} + +static void remove_unneeded_uops(_PyUOpInstruction *buffer, int buffer_size) { int last_set_ip = -1; @@ -59,6 +92,7 @@ _Py_uop_analyze_and_optimize( int curr_stacklen ) { + peephole_opt(co, buffer, buffer_size); remove_unneeded_uops(buffer, buffer_size); return 0; } diff --git a/Python/pystate.c b/Python/pystate.c index 23ddc78..548c77b 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -2608,11 +2608,15 @@ _PyInterpreterState_SetEvalFrameFunc(PyInterpreterState *interp, _PyFrameEvalFunction eval_frame) { if (eval_frame == _PyEval_EvalFrameDefault) { - interp->eval_frame = NULL; + eval_frame = NULL; } - else { - interp->eval_frame = eval_frame; + if (eval_frame == interp->eval_frame) { + return; + } + if (eval_frame != NULL) { + _Py_Executors_InvalidateAll(interp); } + interp->eval_frame = eval_frame; } |
