2015-02-17 30 views
13

Supponiamo di utilizzare una versione moderna di GCC per compilare un programma C. Inoltre, considera che il mio programma contiene branch stantii, ma che mi piacerebbe molto che il codice morto in quei rami stantii fosse compilato e presente nel programma finale. Si consideri il seguente programma:Può GCC essere istruito a non eliminare il codice guasto?

int main(int argc, char** argv) { 
    int a = 0; 
    goto skip; 
     a = -1; 
    skip: ; 
    return a; 
} 

Chiaramente, se uso GCC con impostazioni di ottimizzazione di default, la seconda assegnazione non potrà mai rendere al programma definitivo, come il compilatore può facilmente dire che non sarà mai essere eseguito. Supponiamo che io non voglia che ciò accada.

In GCC, ci sono una serie di flag che si dilettano con il codice di morti (in particolare -fdce), e posso scegliere di disattivare in modo esplicito questi quando invocare GCC di conseguenza:

-fno-dce 
-fno-dse 
-fno-tree-dce 
-fno-tree-dse 

Per quanto posso dire , questo dovrebbe indicare a GCC di non confondere il secondo compito. Tuttavia, il codice in questione non sembra mai farlo nel mio programma.

Perché GCC insistere sulla rimozione del codice morto, e c'è un modo di istruire GCC non per sbarazzarsi del secondo incarico?

+0

stai usando ? – anatolyg

+2

Sono a conoscenza di 'volatile', ma sono curioso di sapere se è possibile farlo con GCC. Per quanto riguarda GCC sto usando la versione 4.8.3, ma sarei interessato a sapere se c'è una soluzione qualsiasi versione specifica! – Caterpillar

+0

Ignora il mio commento. Volatile non impedisce a GCC di saltare il compito. –

risposta

8

Le opzioni -fno-* non funzionano con me con gcc-4.9.2. Detto questo, penso che il seguente dovrebbe essere portatile per tutti gcc (4.5+) obiettivi:

__asm__ goto (""::::no_skip); 
goto skip; 

no_skip: 
    a = -1; 

skip:; 

Dal manuale: "una dichiarazione asm goto è sempre implicitamente considerato volatile"

Inoltre, con gcc-4.8 e versioni successive, si potrebbe prendere in considerazione l'aggiunta di un attributo per consentire al compilatore di sapere che si tratta di un percorso "improbabile". Questo aiuta a prevenire sanzioni ramificazione, ecc, che altrimenti potrebbero verificarsi quando prendendo il sentiero 'atteso':

no_skip: __attribute__ ((cold)); 

E 'ovvio che si potrebbe anche usare:

skip: __attribute__ ((hot)); 
Quale versione gcc
+0

Grazie. Questo fa sorgere la domanda sul perché il mio esempio non è considerato codice morto da GCC, o almeno perché le bandiere indicate non comprendono il secondo compito (forse il ramo stantio è così ovviamente non raggiungibile che è eliminato in una fase precedente non influenzata da le opzioni). – Caterpillar

+0

@Caterpillar - Ho il sospetto che tu abbia ragione, che il codice irraggiungibile sia stato eliminato in precedenza. Un'altra possibilità è che la documentazione non traccia precisamente lo sviluppo. Il documento [internals] (https://gcc.gnu.org/onlinedocs/gccint/Edges.html#Edges) sembra avere alcuni dettagli interessanti. –

Problemi correlati