gh-131798: JIT: Narrow the return type of _CALL_LEN to int (#132940)

Reduce unnecessary guards whenever `len()` is called and used
after.

Co-authored-by: Max Bernstein <tekknolagi@gmail.com>
This commit is contained in:
Diego Russo 2025-04-25 19:57:42 +01:00 committed by GitHub
parent f0485de43a
commit 4c20f46fa0
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 18 additions and 1 deletions

View file

@ -1911,6 +1911,18 @@ class TestUopsOptimization(unittest.TestCase):
self.assertNotIn("_COMPARE_OP_INT", uops) self.assertNotIn("_COMPARE_OP_INT", uops)
self.assertNotIn("_GUARD_IS_TRUE_POP", uops) self.assertNotIn("_GUARD_IS_TRUE_POP", uops)
def test_call_len(self):
def testfunc(n):
a = [1, 2, 3, 4]
for _ in range(n):
_ = len(a) - 1
_, ex = self._run_with_optimizer(testfunc, TIER2_THRESHOLD)
uops = get_opnames(ex)
self.assertNotIn("_GUARD_NOS_INT", uops)
self.assertNotIn("_GUARD_TOS_INT", uops)
self.assertIn("_CALL_LEN", uops)
def global_identity(x): def global_identity(x):
return x return x

View file

@ -0,0 +1 @@
Allow the JIT to remove int guards after ``_CALL_LEN`` by setting the return type to int. Patch by Diego Russo

View file

@ -1055,6 +1055,10 @@ dummy_func(void) {
sym_set_const(callable, (PyObject *)&PyUnicode_Type); sym_set_const(callable, (PyObject *)&PyUnicode_Type);
} }
op(_CALL_LEN, (callable[1], self_or_null[1], args[oparg] -- res)) {
res = sym_new_type(ctx, &PyLong_Type);
}
// END BYTECODES // // END BYTECODES //
} }

View file

@ -2014,7 +2014,7 @@
case _CALL_LEN: { case _CALL_LEN: {
JitOptSymbol *res; JitOptSymbol *res;
res = sym_new_not_null(ctx); res = sym_new_type(ctx, &PyLong_Type);
stack_pointer[-2 - oparg] = res; stack_pointer[-2 - oparg] = res;
stack_pointer += -1 - oparg; stack_pointer += -1 - oparg;
assert(WITHIN_STACK_BOUNDS()); assert(WITHIN_STACK_BOUNDS());