Perché non vi è alcun effetto di limitare il puntatore
-
12-12-2019 - |
Domanda
Non riesco a vedere alcuna differenza di codice tramite GCC per limitare i puntatori.
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++;
}
}
Compilare con
.
gcc -S -std=c99 -masm=intel file1.c
gcc -S -std=c99 -masm=intel file2.c
File1.S e File2.S entrambi sono uguali, ad eccezione della linea .file
, che dice il nome 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
Entrambi di questi codici letti dalla memoria e quindi assegnano il percorso di memoria puntato da a
a b
. Dove mi aspettavo la versione restrict
non ri-leggere gli indirizzi di a
e b
e gli indirizzi di a
e b
verranno incrementati nel registro e alla fine scritta in memoria.
C'è qualcosa di sbagliato, sto facendo? O è la selezione dell'esempio, ok?
Ho provato con diversi interruttori -O0
, -O1
, -O2
, -O3
, -Ofast
e -fstrict-aliasing
con gli stessi risultati identici per entrambi i file.
Nota: GCC --version= GCC (GCC) 4.6.3 20120306 (Red Hat 4.6.3-2)
Modifica Codice modificato.
Soluzione
La cosa è che la seguente espressione:
*c++ = *a++ + *b++;
.
Abbastanza esigenze di dereferenziare tutti i puntatori in ciascuna iterazione del loop comunque, poiché i puntatori cambiano in ciascuna iterazione.Non c'è alcun beneficio per utilizzare restrict
.
Prova a cambiare la linea all'interno del loop su:
*c++ = *a++ + *b;
.
(Potrebbe essere necessario anche abilitare ottimizzazioni come -O2
).
Vedrai che nella custodia restrict
carichi *b
in un registro una volta, mentre nel caso senza limitare è necessario caricare attraverso il puntatore in ciascun iterazione del loop perché non sa se o meno o meno c
Ever Alias b
.
Altri suggerimenti
Stai leggendo solo uno dei puntatori, quindi restrict
non ha importanza.
Vedi Questo esempio dove lo faquestione perché i puntatori possono gli alias degli stessi dati, e i dati sono scritti e letti attraverso entrambi i puntatori.