c - gcc/clang 对 uint8_t* 数组中 uint16_t 的小端加载进行优化

标签 c gcc clang compiler-optimization

鉴于以下情况:

#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 位加载)?负载对齐?

最佳答案

我不编写编译器,但我可以有很好的猜测:

编译器使用的标准优化技术都不会影响 foo 中的代码。要检测它是否与 bar 等效,需要进行特定的优化来发现此特定模式,并输出“改进的”代码。

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

"Insufficient return on investment"

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

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

Alignment of loads?

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

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

关于c - gcc/clang 对 uint8_t* 数组中 uint16_t 的小端加载进行优化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10839745/

相关文章:

c - Linux/C 如何正确结束命令行程序

c++ - 如何从二进制发行版安装 Clang?

比较 2 个不同长度的 char*(不带空终止符)

c - 使用 C 的 B 树

c - C 中的 bmp 段错误

c++ - 链接器错误,使用 g++ 链接到 gcc 编译的库,未定义对该函数的引用

GCC 内联汇编副作用

c++ - GCC C++ 名称修改引用

xcode - 如何在 Xcode 中禁用一个文件的优化

c++ - CMake "clang++ is not able compile a simple test program"(软呢帽 20)