Commit 20a10e73 authored by Stefan Behnel's avatar Stefan Behnel

tune PyLong optimisations at (gcc) assembly level so that they prefer the most...

tune PyLong optimisations at (gcc) assembly level so that they prefer the most common case of a single-digit
parent b79a55d8
......@@ -183,6 +183,10 @@
#define __Pyx_PyMethod_New(func, self, klass) PyMethod_New(func, self, klass)
#endif
#define __Pyx_sst_abs(value) \
(sizeof(int) >= sizeof(Py_ssize_t) ? abs(value) : \
(sizeof(long) >= sizeof(Py_ssize_t) ? labs(value) : llabs(value)))
/* inline attribute */
#ifndef CYTHON_INLINE
#if defined(__GNUC__)
......
......@@ -449,12 +449,16 @@ static PyObject* __Pyx__PyNumber_PowerOf2(PyObject *two, PyObject *exp, PyObject
#endif
if (likely(PyLong_CheckExact(exp))) {
#if CYTHON_USE_PYLONG_INTERNALS
switch (Py_SIZE(exp)) {
case 0: shiftby = 0; break;
case 1: shiftby = ((PyLongObject*)exp)->ob_digit[0]; break;
default:
if (unlikely(Py_SIZE(exp) < 0)) goto fallback;
shiftby = PyLong_AsSsize_t(exp); break;
const Py_ssize_t size = Py_SIZE(exp);
// tuned to optimise branch prediction
if (likely(size == 1)) {
shiftby = ((PyLongObject*)exp)->ob_digit[0];
} else if (size == 0) {
return PyInt_FromLong(1L);
} else if (unlikely(size < 0)) {
goto fallback;
} else {
shiftby = PyLong_AsSsize_t(exp);
}
#else
shiftby = PyLong_AsSsize_t(exp);
......@@ -563,13 +567,12 @@ static PyObject* __Pyx_PyInt_{{op}}{{order}}(PyObject *op1, PyObject *op2, CYTHO
long x, {{ival}};
const digit* digits = ((PyLongObject*){{pyval}})->ob_digit;
const Py_ssize_t size = Py_SIZE({{pyval}});
// handle most common case first to avoid indirect branch and optimise branch prediction
if (likely(__Pyx_sst_abs(size) <= 1)) {
{{ival}} = likely(size) ? digits[0] : 0;
{{if c_op != '%'}}if (size == -1) {{ival}} = -{{ival}};{{endif}}
} else {
switch (size) {
case 0: {{ival}} = 0; break;
case -1: {{if c_op != '%'}}
{{ival}} = -(sdigit)digits[0]; break;
{{endif}}
// fall through to positive calculation for '%'
case 1: {{ival}} = digits[0]; break;
{{for _size in (2, 3, 4)}}
{{for _case in (-_size, _size)}}
case {{_case}}: {{if c_op != '%' or _case > 0}}
......@@ -584,6 +587,7 @@ static PyObject* __Pyx_PyInt_{{op}}{{order}}(PyObject *op1, PyObject *op2, CYTHO
{{endfor}}
default: return PyLong_Type.tp_as_number->nb_{{slot_name}}(op1, op2);
}
}
{{if c_op == '%'}}
x = a % b;
if (unlikely(size < 0) && x) {
......
......@@ -297,12 +297,12 @@ static CYTHON_INLINE Py_ssize_t __Pyx_PyIndex_AsSsize_t(PyObject* b) {
#if CYTHON_USE_PYLONG_INTERNALS
const digit* digits = ((PyLongObject*)b)->ob_digit;
const Py_ssize_t size = Py_SIZE(b);
switch (size) {
case 0: return 0;
case 1: return digits[0];
case -1: return -(sdigit) digits[0];
default:
// move the substantially less common cases out of the way
// handle most common case first to avoid indirect branch and optimise branch prediction
if (likely(__Pyx_sst_abs(size) <= 1)) {
ival = likely(size) ? digits[0] : 0;
if (size == -1) ival = -ival;
return ival;
} else {
switch (size) {
{{for _size in (2, 3, 4)}}
{{for _case in (_size, -_size)}}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment