2012-10-01 29 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

相关问题