https://github.com/python/cpython/commit/691354ccb04f0e8f4faa864ee5003fc5efe8377e
commit: 691354ccb04f0e8f4faa864ee5003fc5efe8377e
branch: main
author: Amit Lavon <amitlavon1.s...@gmail.com>
committer: brandtbucher <brandtbuc...@gmail.com>
date: 2025-03-04T13:20:17-08:00
summary:

GH-130415: Narrow str to "" based on boolean tests (GH-130476)

files:
A 
Misc/NEWS.d/next/Core_and_Builtins/2025-02-22-22-49-00.gh-issue-130415.WyxBYS.rst
M Lib/test/test_capi/test_opt.py
M Misc/ACKS
M Python/optimizer_bytecodes.c
M Python/optimizer_cases.c.h
M Python/optimizer_symbols.c

diff --git a/Lib/test/test_capi/test_opt.py b/Lib/test/test_capi/test_opt.py
index a4faab2124b9c7..c985009e120203 100644
--- a/Lib/test/test_capi/test_opt.py
+++ b/Lib/test/test_capi/test_opt.py
@@ -1531,6 +1531,39 @@ def f(n):
         # 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 2526e78389dea2..d110002ffeb86c 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 00000000000000..2559aa8e212bfa
--- /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 2aeed24a8c6c32..4bdef60dda9d53 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 9555e141ed5c9f..306599bea77877 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 28a2791f5e7de6..5adc1c8a62ce8b 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;

_______________________________________________
Python-checkins mailing list -- python-checkins@python.org
To unsubscribe send an email to python-checkins-le...@python.org
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: arch...@mail-archive.com

Reply via email to