[LLVM 2026] Beyond the Legacy: Speeding Up 32-bit Division on 64-bit Targets

Optimization of 32-bit Unsigned Division by Constants on 64-bit Targets

Summary
Problem
Method
Results
Takeaways
Abstract

This paper introduces a compiler optimization for 32-bit unsigned integer division by constants specifically for 64-bit architectures. By leveraging 64-bit registers to eliminate complex shift-and-add sequences in the classic Granlund-Montgomery (GM) method, the proposed approach achieves significant performance gains in LLVM and GCC.

TL;DR

Modern compilers like GCC and Clang have long relied on the Granlund-Montgomery (GM) method to replace slow division instructions with faster multiplications. However, for a significant portion of divisors, the generated code remains stuck in a "32-bit mindset," using complex instruction sequences to prevent overflows that modern 64-bit registers can handle with ease. This paper proposes a simplified 64-bit-native approach that reduces the operation to a single multiplication, delivering nearly 2x speedups on Apple M4 and Intel Sapphire Rapids.

The Problem: The 32-bit "Ghost" in 64-bit Machines

Integer division is notoriously expensive in terms of CPU cycles. To optimize this, compilers use "magic constants"—precomputed numbers that allow to be calculated via .

However, for about 23% of constant divisors (like 7, 19, or 107), the magic constant requires 33 bits. To avoid overflowing a 32-bit result during intermediate steps, current compilers generate a "shift-add-shift" dance:

  1. Multiply by the lower 32 bits of .
  2. Perform a subtraction and a right shift.
  3. Add the results back and shift again.

While this was necessary for 32-bit CPUs, it is a bottleneck on modern 64-bit hardware where we have plenty of register "headroom."

The Insight: Native 64-bit Scaling

The authors realized that if we are running on a 64-bit target, we can treat the 32-bit dividend as a 64-bit value and scale the magic constant such that the result resides purely in the upper bits of a 128-bit product.

Specifically, the operation is transformed to:

By pre-calculating , the division simply becomes the high 64 bits of the product of and .

Methodology & Architecture

The beauty of this method lies in its simplicity. Instead of the multi-line assembly sequence seen in Listing 2 of the paper, the proposed method utilizes the high-magnitude multiplication instructions available in modern ISAs.

Proposed Method Logic

  • On x86-64 (BMI2): It uses the mulx instruction, which computes a 128-bit product and stores the high/low parts in separate registers.
  • On AArch64 (Apple M4): It uses umulh (Unsigned Multiply High), which directly returns the top 64 bits of the product.

Experimental Results: Real-World Gains

The authors implemented this in LLVM and tested it against a sequence of divisions by 7, 19, and 107.

CPU ArchitectureOriginal Time (s)Optimized Time (s)Speedup
Intel Xeon (Sapphire Rapids)6.333.801.67x
Apple M46.703.381.98x

Performance Comparison

As shown in the assembly comparison (Listing 7 vs 8 in the paper), the loop body shrinks dramatically. The "sequence" of shifts and adds is replaced by a high-throughput multiplication, allowing the CPU's out-of-order execution engine to process iterations much faster.

Critical Analysis & Conclusion

The core contribution here is not a new mathematical theory, but a practical engineering refinement. It identifies a "performance debt" in compiler backends—where code generation strategies failed to evolve alongside register width.

Limitations:

  • This optimization is only applicable when the target is 64-bit; 32-bit embedded systems must still use the legacy GM method.
  • It specifically targets the "33-bit constant" case; the ~77% of cases where fits in 32 bits already use a single multiply-shift.

Takeaway: This work has already been merged into llvm:main. For developers using Clang or eventually GCC, 32-bit unsigned division—a fundamental building block of many algorithms—just got nearly twice as fast on modern hardware. It serves as a reminder that even "solved" problems in computer science often have room for optimization when hardware assumptions change.

Find Similar Papers

Try Our Examples

  • Search for recent updates in GCC or LLVM regarding the optimization of signed integer division by constants on 64-bit architectures.
  • Which original paper by Granlund and Montgomery established the "magic number" approach for division, and how did it handle the 33-bit overflow case?
  • Explore if similar 64-bit register optimizations can be applied to modular exponentiation or other Montgomery reduction-based algorithms in cryptographic libraries.
Contents
[LLVM 2026] Beyond the Legacy: Speeding Up 32-bit Division on 64-bit Targets
1. TL;DR
2. The Problem: The 32-bit "Ghost" in 64-bit Machines
3. The Insight: Native 64-bit Scaling
3.1. Methodology & Architecture
4. Experimental Results: Real-World Gains
5. Critical Analysis & Conclusion