C 编译器忽略寄存器声明的原因

问题描述

C 编译器忽略 register 声明的原因是什么?我知道这个声明对于现代编译器来说基本上没有意义,因为它们在适当的时候将值存储在寄存器中。我正在学习计算机体系结构课程,因此了解旧编译器为何会出现这种情况很重要。

"register 声明通知编译器中的变量 问题将被大量使用。这个想法是 register 变量 将被放置在机器寄存器中,这可能会导致更小和 更快的程序。但是编译器可以随意忽略这些建议。” ~ The C Programming Language 作者:Brian W. Kernighan 和 Dennis M. Ritchie

谢谢!

解决方法

历史上的 C 编译器可能“智能”(复杂)到一次查看一个 C 语句,例如现代的 TinyCC。或者解析整个函数以找出有多少变量,然后返回并且仍然一次只执行代码生成一个语句。有关旧编译器多么简单和幼稚的示例,请参阅 Why do C to Z80 compilers produce poor code? - 显示的一些示例可以针对特殊的简单情况进行了优化,但没有。 (尽管 Z80 和 6502 是相当糟糕的 C 编译器目标,因为(与 PDP-11 不同)“指针”不是您可以仅保留在寄存器中的东西。)

启用优化后,现代编译器确实有足够的 RAM(和编译时间)可用于使用更复杂的算法来映射整个函数的寄存器分配,并在内联之后做出正确的决定。 (例如,将程序逻辑转换为 SSA 形式。)另见 https://en.wikipedia.org/wiki/Register_allocation

register 关键字变得毫无意义;编译器已经可以注意到何时没有获取变量的地址(register 关键字不允许这样做)。或者当它可以优化地址获取并将变量保留在寄存器中时。

TL:DR:现代编译器不再需要以 register 关键字暗示的方式完全应用 as-if 规则。

他们基本上总是将所有内容保存在寄存器中,除非被迫将其溢出回内存,除非您禁用优化以实现完全一致的调试。 (因此您可以在断点处停止时使用调试器更改变量,甚至可以在语句之间跳转。)


有趣的事实:Why does clang produce inefficient asm with -O0 (for this simple floating point sum)? 展示了一个示例,其中 register float 使现代 GCC 和 clang 创建更高效​​的 asm 禁用优化