Skip to content

Optimisation fixes the “33rd-bit problem” and is already in LLVM, with GCC and MSVC updates on the way

Person pointing at upward trending graph displayed on computer screen with code, laptop nearby on desk.

Optimisation removes the “33rd-bit problem” and is already shipping in LLVM, with GCC and MSVC updates close behind

Engineers at Japan’s Cybozu Labs, a company focused on software development and compute optimisation, have introduced a new way to compile division by a constant for 64-bit processors. The approach takes advantage of the spare headroom in today’s 64-bit registers, sidestepping constraints inherited from older 32-bit techniques. The patch has already landed in LLVM (Low Level Virtual Machine), the widely used open-source project that includes the Clang compiler (version 23.0.0). Updates for GCC (GNU Compiler Collection) and MSVC (Microsoft Visual C++) are currently being tested.

Why compilers still carried 32-bit division baggage

Despite running on capable 64-bit systems, mainstream compilers (GCC, Clang and MSVC) have continued to rely on division-by-constant logic that dates back roughly 30 years and was tuned for 32-bit CPUs. Since 1994, the go-to technique in compilers has been the Granlund and Montgomery method (the GM method). It replaces a division with multiplication by a “magic constant” plus bit shifts.

The weakness appears with so-called “33-bit divisors”. In those cases, the GM method ends up performing extra work, which can hurt performance on modern 64-bit processors. In around 3% of division-by-constant cases for 32-bit integers (for example, dividing by 7, 19, or 107), intermediate steps require 33-bit “magic numbers”. That creates a longer critical path and reduces how much the processor can do in parallel.

Cybozu Labs’ 64-bit division-by-constant method (Mitsunari Shigeo and Hoshino Takashi)

Mitsunari Shigeo and Hoshino Takashi’s key change is to stop emulating 33-bit arithmetic and instead rewrite the formula directly in a 64-bit framework. Rather than relying on a lengthy correction sequence, the method uses a compact model:

(x·(2^(64−a)·c)) // 2^64

Here, x is the dividend widened to 64 bits, and c is the magic constant.

On x86-64, the implementation uses MULX (Unsigned Multiply Without Affecting Flags), which avoids changing the processor flags. On ARM and Apple Silicon, it uses UMULH (Unsigned Multiply High), which returns the upper 64 bits of the multiplication result. With these instructions, the division can be completed in a single multiply-high style operation, delivering a substantial speed-up.

Instruction count and latency: GM method versus the new approach

In practical terms, the older GM method can require as many as 9 instructions inside a loop, including additions and shifts, which stretches the dependency chain. The new technique trims that sequence down to 3 operations, cutting latency and reducing data dependencies-an especially important improvement on today’s CPUs.

Benchmark results on Intel Xeon w9-3495X and Apple M4

Benchmarks on Intel’s Xeon w9-3495X and Apple’s M4 showed speed-ups of up to 1.67x and 1.98x respectively. The gain was larger on the Apple M4, attributed to its high multiplier throughput. On the Xeon, the change also made runtimes more consistent, which matters for server workloads; for instance, the standard deviation of execution time dropped from 0.013 seconds to 0.009 seconds.

Rollout in LLVM, and what GCC and MSVC will change for real software

Bringing this method into LLVM and GCC is expected to accelerate software that processes large volumes of data, including databases, cryptographic systems, and network traffic analysis.

This is not merely an academic result but a practical optimisation that is already reaching production toolchains. At present, the patch is fully integrated into LLVM, while GCC and MSVC updates are in final testing. As a result, most programs rebuilt with updated compilers should see meaningful speed gains without any source-code changes. It also removes a long-standing historical anachronism in compiler code generation, finally putting 64-bit processors’ capabilities to work for basic arithmetic-delivering almost a twofold improvement in certain scenarios.

Comments

No comments yet. Be the first to comment!

Leave a Comment