Skip to content
4 changes: 2 additions & 2 deletions Include/internal/pycore_opcode_metadata.h

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

2 changes: 1 addition & 1 deletion Include/internal/pycore_uop_ids.h

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

8 changes: 4 additions & 4 deletions Include/internal/pycore_uop_metadata.h

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

17 changes: 17 additions & 0 deletions Lib/test/test_capi/test_opt.py
Original file line number Diff line number Diff line change
Expand Up @@ -2897,6 +2897,23 @@ def testfunc(n):
self.assertIn("_POP_TOP_NOP", uops)
self.assertLessEqual(count_ops(ex, "_POP_TOP"), 2)

def test_binary_op_extend_float_long_add_refcount_elimination(self):
def testfunc(n):
a = 1.5
b = 2
res = 0.0
for _ in range(n):
res = a + b
return res

res, ex = self._run_with_optimizer(testfunc, TIER2_THRESHOLD)
self.assertEqual(res, 3.5)
self.assertIsNotNone(ex)
uops = get_opnames(ex)
self.assertIn("_BINARY_OP_EXTEND", uops)
self.assertIn("_POP_TOP_NOP", uops)
self.assertLessEqual(count_ops(ex, "_POP_TOP"), 2)

def test_remove_guard_for_slice_list(self):
def f(n):
for i in range(n):
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Eliminate redundant refcounting from ``BINARY_OP_EXTEND``.
36 changes: 23 additions & 13 deletions Modules/_testinternalcapi/test_cases.c.h
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,9 @@
_PyStackRef left;
_PyStackRef right;
_PyStackRef res;
_PyStackRef l;
_PyStackRef r;
_PyStackRef value;
/* Skip 1 cache entry */
// _GUARD_BINARY_OP_EXTEND
{
Expand Down Expand Up @@ -348,25 +351,32 @@
STAT_INC(BINARY_OP, hit);
_PyFrame_SetStackPointer(frame, stack_pointer);
PyObject *res_o = d->action(left_o, right_o);
_PyStackRef tmp = right;
right = PyStackRef_NULL;
stack_pointer[-1] = right;
PyStackRef_CLOSE(tmp);
tmp = left;
left = PyStackRef_NULL;
stack_pointer[-2] = left;
PyStackRef_CLOSE(tmp);
stack_pointer = _PyFrame_GetStackPointer(frame);
stack_pointer += -2;
ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__);
if (res_o == NULL) {
JUMP_TO_LABEL(error);
}
res = PyStackRef_FromPyObjectSteal(res_o);
l = left;
r = right;
}
// _POP_TOP
{
value = r;
stack_pointer[-2] = res;
stack_pointer[-1] = l;
_PyFrame_SetStackPointer(frame, stack_pointer);
PyStackRef_XCLOSE(value);
stack_pointer = _PyFrame_GetStackPointer(frame);
}
// _POP_TOP
{
value = l;
stack_pointer += -1;
ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__);
_PyFrame_SetStackPointer(frame, stack_pointer);
PyStackRef_XCLOSE(value);
stack_pointer = _PyFrame_GetStackPointer(frame);
}
stack_pointer[0] = res;
stack_pointer += 1;
ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__);
DISPATCH();
}

Expand Down
13 changes: 9 additions & 4 deletions Python/bytecodes.c
Original file line number Diff line number Diff line change
Expand Up @@ -829,7 +829,7 @@ dummy_func(
DEOPT_IF(!res);
}

op(_BINARY_OP_EXTEND, (descr/4, left, right -- res)) {
op(_BINARY_OP_EXTEND, (descr/4, left, right -- res, l, r)) {
PyObject *left_o = PyStackRef_AsPyObjectBorrow(left);
PyObject *right_o = PyStackRef_AsPyObjectBorrow(right);
assert(INLINE_CACHE_ENTRIES_BINARY_OP == 5);
Expand All @@ -838,13 +838,18 @@ dummy_func(
STAT_INC(BINARY_OP, hit);

PyObject *res_o = d->action(left_o, right_o);
DECREF_INPUTS();
ERROR_IF(res_o == NULL);
if (res_o == NULL) {
ERROR_NO_POP();
}
res = PyStackRef_FromPyObjectSteal(res_o);
l = left;
r = right;
DEAD(left);
DEAD(right);
}

macro(BINARY_OP_EXTEND) =
unused/1 + _GUARD_BINARY_OP_EXTEND + rewind/-4 + _BINARY_OP_EXTEND;
unused/1 + _GUARD_BINARY_OP_EXTEND + rewind/-4 + _BINARY_OP_EXTEND + POP_TOP + POP_TOP;

macro(BINARY_OP_INPLACE_ADD_UNICODE) =
_GUARD_TOS_UNICODE + _GUARD_NOS_UNICODE + unused/5 + _BINARY_OP_INPLACE_ADD_UNICODE;
Expand Down
24 changes: 10 additions & 14 deletions Python/executor_cases.c.h

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

36 changes: 23 additions & 13 deletions Python/generated_cases.c.h

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

6 changes: 6 additions & 0 deletions Python/optimizer_bytecodes.c
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,12 @@ dummy_func(void) {
r = right;
}

op(_BINARY_OP_EXTEND, (left, right -- res, l, r)) {
res = sym_new_not_null(ctx);
l = left;
r = right;
}

op(_BINARY_OP_INPLACE_ADD_UNICODE, (left, right -- res)) {
if (sym_is_const(ctx, left) && sym_is_const(ctx, right)) {
assert(PyUnicode_CheckExact(sym_get_const(ctx, left)));
Expand Down
15 changes: 13 additions & 2 deletions Python/optimizer_cases.c.h

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

Loading