Skip to content

Commit

Permalink
Add 2-operand support
Browse files Browse the repository at this point in the history
  • Loading branch information
Fidget-Spinner committed Nov 4, 2024
1 parent 6ac0cdf commit 6d6263c
Show file tree
Hide file tree
Showing 11 changed files with 35 additions and 15 deletions.
1 change: 1 addition & 0 deletions Include/internal/pycore_optimizer.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ typedef struct {
};
};
uint64_t operand; // A cache entry
uint64_t operand1;
} _PyUOpInstruction;

typedef struct {
Expand Down
2 changes: 1 addition & 1 deletion Include/internal/pycore_uop_metadata.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 1 addition & 2 deletions Python/bytecodes.c
Original file line number Diff line number Diff line change
Expand Up @@ -3442,8 +3442,7 @@ dummy_func(
EXIT_IF(func->func_version != func_version);
}

tier2 op(_CHECK_FUNCTION_VERSION_INLINE, (callable_o/4 --)) {
uint16_t func_version = oparg;
tier2 op(_CHECK_FUNCTION_VERSION_INLINE, (func_version/2, callable_o/4 --)) {
assert(PyFunction_Check(callable_o));
PyFunctionObject *func = (PyFunctionObject *)callable_o;
EXIT_IF(func->func_version != func_version);
Expand Down
1 change: 1 addition & 0 deletions Python/ceval_macros.h
Original file line number Diff line number Diff line change
Expand Up @@ -410,6 +410,7 @@ do { \
#define CURRENT_OPARG() (next_uop[-1].oparg)

#define CURRENT_OPERAND() (next_uop[-1].operand)
#define CURRENT_OPERAND1() (next_uop[-1].operand1)

#define JUMP_TO_JUMP_TARGET() goto jump_to_jump_target
#define JUMP_TO_ERROR() goto jump_to_error_target
Expand Down
5 changes: 2 additions & 3 deletions Python/executor_cases.c.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 2 additions & 3 deletions Python/optimizer_bytecodes.c
Original file line number Diff line number Diff line change
Expand Up @@ -593,9 +593,8 @@ dummy_func(void) {
(void)self_or_null;
if (sym_is_const(callable) && sym_matches_type(callable, &PyFunction_Type)) {
assert(PyFunction_Check(sym_get_const(callable)));
if (func_version == (uint16_t)func_version) {
REPLACE_OP(this_instr, _CHECK_FUNCTION_VERSION_INLINE, func_version, (uintptr_t)sym_get_const(callable));
}
REPLACE_OP(this_instr, _CHECK_FUNCTION_VERSION_INLINE, 0, func_version);
this_instr->operand1 = (uintptr_t)sym_get_const(callable);
}
sym_set_type(callable, &PyFunction_Type);
}
Expand Down
5 changes: 2 additions & 3 deletions Python/optimizer_cases.c.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Tools/cases_generator/analyzer.py
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ def why_not_viable(self) -> str | None:
return "has tier 1 control flow"
if self.properties.needs_this:
return "uses the 'this_instr' variable"
if len([c for c in self.caches if c.name != "unused"]) > 1:
if len([c for c in self.caches if c.name != "unused"]) > 2:
return "has unused cache entries"
if self.properties.error_with_pop and self.properties.error_without_pop:
return "has both popping and not-popping errors"
Expand Down
7 changes: 5 additions & 2 deletions Tools/cases_generator/tier2_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -181,14 +181,17 @@ def write_uop(uop: Uop, emitter: Emitter, stack: Stack) -> Stack:
code_list, storage = Storage.for_uop(stack, uop)
for code in code_list:
emitter.emit(code)
for cache in uop.caches:
for idx, cache in enumerate(uop.caches):
if cache.name != "unused":
if cache.size == 4:
type = cast = "PyObject *"
else:
type = f"uint{cache.size*16}_t "
cast = f"uint{cache.size*16}_t"
emitter.emit(f"{type}{cache.name} = ({cast})CURRENT_OPERAND();\n")
if idx == 0:
emitter.emit(f"{type}{cache.name} = ({cast})CURRENT_OPERAND();\n")
else:
emitter.emit(f"{type}{cache.name} = ({cast})CURRENT_OPERAND{idx}();\n")
storage = emitter.emit_tokens(uop, storage, None)
except StackError as ex:
raise analysis_error(ex.args[0], uop.body[0]) from None
Expand Down
8 changes: 8 additions & 0 deletions Tools/jit/_stencils.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,11 @@ class HoleValue(enum.Enum):
# The current uop's operand on 32-bit platforms (exposed as _JIT_OPERAND_HI/LO):
OPERAND_HI = enum.auto()
OPERAND_LO = enum.auto()
# The current uop's operand1 on 64-bit platforms (exposed as _JIT_OPERAND):
OPERAND1 = enum.auto()
# The current uop's operand1 on 32-bit platforms (exposed as _JIT_OPERAND_HI/LO):
OPERAND1_HI = enum.auto()
OPERAND1_LO = enum.auto()
# The current uop's target (exposed as _JIT_TARGET):
TARGET = enum.auto()
# The base address of the machine code for the jump target (exposed as _JIT_JUMP_TARGET):
Expand Down Expand Up @@ -102,6 +107,9 @@ class HoleValue(enum.Enum):
HoleValue.OPERAND: "instruction->operand",
HoleValue.OPERAND_HI: "(instruction->operand >> 32)",
HoleValue.OPERAND_LO: "(instruction->operand & UINT32_MAX)",
HoleValue.OPERAND1: "instruction->operand1",
HoleValue.OPERAND1_HI: "(instruction->operand1 >> 32)",
HoleValue.OPERAND1_LO: "(instruction->operand1 & UINT32_MAX)",
HoleValue.TARGET: "instruction->target",
HoleValue.JUMP_TARGET: "state->instruction_starts[instruction->jump_target]",
HoleValue.ERROR_TARGET: "state->instruction_starts[instruction->error_target]",
Expand Down
11 changes: 11 additions & 0 deletions Tools/jit/template.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@
#undef CURRENT_OPERAND
#define CURRENT_OPERAND() (_operand)

#undef CURRENT_OPERAND1
#define CURRENT_OPERAND1() (_operand1)

#undef DEOPT_IF
#define DEOPT_IF(COND, INSTNAME) \
do { \
Expand Down Expand Up @@ -105,6 +108,14 @@ _JIT_ENTRY(_PyInterpreterFrame *frame, _PyStackRef *stack_pointer, PyThreadState
PATCH_VALUE(uint32_t, _operand_hi, _JIT_OPERAND_HI)
PATCH_VALUE(uint32_t, _operand_lo, _JIT_OPERAND_LO)
uint64_t _operand = ((uint64_t)_operand_hi << 32) | _operand_lo;
#endif
#if SIZEOF_VOID_P == 8
PATCH_VALUE(uint64_t, _operand1, _JIT_OPERAND1)
#else
assert(SIZEOF_VOID_P == 4);
PATCH_VALUE(uint32_t, _operand1_hi, _JIT_OPERAND1_HI)
PATCH_VALUE(uint32_t, _operand1_lo, _JIT_OPERAND1_LO)
uint64_t _operand1 = ((uint64_t)_operand1_hi << 32) | _operand1_lo;
#endif
PATCH_VALUE(uint32_t, _target, _JIT_TARGET)

Expand Down

0 comments on commit 6d6263c

Please sign in to comment.