Skip to content

Commit 4615164

Browse files
authored
GH-131798: Optimize away type(x) in the JIT when the result is known (GH-135194)
1 parent f00512d commit 4615164

File tree

4 files changed

+34
-7
lines changed

4 files changed

+34
-7
lines changed

Lib/test/test_capi/test_opt.py

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1778,11 +1778,12 @@ def testfunc(n):
17781778
self.assertNotIn("_GUARD_TOS_UNICODE", uops)
17791779
self.assertIn("_BINARY_OP_ADD_UNICODE", uops)
17801780

1781-
def test_call_type_1(self):
1781+
def test_call_type_1_guards_removed(self):
17821782
def testfunc(n):
17831783
x = 0
17841784
for _ in range(n):
1785-
x += type(42) is int
1785+
foo = eval('42')
1786+
x += type(foo) is int
17861787
return x
17871788

17881789
res, ex = self._run_with_optimizer(testfunc, TIER2_THRESHOLD)
@@ -1793,6 +1794,25 @@ def testfunc(n):
17931794
self.assertNotIn("_GUARD_NOS_NULL", uops)
17941795
self.assertNotIn("_GUARD_CALLABLE_TYPE_1", uops)
17951796

1797+
def test_call_type_1_known_type(self):
1798+
def testfunc(n):
1799+
x = 0
1800+
for _ in range(n):
1801+
x += type(42) is int
1802+
return x
1803+
1804+
res, ex = self._run_with_optimizer(testfunc, TIER2_THRESHOLD)
1805+
self.assertEqual(res, TIER2_THRESHOLD)
1806+
self.assertIsNotNone(ex)
1807+
uops = get_opnames(ex)
1808+
# When the result of type(...) is known, _CALL_TYPE_1 is replaced with
1809+
# _POP_CALL_ONE_LOAD_CONST_INLINE_BORROW which is optimized away in
1810+
# remove_unneeded_uops.
1811+
self.assertNotIn("_CALL_TYPE_1", uops)
1812+
self.assertNotIn("_POP_CALL_ONE_LOAD_CONST_INLINE_BORROW", uops)
1813+
self.assertNotIn("_POP_CALL_LOAD_CONST_INLINE_BORROW", uops)
1814+
self.assertNotIn("_POP_TOP_LOAD_CONST_INLINE_BORROW", uops)
1815+
17961816
def test_call_type_1_result_is_const(self):
17971817
def testfunc(n):
17981818
x = 0
@@ -1806,7 +1826,6 @@ def testfunc(n):
18061826
self.assertEqual(res, TIER2_THRESHOLD)
18071827
self.assertIsNotNone(ex)
18081828
uops = get_opnames(ex)
1809-
self.assertIn("_CALL_TYPE_1", uops)
18101829
self.assertNotIn("_GUARD_IS_NOT_NONE_POP", uops)
18111830

18121831
def test_call_str_1(self):
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Optimize away ``_CALL_TYPE_1`` in the JIT when the return type is known.
2+
Patch by Tomas Roun

Python/optimizer_bytecodes.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -937,8 +937,11 @@ dummy_func(void) {
937937
}
938938

939939
op(_CALL_TYPE_1, (unused, unused, arg -- res)) {
940-
if (sym_has_type(arg)) {
941-
res = sym_new_const(ctx, (PyObject *)sym_get_type(arg));
940+
PyObject* type = (PyObject *)sym_get_type(arg);
941+
if (type) {
942+
res = sym_new_const(ctx, type);
943+
REPLACE_OP(this_instr, _POP_CALL_ONE_LOAD_CONST_INLINE_BORROW, 0,
944+
(uintptr_t)type);
942945
}
943946
else {
944947
res = sym_new_not_null(ctx);

Python/optimizer_cases.c.h

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

0 commit comments

Comments
 (0)