Skip to content

Commit 384429d

Browse files
authored
GH-113710: Add a tier 2 peephole optimization pass. (GH-114487)
* Convert _LOAD_CONST to inline versions * Remove PEP 523 checks
1 parent 1e4f00e commit 384429d

File tree

7 files changed

+66
-6
lines changed

7 files changed

+66
-6
lines changed

Include/internal/pycore_uop_ids.h

Lines changed: 4 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Include/internal/pycore_uop_metadata.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,7 @@ const uint16_t _PyUop_Flags[MAX_UOP_ID+1] = {
202202
[_SAVE_RETURN_OFFSET] = HAS_ARG_FLAG,
203203
[_EXIT_TRACE] = HAS_DEOPT_FLAG,
204204
[_CHECK_VALIDITY] = HAS_DEOPT_FLAG,
205+
[_LOAD_CONST_INLINE] = 0,
205206
[_LOAD_CONST_INLINE_BORROW] = 0,
206207
[_INTERNAL_INCREMENT_OPT_COUNTER] = 0,
207208
};
@@ -329,6 +330,7 @@ const char *const _PyOpcode_uop_name[MAX_UOP_ID+1] = {
329330
[_LOAD_ATTR_WITH_HINT] = "_LOAD_ATTR_WITH_HINT",
330331
[_LOAD_BUILD_CLASS] = "_LOAD_BUILD_CLASS",
331332
[_LOAD_CONST] = "_LOAD_CONST",
333+
[_LOAD_CONST_INLINE] = "_LOAD_CONST_INLINE",
332334
[_LOAD_CONST_INLINE_BORROW] = "_LOAD_CONST_INLINE_BORROW",
333335
[_LOAD_DEREF] = "_LOAD_DEREF",
334336
[_LOAD_FAST] = "_LOAD_FAST",

Python/bytecodes.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4070,6 +4070,10 @@ dummy_func(
40704070
DEOPT_IF(!current_executor->vm_data.valid);
40714071
}
40724072

4073+
op(_LOAD_CONST_INLINE, (ptr/4 -- value)) {
4074+
value = Py_NewRef(ptr);
4075+
}
4076+
40734077
op(_LOAD_CONST_INLINE_BORROW, (ptr/4 -- value)) {
40744078
value = ptr;
40754079
}

Python/executor_cases.c.h

Lines changed: 9 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Python/optimizer.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -588,6 +588,9 @@ translate_bytecode_to_trace(
588588
ADD_TO_TRACE(uop, oparg, operand, target);
589589
if (uop == _POP_FRAME) {
590590
TRACE_STACK_POP();
591+
/* Set the operand to the code object returned to,
592+
* to assist optimization passes */
593+
trace[trace_length-1].operand = (uintptr_t)code;
591594
DPRINTF(2,
592595
"Returning to %s (%s:%d) at byte offset %d\n",
593596
PyUnicode_AsUTF8(code->co_qualname),
@@ -629,6 +632,9 @@ translate_bytecode_to_trace(
629632
instr += _PyOpcode_Caches[_PyOpcode_Deopt[opcode]] + 1;
630633
TRACE_STACK_PUSH();
631634
_Py_BloomFilter_Add(dependencies, new_code);
635+
/* Set the operand to the callee's code object,
636+
* to assist optimization passes */
637+
trace[trace_length-1].operand = (uintptr_t)new_code;
632638
code = new_code;
633639
instr = _PyCode_CODE(code);
634640
DPRINTF(2,

Python/optimizer_analysis.c

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,39 @@
1212
#include <stddef.h>
1313
#include "pycore_optimizer.h"
1414

15+
static void
16+
peephole_opt(PyCodeObject *co, _PyUOpInstruction *buffer, int buffer_size)
17+
{
18+
for (int pc = 0; pc < buffer_size; pc++) {
19+
int opcode = buffer[pc].opcode;
20+
switch(opcode) {
21+
case _LOAD_CONST: {
22+
assert(co != NULL);
23+
PyObject *val = PyTuple_GET_ITEM(co->co_consts, buffer[pc].oparg);
24+
buffer[pc].opcode = _Py_IsImmortal(val) ? _LOAD_CONST_INLINE_BORROW : _LOAD_CONST_INLINE;
25+
buffer[pc].operand = (uintptr_t)val;
26+
break;
27+
}
28+
case _CHECK_PEP_523:
29+
{
30+
/* Setting the eval frame function invalidates
31+
* all executors, so no need to check dynamically */
32+
if (_PyInterpreterState_GET()->eval_frame == NULL) {
33+
buffer[pc].opcode = _NOP;
34+
}
35+
break;
36+
}
37+
case _PUSH_FRAME:
38+
case _POP_FRAME:
39+
co = (PyCodeObject *)buffer[pc].operand;
40+
break;
41+
case _JUMP_TO_TOP:
42+
case _EXIT_TRACE:
43+
return;
44+
}
45+
}
46+
}
47+
1548
static void
1649
remove_unneeded_uops(_PyUOpInstruction *buffer, int buffer_size)
1750
{
@@ -59,6 +92,7 @@ _Py_uop_analyze_and_optimize(
5992
int curr_stacklen
6093
)
6194
{
95+
peephole_opt(co, buffer, buffer_size);
6296
remove_unneeded_uops(buffer, buffer_size);
6397
return 0;
6498
}

Python/pystate.c

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2608,11 +2608,15 @@ _PyInterpreterState_SetEvalFrameFunc(PyInterpreterState *interp,
26082608
_PyFrameEvalFunction eval_frame)
26092609
{
26102610
if (eval_frame == _PyEval_EvalFrameDefault) {
2611-
interp->eval_frame = NULL;
2611+
eval_frame = NULL;
26122612
}
2613-
else {
2614-
interp->eval_frame = eval_frame;
2613+
if (eval_frame == interp->eval_frame) {
2614+
return;
2615+
}
2616+
if (eval_frame != NULL) {
2617+
_Py_Executors_InvalidateAll(interp);
26152618
}
2619+
interp->eval_frame = eval_frame;
26162620
}
26172621

26182622

0 commit comments

Comments
 (0)