gpt4 book ai didi

c - 为什么没有编译器能够优化这段代码?

转载 作者:太空宇宙 更新时间:2023-11-04 00:24:08 25 4
gpt4 key购买 nike

考虑以下 C 代码(假设 80 位 long double)(注意,我确实知道 memcmp,这只是一个实验):

enum { sizeOfFloat80=10 }; // NOTE: sizeof(long double) != sizeOfFloat80
_Bool sameBits1(long double x, long double y)
{
for(int i=0;i<sizeOfFloat80;++i)
if(((char*)&x)[i]!=((char*)&y)[i])
return 0;
return 1;
}

我检查过的所有编译器(gcc.godbolt.org 上的 gcc、clang、icc)都生成类似的代码,这里是带有选项的 gcc 示例 -O3 -std=c11 -fomit-frame-pointer -m32:

sameBits1:
movzx eax, BYTE PTR [esp+16]
cmp BYTE PTR [esp+4], al
jne .L11
movzx eax, BYTE PTR [esp+17]
cmp BYTE PTR [esp+5], al
jne .L11
movzx eax, BYTE PTR [esp+18]
cmp BYTE PTR [esp+6], al
jne .L11
movzx eax, BYTE PTR [esp+19]
cmp BYTE PTR [esp+7], al
jne .L11
movzx eax, BYTE PTR [esp+20]
cmp BYTE PTR [esp+8], al
jne .L11
movzx eax, BYTE PTR [esp+21]
cmp BYTE PTR [esp+9], al
jne .L11
movzx eax, BYTE PTR [esp+22]
cmp BYTE PTR [esp+10], al
jne .L11
movzx eax, BYTE PTR [esp+23]
cmp BYTE PTR [esp+11], al
jne .L11
movzx eax, BYTE PTR [esp+24]
cmp BYTE PTR [esp+12], al
jne .L11
movzx eax, BYTE PTR [esp+25]
cmp BYTE PTR [esp+13], al
sete al
ret
.L11:
xor eax, eax
ret

这看起来很难看,每个字节都有分支,实际上似乎根本没有优化(但至少循环展开了)。很容易看出,这可以优化为等同于以下的代码(通常对于较大的数据使用较大的步幅):

#include <string.h>
_Bool sameBits2(long double x, long double y)
{
long long X=0; memcpy(&X,&x,sizeof x);
long long Y=0; memcpy(&Y,&y,sizeof y);
short Xhi=0; memcpy(&Xhi,sizeof x+(char*)&x,sizeof Xhi);
short Yhi=0; memcpy(&Yhi,sizeof y+(char*)&y,sizeof Yhi);
return X==Y && Xhi==Yhi;
}

这段代码现在得到了更好的编译结果:

sameBits2:
sub esp, 20
mov edx, DWORD PTR [esp+36]
mov eax, DWORD PTR [esp+40]
xor edx, DWORD PTR [esp+24]
xor eax, DWORD PTR [esp+28]
or edx, eax
movzx eax, WORD PTR [esp+48]
sete dl
cmp WORD PTR [esp+36], ax
sete al
add esp, 20
and eax, edx
ret

所以我的问题是:为什么三个编译器都不能进行这种优化?它在 C 代码中很不常见吗?

最佳答案

首先,它无法进行此优化,因为您通过使用过多的内存重新解释来重载代码,从而完全混淆了代码的含义。像这样的代码只会让编译器使用react“我不知道这到底是什么,但如果那是你想要的,那就是你会得到的”。我完全不清楚为什么您希望编译器甚至费心将一种内存重新解释转换为另一种内存重新解释(!)。

其次,它可能在理论上可以做到,但在其优先级列表中可能不是很高。请记住,代码优化通常是由模式匹配 算法完成的,而不是由某种 A.I.这不是它识别的模式之一。

大多数情况下,您手动尝试对代码执行低级优化会挫败编译器执行相同操作的努力。如果你想自己优化它,那就一路走吧。不要指望能够启动然后将其交给编译器为您完成工作。

比较两个 long doublexy 可以很容易地完成:x == y .如果你想要一个位到位的内存比较,你可能会通过在编译器中使用 memcmp 来使编译器的工作更容易,该编译器本身就知道 memcmp 是什么(内置 -在,内在功能)。

关于c - 为什么没有编译器能够优化这段代码?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36376088/

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