Skip to content

Commit 0a5c04a

Browse files
authored
gh-134584: Eliminate redundant refcounting from TO_BOOL_STR (GH-143417)
Signed-off-by: Manjusaka <[email protected]>
1 parent 98e55d7 commit 0a5c04a

File tree

11 files changed

+138
-82
lines changed

11 files changed

+138
-82
lines changed

Include/internal/pycore_opcode_metadata.h

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Include/internal/pycore_uop_ids.h

Lines changed: 18 additions & 16 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Include/internal/pycore_uop_metadata.h

Lines changed: 11 additions & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Lib/test/test_capi/test_opt.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2937,6 +2937,23 @@ def testfunc(n):
29372937
self.assertLessEqual(count_ops(ex, "_POP_TOP"), 1)
29382938
self.assertIn("_POP_TOP_NOP", uops)
29392939

2940+
def test_to_bool_str(self):
2941+
def f(n):
2942+
for i in range(n):
2943+
false = i == TIER2_THRESHOLD
2944+
empty = "X"[:false]
2945+
if empty:
2946+
return 1
2947+
return 0
2948+
2949+
res, ex = self._run_with_optimizer(f, TIER2_THRESHOLD)
2950+
self.assertEqual(res, 0)
2951+
self.assertIsNotNone(ex)
2952+
uops = get_opnames(ex)
2953+
self.assertIn("_TO_BOOL_STR", uops)
2954+
self.assertLessEqual(count_ops(ex, "_POP_TOP"), 3)
2955+
self.assertIn("_POP_TOP_NOP", uops)
2956+
29402957
def test_to_bool_always_true(self):
29412958
def testfunc(n):
29422959
class A:
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Eliminate redundant refcounting from ``TO_BOOL_STR``.

Python/bytecodes.c

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -547,23 +547,16 @@ dummy_func(
547547
EXIT_IF(!PyUnicode_CheckExact(value_o));
548548
}
549549

550-
op(_TO_BOOL_STR, (value -- res)) {
550+
op(_TO_BOOL_STR, (value -- res, v)) {
551551
STAT_INC(TO_BOOL, hit);
552552
PyObject *value_o = PyStackRef_AsPyObjectBorrow(value);
553-
if (value_o == &_Py_STR(empty)) {
554-
assert(_Py_IsImmortal(value_o));
555-
DEAD(value);
556-
res = PyStackRef_False;
557-
}
558-
else {
559-
assert(Py_SIZE(value_o));
560-
PyStackRef_CLOSE(value);
561-
res = PyStackRef_True;
562-
}
553+
res = value_o == &_Py_STR(empty) ? PyStackRef_False : PyStackRef_True;
554+
v = value;
555+
DEAD(value);
563556
}
564557

565558
macro(TO_BOOL_STR) =
566-
_GUARD_TOS_UNICODE + unused/1 + unused/2 + _TO_BOOL_STR;
559+
_GUARD_TOS_UNICODE + unused/1 + unused/2 + _TO_BOOL_STR + _POP_TOP_UNICODE;
567560

568561
op(_REPLACE_WITH_TRUE, (value -- res, v)) {
569562
res = PyStackRef_True;

Python/executor_cases.c.h

Lines changed: 47 additions & 15 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Python/generated_cases.c.h

Lines changed: 9 additions & 14 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Python/optimizer_analysis.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,8 @@ optimize_to_bool(
214214
_PyUOpInstruction *this_instr,
215215
JitOptContext *ctx,
216216
JitOptRef value,
217-
JitOptRef *result_ptr)
217+
JitOptRef *result_ptr,
218+
bool insert_mode)
218219
{
219220
if (sym_matches_type(value, &PyBool_Type)) {
220221
REPLACE_OP(this_instr, _NOP, 0, 0);
@@ -224,7 +225,10 @@ optimize_to_bool(
224225
int truthiness = sym_truthiness(ctx, value);
225226
if (truthiness >= 0) {
226227
PyObject *load = truthiness ? Py_True : Py_False;
227-
REPLACE_OP(this_instr, _POP_TOP_LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)load);
228+
int opcode = insert_mode ?
229+
_INSERT_1_LOAD_CONST_INLINE_BORROW :
230+
_POP_TOP_LOAD_CONST_INLINE_BORROW;
231+
REPLACE_OP(this_instr, opcode, 0, (uintptr_t)load);
228232
*result_ptr = sym_new_const(ctx, load);
229233
return 1;
230234
}

Python/optimizer_bytecodes.c

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,8 @@ optimize_to_bool(
4444
_PyUOpInstruction *this_instr,
4545
JitOptContext *ctx,
4646
JitOptSymbol *value,
47-
JitOptSymbol **result_ptr);
47+
JitOptSymbol **result_ptr,
48+
bool insert_mode);
4849

4950
extern void
5051
eliminate_pop_guard(_PyUOpInstruction *this_instr, bool exit);
@@ -377,36 +378,36 @@ dummy_func(void) {
377378
}
378379

379380
op(_TO_BOOL, (value -- res)) {
380-
int already_bool = optimize_to_bool(this_instr, ctx, value, &res);
381+
int already_bool = optimize_to_bool(this_instr, ctx, value, &res, false);
381382
if (!already_bool) {
382383
res = sym_new_truthiness(ctx, value, true);
383384
}
384385
}
385386

386387
op(_TO_BOOL_BOOL, (value -- value)) {
387-
int already_bool = optimize_to_bool(this_instr, ctx, value, &value);
388+
int already_bool = optimize_to_bool(this_instr, ctx, value, &value, false);
388389
if (!already_bool) {
389390
sym_set_type(value, &PyBool_Type);
390391
}
391392
}
392393

393394
op(_TO_BOOL_INT, (value -- res)) {
394-
int already_bool = optimize_to_bool(this_instr, ctx, value, &res);
395+
int already_bool = optimize_to_bool(this_instr, ctx, value, &res, false);
395396
if (!already_bool) {
396397
sym_set_type(value, &PyLong_Type);
397398
res = sym_new_truthiness(ctx, value, true);
398399
}
399400
}
400401

401402
op(_TO_BOOL_LIST, (value -- res)) {
402-
int already_bool = optimize_to_bool(this_instr, ctx, value, &res);
403+
int already_bool = optimize_to_bool(this_instr, ctx, value, &res, false);
403404
if (!already_bool) {
404405
res = sym_new_type(ctx, &PyBool_Type);
405406
}
406407
}
407408

408409
op(_TO_BOOL_NONE, (value -- res)) {
409-
int already_bool = optimize_to_bool(this_instr, ctx, value, &res);
410+
int already_bool = optimize_to_bool(this_instr, ctx, value, &res, false);
410411
if (!already_bool) {
411412
sym_set_const(value, Py_None);
412413
res = sym_new_const(ctx, Py_False);
@@ -431,8 +432,9 @@ dummy_func(void) {
431432
sym_set_type(value, &PyUnicode_Type);
432433
}
433434

434-
op(_TO_BOOL_STR, (value -- res)) {
435-
int already_bool = optimize_to_bool(this_instr, ctx, value, &res);
435+
op(_TO_BOOL_STR, (value -- res, v)) {
436+
int already_bool = optimize_to_bool(this_instr, ctx, value, &res, true);
437+
v = value;
436438
if (!already_bool) {
437439
res = sym_new_truthiness(ctx, value, true);
438440
}

0 commit comments

Comments
 (0)