c – 为什么ARM使用两条指令来屏蔽值?

前端之家收集整理的这篇文章主要介绍了c – 为什么ARM使用两条指令来屏蔽值?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
对于以下功能……
uint16_t swap(const uint16_t value)
{
    return value << 8 | value >> 8;
}

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

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

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

解决方法

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

所以,我们可以从内存加载并执行和(慢),
用2条指令创建值,1到和(更长),
或者只是便宜地换两次并称之为好.

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

现在进行现实检查:

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

编辑:

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

编辑2

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

猜你在找的C&C++相关文章