GCC vs CLANG指向char * optimization

时间:2017-09-09 09:15:17

标签: c gcc assembly clang

我有这个代码:     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

1 个答案:

答案 0 :(得分:0)

区别的解释:编译器优化是 hard 要做的,不同的编译器会以不同的方式优化你的代码。

因为表达式相对简单,我们可以假设*s在两个地方都是相同的值,并且实际上只需要一个负载。

但是弄清楚优化是棘手的,因为编译器必须绝对"知道"那"无论什么指向"不能在第一个参考和第二个参考之间进行更改。

在你的例子中,clang比gcc更好地计算出来。