mirror of
https://github.com/python/cpython.git
synced 2026-04-20 02:40:59 +00:00
gh-146393: Use recorded type instead of instance in BINARY_OP (#148569)
This commit is contained in:
parent
0012686d92
commit
5c3decad66
8 changed files with 1042 additions and 1013 deletions
2
Include/internal/pycore_opcode_metadata.h
generated
2
Include/internal/pycore_opcode_metadata.h
generated
|
|
@ -1345,7 +1345,7 @@ extern const struct opcode_macro_expansion _PyOpcode_macro_expansion[256];
|
|||
#ifdef NEED_OPCODE_METADATA
|
||||
const struct opcode_macro_expansion
|
||||
_PyOpcode_macro_expansion[256] = {
|
||||
[BINARY_OP] = { .nuops = 5, .uops = { { _RECORD_TOS, OPARG_SIMPLE, 0 }, { _RECORD_NOS, OPARG_SIMPLE, 0 }, { _BINARY_OP, OPARG_SIMPLE, 4 }, { _POP_TOP, OPARG_SIMPLE, 4 }, { _POP_TOP, OPARG_SIMPLE, 4 } } },
|
||||
[BINARY_OP] = { .nuops = 5, .uops = { { _RECORD_TOS_TYPE, OPARG_SIMPLE, 0 }, { _RECORD_NOS_TYPE, OPARG_SIMPLE, 0 }, { _BINARY_OP, OPARG_SIMPLE, 4 }, { _POP_TOP, OPARG_SIMPLE, 4 }, { _POP_TOP, OPARG_SIMPLE, 4 } } },
|
||||
[BINARY_OP_ADD_FLOAT] = { .nuops = 5, .uops = { { _GUARD_TOS_FLOAT, OPARG_SIMPLE, 0 }, { _GUARD_NOS_FLOAT, OPARG_SIMPLE, 0 }, { _BINARY_OP_ADD_FLOAT, OPARG_SIMPLE, 5 }, { _POP_TOP_FLOAT, OPARG_SIMPLE, 5 }, { _POP_TOP_FLOAT, OPARG_SIMPLE, 5 } } },
|
||||
[BINARY_OP_ADD_INT] = { .nuops = 5, .uops = { { _GUARD_TOS_INT, OPARG_SIMPLE, 0 }, { _GUARD_NOS_INT, OPARG_SIMPLE, 0 }, { _BINARY_OP_ADD_INT, OPARG_SIMPLE, 5 }, { _POP_TOP_INT, OPARG_SIMPLE, 5 }, { _POP_TOP_INT, OPARG_SIMPLE, 5 } } },
|
||||
[BINARY_OP_ADD_UNICODE] = { .nuops = 5, .uops = { { _GUARD_TOS_UNICODE, OPARG_SIMPLE, 0 }, { _GUARD_NOS_UNICODE, OPARG_SIMPLE, 0 }, { _BINARY_OP_ADD_UNICODE, OPARG_SIMPLE, 5 }, { _POP_TOP_UNICODE, OPARG_SIMPLE, 5 }, { _POP_TOP_UNICODE, OPARG_SIMPLE, 5 } } },
|
||||
|
|
|
|||
2005
Include/internal/pycore_uop_ids.h
generated
2005
Include/internal/pycore_uop_ids.h
generated
File diff suppressed because it is too large
Load diff
4
Include/internal/pycore_uop_metadata.h
generated
4
Include/internal/pycore_uop_metadata.h
generated
|
|
@ -410,6 +410,7 @@ const uint32_t _PyUop_Flags[MAX_UOP_ID+1] = {
|
|||
[_RECORD_TOS] = HAS_RECORDS_VALUE_FLAG,
|
||||
[_RECORD_TOS_TYPE] = HAS_RECORDS_VALUE_FLAG,
|
||||
[_RECORD_NOS] = HAS_RECORDS_VALUE_FLAG,
|
||||
[_RECORD_NOS_TYPE] = HAS_RECORDS_VALUE_FLAG,
|
||||
[_RECORD_NOS_GEN_FUNC] = HAS_RECORDS_VALUE_FLAG,
|
||||
[_RECORD_3OS_GEN_FUNC] = HAS_RECORDS_VALUE_FLAG,
|
||||
[_RECORD_4OS] = HAS_RECORDS_VALUE_FLAG,
|
||||
|
|
@ -5736,6 +5737,7 @@ const char *const _PyOpcode_uop_name[MAX_UOP_REGS_ID+1] = {
|
|||
[_RECORD_CODE] = "_RECORD_CODE",
|
||||
[_RECORD_NOS] = "_RECORD_NOS",
|
||||
[_RECORD_NOS_GEN_FUNC] = "_RECORD_NOS_GEN_FUNC",
|
||||
[_RECORD_NOS_TYPE] = "_RECORD_NOS_TYPE",
|
||||
[_RECORD_TOS] = "_RECORD_TOS",
|
||||
[_RECORD_TOS_TYPE] = "_RECORD_TOS_TYPE",
|
||||
[_REPLACE_WITH_TRUE] = "_REPLACE_WITH_TRUE",
|
||||
|
|
@ -6694,6 +6696,8 @@ int _PyUop_num_popped(int opcode, int oparg)
|
|||
return 0;
|
||||
case _RECORD_NOS:
|
||||
return 0;
|
||||
case _RECORD_NOS_TYPE:
|
||||
return 0;
|
||||
case _RECORD_NOS_GEN_FUNC:
|
||||
return 0;
|
||||
case _RECORD_3OS_GEN_FUNC:
|
||||
|
|
|
|||
|
|
@ -3708,8 +3708,8 @@ def testfunc(args):
|
|||
self.assertIn("_BINARY_OP_TRUEDIV_FLOAT_INPLACE_RIGHT", uops)
|
||||
|
||||
def test_float_truediv_speculative_guards_from_tracing(self):
|
||||
# a, b are locals with no statically known type. _RECORD_TOS /
|
||||
# _RECORD_NOS (added to the BINARY_OP macro) capture the observed
|
||||
# a, b are locals with no statically known type. _RECORD_TOS_TYPE /
|
||||
# _RECORD_NOS_TYPE (added to the BINARY_OP macro) capture the observed
|
||||
# operand types during tracing, and the optimizer then speculatively
|
||||
# emits _GUARD_{TOS,NOS}_FLOAT and specializes the division.
|
||||
def testfunc(args):
|
||||
|
|
|
|||
|
|
@ -5725,7 +5725,7 @@ dummy_func(
|
|||
DEAD(rhs);
|
||||
}
|
||||
|
||||
macro(BINARY_OP) = _SPECIALIZE_BINARY_OP + _RECORD_TOS + _RECORD_NOS + unused/4 + _BINARY_OP + POP_TOP + POP_TOP;
|
||||
macro(BINARY_OP) = _SPECIALIZE_BINARY_OP + _RECORD_TOS_TYPE + _RECORD_NOS_TYPE + unused/4 + _BINARY_OP + POP_TOP + POP_TOP;
|
||||
|
||||
pure replicate(2:4) inst(SWAP, (bottom, unused[oparg-2], top --
|
||||
bottom, unused[oparg-2], top)) {
|
||||
|
|
@ -6178,6 +6178,10 @@ dummy_func(
|
|||
RECORD_VALUE(PyStackRef_AsPyObjectBorrow(nos));
|
||||
}
|
||||
|
||||
tier2 op(_RECORD_NOS_TYPE, (nos, tos -- nos, tos)) {
|
||||
RECORD_VALUE(Py_TYPE(PyStackRef_AsPyObjectBorrow(nos)));
|
||||
}
|
||||
|
||||
tier2 op(_RECORD_NOS_GEN_FUNC, (nos, tos -- nos, tos)) {
|
||||
PyObject *obj = PyStackRef_AsPyObjectBorrow(nos);
|
||||
if (PyGen_Check(obj)) {
|
||||
|
|
|
|||
|
|
@ -294,10 +294,10 @@ dummy_func(void) {
|
|||
bool is_remainder = (oparg == NB_REMAINDER
|
||||
|| oparg == NB_INPLACE_REMAINDER);
|
||||
// Promote probable-float operands to known floats via speculative
|
||||
// guards. _RECORD_TOS / _RECORD_NOS in the BINARY_OP macro record
|
||||
// the observed operand during tracing, which sym_get_probable_type
|
||||
// reads here. Applied only to ops where narrowing unlocks a
|
||||
// meaningful downstream win:
|
||||
// guards. _RECORD_TOS_TYPE / _RECORD_NOS_TYPE in the BINARY_OP macro
|
||||
// record the observed operand type during tracing, which
|
||||
// sym_get_probable_type reads here. Applied only to ops where
|
||||
// narrowing unlocks a meaningful downstream win:
|
||||
// - NB_TRUE_DIVIDE: enables the specialized float path below.
|
||||
// - NB_REMAINDER: lets the float result type propagate.
|
||||
// NB_POWER is excluded — speculative guards there regressed
|
||||
|
|
@ -2424,6 +2424,11 @@ dummy_func(void) {
|
|||
sym_set_recorded_value(nos, (PyObject *)this_instr->operand0);
|
||||
}
|
||||
|
||||
op(_RECORD_NOS_TYPE, (nos, tos -- nos, tos)) {
|
||||
PyTypeObject *tp = (PyTypeObject *)this_instr->operand0;
|
||||
sym_set_recorded_type(nos, tp);
|
||||
}
|
||||
|
||||
op(_RECORD_4OS, (value, _3os, nos, tos -- value, _3os, nos, tos)) {
|
||||
sym_set_recorded_value(value, (PyObject *)this_instr->operand0);
|
||||
}
|
||||
|
|
|
|||
8
Python/optimizer_cases.c.h
generated
8
Python/optimizer_cases.c.h
generated
|
|
@ -5482,6 +5482,14 @@
|
|||
break;
|
||||
}
|
||||
|
||||
case _RECORD_NOS_TYPE: {
|
||||
JitOptRef nos;
|
||||
nos = stack_pointer[-2];
|
||||
PyTypeObject *tp = (PyTypeObject *)this_instr->operand0;
|
||||
sym_set_recorded_type(nos, tp);
|
||||
break;
|
||||
}
|
||||
|
||||
case _RECORD_NOS_GEN_FUNC: {
|
||||
JitOptRef nos;
|
||||
nos = stack_pointer[-2];
|
||||
|
|
|
|||
13
Python/record_functions.c.h
generated
13
Python/record_functions.c.h
generated
|
|
@ -27,6 +27,13 @@ void _PyOpcode_RecordFunction_NOS(_PyInterpreterFrame *frame, _PyStackRef *stack
|
|||
Py_INCREF(*recorded_value);
|
||||
}
|
||||
|
||||
void _PyOpcode_RecordFunction_NOS_TYPE(_PyInterpreterFrame *frame, _PyStackRef *stack_pointer, int oparg, PyObject **recorded_value) {
|
||||
_PyStackRef nos;
|
||||
nos = stack_pointer[-2];
|
||||
*recorded_value = (PyObject *)Py_TYPE(PyStackRef_AsPyObjectBorrow(nos));
|
||||
Py_INCREF(*recorded_value);
|
||||
}
|
||||
|
||||
void _PyOpcode_RecordFunction_NOS_GEN_FUNC(_PyInterpreterFrame *frame, _PyStackRef *stack_pointer, int oparg, PyObject **recorded_value) {
|
||||
_PyStackRef nos;
|
||||
nos = stack_pointer[-2];
|
||||
|
|
@ -99,7 +106,7 @@ void _PyOpcode_RecordFunction_CODE(_PyInterpreterFrame *frame, _PyStackRef *stac
|
|||
#define _RECORD_BOUND_METHOD_INDEX 6
|
||||
#define _RECORD_CALLABLE_KW_INDEX 7
|
||||
#define _RECORD_4OS_INDEX 8
|
||||
#define _RECORD_TOS_INDEX 9
|
||||
#define _RECORD_NOS_TYPE_INDEX 9
|
||||
|
||||
const _PyOpcodeRecordEntry _PyOpcode_RecordEntries[256] = {
|
||||
[TO_BOOL_ALWAYS_TRUE] = {1, {_RECORD_TOS_TYPE_INDEX}},
|
||||
|
|
@ -138,7 +145,7 @@ const _PyOpcodeRecordEntry _PyOpcode_RecordEntries[256] = {
|
|||
[CALL_KW_PY] = {1, {_RECORD_CALLABLE_KW_INDEX}},
|
||||
[CALL_KW_BOUND_METHOD] = {1, {_RECORD_CALLABLE_KW_INDEX}},
|
||||
[CALL_EX_PY] = {1, {_RECORD_4OS_INDEX}},
|
||||
[BINARY_OP] = {2, {_RECORD_TOS_INDEX, _RECORD_NOS_INDEX}},
|
||||
[BINARY_OP] = {2, {_RECORD_TOS_TYPE_INDEX, _RECORD_NOS_TYPE_INDEX}},
|
||||
};
|
||||
|
||||
const _Py_RecordFuncPtr _PyOpcode_RecordFunctions[10] = {
|
||||
|
|
@ -151,5 +158,5 @@ const _Py_RecordFuncPtr _PyOpcode_RecordFunctions[10] = {
|
|||
[_RECORD_BOUND_METHOD_INDEX] = _PyOpcode_RecordFunction_BOUND_METHOD,
|
||||
[_RECORD_CALLABLE_KW_INDEX] = _PyOpcode_RecordFunction_CALLABLE_KW,
|
||||
[_RECORD_4OS_INDEX] = _PyOpcode_RecordFunction_4OS,
|
||||
[_RECORD_TOS_INDEX] = _PyOpcode_RecordFunction_TOS,
|
||||
[_RECORD_NOS_TYPE_INDEX] = _PyOpcode_RecordFunction_NOS_TYPE,
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue