Introduction
LLVM 23 has marked a turning point in compile-time optimization, achieving a notable reduction of -6.75% in -O3 builds, especially on sqlite3 with an impressive -10.53%. These performance gains are crucial for developers looking to optimize their development cycles and reduce operational costs. Let's dive into the specifics of the major improvements that made this possible.
Data Structure Improvements
ADT Hash Maps/Sets
One of the main sources of improvement lies in the hash maps and sets used by LLVM. Three significant changes were made:
- Shift to Linear Probing: Moving away from quadratically probed hash tables to linear probing has provided a direct improvement, eliminating the need for tombstone keys.
- Compact Bit Array: DenseMap occupancy is now stored in a compact bit array, avoiding the need for empty keys.
- XXH3 Hash Function: Transitioning from CityHash to XXH3 not only improved performance but also enabled the previous modifications.
SmallVector and BumpAllocator
In SmallVector, trivially-copyable operations were optimized to allow tail call optimization, reducing instructions and increasing the potential for inlining.
The BumpAllocator was also simplified, improving overall performance despite some compile-time variations due to inlining heuristics.
Traversal and Representation Improvements
Post-Order Traversal
Rewriting the post-order traversal, although still not ideal, allowed iterator moves to be less costly, paving the way for more inlining optimization.
Dominator Tree
The dominator tree representation was altered to use a child-sibling representation, reducing allocations and calls to malloc()/free(), crucial for the numerous dominator trees constructed during compilation.
Conclusion
The improvements in LLVM 23 are not just numbers. They represent a significant stride towards faster and more efficient compilation, which is essential in a world where every second counts for developers and tech companies. Let's discuss your project in 15 minutes.