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.

È stato utile?

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.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top