首页 > 解决方案 > Clang 不优化这段代码有什么原因吗?

问题描述

考虑我在这个问题中找到的这个函数:

void to_bytes(uint64_t const& x, uint8_t* dest) {
    dest[7] = uint8_t(x >> 8*7);
    dest[6] = uint8_t(x >> 8*6);
    dest[5] = uint8_t(x >> 8*5);
    dest[4] = uint8_t(x >> 8*4);
    dest[3] = uint8_t(x >> 8*3);
    dest[2] = uint8_t(x >> 8*2);
    dest[1] = uint8_t(x >> 8*1);
    dest[0] = uint8_t(x >> 8*0);
}

由于xdest可能指向相同的内存,因此不允许编译器将其优化为单个 qword 移动(每行可能会更改 的值x)。

到目前为止,一切都很好。

但是,如果您x改为按值传递,则此论点不再成立。事实上,GCC 将其优化为一个简单的mov指令,正如预期的那样:https ://godbolt.org/z/iYj1or

但是,clang 没有:https ://godbolt.org/z/Hgg5z9

我假设,因为它甚至不能保证占用任何堆栈内存,所以在调用函数之前任何指向的x尝试都会导致未定义的行为,因此编译器可以假设这永远不会发生。这意味着 clang 在这里错过了一些机会。但我不确定。有人可以澄清吗?destx

标签: c++optimizationclang

解决方案


您提供的代码过于复杂。您可以将其替换为:

void to_bytes(uint64_t x, uint8_t* dest) {
    x = htole64(x);
    std::memcpy(dest, &x, sizeof(x));
}

是的,这使用了 Linux-ism htole64(),但是如果您在另一个平台上,您可以轻松地重新实现它。

Clang 和 GCC 在 little-endian 和 big-endian 平台上都对此进行了完美优化。


推荐阅读