My 2025 in LLVM: samesign, HashRecognize, and VPlan

As the year draws to a close, it helps to look back and reflect on some key changes in LLVM. The article is written from my perspective, summarizing work I landed, along with adjacent work, in chronological order.

In September 2024, Nikita Popov proposed signedness-independent integer-compares, and the necessary work for enabling optimizations with it occupied the first two months of my 2025. In January, Florian Hahn introduced the initial version of a pattern-matcher for ScalarEvolution, which I would flesh out and use to improve code over the course of the year.

March and April were not very productive, as I was on vacation and attending EuroLLVM. In the little time I had, I fixed a vectorization bug and improved code by introducing a new iterator in a fundamental data structure.

In May, I introduced a constant folder in VPlan, guided by Florian, and fixed another vectorization bug. In collaboration with Mel Chen, I made a small improvement to the routine that checks patterns for vectorization.

In June, an analysis to recognize cyclic-redundancy-check loops landed, but required several months of improvements, before finally enabling optimization of CRC loops in September: the work was done in close collaboration with Piotr Fusik. While reviewing one of Florian's patches, I also extended a pattern for vectorization, which Florian built upon.

In July, I was occupied with instruction selection and cost-modeling work for the intrinsics lrint, lround, and ldexp on RISC-V, guided by Craig Topper.

In August, Luke Lau used parameter packs to greatly improve the pattern-matcher in VPlan. Inspired by another of his patches, I would introduce a integer/floating-point compare matcher, using it for optimization benefit. I would also fix some issued related to wrap-flags in VPlan.

In September, I introduced a common-subexpression-elimination transform in VPlan, guided by Florian. I also picked up and completed one of Luke's abandoned patches, a match functor. Nikita would introduce a new transform to strip unnecessary llvm.assume instructions.

In October, I would obsess over the loop-invariant code motion in VPlan, and factor out the legality check for hoisting/sinking, fixing a miscompile. My routine would bail out on memory operations due to aliasing issues, and I was thinking about how to get aliasing information in VPlan.

In November, I would fix long-standing issues related to wrap-flags in VPlan, and make an improvement to a routine to undo sub-optimal widening decisions in VPlan. Florian would build upon my improvement to yield the final version. He would also create specialized hoisting/sinking routines for memory operations, based on the noalias metadata: I plan to re-use the legality checks to improve the general case.

Finally, we're in December. The main outstanding patches are directly unrolling a recipe in VPlan, and introducing a carry-less multiply intrinsic, whose design was guided by Craig and Piotr. Both will hopefully land soon.