From: Amit Lavon Date: Tue, 4 Mar 2025 21:20:17 +0000 (-0800) Subject: GH-130415: Narrow str to "" based on boolean tests (GH-130476) X-Git-Tag: v3.14.0a6~156 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=691354ccb04f0e8f4faa864ee5003fc5efe8377e;p=thirdparty%2FPython%2Fcpython.git GH-130415: Narrow str to "" based on boolean tests (GH-130476) --- diff --git a/Lib/test/test_capi/test_opt.py b/Lib/test/test_capi/test_opt.py index a4faab2124b9..c985009e1202 100644 --- a/Lib/test/test_capi/test_opt.py +++ b/Lib/test/test_capi/test_opt.py @@ -1531,6 +1531,39 @@ class TestUopsOptimization(unittest.TestCase): # But all of the appends we care about are still there: self.assertEqual(uops.count("_CALL_LIST_APPEND"), len("ABCDEFG")) +def test_narrow_type_to_constant_str_empty(self): + def f(n): + trace = [] + for i in range(n): + # Hopefully the optimizer can't guess what the value is. + # empty is always "", but we can only prove that it's a string: + false = i == TIER2_THRESHOLD + empty = "X"[:false] + trace.append("A") + if not empty: # Kept. + trace.append("B") + if not empty: # Removed! + trace.append("C") + trace.append("D") + if empty: # Removed! + trace.append("X") + trace.append("E") + trace.append("F") + if empty: # Removed! + trace.append("X") + trace.append("G") + return trace + + trace, ex = self._run_with_optimizer(f, TIER2_THRESHOLD) + self.assertEqual(trace, list("ABCDEFG") * TIER2_THRESHOLD) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + # Only one guard remains: + self.assertEqual(uops.count("_GUARD_IS_FALSE_POP"), 1) + self.assertEqual(uops.count("_GUARD_IS_TRUE_POP"), 0) + # But all of the appends we care about are still there: + self.assertEqual(uops.count("_CALL_LIST_APPEND"), len("ABCDEFG")) + def global_identity(x): return x diff --git a/Misc/ACKS b/Misc/ACKS index 2526e78389de..d110002ffeb8 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -1065,6 +1065,7 @@ Keenan Lau Piers Lauder Ben Laurie Yoni Lavi +Amit Lavon Simon Law Julia Lawall Chris Lawrence diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-02-22-22-49-00.gh-issue-130415.WyxBYS.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-02-22-22-49-00.gh-issue-130415.WyxBYS.rst new file mode 100644 index 000000000000..2559aa8e212b --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2025-02-22-22-49-00.gh-issue-130415.WyxBYS.rst @@ -0,0 +1 @@ +Improve JIT's ability to optimize strings in boolean contexts. diff --git a/Python/optimizer_bytecodes.c b/Python/optimizer_bytecodes.c index 2aeed24a8c6c..4bdef60dda9d 100644 --- a/Python/optimizer_bytecodes.c +++ b/Python/optimizer_bytecodes.c @@ -426,7 +426,7 @@ dummy_func(void) { op(_TO_BOOL_STR, (value -- res)) { if (!optimize_to_bool(this_instr, ctx, value, &res)) { - res = sym_new_type(ctx, &PyBool_Type); + res = sym_new_truthiness(ctx, value, true); sym_set_type(value, &PyUnicode_Type); } } diff --git a/Python/optimizer_cases.c.h b/Python/optimizer_cases.c.h index 9555e141ed5c..306599bea778 100644 --- a/Python/optimizer_cases.c.h +++ b/Python/optimizer_cases.c.h @@ -213,7 +213,7 @@ JitOptSymbol *res; value = stack_pointer[-1]; if (!optimize_to_bool(this_instr, ctx, value, &res)) { - res = sym_new_type(ctx, &PyBool_Type); + res = sym_new_truthiness(ctx, value, true); sym_set_type(value, &PyUnicode_Type); } stack_pointer[-1] = res; diff --git a/Python/optimizer_symbols.c b/Python/optimizer_symbols.c index 28a2791f5e7d..5adc1c8a62ce 100644 --- a/Python/optimizer_symbols.c +++ b/Python/optimizer_symbols.c @@ -302,6 +302,9 @@ _Py_uop_sym_set_const(JitOptContext *ctx, JitOptSymbol *sym, PyObject *const_val else if (type == &PyLong_Type) { _Py_uop_sym_set_const(ctx, value, Py_GetConstant(Py_CONSTANT_ZERO)); } + else if (type == &PyUnicode_Type) { + _Py_uop_sym_set_const(ctx, value, Py_GetConstant(Py_CONSTANT_EMPTY_STR)); + } // TODO: More types (GH-130415)! make_const(sym, const_val); return;