我有这个代码: mainP.c:
int main(int c, char **v){
char *s = v[0];
while (*s++ != 0) {
if ((*s == 'a') && (*s != 'b')) {
return 1;
}
}
return 0;
}
我用clang和gcc编译生成汇编代码来比较优化:
clang-3.9 -S -masm=intel -O3 mainP.c
gcc -S -masm=intel -O3 mainP.c
编译器版本为:
clang version 3.9.1-9 (tags/RELEASE_391/rc2)
Target: x86_64-pc-linux-gnu
gcc (Debian 6.3.0-18) 6.3.0 20170516
得到的2个汇编代码是:
gcc汇编代码:
main:
.LFB0:
.cfi_startproc
mov rax, QWORD PTR [rsi]
jmp .L2
.p2align 4,,10
.p2align 3
.L4:
cmp BYTE PTR [rax], 97
je .L5
.L2:
add rax, 1
cmp BYTE PTR -1[rax], 0
jne .L4
xor eax, eax
ret
.L5:
mov eax, 1
ret
clang汇编代码:
main: # @main
.cfi_startproc
# BB#0:
mov rcx, qword ptr [rsi]
mov dl, byte ptr [rcx]
inc rcx
.p2align 4, 0x90
.LBB0_1: # =>This Inner Loop Header: Depth=1
xor eax, eax
test dl, dl
je .LBB0_3
# BB#2: # in Loop: Header=BB0_1 Depth=1
movzx edx, byte ptr [rcx]
inc rcx
mov eax, 1
cmp dl, 97
jne .LBB0_1
.LBB0_3:
ret
我注意到这一点:在gcc汇编代码中,* s在循环中被访问两次,而* s只在clang汇编代码中被访问。
是否有差异的解释?
然后稍微更改C代码(添加一个本地char变量)后,我得到与GCC相同的汇编代码:
int main(int c, char **v){
char *s = v[0];
char ch;
ch = *s;
while (ch != 0) {
if ((ch == 'a') && (ch != 'b')) {
return 1;
}
ch = *s++;
}
return 0;
}
使用GCC生成汇编代码:
main:
.LFB0:
.cfi_startproc
mov rax, QWORD PTR [rsi]
movzx edx, BYTE PTR [rax]
test dl, dl
je .L6
add rax, 1
cmp dl, 97
jne .L5
jmp .L8
.p2align 4,,10
.p2align 3
.L4:
cmp dl, 97
je .L8
.L5:
add rax, 1
movzx edx, BYTE PTR -1[rax]
test dl, dl
jne .L4
.L6:
xor eax, eax
ret
.L8:
mov eax, 1
ret
答案 0 :(得分:0)
区别的解释:编译器优化是 hard 要做的,不同的编译器会以不同的方式优化你的代码。
因为表达式相对简单,我们可以假设*s
在两个地方都是相同的值,并且实际上只需要一个负载。
但是弄清楚优化是棘手的,因为编译器必须绝对"知道"那"无论什么指向"不能在第一个参考和第二个参考之间进行更改。
在你的例子中,clang比gcc更好地计算出来。