为什么窥孔优化是针对汇编代码而不是 IR 代码进行的?

Why peephole optimization is done on assembly code but not on IR code?

我不明白为什么需要窥视孔优化?因为编译器足够聪明来优化代码?你能给我一些需要优化窥孔的例子吗?

窥视孔通常是target-specific
它们可能仅在目标寄存器 (RTL) 方面有意义,而不是 IR。

例如x86 xor eax, eax 而不是 mov eax,0。 ()。没有理由在 IR 中执行此操作,并且在最后一刻(最终 code-generation)之前执行此操作会混淆其他优化值为零的事实。对除 x86 以外的任何机器执行此操作将是 anti-optimization(创建错误的依赖项)。 OTOH 你不想把它 太晚 ,否则你可能无法在设置 FLAGS 的东西之前重新排序它,例如

  xor  eax,eax
  cmp  ecx, edx
  sete al           ; boolean 0 or 1  zero-extended to 64-bit RAX

而不是

  cmp   ecx, edx
  sete  al               ; false dependency on old RAX
  movzx eax, al          ; no mov-elimination, extra critical path latency

  cmp   ecx, edx
  mov   eax, 0          ; less efficient instruction to leave FLAGS untouched
  sete  al              ; later reads of RAX will have partial-register stalls on P6-family

或者作为另一个示例,x86 可以使用 LEA 乘以 3、5 或 9,以利用 2 位移位并添加到 2 寄存器 addressing-modes。对于优化器来说,知道这是一个有效的 building-block 并旨在将 re-factor 乘以 9 的目标可能是有用的,但实际上将乘以 10 转换为 (x * 5) * 2 并不是对于 (x<<3) + (x<<1) 效率更高的目标 (x*10 = x*8 + x*2).

,您希望如何执行此操作

  • - 展示了一些编译如何有时会错过窥孔优化,并讨论了 imul 与 2x lea 的权衡以及现代 CPU 如何具有快速 imul使最多花费 2 条指令替换乘法是值得的,如果瓶颈是吞吐量而不是延迟,则只需要 1 条指令。除非你能像 LEA 那样把加法折进去...