Technology1 min read

Beating the compiler at signed 32-bit division

By · Published by Everything Blog

In short

Compilers traditionally follow standard algorithms that require an extra addition step for 38 percent of divisors between 3 and 1,000 when the multiplier exceeds a signed 32-bit integer. Co-authored with Colin Bartlett and Owen Kaser, the refined technique instead fits a 33-bit multiplier inside a signed 64-bit product for signed 32-bit inputs. Loading the constant remains inexpensive because the multiplier fits into 32 bits as an unsigned integer. Benchmark testing on 16,384 random signed integers confirmed execution speed improvements on hardware including Intel Xeon Gold and Apple M4 Max processors.

Key points

  • Modern compilers can be surpassed on 64-bit platforms by eliminating redundant mathematic…: Modern compilers can be surpassed on 64-bit platforms by eliminating redundant mathematical steps in constant division.
  • Shortening the dependent instruction chain yields measurable latency reductions across bo…: Shortening the dependent instruction chain yields measurable latency reductions across both Intel and Apple ARM chips.
  • Unsigned 32-bit constant encoding keeps memory loads cheap while bypassing standard addit…: Unsigned 32-bit constant encoding keeps memory loads cheap while bypassing standard addition workarounds.

Sources checked by our analysis pipeline: 1

31 October 2026 · 10 min

Dividing integers is slow on our processors. A 32-bit division costs:

On Zen 4 and Zen 5, the latency depends on the inputs. The x86 rows are idiv

(uops.info). The Apple row is sdiv

(measurements).

A multiplication has a latency of 3 cycles. Emerald Rapids can do one every cycle. Zen 5 and Arrow Lake do three 64-bit multiplications per cycle (uops.info).

Thankfully, when the divisor is a constant, compilers replace the division by a multiplication and a shift (Granlund and Montgomery, 1994). Dividing by 7 is like multiplying by 1/7. In integer arithmetic, we multiply by an integer close to and we divide by with a shift.

Can we do better than the compiler? With signed 32-bit integers on a 64-bit system, often yes.

The compiler’s approach

Let us divide a signed 32-bit integer by 7:

int32_t div7(int32_t x) { return x / 7; }

GCC 14 produces the following code on an x64 processor:

movsx rax, edi

imul rax, rax, -1840700269

shr rax, 32

add eax, edi

sar edi, 31

sar eax,…

Technology