我试图了解gcc在设置-O3标志时执行什么样的优化。我很困惑这两句话是什么,
xor %esi, %esi
lea 0x0(%esi), %esi在我看来是多余的。在这里使用精益指令有什么意义?
发布于 2013-09-30 04:36:42
该指令用于为对齐目的填充空间。当循环开始于对齐地址时,速度会更快,因为处理器以块的形式将内存加载到解码器中。通过调整循环和函数的开始,它们更有可能出现在其中一个块的开头。这防止了以前不会被加载的指令,最大限度地增加了未来指令的数量,可能最重要的是,确保第一条指令完全在第一个块中,因此执行它不需要两个负载。
编译器知道对齐循环是最好的,并且有两个选项可以这样做。它可以跳转到循环的开始,或者用无操作来填补空白,让处理器通过它们。跳转指令破坏了指令流,经常在现代处理器上造成浪费周期,因此不必要地添加它们是不可取的。像这样的短距离,没有行动就更好了。
x86体系结构包含一个专门用于不做任何事情的指令,nop。然而,这是一个字节长,所以需要一个以上的循环对齐。解码每个指令,并决定它不需要时间,所以简单地插入另一个没有副作用的更长的指令就更快了。因此,编译器插入了您看到的lea指令。它绝对没有效果,编译器选择它来获得所需的精确长度。事实上,最近的处理器有标准的多字节无操作指令,所以这很可能在解码过程中被识别,甚至永远不会执行。
发布于 2013-09-30 11:28:29
正如ughoavgfhw所解释的那样,这些是用于更好的代码对齐的垫子。您可以在以下链接中找到这个lea -
http://mail.openjdk.java.net/pipermail/hotspot-compiler-dev/2010-September/003881.html
引用:
1-byte: XCHG EAX, EAX
2-byte: 66 NOP
3-byte: LEA REG, 0 (REG) (8-bit displacement)
4-byte: NOP DWORD PTR [EAX + 0] (8-bit displacement)
5-byte: NOP DWORD PTR [EAX + EAX*1 + 0] (8-bit displacement)
**6-byte: LEA REG, 0 (REG) (32-bit displacement)**
7-byte: NOP DWORD PTR [EAX + 0] (32-bit displacement)
8-byte: NOP DWORD PTR [EAX + EAX*1 + 0] (32-bit displacement)
9-byte: NOP WORD PTR [EAX + EAX*1 + 0] (32-bit displacement)还要注意这个问题,所以请用更多的细节来描述它- What does NOPL do in x86 system?
请注意,xor本身不是nop (它改变了reg的值),但是执行起来也很便宜,因为它是一个零成语- What is the purpose of XORing a register with itself?。
https://stackoverflow.com/questions/19085663
复制相似问题