gpt4 book ai didi

c++ - 使用 -fno-inline 对 memcmp 进行错误的 GCC 9(及更高版本)优化

转载 作者:行者123 更新时间:2023-12-03 06:49:42 28 4
gpt4 key购买 nike

有一个小func将内存块与静态 const 归零数组进行比较的函数。这是一个说明问题的原始示例:

#include <cstring>
#include <memory>

#define MAX_BYTES (256)

inline int my_memcmp(const void * mem1, const void * mem2, const size_t size)
{
const auto *first = reinterpret_cast<const uint8_t *>(mem1);
const auto *second = reinterpret_cast<const uint8_t *>(mem2);
if (size < 8)
{
for (int i = 0; i < size; ++i) {
if (*first != *second) return (*first > *second) ? 1 : -1;
++first; ++second;
}
return 0;
}

return std::memcmp(mem1, mem2, size);
}

bool func(const uint8_t* in, size_t size)
{
size_t remain = size;
static const uint8_t zero_arr[MAX_BYTES] = { 0 };

while (remain >= MAX_BYTES)
{
if (my_memcmp(in, zero_arr, MAX_BYTES) != 0)
{
return false;
}
remain -= MAX_BYTES;
in += MAX_BYTES;
}

return true;
}
  • 编译器:gcc 9.1 及更高版本
  • 编译器标志:-fno-inline -O3
  • Godbolt 拆机链接:https://godbolt.org/z/P8vKGq
  • Godbolt程序执行链接:https://godbolt.org/z/qr8f16

  • 如果我使用 -fno-inline编译器标志,编译器尝试优化上面的代码,只为 my_memcmp 生成 2 行代码函数,但它似乎总是返回 0:
    my_memcmp(void const*, void const*, unsigned long) [clone .constprop.0]:
    movzx eax, BYTE PTR [rdi]
    ret
    在我添加 -fno-inline 之前无法重现该问题(我在编译覆盖测试的代码时遇到了这个问题,所以我需要添加 no-inline 以使报告更清晰。)另外我发现 gcc 8 没有这样的问题。是否有合理的解释,还是只是 GCC 9 和 10 中的一个错误?

    最佳答案

    这是 GCC 错误 95189,https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95189
    基本上,如果其中一个缓冲区具有已知内容,则 GCC 可以为 memcmp 发出专门的代码,但是如果遇到零字节(因为它对于 strcmp 等其他函数是特殊的),这种专门化就不能正常工作。
    它似乎已经在 GCC 主要开发分支(主干)上修复,但该修复尚未向后移植到 9.x 和 10.x 发布分支。
    C 中的这个最小复制在 -O2 处被错误编译,错误的评论中提到了一个类似的例子:

    int f(const char *p)
    {
    return __builtin_memcmp(p, "\0\0\0", 4);
    }

    关于c++ - 使用 -fno-inline 对 memcmp 进行错误的 GCC 9(及更高版本)优化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63724679/

    28 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com