2012-10-01 34 views
8

No puedo ver ninguna diferencia de código por gcc para restringir los punteros.Por qué no hay efecto de restringir el puntero

archivo1

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

fichero2

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

compilar con

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

file1.s y file2.s ambos son iguales, excepto la línea .file, que le dice el nombre del archivo:

.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 

Ambos código leído de la memoria y luego asignar la ubicación de memoria a la que apunta a ab. Donde esperaba, la versión restrict no volverá a leer las direcciones de a y b, y las direcciones de a y b se incrementarán en el registro y al final se escribirán en la memoria.

¿Hay algo malo que esté haciendo? ¿O está bien la selección del ejemplo?

He tratado con diferentes interruptores -O0, -O1, -O2, -O3, -Ofast y -fstrict-aliasing con los mismos resultados idénticos para los dos archivos.

Nota: gcc gcc --version = (GCC) 4.6.3 20120306 (Red Hat 4.6.3-2)

EDITAR Código cambió.

Respuesta

3

La cosa es que la siguiente expresión:

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

más o menos a las necesidades de eliminar la referencia de todos los punteros en cada iteración del bucle todos modos, ya que el cambio punteros en cada iteración. No hay beneficio al usar restrict.

trate de cambiar la línea en el interior del bucle para:

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

(puede que tenga que activar también optimizaciones tales como -O2).

Verás que en el caso restrict se carga *b en un registro de una sola vez, mientras que en el caso sin restringir necesita cargar a través del puntero en cada iteración del bucle, ya que no sabe si alguna vez o no c alias b.

+0

Entender, gracias. – phoxis

7

Solo está leyendo a través de uno de los punteros, por lo que restrict no importa.

Consulte this example donde sí importa porque los punteros pueden alias los mismos datos, y los datos se escriben y se leen a través de ambos punteros.

+0

He cambiado el código, ¿pueden echar un vistazo al nuevo? – phoxis

+0

La nueva versión no vuelve a leer ninguna memoria en ninguno de los casos, así que de nuevo, restringir no tiene ningún efecto. Es decir, cada 'int' se lee una vez. Es la información apuntada por el puntero, no el puntero mismo que está en cuestión con 'restrict'. –

+0

Entendido, gracias. – phoxis

Cuestiones relacionadas