[Python-checkins] bpo-45510: Specialize BINARY_SUBTRACT (GH-29523)

markshannon webhook-mailer at python.org
Thu Nov 18 04:20:08 EST 2021


https://github.com/python/cpython/commit/345ba3f080c140dee3102f472bc166c2db191bcc
commit: 345ba3f080c140dee3102f472bc166c2db191bcc
branch: main
author: Dong-hee Na <donghee.na at python.org>
committer: markshannon <mark at hotpy.org>
date: 2021-11-18T09:19:58Z
summary:

bpo-45510: Specialize BINARY_SUBTRACT (GH-29523)

files:
M Include/internal/pycore_long.h
M Include/opcode.h
M Lib/opcode.py
M Objects/longobject.c
M Python/ceval.c
M Python/opcode_targets.h
M Python/specialize.c

diff --git a/Include/internal/pycore_long.h b/Include/internal/pycore_long.h
index 2f786083e4527..b9f926996d810 100644
--- a/Include/internal/pycore_long.h
+++ b/Include/internal/pycore_long.h
@@ -23,6 +23,7 @@ static inline PyObject* _PyLong_GetOne(void)
 
 PyObject *_PyLong_Add(PyLongObject *left, PyLongObject *right);
 PyObject *_PyLong_Multiply(PyLongObject *left, PyLongObject *right);
+PyObject *_PyLong_Subtract(PyLongObject *left, PyLongObject *right);
 
 /* Used by Python/mystrtoul.c, _PyBytes_FromHex(),
    _PyBytes_DecodeEscape(), etc. */
diff --git a/Include/opcode.h b/Include/opcode.h
index c7354de9a0687..ca20ccda1199b 100644
--- a/Include/opcode.h
+++ b/Include/opcode.h
@@ -118,39 +118,41 @@ extern "C" {
 #define BINARY_OP_INPLACE_ADD_UNICODE    16
 #define BINARY_OP_MULTIPLY_INT           17
 #define BINARY_OP_MULTIPLY_FLOAT         18
-#define BINARY_SUBSCR_ADAPTIVE           19
-#define BINARY_SUBSCR_LIST_INT           20
-#define BINARY_SUBSCR_TUPLE_INT          21
-#define BINARY_SUBSCR_DICT               22
-#define CALL_FUNCTION_ADAPTIVE           23
-#define CALL_FUNCTION_BUILTIN_O          24
-#define CALL_FUNCTION_BUILTIN_FAST       26
-#define CALL_FUNCTION_LEN                27
-#define CALL_FUNCTION_ISINSTANCE         28
-#define CALL_FUNCTION_PY_SIMPLE          29
-#define JUMP_ABSOLUTE_QUICK              34
-#define LOAD_ATTR_ADAPTIVE               36
-#define LOAD_ATTR_INSTANCE_VALUE         38
-#define LOAD_ATTR_WITH_HINT              39
-#define LOAD_ATTR_SLOT                   40
-#define LOAD_ATTR_MODULE                 41
-#define LOAD_GLOBAL_ADAPTIVE             42
-#define LOAD_GLOBAL_MODULE               43
-#define LOAD_GLOBAL_BUILTIN              44
-#define LOAD_METHOD_ADAPTIVE             45
-#define LOAD_METHOD_CACHED               46
-#define LOAD_METHOD_CLASS                47
-#define LOAD_METHOD_MODULE               48
-#define LOAD_METHOD_NO_DICT              55
-#define STORE_ATTR_ADAPTIVE              56
-#define STORE_ATTR_INSTANCE_VALUE        57
-#define STORE_ATTR_SLOT                  58
-#define STORE_ATTR_WITH_HINT             59
-#define LOAD_FAST__LOAD_FAST             62
-#define STORE_FAST__LOAD_FAST            63
-#define LOAD_FAST__LOAD_CONST            64
-#define LOAD_CONST__LOAD_FAST            65
-#define STORE_FAST__STORE_FAST           66
+#define BINARY_OP_SUBTRACT_INT           19
+#define BINARY_OP_SUBTRACT_FLOAT         20
+#define BINARY_SUBSCR_ADAPTIVE           21
+#define BINARY_SUBSCR_LIST_INT           22
+#define BINARY_SUBSCR_TUPLE_INT          23
+#define BINARY_SUBSCR_DICT               24
+#define CALL_FUNCTION_ADAPTIVE           26
+#define CALL_FUNCTION_BUILTIN_O          27
+#define CALL_FUNCTION_BUILTIN_FAST       28
+#define CALL_FUNCTION_LEN                29
+#define CALL_FUNCTION_ISINSTANCE         34
+#define CALL_FUNCTION_PY_SIMPLE          36
+#define JUMP_ABSOLUTE_QUICK              38
+#define LOAD_ATTR_ADAPTIVE               39
+#define LOAD_ATTR_INSTANCE_VALUE         40
+#define LOAD_ATTR_WITH_HINT              41
+#define LOAD_ATTR_SLOT                   42
+#define LOAD_ATTR_MODULE                 43
+#define LOAD_GLOBAL_ADAPTIVE             44
+#define LOAD_GLOBAL_MODULE               45
+#define LOAD_GLOBAL_BUILTIN              46
+#define LOAD_METHOD_ADAPTIVE             47
+#define LOAD_METHOD_CACHED               48
+#define LOAD_METHOD_CLASS                55
+#define LOAD_METHOD_MODULE               56
+#define LOAD_METHOD_NO_DICT              57
+#define STORE_ATTR_ADAPTIVE              58
+#define STORE_ATTR_INSTANCE_VALUE        59
+#define STORE_ATTR_SLOT                  62
+#define STORE_ATTR_WITH_HINT             63
+#define LOAD_FAST__LOAD_FAST             64
+#define STORE_FAST__LOAD_FAST            65
+#define LOAD_FAST__LOAD_CONST            66
+#define LOAD_CONST__LOAD_FAST            67
+#define STORE_FAST__STORE_FAST           75
 #define DO_TRACING                      255
 #ifdef NEED_OPCODE_JUMP_TABLES
 static uint32_t _PyOpcode_RelativeJump[8] = {
diff --git a/Lib/opcode.py b/Lib/opcode.py
index 940e169d5597d..4abe99fcbec17 100644
--- a/Lib/opcode.py
+++ b/Lib/opcode.py
@@ -231,6 +231,8 @@ def jabs_op(name, op):
     "BINARY_OP_INPLACE_ADD_UNICODE",
     "BINARY_OP_MULTIPLY_INT",
     "BINARY_OP_MULTIPLY_FLOAT",
+    "BINARY_OP_SUBTRACT_INT",
+    "BINARY_OP_SUBTRACT_FLOAT",
     "BINARY_SUBSCR_ADAPTIVE",
     "BINARY_SUBSCR_LIST_INT",
     "BINARY_SUBSCR_TUPLE_INT",
diff --git a/Objects/longobject.c b/Objects/longobject.c
index a4d90b1704321..ce4f0d72540d3 100644
--- a/Objects/longobject.c
+++ b/Objects/longobject.c
@@ -3155,14 +3155,11 @@ long_add(PyLongObject *a, PyLongObject *b)
     return _PyLong_Add(a, b);
 }
 
-
-static PyObject *
-long_sub(PyLongObject *a, PyLongObject *b)
+PyObject *
+_PyLong_Subtract(PyLongObject *a, PyLongObject *b)
 {
     PyLongObject *z;
 
-    CHECK_BINOP(a, b);
-
     if (IS_MEDIUM_VALUE(a) && IS_MEDIUM_VALUE(b)) {
         return _PyLong_FromSTwoDigits(medium_value(a) - medium_value(b));
     }
@@ -3187,6 +3184,13 @@ long_sub(PyLongObject *a, PyLongObject *b)
     return (PyObject *)z;
 }
 
+static PyObject *
+long_sub(PyLongObject *a, PyLongObject *b)
+{
+    CHECK_BINOP(a, b);
+    return _PyLong_Subtract(a, b);
+}
+
 /* Grade school multiplication, ignoring the signs.
  * Returns the absolute value of the product, or NULL if error.
  */
diff --git a/Python/ceval.c b/Python/ceval.c
index c02e3517d44f4..e579edefdb7af 100644
--- a/Python/ceval.c
+++ b/Python/ceval.c
@@ -2009,6 +2009,41 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr
             DISPATCH();
         }
 
+        TARGET(BINARY_OP_SUBTRACT_INT) {
+            PyObject *left = SECOND();
+            PyObject *right = TOP();
+            DEOPT_IF(!PyLong_CheckExact(left), BINARY_OP);
+            DEOPT_IF(!PyLong_CheckExact(right), BINARY_OP);
+            STAT_INC(BINARY_OP, hit);
+            PyObject *sub = _PyLong_Subtract((PyLongObject *)left, (PyLongObject *)right);
+            SET_SECOND(sub);
+            Py_DECREF(right);
+            Py_DECREF(left);
+            STACK_SHRINK(1);
+            if (sub == NULL) {
+                goto error;
+            }
+            DISPATCH();
+        }
+
+        TARGET(BINARY_OP_SUBTRACT_FLOAT) {
+            PyObject *left = SECOND();
+            PyObject *right = TOP();
+            DEOPT_IF(!PyFloat_CheckExact(left), BINARY_OP);
+            DEOPT_IF(!PyFloat_CheckExact(right), BINARY_OP);
+            STAT_INC(BINARY_OP, hit);
+            double dsub = ((PyFloatObject *)left)->ob_fval - ((PyFloatObject *)right)->ob_fval;
+            PyObject *sub = PyFloat_FromDouble(dsub);
+            SET_SECOND(sub);
+            Py_DECREF(right);
+            Py_DECREF(left);
+            STACK_SHRINK(1);
+            if (sub == NULL) {
+                goto error;
+            }
+            DISPATCH();
+        }
+
         TARGET(BINARY_OP_ADD_UNICODE) {
             PyObject *left = SECOND();
             PyObject *right = TOP();
diff --git a/Python/opcode_targets.h b/Python/opcode_targets.h
index a57617e022e1d..07852d167c769 100644
--- a/Python/opcode_targets.h
+++ b/Python/opcode_targets.h
@@ -18,25 +18,27 @@ static void *opcode_targets[256] = {
     &&TARGET_BINARY_OP_INPLACE_ADD_UNICODE,
     &&TARGET_BINARY_OP_MULTIPLY_INT,
     &&TARGET_BINARY_OP_MULTIPLY_FLOAT,
+    &&TARGET_BINARY_OP_SUBTRACT_INT,
+    &&TARGET_BINARY_OP_SUBTRACT_FLOAT,
     &&TARGET_BINARY_SUBSCR_ADAPTIVE,
     &&TARGET_BINARY_SUBSCR_LIST_INT,
     &&TARGET_BINARY_SUBSCR_TUPLE_INT,
     &&TARGET_BINARY_SUBSCR_DICT,
+    &&TARGET_BINARY_SUBSCR,
     &&TARGET_CALL_FUNCTION_ADAPTIVE,
     &&TARGET_CALL_FUNCTION_BUILTIN_O,
-    &&TARGET_BINARY_SUBSCR,
     &&TARGET_CALL_FUNCTION_BUILTIN_FAST,
     &&TARGET_CALL_FUNCTION_LEN,
-    &&TARGET_CALL_FUNCTION_ISINSTANCE,
-    &&TARGET_CALL_FUNCTION_PY_SIMPLE,
     &&TARGET_GET_LEN,
     &&TARGET_MATCH_MAPPING,
     &&TARGET_MATCH_SEQUENCE,
     &&TARGET_MATCH_KEYS,
-    &&TARGET_JUMP_ABSOLUTE_QUICK,
+    &&TARGET_CALL_FUNCTION_ISINSTANCE,
     &&TARGET_PUSH_EXC_INFO,
-    &&TARGET_LOAD_ATTR_ADAPTIVE,
+    &&TARGET_CALL_FUNCTION_PY_SIMPLE,
     &&TARGET_POP_EXCEPT_AND_RERAISE,
+    &&TARGET_JUMP_ABSOLUTE_QUICK,
+    &&TARGET_LOAD_ATTR_ADAPTIVE,
     &&TARGET_LOAD_ATTR_INSTANCE_VALUE,
     &&TARGET_LOAD_ATTR_WITH_HINT,
     &&TARGET_LOAD_ATTR_SLOT,
@@ -46,27 +48,25 @@ static void *opcode_targets[256] = {
     &&TARGET_LOAD_GLOBAL_BUILTIN,
     &&TARGET_LOAD_METHOD_ADAPTIVE,
     &&TARGET_LOAD_METHOD_CACHED,
-    &&TARGET_LOAD_METHOD_CLASS,
-    &&TARGET_LOAD_METHOD_MODULE,
     &&TARGET_WITH_EXCEPT_START,
     &&TARGET_GET_AITER,
     &&TARGET_GET_ANEXT,
     &&TARGET_BEFORE_ASYNC_WITH,
     &&TARGET_BEFORE_WITH,
     &&TARGET_END_ASYNC_FOR,
+    &&TARGET_LOAD_METHOD_CLASS,
+    &&TARGET_LOAD_METHOD_MODULE,
     &&TARGET_LOAD_METHOD_NO_DICT,
     &&TARGET_STORE_ATTR_ADAPTIVE,
     &&TARGET_STORE_ATTR_INSTANCE_VALUE,
-    &&TARGET_STORE_ATTR_SLOT,
-    &&TARGET_STORE_ATTR_WITH_HINT,
     &&TARGET_STORE_SUBSCR,
     &&TARGET_DELETE_SUBSCR,
+    &&TARGET_STORE_ATTR_SLOT,
+    &&TARGET_STORE_ATTR_WITH_HINT,
     &&TARGET_LOAD_FAST__LOAD_FAST,
     &&TARGET_STORE_FAST__LOAD_FAST,
     &&TARGET_LOAD_FAST__LOAD_CONST,
     &&TARGET_LOAD_CONST__LOAD_FAST,
-    &&TARGET_STORE_FAST__STORE_FAST,
-    &&_unknown_opcode,
     &&TARGET_GET_ITER,
     &&TARGET_GET_YIELD_FROM_ITER,
     &&TARGET_PRINT_EXPR,
@@ -74,7 +74,7 @@ static void *opcode_targets[256] = {
     &&TARGET_YIELD_FROM,
     &&TARGET_GET_AWAITABLE,
     &&TARGET_LOAD_ASSERTION_ERROR,
-    &&_unknown_opcode,
+    &&TARGET_STORE_FAST__STORE_FAST,
     &&_unknown_opcode,
     &&_unknown_opcode,
     &&_unknown_opcode,
diff --git a/Python/specialize.c b/Python/specialize.c
index cfc21bf70ad6b..dd15de72d2796 100644
--- a/Python/specialize.c
+++ b/Python/specialize.c
@@ -1424,6 +1424,19 @@ _Py_Specialize_BinaryOp(PyObject *lhs, PyObject *rhs, _Py_CODEUNIT *instr,
                 goto success;
             }
             break;
+        case NB_SUBTRACT:
+        case NB_INPLACE_SUBTRACT:
+            if (PyLong_CheckExact(lhs)) {
+                *instr = _Py_MAKECODEUNIT(BINARY_OP_SUBTRACT_INT,
+                                          _Py_OPARG(*instr));
+                goto success;
+            }
+            if (PyFloat_CheckExact(lhs)) {
+                *instr = _Py_MAKECODEUNIT(BINARY_OP_SUBTRACT_FLOAT,
+                                          _Py_OPARG(*instr));
+                goto success;
+            }
+            break;
         default:
             // These operators don't have any available specializations. Rather
             // than repeatedly attempting to specialize them, just convert them



More information about the Python-checkins mailing list