c++ - 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);
}
由于x
和dest
可能指向相同的内存,因此不允许编译器将其优化为单个 qword 移动(每行可能会更改 的值x
)。
到目前为止,一切都很好。
但是,如果您x
改为按值传递,则此论点不再成立。事实上,GCC 将其优化为一个简单的mov
指令,正如预期的那样:https ://godbolt.org/z/iYj1or
但是,clang 没有:https ://godbolt.org/z/Hgg5z9
我假设,因为它甚至不能保证占用任何堆栈内存,所以在调用函数之前任何指向的x
尝试都会导致未定义的行为,因此编译器可以假设这永远不会发生。这意味着 clang 在这里错过了一些机会。但我不确定。有人可以澄清吗?dest
x
解决方案
您提供的代码过于复杂。您可以将其替换为:
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 平台上都对此进行了完美优化。
推荐阅读
- c - “file.c”和“file.h”有什么区别?
- bash - -Exec 在 find 命令中缺少参数(\; 和 + 之间的差异)
- oracle - 我想从远程 PC 连接到带有 oracle DB 的主机
- python - 在python上读取txt文件的列
- java - Hibernate:在不同的会话中更新相同的对象
- python - 从批处理脚本运行的 Python 脚本,在一台 PC 上运行,在另一台 PC 上运行 IndexError
- python - 熊猫:增长的简单分析(比较)和 Fillna
- selenium - 如何从自动建议文本框中选择值?
- java - Maven 告诉我“编译中的致命错误:无效的目标版本”尽管 java 版本是正确的
- angular - 如何在离子 3 中将按钮更改为 2 个按钮 onClick