2015-07-30 12 views
13

Durante la compilazione di un'unità di traduzione il compilatore sta eseguendo molte ottimizzazioni: inlining, piegatura/propagazione costante, analisi alias, srotolamento del loop, eliminazione del codice morto e molti altri di cui non ho nemmeno sentito parlare. Sono tutti fatti quando si utilizza LTO/LTCG/WPO tra più unità di traduzione o solo un sottoinsieme (o una variante) di essi (ho sentito parlare di inlining)? Se non tutte le ottimizzazioni sono fatte considererei le build di unità superiori a LTO (o forse li useremo entrambi quando ci sono più di 1 file sorgente di unità).Le ottimizzazioni fatte in LTO sono le stesse della normale compilazione?

La mia ipotesi è che non è lo stesso (unità costruisce con il set completo di ottimizzazioni) e anche che varia molto tra i compilatori.

La documentazione su lto di ciascun compilatore non risponde precisamente a questo (o non riesco a capirlo).

Poiché lto implica il salvataggio della rappresentazione intermedia nei file oggetto, in teoria LTO potrebbe fare tutte le ottimizzazioni ... giusto?

Nota che non sto chiedendo informazioni sulla velocità di costruzione: si tratta di un problema separato.

EDIT: Sono principalmente interessato a gcc/llvm.

+0

Come hai detto tu stesso, è probabile che vari notevolmente tra i compilatori. Potrebbe essere possibile rispondere sia per GCC che per LLVM, ma oltre a ciò è troppo ampio. Si prega di restringere l'ambito. –

+0

Che cos'è "LTO" ?? –

+1

@ BЈовић ottimizzazioni link-time (o generazione di un time code del collegamento o ottimizzazione dell'intero programma) – onqtam

risposta

8

Se si dispone di uno sguardo alla documentazione di gcc si trova:

-flto [= n]

Questa opzione esegue l'ottimizzatore di collegamento-tempo standard. Quando viene invocato con il codice sorgente, genera GIMPLE (una delle rappresentazioni interne di GCC) e lo scrive in speciali sezioni ELF nel file oggetto. Quando i file oggetto sono collegati insieme, tutti i corpi delle funzioni vengono letti da queste sezioni ELF e istanziati come se fossero stati parte della stessa unità di traduzione.

Per utilizzare l'ottimizzatore del collegamento, è necessario specificare le opzioni -flto e di ottimizzazione al momento della compilazione e durante il collegamento finale. Ad esempio:

  gcc -c -O2 -flto foo.c 
      gcc -c -O2 -flto bar.c 
      gcc -o myprog -flto -O2 foo.o bar.o 

I primi due invocazioni GCC a salvare una rappresentazione bytecode di Gimple in sezioni speciali ELF all'interno foo.o e bar.o. L'invocazione finale legge il bytecode di GIMPLE da foo.o e bar.o, unisce i due file in una singola immagine interna e compila il risultato come al solito. Poiché sia ​​foo.o che bar.o sono uniti in un'unica immagine, , questo fa sì che tutte le analisi e le ottimizzazioni interprocedurali in GCC funzionino tra i due file come se fossero uno solo. Ciò significa, ad esempio, che l'inliner è in grado di integrare funzioni in bar.o in funzioni in foo.o e viceversa.

Come dice la documentazione, sì, tutto! le ottimizzazioni sono come il programma è compilato in un singolo file. Anche questo può essere fatto con -fwhole-program per ottenere lo "stesso" risultato di ottimizzazione.

Se si compila questo esempio molto semplice:

f1.cpp:

int f1() { return 10; } 

f2.cpp:

int f2(int i) { return 2*i; } 

main.cpp:

int main() 
{ 
    int res=f1(); 
    res=f2(res); 
    res++; 

    return res; 
} 

ho ottenuto come output assembler:

00000000004005e0 <main>: 
    4005e0: b8 15 00 00 00   mov $0x15,%eax 
    4005e5: c3      retq 
    4005e6: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1) 
    4005ed: 00 00 00 

Tutto il codice è inline come previsto.

La mia esperienza è che l'attuale gcc si ottimizza esattamente come compilato in un singolo file. In condizioni molto rare ho ottenuto ICE durante l'utilizzo di lto. Ma con la versione 5.2.0 effettiva non ho più visto nessun ICE.

[ICE] -> Errore interno del compilatore

+0

Bella risposta .... –

Problemi correlati