Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
use add_op to save optimized uops
  • Loading branch information
cocolato committed Jan 11, 2026
commit e771fd001005373cf1b62a0fd3473480fefe31fe
4 changes: 4 additions & 0 deletions Include/internal/pycore_optimizer_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,10 @@ typedef struct _JitOptContext {
JitOptRef *n_consumed;
JitOptRef *limit;
JitOptRef locals_and_stack[MAX_ABSTRACT_INTERP_SIZE];

// buffer to save optimized result
int out_len;
_PyUOpInstruction out_buffer[UOP_MAX_TRACE_LENGTH];
Comment thread
cocolato marked this conversation as resolved.
Outdated
} JitOptContext;


Expand Down
1 change: 1 addition & 0 deletions Python/optimizer.c
Original file line number Diff line number Diff line change
Expand Up @@ -1509,6 +1509,7 @@ uop_optimize(
if (length <= 0) {
return length;
}
buffer = _tstate->jit_tracer_state->opt_context.out_buffer;
}
assert(length < UOP_MAX_TRACE_LENGTH/2);
assert(length >= 1);
Expand Down
42 changes: 35 additions & 7 deletions Python/optimizer_analysis.c
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,16 @@ incorrect_keys(PyObject *obj, uint32_t version)
(INST)->oparg = ARG; \
(INST)->operand0 = OPERAND;

#define ADD_OP(OP, ARG, OPERAND) ( \
Comment thread
cocolato marked this conversation as resolved.
Outdated
ctx->out_buffer[ctx->out_len].opcode = (OP), \
ctx->out_buffer[ctx->out_len].format = this_instr->format, \
ctx->out_buffer[ctx->out_len].oparg = (ARG), \
ctx->out_buffer[ctx->out_len].target = this_instr->target, \
ctx->out_buffer[ctx->out_len].operand0 = (OPERAND), \
ctx->out_buffer[ctx->out_len].operand1 = this_instr->operand1, \
ctx->out_len++ \
)

/* Shortened forms for convenience, used in optimizer_bytecodes.c */
#define sym_is_not_null _Py_uop_sym_is_not_null
#define sym_is_const _Py_uop_sym_is_const
Expand Down Expand Up @@ -219,7 +229,7 @@ optimize_to_bool(
bool insert_mode)
{
if (sym_matches_type(value, &PyBool_Type)) {
REPLACE_OP(this_instr, _NOP, 0, 0);
Comment thread
cocolato marked this conversation as resolved.
ADD_OP(_NOP, 0, 0);
*result_ptr = value;
return 1;
}
Expand All @@ -229,17 +239,17 @@ optimize_to_bool(
int opcode = insert_mode ?
_INSERT_1_LOAD_CONST_INLINE_BORROW :
_POP_TOP_LOAD_CONST_INLINE_BORROW;
REPLACE_OP(this_instr, opcode, 0, (uintptr_t)load);
ADD_OP(opcode, 0, (uintptr_t)load);
*result_ptr = sym_new_const(ctx, load);
return 1;
}
return 0;
}

static void
eliminate_pop_guard(_PyUOpInstruction *this_instr, bool exit)
eliminate_pop_guard(_PyUOpInstruction *this_instr, JitOptContext *ctx, bool exit)
{
REPLACE_OP(this_instr, _POP_TOP, 0, 0);
ADD_OP(_POP_TOP, 0, 0);
if (exit) {
REPLACE_OP((this_instr+1), _EXIT_TRACE, 0, 0);
this_instr[1].target = this_instr->target;
Expand All @@ -256,7 +266,7 @@ lookup_attr(JitOptContext *ctx, _PyBloomFilter *dependencies, _PyUOpInstruction
PyObject *lookup = _PyType_Lookup(type, name);
if (lookup) {
int opcode = _Py_IsImmortal(lookup) ? immortal : mortal;
REPLACE_OP(this_instr, opcode, 0, (uintptr_t)lookup);
ADD_OP(opcode, 0, (uintptr_t)lookup);
PyType_Watch(TYPE_WATCHER_ID, (PyObject *)type);
_Py_BloomFilter_Add(dependencies, type);
return sym_new_const(ctx, lookup);
Expand Down Expand Up @@ -364,6 +374,7 @@ optimize_uops(
frame->func = func;
ctx->curr_frame_depth++;
ctx->frame = frame;
ctx->out_len = 0;

_PyUOpInstruction *this_instr = NULL;
JitOptRef *stack_pointer = ctx->frame->stack_pointer;
Expand All @@ -387,6 +398,7 @@ optimize_uops(
}
#endif

int out_len_before = ctx->out_len;
switch (opcode) {

#include "optimizer_cases.c.h"
Expand All @@ -395,6 +407,10 @@ optimize_uops(
DPRINTF(1, "\nUnknown opcode in abstract interpreter\n");
Py_UNREACHABLE();
}
// If no ADD_OP was called during this iteration, copy the original instruction
if (ctx->out_len == out_len_before) {
ctx->out_buffer[ctx->out_len++] = *this_instr;
}
assert(ctx->frame != NULL);
if (!CURRENT_FRAME_IS_INIT_SHIM()) {
DPRINTF(3, " stack_level %d\n", STACK_LEVEL());
Expand Down Expand Up @@ -423,7 +439,18 @@ optimize_uops(
/* Either reached the end or cannot optimize further, but there
* would be no benefit in retrying later */
_Py_uop_abstractcontext_fini(ctx);
return trace_len;
// Check that the trace ends with a proper terminator
if (ctx->out_len > 0) {
int last_opcode = ctx->out_buffer[ctx->out_len - 1].opcode;
if (last_opcode != _EXIT_TRACE &&
last_opcode != _JUMP_TO_TOP &&
last_opcode != _DYNAMIC_EXIT &&
last_opcode != _DEOPT) {
return 0;
Comment thread
cocolato marked this conversation as resolved.
Outdated
}
}

return ctx->out_len;

error:
DPRINTF(3, "\n");
Expand Down Expand Up @@ -584,6 +611,7 @@ _Py_uop_analyze_and_optimize(
)
{
OPT_STAT_INC(optimizer_attempts);
JitOptContext *ctx = &tstate->jit_tracer_state->opt_context;
Comment thread
cocolato marked this conversation as resolved.
Outdated

length = optimize_uops(
tstate, buffer,
Expand All @@ -595,7 +623,7 @@ _Py_uop_analyze_and_optimize(

assert(length > 0);

length = remove_unneeded_uops(buffer, length);
length = remove_unneeded_uops(ctx->out_buffer, length);
assert(length > 0);

OPT_STAT_INC(optimizer_successes);
Expand Down
Loading
Loading