2

並んだリストを操作するコードがあります。テールコールを使用します。残念ながら、GCC は呼び出しを最適化しません。

以下は、連結リストの長さを再帰的に計算する関数の C コードです。

size_t ll_length(const ll_t* list) {
    return ll_length_rec(list, 0);
}

size_t ll_length_rec(const ll_t* list, size_t size_so_far)
{
    if (list)   {
        return ll_length_rec(list->next, size_so_far + 1);
    } else {
        return size_so_far;
    }
}

アセンブラコードは次のとおりです。

.globl _ll_length_rec
_ll_length_rec:
LFB8:
    .loc 1 47 0
    pushq   %rbp
LCFI6:
    movq    %rsp, %rbp
LCFI7:
    subq    $32, %rsp
LCFI8:
    movq    %rdi, -8(%rbp)
    movq    %rsi, -16(%rbp)
    .loc 1 48 0
    cmpq    $0, -8(%rbp)
    je  L8
    .loc 1 49 0
    movq    -16(%rbp), %rsi
    incq    %rsi
    movq    -8(%rbp), %rax
    movq    8(%rax), %rdi
    call    _ll_length_rec  # < THIS SHOUD BE OPTIMIZED
    movq    %rax, -24(%rbp)
    jmp L10

callGCCがそれを最適化する場合、asmにはありません。私はそれをコンパイルします:

gcc  -S -fnested-functions -foptimize-sibling-calls \
    -03 -g -Wall -o llist llist.c

GCC のバージョンは次のとおりです。

i686-apple-darwin10-gcc-4.2.1 (GCC) 4.2.1 (Apple Inc. build 5666) (dot 3)
4

3 に答える 3

9

コンパイル行に追加-O3すると、問題のある呼び出しが生成されないように見えますが、それがないと、最適化されていない呼び出しが発生します。頭の中ですべての gcc オプションを知っているわけではありませんが-03、タイプミスですか、-O3それとも意図的なものですか?

Ltmp2:
        pushq   %rbp
Ltmp0:
        movq    %rsp, %rbp
Ltmp1:
        jmp     LBB1_1
        .align  4, 0x90
LBB1_3:
        addq    $2, %rsi
Ltmp3:
        movq    (%rax), %rdi
Ltmp4:
LBB1_1:
Ltmp5:
        testq   %rdi, %rdi
        je      LBB1_5
Ltmp6:
        movq    (%rdi), %rax
        testq   %rax, %rax
        jne     LBB1_3
        incq    %rsi
LBB1_5:
        movq    %rsi, %rax
Ltmp7:
Ltmp8:
        popq    %rbp
        ret
于 2013-07-13T07:35:59.330 に答える
2

おそらく、どちらの関数も として宣言されていないためです。staticつまり、リンク時に他のコンパイルユニットがシンボルを必要とする場合に備えて、シンボルがリンカーに表示されている必要があります。-fwhole-program フラグを指定してコンパイルし、何が起こるかを確認してください。

于 2013-07-13T07:26:39.447 に答える
1

おそらく、GCC のバージョンと特定のビルドに依存します。これは、WindowsのGCC 3.4.4以降から取得したもの-O2です

.globl _ll_length_rec
    .def    _ll_length_rec; .scl    2;  .type   32; .endef
_ll_length_rec:
    pushl   %ebp
    movl    %esp, %ebp
    movl    8(%ebp), %edx
    movl    12(%ebp), %eax
    jmp L3
    .p2align 4,,7
L6:
    movl    (%edx), %edx
    incl    %eax
L3:
    testl   %edx, %edx
    jne L6
    popl    %ebp
    ret
于 2013-07-13T07:36:38.430 に答える