Clang不优化此代码是否有原因?

时间:2019-05-13 11:57:41

标签: c++ optimization clang

考虑一下我在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

但是,铛不会:https://godbolt.org/z/Hgg5z9

我假设,由于甚至无法保证x根本不占用任何堆栈内存,因此任何试图使dest指向x的尝试都是之前调用该函数将导致未定义的行为,因此编译器可以假定这种情况永远不会发生。那意味着c在这里失去了一些机会。但是我不确定。有人可以澄清吗?

1 个答案:

答案 0 :(得分:2)

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

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

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

在小端和大端平台上,Clang和GCC可以完美地优化这一点。