Skip to content

Commit 4815131

Browse files
authored
gh-100239: specialize bitwise logical binary ops on ints (#128927)
1 parent 03d9cdb commit 4815131

File tree

7 files changed

+82
-3
lines changed

7 files changed

+82
-3
lines changed

Include/internal/pycore_opcode_metadata.h

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Include/internal/pycore_uop_metadata.h

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Lib/test/test_opcache.py

+23
Original file line numberDiff line numberDiff line change
@@ -1396,6 +1396,29 @@ def compactlong_rhs(arg):
13961396

13971397
binary_op_nan()
13981398

1399+
def binary_op_bitwise_extend():
1400+
for _ in range(100):
1401+
a, b = 2, 7
1402+
x = a | b
1403+
self.assertEqual(x, 7)
1404+
y = a & b
1405+
self.assertEqual(y, 2)
1406+
z = a ^ b
1407+
self.assertEqual(z, 5)
1408+
a, b = 3, 9
1409+
a |= b
1410+
self.assertEqual(a, 11)
1411+
a, b = 11, 9
1412+
a &= b
1413+
self.assertEqual(a, 9)
1414+
a, b = 3, 9
1415+
a ^= b
1416+
self.assertEqual(a, 10)
1417+
1418+
binary_op_bitwise_extend()
1419+
self.assert_specialized(binary_op_bitwise_extend, "BINARY_OP_EXTEND")
1420+
self.assert_no_opcode(binary_op_bitwise_extend, "BINARY_OP")
1421+
13991422
@cpython_only
14001423
@requires_specialization_ft
14011424
def test_load_super_attr(self):
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Specialize ``BINARY_OP`` for bitwise logical operations on compact ints.

Python/bytecodes.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -759,7 +759,7 @@ dummy_func(
759759
assert(INLINE_CACHE_ENTRIES_BINARY_OP == 5);
760760
assert(d && d->guard);
761761
int res = d->guard(left_o, right_o);
762-
EXIT_IF(!res);
762+
DEOPT_IF(!res);
763763
}
764764

765765
pure op(_BINARY_OP_EXTEND, (descr/4, left, right -- res)) {

Python/specialize.c

+54
Original file line numberDiff line numberDiff line change
@@ -581,6 +581,10 @@ _PyCode_Quicken(_Py_CODEUNIT *instructions, Py_ssize_t size, PyObject *consts,
581581
#define SPEC_FAIL_BINARY_OP_TRUE_DIVIDE_FLOAT 26
582582
#define SPEC_FAIL_BINARY_OP_TRUE_DIVIDE_OTHER 27
583583
#define SPEC_FAIL_BINARY_OP_XOR 28
584+
#define SPEC_FAIL_BINARY_OP_OR_INT 29
585+
#define SPEC_FAIL_BINARY_OP_OR_DIFFERENT_TYPES 30
586+
#define SPEC_FAIL_BINARY_OP_XOR_INT 31
587+
#define SPEC_FAIL_BINARY_OP_XOR_DIFFERENT_TYPES 32
584588

585589
/* Calls */
586590

@@ -2379,6 +2383,12 @@ binary_op_fail_kind(int oparg, PyObject *lhs, PyObject *rhs)
23792383
return SPEC_FAIL_BINARY_OP_MULTIPLY_OTHER;
23802384
case NB_OR:
23812385
case NB_INPLACE_OR:
2386+
if (!Py_IS_TYPE(lhs, Py_TYPE(rhs))) {
2387+
return SPEC_FAIL_BINARY_OP_OR_DIFFERENT_TYPES;
2388+
}
2389+
if (PyLong_CheckExact(lhs)) {
2390+
return SPEC_FAIL_BINARY_OP_OR_INT;
2391+
}
23822392
return SPEC_FAIL_BINARY_OP_OR;
23832393
case NB_POWER:
23842394
case NB_INPLACE_POWER:
@@ -2406,6 +2416,12 @@ binary_op_fail_kind(int oparg, PyObject *lhs, PyObject *rhs)
24062416
return SPEC_FAIL_BINARY_OP_TRUE_DIVIDE_OTHER;
24072417
case NB_XOR:
24082418
case NB_INPLACE_XOR:
2419+
if (!Py_IS_TYPE(lhs, Py_TYPE(rhs))) {
2420+
return SPEC_FAIL_BINARY_OP_XOR_DIFFERENT_TYPES;
2421+
}
2422+
if (PyLong_CheckExact(lhs)) {
2423+
return SPEC_FAIL_BINARY_OP_XOR_INT;
2424+
}
24092425
return SPEC_FAIL_BINARY_OP_XOR;
24102426
}
24112427
Py_UNREACHABLE();
@@ -2414,6 +2430,34 @@ binary_op_fail_kind(int oparg, PyObject *lhs, PyObject *rhs)
24142430

24152431
/** Binary Op Specialization Extensions */
24162432

2433+
/* long-long */
2434+
2435+
static inline int
2436+
is_compactlong(PyObject *v)
2437+
{
2438+
return PyLong_CheckExact(v) &&
2439+
_PyLong_IsCompact((PyLongObject *)v);
2440+
}
2441+
2442+
static int
2443+
compactlongs_guard(PyObject *lhs, PyObject *rhs)
2444+
{
2445+
return (is_compactlong(lhs) && is_compactlong(rhs));
2446+
}
2447+
2448+
#define BITWISE_LONGS_ACTION(NAME, OP) \
2449+
static PyObject * \
2450+
(NAME)(PyObject *lhs, PyObject *rhs) \
2451+
{ \
2452+
Py_ssize_t rhs_val = _PyLong_CompactValue((PyLongObject *)rhs); \
2453+
Py_ssize_t lhs_val = _PyLong_CompactValue((PyLongObject *)lhs); \
2454+
return PyLong_FromSsize_t(lhs_val OP rhs_val); \
2455+
}
2456+
BITWISE_LONGS_ACTION(compactlongs_or, |)
2457+
BITWISE_LONGS_ACTION(compactlongs_and, &)
2458+
BITWISE_LONGS_ACTION(compactlongs_xor, ^)
2459+
#undef BITWISE_LONGS_ACTION
2460+
24172461
/* float-long */
24182462

24192463
static inline int
@@ -2484,6 +2528,15 @@ LONG_FLOAT_ACTION(compactlong_float_multiply, *)
24842528
LONG_FLOAT_ACTION(compactlong_float_true_div, /)
24852529
#undef LONG_FLOAT_ACTION
24862530

2531+
static _PyBinaryOpSpecializationDescr compactlongs_specs[NB_OPARG_LAST+1] = {
2532+
[NB_OR] = {compactlongs_guard, compactlongs_or},
2533+
[NB_AND] = {compactlongs_guard, compactlongs_and},
2534+
[NB_XOR] = {compactlongs_guard, compactlongs_xor},
2535+
[NB_INPLACE_OR] = {compactlongs_guard, compactlongs_or},
2536+
[NB_INPLACE_AND] = {compactlongs_guard, compactlongs_and},
2537+
[NB_INPLACE_XOR] = {compactlongs_guard, compactlongs_xor},
2538+
};
2539+
24872540
static _PyBinaryOpSpecializationDescr float_compactlong_specs[NB_OPARG_LAST+1] = {
24882541
[NB_ADD] = {float_compactlong_guard, float_compactlong_add},
24892542
[NB_SUBTRACT] = {float_compactlong_guard, float_compactlong_subtract},
@@ -2512,6 +2565,7 @@ binary_op_extended_specialization(PyObject *lhs, PyObject *rhs, int oparg,
25122565

25132566
LOOKUP_SPEC(compactlong_float_specs, oparg);
25142567
LOOKUP_SPEC(float_compactlong_specs, oparg);
2568+
LOOKUP_SPEC(compactlongs_specs, oparg);
25152569
#undef LOOKUP_SPEC
25162570
return 0;
25172571
}

Tools/c-analyzer/cpython/ignored.tsv

+1
Original file line numberDiff line numberDiff line change
@@ -381,6 +381,7 @@ Python/pylifecycle.c - INTERPRETER_TRAMPOLINE_CODEDEF -
381381
Python/pystate.c - initial -
382382
Python/specialize.c - adaptive_opcodes -
383383
Python/specialize.c - cache_requirements -
384+
Python/specialize.c - compactlongs_specs -
384385
Python/specialize.c - float_compactlong_specs -
385386
Python/specialize.c - compactlong_float_specs -
386387
Python/stdlib_module_names.h - _Py_stdlib_module_names -

0 commit comments

Comments
 (0)