]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
bpo-46504: faster code for trial quotient in x_divrem() (GH-30856)
authorTim Peters <tim.peters@gmail.com>
Tue, 25 Jan 2022 01:06:00 +0000 (19:06 -0600)
committerGitHub <noreply@github.com>
Tue, 25 Jan 2022 01:06:00 +0000 (19:06 -0600)
* bpo-46504: faster code for trial quotient in x_divrem()

This brings x_divrem() back into synch with x_divrem1(), which was changed
in bpo-46406 to generate faster code to find machine-word division
quotients and remainders. Modern processors compute both with a single
machine instruction, but convincing C to exploit that requires writing
_less_ "clever" C code.

Objects/longobject.c

index ee20e2638bcad1edd2819e01af1d0bd3b10093fd..5f0cc579c2cca57fe7cc184a242a676857138e63 100644 (file)
@@ -2767,8 +2767,15 @@ x_divrem(PyLongObject *v1, PyLongObject *w1, PyLongObject **prem)
         vtop = vk[size_w];
         assert(vtop <= wm1);
         vv = ((twodigits)vtop << PyLong_SHIFT) | vk[size_w-1];
+        /* The code used to compute the remainder via
+         *     r = (digit)(vv - (twodigits)wm1 * q);
+         * and compilers generally generated code to do the * and -.
+         * But modern processors generally compute q and r with a single
+         * instruction, and modern optimizing compilers exploit that if we
+         * _don't_ try to optimize it.
+         */
         q = (digit)(vv / wm1);
-        r = (digit)(vv - (twodigits)wm1 * q); /* r = vv % wm1 */
+        r = (digit)(vv % wm1);
         while ((twodigits)wm2 * q > (((twodigits)r << PyLong_SHIFT)
                                      | vk[size_w-2])) {
             --q;