Prima di tutto sto sviluppando per un microcontrollore in modo RAM e ROM utilizzo sono le priorità.GCC non ottimizza una copia struct del const static Non inizializzato
Mi rendo conto che può leggere come un bug report o non abbastanza specifica. Se non ottengo alcuna risposta qui, la archiverò come tale.
Mi piace usare le strutture static const
per inizializzare strutture a pila ai valori predefiniti. Nella maggior parte dei casi la struttura predefinita è tutti zero. Io preferisco farlo con le strutture static const
piuttosto che un memset
(memset or struct assignment, static const assignment)
mio toolchain attuale è arm-none-eabi-gcc-4_7_3
, compilazione per un target Cortex M4 con l'ottimizzazione -Os
.
ho notato quanto segue; GCC produce codice diverso se inizializzo esplicitamente il mio static const
struct a zero che se non lo faccio (static const struct foo;
vs static const struct foo = {0};
). In particolare, alloca le strutture static const
non inizializzate in memoria ed esegue operazioni di copia.
Ecco un esempio di codice:
struct foo {int foo; int bar;};
struct bar {int bar[20];};
static const struct foo foo1_init, foo2_init = {0};
static const struct bar bar1_init, bar2_init = {0};
extern struct foo foo1, foo2;
extern struct bar bar1, bar2;
void init_foo1(void)
{
foo1 = foo1_init;
}
void init_foo2(void)
{
foo2 = foo2_init;
}
void init_bar1(void)
{
bar1 = bar1_init;
}
void init_bar2(void)
{
bar2 = bar2_init;
}
Compilato, questo produce i seguenti assembler che elenca (riarrangiato e tagliati per brevità):
396 .section .bss.foo1_init,"aw",%nobits
397 .align 2
398 .set .LANCHOR0,. + 0
401 foo1_init:
402 0000 00000000 .space 8
402 00000000
40 .L2:
41 0010 00000000 .word .LANCHOR0
42 0014 00000000 .word foo1
55: **** foo1 = foo1_init;
32 .loc 1 55 0
33 0000 034A ldr r2, .L2
34 0002 044B ldr r3, .L2+4
35 0004 92E80300 ldmia r2, {r0, r1}
36 0008 83E80300 stmia r3, {r0, r1}
67 .L5:
68 000c 00000000 .word foo2
60: **** foo2 = foo2_init;
60 0000 024B ldr r3, .L5
61 0002 0022 movs r2, #0
62 0004 1A60 str r2, [r3, #0]
63 0006 5A60 str r2, [r3, #4]
389 .section .bss.bar1_init,"aw",%nobits
390 .align 2
391 .set .LANCHOR1,. + 0
394 bar1_init:
395 0000 00000000 .space 80
395 00000000
395 00000000
395 00000000
395 00000000
98 .L8:
99 0010 00000000 .word .LANCHOR1
100 0014 00000000 .word bar1
65: **** bar1 = bar1_init;
89 .loc 1 65 0
90 0002 0349 ldr r1, .L8
91 0004 0348 ldr r0, .L8+4
92 0006 5022 movs r2, #80
93 0008 FFF7FEFF bl memcpy
130 .L11:
131 0010 00000000 .word bar2
70: **** bar2 = bar2_init;
121 .loc 1 70 0
122 0002 0021 movs r1, #0
123 0004 5022 movs r2, #80
124 0006 0248 ldr r0, .L11
125 0008 FFF7FEFF bl memset
possiamo vedere che per foo2 = init_foo2
e bar2 = init_bar2
il compilatore ha ottimizzato le copie basso per memorizzare zeri per foo2
direttamente o chiamando memset
per bar2
.
Possiamo vedere che per foo1 = init_foo1
e bar1 = init_bar1
il compilatore sta eseguendo copie espliciti, il caricamento e il salvataggio di dai registri per foo1
e chiedendo memcpy
per foo2
.
ho alcune domande:
- E` previsto operazione GCC? Mi aspetto che le strutture non inizializzate
static const
seguano lo stesso percorso all'interno di GCC come le strutture inizializzate distatic const
e quindi producano lo stesso output. - Accade questo per altre versioni di ARM GCC? Non ho altre versioni a portata di mano, e tutti i compilatori online degli assembly
C
sono in realtàC++
. - Questo succede per altre architetture di destinazione di GCC? Ancora una volta, non ho altre versioni a portata di mano.
Potrebbe modificare il codice per la coerenza? Attualmente si riferisce a 'foo1_init' ecc., Che non sono definiti nel tuo codice (al suo posto definisce' init_foo1'). Immagino sia solo un refuso, dato che hai 'init_foo1' come una variabile e una funzione nello stesso scope. –
Una chiamata a 'memcpy()' è abbastanza economica in termini di spazio, l'hai confrontata con quello che costerebbe inserire le copie in linea? Forse c'è un'euristica che emette la chiamata quando il numero di byte è abbastanza grande. – unwind
@Ian Effettivamente un errore di battitura. Originariamente avevo una singola funzione chiamata qualcos'altro ma che rendeva l'output dell'assembly difficile da comprendere. –