【问题标题】:gcc/clang optimization of little-endian load of uint16_t from uint8_t* arraygcc/clang 优化 uint8_t* 数组中 uint16_t 的 little-endian 负载
【发布时间】:2012-05-31 19:07:20
【问题描述】:

鉴于以下情况:

#include <stdint.h>
#include <stdio.h>

uint16_t foo(uint8_t* x)
{
  uint16_t r = (x[1] << 8) | x[0];
  return r;
}

uint16_t bar(uint8_t* x)
{
  uint16_t r = ((uint16_t*) x)[0];
  return r;
}

在 x86_64 上,GCC 和 Clang 生成的代码类似于:

foo:                                    # @foo
        .cfi_startproc
# BB#0:                                 # %entry
        movzbl  (%rdi), %ecx
        movzbl  1(%rdi), %eax
        shll    $8, %eax
        orl     %ecx, %eax
        movzwl  %ax, %eax
        ret

bar:                                    # @bar
        .cfi_startproc
# BB#0:                                 # %entry
        movzwl  (%rdi), %eax
        ret

是否有任何理由不将 foo 优化为等同于 bar(即执行单个 16 位加载)?负载对齐?

【问题讨论】:

  • 您不应该在转换之前将x[1] 类型转换为 uint16_t 吗?否则,您似乎会得到x[1] &lt;&lt; 8 == 0,因为只有 8 位并且您将它们全部移出。
  • @Matt x[1]x[1] &lt;&lt; 8 中提升为int
  • @Matt:不,“整数促销”适用,在班次前x[1] 被提升为int

标签: c gcc clang compiler-optimization


【解决方案1】:

我不写编译器,但我可以猜到:

编译器使用的标准优化技术都不会影响foo 中的代码。要检测它是否等同于bar,需要进行专门的优化以发现这种特定模式,并改为输出“改进的”代码。

那么,为什么没有对此进行具体优化呢?可能是通常的原因:

“投资回报不足”

换句话说,编码、调试和维护优化所花费的时间 - 以及检查该模式的每一行源代码所花费的额外编译时间 - 将淹没从中获得的任何好处。

当然,您已经拥有htons/ntohs。我就用那些。

负载对齐?

这很有趣,我不得不查一下。如果您的传入指针“x”不是字对齐的,那么bar 会在许多架构上崩溃,而foo 应该仍然可以工作。

但是 x86 架构允许未对齐的负载,因此即使对于未对齐的 x 值,这两个函数也应该可以工作。

【讨论】:

  • 我记得以前看到过这样的优化,这就是我问的原因。当然,我完全有可能只是记错了,事实上,gcc 或 Clang 都没有对此进行优化。 :)
  • x86 允许未对齐的负载,但它们对性能有(相对)较大的影响——因此编译器完全有可能避免创建它们。
  • @gsnedders,我同意这会对性能产生影响 - 但无论如何,未对齐数据上的“bar”可能会优于“foo”。
  • @Roddy:有两种系统“允许”未对齐的负载;一些将负载分解为一系列操作,这些操作可能是也可能不是完美的,但不会离它很远;其他人将陷入操作系统例程,该例程可以观察哪些指令尝试了未对齐的加载,“模拟”其行为,并返回到底层程序。在为前一种实现生成代码时,如果需要一个未对齐的加载,则应该使用一个;对于后一种实现,应始终避免使用它们。无论哪种情况...
  • ...如果在速度关键代码中可能需要一堆连续未对齐的加载,最好手动处理各种情况(例如加载一个奇数字节加上八个对齐的 32 位字到寄存器中,将字节循环到存储在寄存器中的字中,然后存储所有八个对齐的 32 位寄存器)。
猜你喜欢
  • 2021-11-30
  • 2020-12-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-05-15
  • 2019-06-30
  • 2013-03-29
  • 1970-01-01
相关资源
最近更新 更多