8000 GH-115480: Reduce guard strength for binary ops when type of one oper… · python/cpython@a6647d1 · GitHub
[go: up one dir, main page]

Skip to content

Commit a6647d1

Browse files
authored
GH-115480: Reduce guard strength for binary ops when type of one operand is known already (GH-118050)
1 parent ceb6038 commit a6647d1

10 files changed

+316
-103
lines changed

Include/internal/pycore_optimizer.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ extern bool _Py_uop_sym_set_type(_Py_UopsSymbol *sym, PyTypeObject *typ);
9898
extern bool _Py_uop_sym_set_const(_Py_UopsSymbol *sym, PyObject *const_val);
9999
extern bool _Py_uop_sym_is_bottom(_Py_UopsSymbol *sym);
100100
extern int _Py_uop_sym_truthiness(_Py_UopsSymbol *sym);
101+
extern PyTypeObject *_Py_uop_sym_get_type(_Py_UopsSymbol *sym);
101102

102103

103104
extern int _Py_uop_abstractcontext_init(_Py_UOpsContext *ctx);

Include/internal/pycore_uop_ids.h

Lines changed: 86 additions & 82 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: 16 additions & 0 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: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -903,10 +903,50 @@ def testfunc(n):
903903
self.assertTrue(res)
904904
self.assertIsNotNone(ex)
905905
uops = get_opnames(ex)
906-
guard_both_float_count = [opname for opname in iter_opnames(ex) if opname == "_GUARD_BOTH_INT"]
907-
self.assertLessEqual(len(guard_both_float_count), 1)
906+
guard_both_int_count = [opname for opname in iter_opnames(ex) if opname == "_GUARD_BOTH_INT"]
907+
self.assertLessEqual(len(guard_both_int_count), 1)
908908
self.assertIn("_COMPARE_OP_INT", uops)
909909

910+
def test_compare_op_type_propagation_int_partial(self):
911+
def testfunc(n):
912+
a = 1
913+
for _ in range(n):
914+
if a > 2:
915+
x = 0
916+
if a < 2:
917+
x = 1
918+
return x
919+
920+
res, ex = self._run_with_optimizer(testfunc, 32)
921+
self.assertEqual(res, 1)
922+
self.assertIsNotNone(ex)
923+
uops = get_opnames(ex)
924+
guard_left_int_count = [opname for opname in iter_opnames(ex) if opname == "_GUARD_NOS_INT"]
925+
guard_both_int_count = [opname for opname in iter_opnames(ex) if opname == "_GUARD_BOTH_INT"]
926+
self.assertLessEqual(len(guard_left_int_count), 1)
927+
self.assertEqual(len(guard_both_int_count), 0)
928+
self.assertIn("_COMPARE_OP_INT", uops)
929+
930+
def test_compare_op_type_propagation_float_partial(self):
931+
def testfunc(n):
932+
a = 1.0
933+
for _ in range(n):
934+
if a > 2.0:
935+
x = 0
936+
if a < 2.0:
937+
x = 1
938+
return x
939+
940+
res, ex = self._run_with_optimizer(testfunc, 32)
941+
self.assertEqual(res, 1)
942+
self.assertIsNotNone(ex)
943+
uops = get_opnames(ex)
944+
guard_left_float_count = [opname for opname in iter_opnames(ex) if opname == "_GUARD_NOS_FLOAT"]
945+
guard_both_float_count = [opname for opname in iter_opnames(ex) if opname == "_GUARD_BOTH_FLOAT"]
946+
self.assertLessEqual(len(guard_left_float_count), 1)
947+
self.assertEqual(len(guard_both_float_count), 0)
948+
self.assertIn("_COMPARE_OP_FLOAT", uops)
949+
910950
def test_compare_op_type_propagation_unicode(self):
911951
def testfunc(n):
912952
a = ""

Python/bytecodes.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -426,6 +426,14 @@ dummy_func(
426426
EXIT_IF(!PyLong_CheckExact(right));
427427
}
428428

429+
op(_GUARD_NOS_INT, (left, unused -- left, unused)) {
430+
EXIT_IF(!PyLong_CheckExact(left));
431+
}
432+
433+
op(_GUARD_TOS_INT, (value -- value)) {
434+
EXIT_IF(!PyLong_CheckExact(value));
435+
}
436+
429437
pure op(_BINARY_OP_MULTIPLY_INT, (left, right -- res)) {
430438
STAT_INC(BINARY_OP, hit);
431439
res = _PyLong_Multiply((PyLongObject *)left, (PyLongObject *)right);
@@ -462,6 +470,14 @@ dummy_func(
462470
EXIT_IF(!PyFloat_CheckExact(right));
463471
}
464472

473+
op(_GUARD_NOS_FLOAT, (left, unused -- left, unused)) {
474+
EXIT_IF(!PyFloat_CheckExact(left));
475+
}
476+
477+
op(_GUARD_TOS_FLOAT, (value -- value)) {
478+
EXIT_IF(!PyFloat_CheckExact(value));
479+
}
480+
465481
pure op(_BINARY_OP_MULTIPLY_FLOAT, (left, right -- res)) {
466482
STAT_INC(BINARY_OP, hit);
467483
double dres =

0 commit comments

Comments
 (0)
0