Skip to content

Commit df396b5

Browse files
gh-104909: Split BINARY_OP into micro-ops (#104910)
Co-authored-by: Brandt Bucher <brandtbucher@gmail.com>
1 parent fbc9d0d commit df396b5

File tree

4 files changed

+785
-631
lines changed

4 files changed

+785
-631
lines changed

Python/bytecodes.c

Lines changed: 68 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -279,73 +279,111 @@ dummy_func(
279279

280280
family(binary_op, INLINE_CACHE_ENTRIES_BINARY_OP) = {
281281
BINARY_OP,
282-
BINARY_OP_ADD_FLOAT,
282+
BINARY_OP_MULTIPLY_INT,
283283
BINARY_OP_ADD_INT,
284-
BINARY_OP_ADD_UNICODE,
285-
// BINARY_OP_INPLACE_ADD_UNICODE, // This is an odd duck.
284+
BINARY_OP_SUBTRACT_INT,
286285
BINARY_OP_MULTIPLY_FLOAT,
287-
BINARY_OP_MULTIPLY_INT,
286+
BINARY_OP_ADD_FLOAT,
288287
BINARY_OP_SUBTRACT_FLOAT,
289-
BINARY_OP_SUBTRACT_INT,
288+
BINARY_OP_ADD_UNICODE,
289+
// BINARY_OP_INPLACE_ADD_UNICODE, // See comments at that opcode.
290290
};
291291

292-
293-
inst(BINARY_OP_MULTIPLY_INT, (unused/1, left, right -- prod)) {
292+
op(_GUARD_BOTH_INT, (left, right -- left, right)) {
294293
DEOPT_IF(!PyLong_CheckExact(left), BINARY_OP);
295294
DEOPT_IF(!PyLong_CheckExact(right), BINARY_OP);
295+
}
296+
297+
op(_BINARY_OP_MULTIPLY_INT, (unused/1, left, right -- res)) {
296298
STAT_INC(BINARY_OP, hit);
297-
prod = _PyLong_Multiply((PyLongObject *)left, (PyLongObject *)right);
299+
res = _PyLong_Multiply((PyLongObject *)left, (PyLongObject *)right);
298300
_Py_DECREF_SPECIALIZED(right, (destructor)PyObject_Free);
299301
_Py_DECREF_SPECIALIZED(left, (destructor)PyObject_Free);
300-
ERROR_IF(prod == NULL, error);
302+
ERROR_IF(res == NULL, error);
301303
}
302304

303-
inst(BINARY_OP_MULTIPLY_FLOAT, (unused/1, left, right -- prod)) {
304-
DEOPT_IF(!PyFloat_CheckExact(left), BINARY_OP);
305-
DEOPT_IF(!PyFloat_CheckExact(right), BINARY_OP);
305+
op(_BINARY_OP_ADD_INT, (unused/1, left, right -- res)) {
306306
STAT_INC(BINARY_OP, hit);
307-
double dprod = ((PyFloatObject *)left)->ob_fval *
308-
((PyFloatObject *)right)->ob_fval;
309-
DECREF_INPUTS_AND_REUSE_FLOAT(left, right, dprod, prod);
307+
res = _PyLong_Add((PyLongObject *)left, (PyLongObject *)right);
308+
_Py_DECREF_SPECIALIZED(right, (destructor)PyObject_Free);
309+
_Py_DECREF_SPECIALIZED(left, (destructor)PyObject_Free);
310+
ERROR_IF(res == NULL, error);
310311
}
311312

312-
inst(BINARY_OP_SUBTRACT_INT, (unused/1, left, right -- sub)) {
313-
DEOPT_IF(!PyLong_CheckExact(left), BINARY_OP);
314-
DEOPT_IF(!PyLong_CheckExact(right), BINARY_OP);
313+
op(_BINARY_OP_SUBTRACT_INT, (unused/1, left, right -- res)) {
315314
STAT_INC(BINARY_OP, hit);
316-
sub = _PyLong_Subtract((PyLongObject *)left, (PyLongObject *)right);
315+
res = _PyLong_Subtract((PyLongObject *)left, (PyLongObject *)right);
317316
_Py_DECREF_SPECIALIZED(right, (destructor)PyObject_Free);
318317
_Py_DECREF_SPECIALIZED(left, (destructor)PyObject_Free);
319-
ERROR_IF(sub == NULL, error);
318+
ERROR_IF(res == NULL, error);
320319
}
321320

322-
inst(BINARY_OP_SUBTRACT_FLOAT, (unused/1, left, right -- sub)) {
321+
macro(BINARY_OP_MULTIPLY_INT) =
322+
_GUARD_BOTH_INT + _BINARY_OP_MULTIPLY_INT;
323+
macro(BINARY_OP_ADD_INT) =
324+
_GUARD_BOTH_INT + _BINARY_OP_ADD_INT;
325+
macro(BINARY_OP_SUBTRACT_INT) =
326+
_GUARD_BOTH_INT + _BINARY_OP_SUBTRACT_INT;
327+
328+
op(_GUARD_BOTH_FLOAT, (left, right -- left, right)) {
323329
DEOPT_IF(!PyFloat_CheckExact(left), BINARY_OP);
324330
DEOPT_IF(!PyFloat_CheckExact(right), BINARY_OP);
331+
}
332+
333+
op(_BINARY_OP_MULTIPLY_FLOAT, (unused/1, left, right -- res)) {
325334
STAT_INC(BINARY_OP, hit);
326-
double dsub = ((PyFloatObject *)left)->ob_fval - ((PyFloatObject *)right)->ob_fval;
327-
DECREF_INPUTS_AND_REUSE_FLOAT(left, right, dsub, sub);
335+
double dres =
336+
((PyFloatObject *)left)->ob_fval *
337+
((PyFloatObject *)right)->ob_fval;
338+
DECREF_INPUTS_AND_REUSE_FLOAT(left, right, dres, res);
339+
}
340+
341+
op(_BINARY_OP_ADD_FLOAT, (unused/1, left, right -- res)) {
342+
STAT_INC(BINARY_OP, hit);
343+
double dres =
344+
((PyFloatObject *)left)->ob_fval +
345+
((PyFloatObject *)right)->ob_fval;
346+
DECREF_INPUTS_AND_REUSE_FLOAT(left, right, dres, res);
347+
}
348+
349+
op(_BINARY_OP_SUBTRACT_FLOAT, (unused/1, left, right -- res)) {
350+
STAT_INC(BINARY_OP, hit);
351+
double dres =
352+
((PyFloatObject *)left)->ob_fval -
353+
((PyFloatObject *)right)->ob_fval;
354+
DECREF_INPUTS_AND_REUSE_FLOAT(left, right, dres, res);
328355
}
329356

330-
inst(BINARY_OP_ADD_UNICODE, (unused/1, left, right -- res)) {
357+
macro(BINARY_OP_MULTIPLY_FLOAT) =
358+
_GUARD_BOTH_FLOAT + _BINARY_OP_MULTIPLY_FLOAT;
359+
macro(BINARY_OP_ADD_FLOAT) =
360+
_GUARD_BOTH_FLOAT + _BINARY_OP_ADD_FLOAT;
361+
macro(BINARY_OP_SUBTRACT_FLOAT) =
362+
_GUARD_BOTH_FLOAT + _BINARY_OP_SUBTRACT_FLOAT;
363+
364+
op(_GUARD_BOTH_UNICODE, (left, right -- left, right)) {
331365
DEOPT_IF(!PyUnicode_CheckExact(left), BINARY_OP);
332-
DEOPT_IF(Py_TYPE(right) != Py_TYPE(left), BINARY_OP);
366+
DEOPT_IF(!PyUnicode_CheckExact(right), BINARY_OP);
367+
}
368+
369+
op(_BINARY_OP_ADD_UNICODE, (unused/1, left, right -- res)) {
333370
STAT_INC(BINARY_OP, hit);
334371
res = PyUnicode_Concat(left, right);
335372
_Py_DECREF_SPECIALIZED(left, _PyUnicode_ExactDealloc);
336373
_Py_DECREF_SPECIALIZED(right, _PyUnicode_ExactDealloc);
337374
ERROR_IF(res == NULL, error);
338375
}
339376

377+
macro(BINARY_OP_ADD_UNICODE) =
378+
_GUARD_BOTH_UNICODE + _BINARY_OP_ADD_UNICODE;
379+
340380
// This is a subtle one. It's a super-instruction for
341381
// BINARY_OP_ADD_UNICODE followed by STORE_FAST
342382
// where the store goes into the left argument.
343383
// So the inputs are the same as for all BINARY_OP
344384
// specializations, but there is no output.
345385
// At the end we just skip over the STORE_FAST.
346-
inst(BINARY_OP_INPLACE_ADD_UNICODE, (left, right --)) {
347-
DEOPT_IF(!PyUnicode_CheckExact(left), BINARY_OP);
348-
DEOPT_IF(Py_TYPE(right) != Py_TYPE(left), BINARY_OP);
386+
op(_BINARY_OP_INPLACE_ADD_UNICODE, (left, right --)) {
349387
_Py_CODEUNIT true_next = next_instr[INLINE_CACHE_ENTRIES_BINARY_OP];
350388
assert(true_next.op.code == STORE_FAST ||
351389
true_next.op.code == STORE_FAST__LOAD_FAST);
@@ -372,24 +410,8 @@ dummy_func(
372410
JUMPBY(INLINE_CACHE_ENTRIES_BINARY_OP + 1);
373411
}
374412

375-
inst(BINARY_OP_ADD_FLOAT, (unused/1, left, right -- sum)) {
376-
DEOPT_IF(!PyFloat_CheckExact(left), BINARY_OP);
377-
DEOPT_IF(Py_TYPE(right) != Py_TYPE(left), BINARY_OP);
378-
STAT_INC(BINARY_OP, hit);
379-
double dsum = ((PyFloatObject *)left)->ob_fval +
380-
((PyFloatObject *)right)->ob_fval;
381-
DECREF_INPUTS_AND_REUSE_FLOAT(left, right, dsum, sum);
382-
}
383-
384-
inst(BINARY_OP_ADD_INT, (unused/1, left, right -- sum)) {
385-
DEOPT_IF(!PyLong_CheckExact(left), BINARY_OP);
386-
DEOPT_IF(Py_TYPE(right) != Py_TYPE(left), BINARY_OP);
387-
STAT_INC(BINARY_OP, hit);
388-
sum = _PyLong_Add((PyLongObject *)left, (PyLongObject *)right);
389-
_Py_DECREF_SPECIALIZED(right, (destructor)PyObject_Free);
390-
_Py_DECREF_SPECIALIZED(left, (destructor)PyObject_Free);
391-
ERROR_IF(sum == NULL, error);
392-
}
413+
macro(BINARY_OP_INPLACE_ADD_UNICODE) =
414+
_GUARD_BOTH_UNICODE + _BINARY_OP_INPLACE_ADD_UNICODE;
393415

394416
family(binary_subscr, INLINE_CACHE_ENTRIES_BINARY_SUBSCR) = {
395417
BINARY_SUBSCR,

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy