2012-10-01 32 views
8

我看不出gcc代碼限制指針的任何區別。爲什麼沒有限制指針的效果

file1的

void test (int *a, int *b, int *c) 
{ 
    while (*a) 
    { 
    *c++ = *a++ + *b++; 
    } 
} 

file2的

void test (int *restrict a, int *restrict b, int *restrict c) 
{ 
    while (*a) 
    { 
    *c++ = *a++ + *b++; 
    } 
} 

編譯

gcc -S -std=c99 -masm=intel file1.c 
    gcc -S -std=c99 -masm=intel file2.c 

file1.sfile2.s兩者都是相同的,除了在.file線,它告訴的文件名:

.file "file1.c" 
    .text 
    .globl test 
    .type test, @function 
test: 
.LFB0: 
    .cfi_startproc 
    pushq %rbp 
    .cfi_def_cfa_offset 16 
    .cfi_offset 6, -16 
    movq %rsp, %rbp 
    .cfi_def_cfa_register 6 
    movq %rdi, -8(%rbp) 
    movq %rsi, -16(%rbp) 
    movq %rdx, -24(%rbp) 
    jmp .L2 
.L3: 
    movq -8(%rbp), %rax 
    movl (%rax), %edx 
    movq -16(%rbp), %rax 
    movl (%rax), %eax 
    addl %eax, %edx 
    movq -24(%rbp), %rax 
    movl %edx, (%rax) 
    addq $4, -24(%rbp) 
    addq $4, -8(%rbp) 
    addq $4, -16(%rbp) 
.L2: 
    movq -8(%rbp), %rax 
    movl (%rax), %eax 
    testl %eax, %eax 
    jne .L3 
    popq %rbp 
    .cfi_def_cfa 7, 8 
    ret 
    .cfi_endproc 
.LFE0: 
    .size test, .-test 
    .ident "GCC: (GNU) 4.6.3 20120306 (Red Hat 4.6.3-2)" 
    .section .note.GNU-stack,"",@progbits 

的這兩個代碼從存儲器讀出,然後分配的存儲器位置所指向的ab。在我預計restrict版本將不會重新讀取ab的地址,並且ab的地址將在寄存器中遞增,並在最後寫入內存。

我在做什麼錯?或者,示例的選擇是否正確?

我試圖與不同的開關-O0-O1-O2-O3-Ofast-fstrict-aliasing有用於這兩個文件的相同的相同的結果。

注:的gcc --version =海合會(GCC)4.6.3 20120306(紅帽4.6.3-2)

編輯代碼改變。

回答

3

的事情是,下面的表達式:

*c++ = *a++ + *b++; 

非常需要取消引用每次循環迭代所有的指針無論如何,因爲在每次迭代指針的變化。使用restrict沒有任何好處。

嘗試改變線內環路到:

*c++ = *a++ + *b; 

(您可能還需要實現優化,比如-O2)。

你會看到,在restrict情況下,它加載*b到寄存器一次,而在案件沒有限制,它需要通過在每次循環迭代指針加載,因爲它不知道是否c曾經別名b

+0

明白了,謝謝。 – phoxis

7

您只通過其中一個指針讀數,所以restrict並不重要。

請參閱this example它在哪裏很重要,因爲指針可能會混淆相同的數據,並且通過這兩個指針寫入和讀取數據。

+0

我已經改變了代碼,你可以看看新的代碼嗎? – phoxis

+0

在這兩種情況下,新版本都不會重新讀取任何內存,所以再次限制不起作用。即,每個「int」都被讀取一次。它是指針指向的數據,而不是指向「restrict」的指針本身。 –

+0

明白了,謝謝。 – phoxis

相關問題