【问题标题】:Is there a reason why Clang does not optimize this code?Clang 不优化这段代码有什么原因吗?
【发布时间】:2019-05-13 11:57:41
【问题描述】:

考虑一下我在this question 中找到的这个函数:

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 占用任何堆栈内存,所以任何尝试使 dest 指向 x 在调用函数之前会导致未定义的行为,因此编译器可以假设这永远不会发生。这意味着 clang 在这里错过了一些机会。但我不确定。有人可以澄清一下吗?

【问题讨论】:

  • 对齐浮现在脑海中。不确定您是否可以使用未对齐的 qword mov。
  • @Someprogrammerdude 我不想让编译器不优化它。我只是想知道 clang 是否有正当理由不像 gcc 那样优化它
  • dest 不能指向局部变量,因为它还不存在。也许报告一个错过的优化错误
  • @M.M 是的,这和我的想法一样。将尽快提交报告
  • 你在问为什么clang不做gcc做的一些/所有优化?也许是因为它不是必需的。

标签: c++ optimization clang


【解决方案1】:

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

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

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

Clang 和 GCC 在小端和大端平台上都对此进行了完美优化。

【讨论】:

  • 好吧,如果我必须重新实现它,我会得到我发布的代码 :) 但很高兴知道这种方式 clang 看到了优化机会。
猜你喜欢
  • 2014-07-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-03-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多