我在不同的项目中使用了这两个编译器。
它们在代码处理和输出生成方面有何不同?例如,gcc
和clang
都有用于优化的-O2
选项。它们在优化代码方面的操作方式(高层)是相同的吗?我做了一个小测试,例如,如果我有以下代码:
int foo(int num) {
if(num % 2 == 1)
return num * num;
else
return num * num +1;
}
以下是clang和-O2的输出程序集:
----gcc 5.3.0----- ----clang 3.8.0----
foo(int): foo(int):
movl %edi, %edx movl %edi, %eax
shrl $31, %edx shrl $31, %eax
leal (%rdi,%rdx), %eax addl %edi, %eax
andl $1, %eax andl $-2, %eax
subl %edx, %eax movl %edi, %ecx
cmpl $1, %eax subl %eax, %ecx
je .L5 imull %edi, %edi
imull %edi, %edi cmpl $1, %ecx
leal 1(%rdi), %eax setne %al
ret movzbl %al, %eax
.L5: addl %edi, %eax
movl %edi, %eax retq
imull %edi, %eax
ret
可以看出,输出具有不同的指令。所以我的问题是,在不同的项目中,他们中的一个是否比另一个更有优势?
发布于 2016-04-11 15:51:49
发布于 2016-04-11 15:50:11
在本例中,Clang输出更好一些,因为它不进行分支;相反,它加载num % 2 == 1
的值以al
由gcc生成的代码使用跳转。如果期望num
是偶数/奇数,概率为50%,并且没有重复模式,则由GCC生成的代码将是susceptible to branch prediction failure。
但是,您也可以通过执行以下操作来使代码在GCC上运行良好
int foo(int num) {
return num * num + (num % 2 != 1);
}
更重要的是,看起来你的算法实际上是为无符号数定义的,你应该使用unsigned int
(它们对于负数是不同的)-实际上你通过使用unsigned int
作为参数可以获得很大的加速,因为现在GCC/Clang可以将num % 2
优化为num & 1
unsigned int foo(unsigned int num) {
return num * num + (num % 2 != 1);
}
由gcc -O2
生成的结果代码
movl %edi, %edx
imull %edi, %edi
andl $1, %edx
xorl $1, %edx
leal (%rdi,%rdx), %eax
ret
比由这两个编译器生成的原始函数的代码要好得多。因此,编译器并不像知道自己在做什么的程序员那么重要。
https://stackoverflow.com/questions/36542284
复制相似问题