你无法欺骗优化器。
You can't fool the optimizer

原始链接: https://xania.org/202512/03-more-adding-integers

编译器具有显著的代码优化能力,即使代码编写方式复杂也能有效优化。 这通过几个不同的ARM汇编例程展示,包括一个递归函数,它们都旨在简单地将两个数字相加 (x + y)。 尽管它们采用了不同的方法,编译器始终将它们简化为单个高效指令 `add w0, w1, w0`。 这种优化并非通过“愚蠢代码”模式数据库实现的。 相反,编译器将源代码转换为中间表示——一种简化、抽象的形式。 这使其能够识别数学等价关系,例如有效地递增值的 `while` 循环,并将不同的代码模式转换为标准“规范”形式。 在代码生成时,所有变体对优化器来说都看起来相同,从而实现强大且出人意料的转换。 本系列文章“编译器优化之旅2025”将深入探讨这一过程。

相关文章

原文

Written by me, proof-read by an LLM.
Details at end.

Sometimes you’ll step through code in a debugger and find a complex-looking loop… that executes as a single instruction. The compiler saw through the obfuscation and generated the obvious code anyway.

Consider this assortment of highly questionable unsigned addition routines - for variety, here compiled for ARM (unlike yesterday’s addition example).

Despite these all being very different ways of returning x + y, the compiler sees through it all and recognises that it’s just a single add w0, w1, w0 instruction. Even the recursive add_v4 - which calls itself - gets optimised down to the same single instruction.

The compiler’s ability to recognise patterns and replace them with efficient alternatives - even when the code is pretty obfuscated - is a superpower. It lets programmers choose how to write their code that’s intention-revealing (not like these contrived examples, obviously!) and leave the code generation up to the compiler, knowing that most of the time it’ll do the right thing.

So how does the compiler spot these patterns? Is it maintaining a database of “silly ways to add numbers”? Not quite. Internally, it translates your code into an intermediate representation - a simplified, abstract form that’s easier to analyse. When the compiler sees the while loop in add_v3, it transforms it into something like “increment y by x, then return y”, which it then recognises as mathematically equivalent to “return x + y”. This process of converting different code patterns into a standard, canonical form is what lets the compiler treat them all identically. By the time code generation happens, all four functions look the same to the optimiser.

This pattern recognition is remarkably robust - the compiler will happily optimise code you’d never want to write in the first place. Throughout this series we’ll see how far this canonicalisation can take us.

See the video that accompanies this post.


This post is day 3 of Advent of Compiler Optimisations 2025, a 25-day series exploring how compilers transform our code.

This post was written by a human (Matt Godbolt) and reviewed and proof-read by LLMs and humans.

Support Compiler Explorer on Patreon or GitHub, or by buying CE products in the Compiler Explorer Shop.

联系我们 contact @ memedata.com