Jon*_*anE 35 c c++ assembly gcc x86-64
我一直在玩x86-64程序集试图了解更多有关可用的各种SIMD扩展(MMX,SSE,AVX).
为了了解GCC如何将不同的C或C++构造转换为机器代码,我一直在使用Compiler Explorer,这是一个极好的工具.
在我的一个"游戏会话"期间,我想看看GCC如何优化整数数组的简单运行时初始化.在这种情况下,我试图将数字0到2047写入2048个无符号整数的数组.
代码如下:
unsigned int buffer[2048];
void setup()
{
for (unsigned int i = 0; i < 2048; ++i)
{
buffer[i] = i;
}
}
Run Code Online (Sandbox Code Playgroud)
如果我启用优化和AVX-512指令,-O3 -mavx512f -mtune=intelGCC 6.3会生成一些非常聪明的代码:)
setup():
mov eax, OFFSET FLAT:buffer
mov edx, OFFSET FLAT:buffer+8192
vmovdqa64 zmm0, ZMMWORD PTR .LC0[rip]
vmovdqa64 zmm1, ZMMWORD PTR .LC1[rip]
.L2:
vmovdqa64 ZMMWORD PTR [rax], zmm0
add rax, 64
cmp rdx, rax
vpaddd zmm0, zmm0, zmm1
jne .L2
ret
buffer:
.zero 8192
.LC0:
.long 0
.long 1
.long 2
.long 3
.long 4
.long 5
.long 6
.long 7
.long 8
.long 9
.long 10
.long 11
.long 12
.long 13
.long 14
.long 15
.LC1:
.long 16
.long 16
.long 16
.long 16
.long 16
.long 16
.long 16
.long 16
.long 16
.long 16
.long 16
.long 16
.long 16
.long 16
.long 16
.long 16
Run Code Online (Sandbox Code Playgroud)
但是,当我测试通过添加标志使用GCC C编译器编译相同代码时将生成的内容-x c我真的很惊讶.
我希望类似的,如果不相同,结果却在C编译器似乎产生太多复杂想必也慢得多的机器代码.将所得的组件太大,贴在这里全面,但它可以在godbolt.org按照观看此链接.
生成的代码的片段,第58到83行,如下所示:
.L2:
vpbroadcastd zmm0, r8d
lea rsi, buffer[0+rcx*4]
vmovdqa64 zmm1, ZMMWORD PTR .LC1[rip]
vpaddd zmm0, zmm0, ZMMWORD PTR .LC0[rip]
xor ecx, ecx
.L4:
add ecx, 1
add rsi, 64
vmovdqa64 ZMMWORD PTR [rsi-64], zmm0
cmp ecx, edi
vpaddd zmm0, zmm0, zmm1
jb .L4
sub edx, r10d
cmp r9d, r10d
lea eax, [r8+r10]
je .L1
mov ecx, eax
cmp edx, 1
mov DWORD PTR buffer[0+rcx*4], eax
lea ecx, [rax+1]
je .L1
mov esi, ecx
cmp edx, 2
mov DWORD PTR buffer[0+rsi*4], ecx
lea ecx, [rax+2]
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,此代码具有许多复杂的移动和跳转,并且通常感觉像执行简单数组初始化的非常复杂的方式.
为什么生成的代码有这么大的差异?
与C编译器相比,GCC C++ - 编译器在优化C和C++中有效的代码方面是否更好?
Jes*_*ter 39
额外的代码用于处理未对齐,因为使用的指令vmovdqa64需要64字节对齐.
我的测试显示,即使标准没有,gcc确实允许另一个模块中的定义在C模式下覆盖此处的定义.该定义可能只符合基本对齐要求(4个字节),因此编译器不能依赖更大的对齐.从技术上讲,gcc .comm为此暂定定义发出汇编指令,而外部定义在该.data部分中使用正常符号.在链接期间,此符号优先于该符号.comm.
请注意,如果您更改要使用的程序,extern unsigned int buffer[2048];那么即使C++版本也会添加代码.相反,制作它static unsigned int buffer[2048];会将C版本变为优化版本.
| 归档时间: |
|
| 查看次数: |
1797 次 |
| 最近记录: |