为什么ARM使用两条指令来掩盖值?

Jim*_*m V 7 c++ assembly gcc arm

对于以下功能......

uint16_t swap(const uint16_t value)
{
    return value << 8 | value >> 8;
}
Run Code Online (Sandbox Code Playgroud)

...为什么带有-O2的ARM gcc 6.3.0会产生以下程序集?

swap(unsigned short):
  lsr r3, r0, #8
  orr r0, r3, r0, lsl #8
  lsl r0, r0, #16         # shift left
  lsr r0, r0, #16         # shift right
  bx lr
Run Code Online (Sandbox Code Playgroud)

似乎编译器使用两个移位来屏蔽不需要的字节,而不是使用逻辑AND.编译器可以改用and r0, r0, #4294901760吗?

Mic*_*gan 7

较旧的ARM程序集无法轻松创建常量.相反,它们被加载到文字池中,然后通过内存负载读入.这个and你建议我只能相信一个带有移位的8位字面值.您0xFFFF0000需要16位作为1条指令.

因此,我们可以从内存加载并执行and(慢速),Take 2指令来创建值,1和(更长),或者只是便宜地移动两次并称之为好.

编译器选择了轮班,老实说,它很快.

现在进行现实检查:

担心单一班次,除非这是一个100%肯定的瓶颈是浪费时间.即使编译器是次优的,你几乎也不会感​​觉到它.担心代码中的"热"循环而不是像这样的微操作.从好奇心看这个很棒.担心这个确切的代码在您的应用程序中的性能,而不是.


编辑:

其他人已经注意到,ARM规范的新版本允许更有效地完成此类事情.这表明,在这个级别进行讨论时,重要的是指定芯片或至少指定我们正在处理的精确ARM规范.我从你的输出中缺少"更新"的指令来假设古老的ARM.如果我们正在跟踪编译器错误,那么这个假设可能不成立,并且知道规范甚至更重要.对于像这样的交换,在更高版本中确实有更简单的指令来处理它.


编辑2

可能做得更快的一件事就是使其内联.在这种情况下,编译器可以将这些操作与其他工作交错.根据CPU的不同,这可能会使吞吐量翻倍,因为许多ARM CPU都有2个整数指令流水线.尽可能地扩展说明,以便没有危险,然后就可以了.这必须权衡I-Cache的使用,但在重要的情况下,你可以看到更好的东西.

  • 担心的原因不是某个特定的应用程序,而是您是否应该报告 [missed-optimization gcc bug](https://gcc.gnu.org/bugzilla/buglist.cgi?quicksearch=missed-optimization&amp;list_id=195134) 所以编译器可以在未来为*每个人*生成稍微更快和/或更小的代码。 (2认同)

归档时间:

查看次数:

555 次

最近记录:

8 年 前