[Python-checkins] gh-99761: Add `_PyLong_IsPositiveSingleDigit` function to check for single digit integers (#100064)

kumaraditya303 webhook-mailer at python.org
Thu Dec 22 06:30:28 EST 2022


https://github.com/python/cpython/commit/2b82c36f17ada471e734c3ad93e6eff8b36a5ad9
commit: 2b82c36f17ada471e734c3ad93e6eff8b36a5ad9
branch: main
author: Pieter Eendebak <pieter.eendebak at gmail.com>
committer: kumaraditya303 <59607654+kumaraditya303 at users.noreply.github.com>
date: 2022年12月22日T17:00:18+05:30
summary:
gh-99761: Add `_PyLong_IsPositiveSingleDigit` function to check for single digit integers (#100064)
files:
M Include/internal/pycore_long.h
M Python/bytecodes.c
M Python/generated_cases.c.h
diff --git a/Include/internal/pycore_long.h b/Include/internal/pycore_long.h
index 30c97b7edc98..8c1d017bb95e 100644
--- a/Include/internal/pycore_long.h
+++ b/Include/internal/pycore_long.h
@@ -110,6 +110,25 @@ PyAPI_FUNC(char*) _PyLong_FormatBytesWriter(
 int base,
 int alternate);
 
+/* Return 1 if the argument is positive single digit int */
+static inline int
+_PyLong_IsPositiveSingleDigit(PyObject* sub) {
+ /* For a positive single digit int, the value of Py_SIZE(sub) is 0 or 1.
+
+ We perform a fast check using a single comparison by casting from int
+ to uint which casts negative numbers to large positive numbers.
+ For details see Section 14.2 "Bounds Checking" in the Agner Fog
+ optimization manual found at:
+ https://www.agner.org/optimize/optimizing_cpp.pdf
+
+ The function is not affected by -fwrapv, -fno-wrapv and -ftrapv
+ compiler options of GCC and clang
+ */
+ assert(PyLong_CheckExact(sub));
+ Py_ssize_t signed_size = Py_SIZE(sub);
+ return ((size_t)signed_size) <= 1;
+}
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/Python/bytecodes.c b/Python/bytecodes.c
index b29e16e080e9..c0b625bd662c 100644
--- a/Python/bytecodes.c
+++ b/Python/bytecodes.c
@@ -391,8 +391,7 @@ dummy_func(
 DEOPT_IF(!PyList_CheckExact(list), BINARY_SUBSCR);
 
 // Deopt unless 0 <= sub < PyList_Size(list)
- Py_ssize_t signed_magnitude = Py_SIZE(sub);
- DEOPT_IF(((size_t)signed_magnitude) > 1, BINARY_SUBSCR);
+ DEOPT_IF(!_PyLong_IsPositiveSingleDigit(sub), BINARY_SUBSCR);
 assert(((PyLongObject *)_PyLong_GetZero())->ob_digit[0] == 0);
 Py_ssize_t index = ((PyLongObject*)sub)->ob_digit[0];
 DEOPT_IF(index >= PyList_GET_SIZE(list), BINARY_SUBSCR);
@@ -410,8 +409,7 @@ dummy_func(
 DEOPT_IF(!PyTuple_CheckExact(tuple), BINARY_SUBSCR);
 
 // Deopt unless 0 <= sub < PyTuple_Size(list)
- Py_ssize_t signed_magnitude = Py_SIZE(sub);
- DEOPT_IF(((size_t)signed_magnitude) > 1, BINARY_SUBSCR);
+ DEOPT_IF(!_PyLong_IsPositiveSingleDigit(sub), BINARY_SUBSCR);
 assert(((PyLongObject *)_PyLong_GetZero())->ob_digit[0] == 0);
 Py_ssize_t index = ((PyLongObject*)sub)->ob_digit[0];
 DEOPT_IF(index >= PyTuple_GET_SIZE(tuple), BINARY_SUBSCR);
@@ -508,7 +506,7 @@ dummy_func(
 DEOPT_IF(!PyList_CheckExact(list), STORE_SUBSCR);
 
 // Ensure nonnegative, zero-or-one-digit ints.
- DEOPT_IF(((size_t)Py_SIZE(sub)) > 1, STORE_SUBSCR);
+ DEOPT_IF(!_PyLong_IsPositiveSingleDigit(sub), STORE_SUBSCR);
 Py_ssize_t index = ((PyLongObject*)sub)->ob_digit[0];
 // Ensure index < len(list)
 DEOPT_IF(index >= PyList_GET_SIZE(list), STORE_SUBSCR);
diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h
index 6d84a643b457..42b7ca086705 100644
--- a/Python/generated_cases.c.h
+++ b/Python/generated_cases.c.h
@@ -491,8 +491,7 @@
 DEOPT_IF(!PyList_CheckExact(list), BINARY_SUBSCR);
 
 // Deopt unless 0 <= sub < PyList_Size(list)
- Py_ssize_t signed_magnitude = Py_SIZE(sub);
- DEOPT_IF(((size_t)signed_magnitude) > 1, BINARY_SUBSCR);
+ DEOPT_IF(!_PyLong_IsPositiveSingleDigit(sub), BINARY_SUBSCR);
 assert(((PyLongObject *)_PyLong_GetZero())->ob_digit[0] == 0);
 Py_ssize_t index = ((PyLongObject*)sub)->ob_digit[0];
 DEOPT_IF(index >= PyList_GET_SIZE(list), BINARY_SUBSCR);
@@ -517,8 +516,7 @@
 DEOPT_IF(!PyTuple_CheckExact(tuple), BINARY_SUBSCR);
 
 // Deopt unless 0 <= sub < PyTuple_Size(list)
- Py_ssize_t signed_magnitude = Py_SIZE(sub);
- DEOPT_IF(((size_t)signed_magnitude) > 1, BINARY_SUBSCR);
+ DEOPT_IF(!_PyLong_IsPositiveSingleDigit(sub), BINARY_SUBSCR);
 assert(((PyLongObject *)_PyLong_GetZero())->ob_digit[0] == 0);
 Py_ssize_t index = ((PyLongObject*)sub)->ob_digit[0];
 DEOPT_IF(index >= PyTuple_GET_SIZE(tuple), BINARY_SUBSCR);
@@ -642,7 +640,7 @@
 DEOPT_IF(!PyList_CheckExact(list), STORE_SUBSCR);
 
 // Ensure nonnegative, zero-or-one-digit ints.
- DEOPT_IF(((size_t)Py_SIZE(sub)) > 1, STORE_SUBSCR);
+ DEOPT_IF(!_PyLong_IsPositiveSingleDigit(sub), STORE_SUBSCR);
 Py_ssize_t index = ((PyLongObject*)sub)->ob_digit[0];
 // Ensure index < len(list)
 DEOPT_IF(index >= PyList_GET_SIZE(list), STORE_SUBSCR);


More information about the Python-checkins mailing list

AltStyle によって変換されたページ (->オリジナル) /