GH-132732: Use pure op machinery to optimize various instructions with _POP_TOP and _POP_TWO (#137577)

This commit is contained in:
Savannah Bailey 2025-09-15 16:29:45 +01:00 committed by GitHub
parent 5c4bb9b7f6
commit 9c9a0f7da7
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 258 additions and 22 deletions

View file

@ -188,6 +188,31 @@
JitOptRef value;
JitOptRef res;
value = stack_pointer[-1];
if (
sym_is_safe_const(ctx, value)
) {
JitOptRef value_sym = value;
_PyStackRef value = sym_get_const_as_stackref(ctx, value_sym);
_PyStackRef res_stackref;
/* Start of uop copied from bytecodes for constant evaluation */
PyObject *res_o = PyNumber_Negative(PyStackRef_AsPyObjectBorrow(value));
PyStackRef_CLOSE(value);
if (res_o == NULL) {
goto error;
}
res_stackref = PyStackRef_FromPyObjectSteal(res_o);
/* End of uop copied from bytecodes for constant evaluation */
res = sym_new_const_steal(ctx, PyStackRef_AsPyObjectSteal(res_stackref));
if (sym_is_const(ctx, res)) {
PyObject *result = sym_get_const(ctx, res);
if (_Py_IsImmortal(result)) {
// Replace with _POP_TOP_LOAD_CONST_INLINE_BORROW since we have one input and an immortal result
REPLACE_OP(this_instr, _POP_TOP_LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)result);
}
}
stack_pointer[-1] = res;
break;
}
if (sym_is_compact_int(value)) {
res = sym_new_compact_int(ctx);
}
@ -220,6 +245,13 @@
? PyStackRef_True : PyStackRef_False;
/* End of uop copied from bytecodes for constant evaluation */
res = sym_new_const_steal(ctx, PyStackRef_AsPyObjectSteal(res_stackref));
if (sym_is_const(ctx, res)) {
PyObject *result = sym_get_const(ctx, res);
if (_Py_IsImmortal(result)) {
// Replace with _POP_TOP_LOAD_CONST_INLINE_BORROW since we have one input and an immortal result
REPLACE_OP(this_instr, _POP_TOP_LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)result);
}
}
stack_pointer[-1] = res;
break;
}
@ -359,6 +391,33 @@
JitOptRef value;
JitOptRef res;
value = stack_pointer[-1];
if (!sym_matches_type(value, &PyBool_Type)) {
if (
sym_is_safe_const(ctx, value)
) {
JitOptRef value_sym = value;
_PyStackRef value = sym_get_const_as_stackref(ctx, value_sym);
_PyStackRef res_stackref;
/* Start of uop copied from bytecodes for constant evaluation */
PyObject *res_o = PyNumber_Invert(PyStackRef_AsPyObjectBorrow(value));
PyStackRef_CLOSE(value);
if (res_o == NULL) {
goto error;
}
res_stackref = PyStackRef_FromPyObjectSteal(res_o);
/* End of uop copied from bytecodes for constant evaluation */
res = sym_new_const_steal(ctx, PyStackRef_AsPyObjectSteal(res_stackref));
if (sym_is_const(ctx, res)) {
PyObject *result = sym_get_const(ctx, res);
if (_Py_IsImmortal(result)) {
// Replace with _POP_TOP_LOAD_CONST_INLINE_BORROW since we have one input and an immortal result
REPLACE_OP(this_instr, _POP_TOP_LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)result);
}
}
stack_pointer[-1] = res;
break;
}
}
if (sym_matches_type(value, &PyLong_Type)) {
res = sym_new_type(ctx, &PyLong_Type);
}
@ -438,7 +497,6 @@
PyStackRef_CLOSE_SPECIALIZED(left, _PyLong_ExactDealloc);
/* End of uop copied from bytecodes for constant evaluation */
res = sym_new_const_steal(ctx, PyStackRef_AsPyObjectSteal(res_stackref));
if (sym_is_const(ctx, res)) {
PyObject *result = sym_get_const(ctx, res);
if (_Py_IsImmortal(result)) {
@ -489,7 +547,6 @@
PyStackRef_CLOSE_SPECIALIZED(left, _PyLong_ExactDealloc);
/* End of uop copied from bytecodes for constant evaluation */
res = sym_new_const_steal(ctx, PyStackRef_AsPyObjectSteal(res_stackref));
if (sym_is_const(ctx, res)) {
PyObject *result = sym_get_const(ctx, res);
if (_Py_IsImmortal(result)) {
@ -540,7 +597,6 @@
PyStackRef_CLOSE_SPECIALIZED(left, _PyLong_ExactDealloc);
/* End of uop copied from bytecodes for constant evaluation */
res = sym_new_const_steal(ctx, PyStackRef_AsPyObjectSteal(res_stackref));
if (sym_is_const(ctx, res)) {
PyObject *result = sym_get_const(ctx, res);
if (_Py_IsImmortal(result)) {
@ -610,7 +666,6 @@
}
/* End of uop copied from bytecodes for constant evaluation */
res = sym_new_const_steal(ctx, PyStackRef_AsPyObjectSteal(res_stackref));
if (sym_is_const(ctx, res)) {
PyObject *result = sym_get_const(ctx, res);
if (_Py_IsImmortal(result)) {
@ -663,7 +718,6 @@
}
/* End of uop copied from bytecodes for constant evaluation */
res = sym_new_const_steal(ctx, PyStackRef_AsPyObjectSteal(res_stackref));
if (sym_is_const(ctx, res)) {
PyObject *result = sym_get_const(ctx, res);
if (_Py_IsImmortal(result)) {
@ -716,7 +770,6 @@
}
/* End of uop copied from bytecodes for constant evaluation */
res = sym_new_const_steal(ctx, PyStackRef_AsPyObjectSteal(res_stackref));
if (sym_is_const(ctx, res)) {
PyObject *result = sym_get_const(ctx, res);
if (_Py_IsImmortal(result)) {
@ -796,7 +849,6 @@
res_stackref = PyStackRef_FromPyObjectSteal(res_o);
/* End of uop copied from bytecodes for constant evaluation */
res = sym_new_const_steal(ctx, PyStackRef_AsPyObjectSteal(res_stackref));
if (sym_is_const(ctx, res)) {
PyObject *result = sym_get_const(ctx, res);
if (_Py_IsImmortal(result)) {
@ -1642,7 +1694,53 @@
}
case _COMPARE_OP: {
JitOptRef right;
JitOptRef left;
JitOptRef res;
right = stack_pointer[-1];
left = stack_pointer[-2];
if (
sym_is_safe_const(ctx, left) &&
sym_is_safe_const(ctx, right)
) {
JitOptRef left_sym = left;
JitOptRef right_sym = right;
_PyStackRef left = sym_get_const_as_stackref(ctx, left_sym);
_PyStackRef right = sym_get_const_as_stackref(ctx, right_sym);
_PyStackRef res_stackref;
/* Start of uop copied from bytecodes for constant evaluation */
PyObject *left_o = PyStackRef_AsPyObjectBorrow(left);
PyObject *right_o = PyStackRef_AsPyObjectBorrow(right);
assert((oparg >> 5) <= Py_GE);
PyObject *res_o = PyObject_RichCompare(left_o, right_o, oparg >> 5);
if (res_o == NULL) {
goto error;
}
if (oparg & 16) {
int res_bool = PyObject_IsTrue(res_o);
Py_DECREF(res_o);
if (res_bool < 0) {
goto error;
}
res_stackref = res_bool ? PyStackRef_True : PyStackRef_False;
}
else {
res_stackref = PyStackRef_FromPyObjectSteal(res_o);
}
/* End of uop copied from bytecodes for constant evaluation */
res = sym_new_const_steal(ctx, PyStackRef_AsPyObjectSteal(res_stackref));
if (sym_is_const(ctx, res)) {
PyObject *result = sym_get_const(ctx, res);
if (_Py_IsImmortal(result)) {
// Replace with _POP_TWO_LOAD_CONST_INLINE_BORROW since we have two inputs and an immortal result
REPLACE_OP(this_instr, _POP_TWO_LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)result);
}
}
stack_pointer[-2] = res;
stack_pointer += -1;
assert(WITHIN_STACK_BOUNDS());
break;
}
if (oparg & 16) {
res = sym_new_type(ctx, &PyBool_Type);
}
@ -1682,7 +1780,6 @@
res_stackref = (sign_ish & oparg) ? PyStackRef_True : PyStackRef_False;
/* End of uop copied from bytecodes for constant evaluation */
res = sym_new_const_steal(ctx, PyStackRef_AsPyObjectSteal(res_stackref));
if (sym_is_const(ctx, res)) {
PyObject *result = sym_get_const(ctx, res);
if (_Py_IsImmortal(result)) {
@ -1733,7 +1830,6 @@
res_stackref = (sign_ish & oparg) ? PyStackRef_True : PyStackRef_False;
/* End of uop copied from bytecodes for constant evaluation */
res = sym_new_const_steal(ctx, PyStackRef_AsPyObjectSteal(res_stackref));
if (sym_is_const(ctx, res)) {
PyObject *result = sym_get_const(ctx, res);
if (_Py_IsImmortal(result)) {
@ -1782,7 +1878,6 @@
res_stackref = ((COMPARISON_NOT_EQUALS + eq) & oparg) ? PyStackRef_True : PyStackRef_False;
/* End of uop copied from bytecodes for constant evaluation */
res = sym_new_const_steal(ctx, PyStackRef_AsPyObjectSteal(res_stackref));
if (sym_is_const(ctx, res)) {
PyObject *result = sym_get_const(ctx, res);
if (_Py_IsImmortal(result)) {
@ -1812,7 +1907,42 @@
}
case _CONTAINS_OP: {
JitOptRef right;
JitOptRef left;
JitOptRef b;
right = stack_pointer[-1];
left = stack_pointer[-2];
if (
sym_is_safe_const(ctx, left) &&
sym_is_safe_const(ctx, right)
) {
JitOptRef left_sym = left;
JitOptRef right_sym = right;
_PyStackRef left = sym_get_const_as_stackref(ctx, left_sym);
_PyStackRef right = sym_get_const_as_stackref(ctx, right_sym);
_PyStackRef b_stackref;
/* Start of uop copied from bytecodes for constant evaluation */
PyObject *left_o = PyStackRef_AsPyObjectBorrow(left);
PyObject *right_o = PyStackRef_AsPyObjectBorrow(right);
int res = PySequence_Contains(right_o, left_o);
if (res < 0) {
goto error;
}
b_stackref = (res ^ oparg) ? PyStackRef_True : PyStackRef_False;
/* End of uop copied from bytecodes for constant evaluation */
b = sym_new_const_steal(ctx, PyStackRef_AsPyObjectSteal(b_stackref));
if (sym_is_const(ctx, b)) {
PyObject *result = sym_get_const(ctx, b);
if (_Py_IsImmortal(result)) {
// Replace with _POP_TWO_LOAD_CONST_INLINE_BORROW since we have two inputs and an immortal result
REPLACE_OP(this_instr, _POP_TWO_LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)result);
}
}
stack_pointer[-2] = b;
stack_pointer += -1;
assert(WITHIN_STACK_BOUNDS());
break;
}
b = sym_new_type(ctx, &PyBool_Type);
stack_pointer[-2] = b;
stack_pointer += -1;
@ -2885,7 +3015,6 @@
res_stackref = PyStackRef_FromPyObjectSteal(res_o);
/* End of uop copied from bytecodes for constant evaluation */
res = sym_new_const_steal(ctx, PyStackRef_AsPyObjectSteal(res_stackref));
if (sym_is_const(ctx, res)) {
PyObject *result = sym_get_const(ctx, res);
if (_Py_IsImmortal(result)) {