mirror of
https://github.com/python/cpython.git
synced 2026-04-20 02:40:59 +00:00
gh-146393: Optimize float division operations by mutating uniquely-referenced operands in place (JIT only) (GH-146397)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
bdb0b36192
commit
95cbd4a232
13 changed files with 1940 additions and 1263 deletions
|
|
@ -895,6 +895,53 @@ dummy_func(
|
|||
INPUTS_DEAD();
|
||||
}
|
||||
|
||||
// Float true division — not specialized at tier 1, emitted by the
|
||||
// tier 2 optimizer when both operands are known floats.
|
||||
tier2 op(_BINARY_OP_TRUEDIV_FLOAT, (left, right -- res, l, r)) {
|
||||
PyObject *left_o = PyStackRef_AsPyObjectBorrow(left);
|
||||
PyObject *right_o = PyStackRef_AsPyObjectBorrow(right);
|
||||
assert(PyFloat_CheckExact(left_o));
|
||||
assert(PyFloat_CheckExact(right_o));
|
||||
STAT_INC(BINARY_OP, hit);
|
||||
double divisor = ((PyFloatObject *)right_o)->ob_fval;
|
||||
if (divisor == 0.0) {
|
||||
PyErr_SetString(PyExc_ZeroDivisionError,
|
||||
"float division by zero");
|
||||
ERROR_NO_POP();
|
||||
}
|
||||
double dres = ((PyFloatObject *)left_o)->ob_fval / divisor;
|
||||
PyObject *d = PyFloat_FromDouble(dres);
|
||||
if (d == NULL) {
|
||||
ERROR_NO_POP();
|
||||
}
|
||||
res = PyStackRef_FromPyObjectSteal(d);
|
||||
l = left;
|
||||
r = right;
|
||||
INPUTS_DEAD();
|
||||
}
|
||||
|
||||
tier2 op(_BINARY_OP_TRUEDIV_FLOAT_INPLACE, (left, right -- res, l, r)) {
|
||||
FLOAT_INPLACE_DIVOP(left, right, left);
|
||||
if (_divop_err) {
|
||||
ERROR_NO_POP();
|
||||
}
|
||||
res = left;
|
||||
l = PyStackRef_NULL;
|
||||
r = right;
|
||||
INPUTS_DEAD();
|
||||
}
|
||||
|
||||
tier2 op(_BINARY_OP_TRUEDIV_FLOAT_INPLACE_RIGHT, (left, right -- res, l, r)) {
|
||||
FLOAT_INPLACE_DIVOP(left, right, right);
|
||||
if (_divop_err) {
|
||||
ERROR_NO_POP();
|
||||
}
|
||||
res = right;
|
||||
l = left;
|
||||
r = PyStackRef_NULL;
|
||||
INPUTS_DEAD();
|
||||
}
|
||||
|
||||
pure op(_BINARY_OP_ADD_UNICODE, (left, right -- res, l, r)) {
|
||||
PyObject *left_o = PyStackRef_AsPyObjectBorrow(left);
|
||||
PyObject *right_o = PyStackRef_AsPyObjectBorrow(right);
|
||||
|
|
@ -983,6 +1030,11 @@ dummy_func(
|
|||
if (res_o == NULL) {
|
||||
ERROR_NO_POP();
|
||||
}
|
||||
// The JIT and tier 2 optimizer assume that float results from
|
||||
// binary operations are always uniquely referenced (refcount == 1).
|
||||
// If this assertion fails, update the optimizer to stop marking
|
||||
// float results as unique in optimizer_bytecodes.c.
|
||||
assert(!PyFloat_CheckExact(res_o) || Py_REFCNT(res_o) == 1);
|
||||
res = PyStackRef_FromPyObjectSteal(res_o);
|
||||
l = left;
|
||||
r = right;
|
||||
|
|
@ -5673,7 +5725,7 @@ dummy_func(
|
|||
DEAD(rhs);
|
||||
}
|
||||
|
||||
macro(BINARY_OP) = _SPECIALIZE_BINARY_OP + unused/4 + _BINARY_OP + POP_TOP + POP_TOP;
|
||||
macro(BINARY_OP) = _SPECIALIZE_BINARY_OP + _RECORD_TOS + _RECORD_NOS + unused/4 + _BINARY_OP + POP_TOP + POP_TOP;
|
||||
|
||||
pure replicate(2:4) inst(SWAP, (bottom, unused[oparg-2], top --
|
||||
bottom, unused[oparg-2], top)) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue