Sto provando a scrivere un programma in stile funzionale con C il più possibile. Conosco silenziosi compilatori come GCC/Clang do tail, ma non è garantito. C'è qualche opzione per forzare l'ottimizzazione delle chiamate tail sui compilatori? (Ovviamente quando viene chiamato solo alla fine di se stesso)È possibile forzare l'ottimizzazione delle chiamate tail su GCC/Clang?
risposta
Clang non esegue alcuna ottimizzazione. C'è un pass LLVM tailcallelim
che può fare ciò che vuoi (ma non è garantito). Puoi eseguirlo separatamente con opt
.
Qual è l'opzione? Posso avere qualche link per questo? – Eonil
opt è uno strumento da riga di comando fornito con llvm, http://llvm.org/cmds/opt.html –
In alternativa è possibile modificare il driver clang per assicurarsi che venga eseguito questo passaggio in modo esplicito. –
In realtà un sacco di compilatori per C lo gestiscono già per te. Come accennato, potresti anche lasciare che il compilatore gestisca la maggior parte di queste cose piuttosto che provare a creare ottimizzazioni che non funzioneranno altrove. Spesso, anche se imposti i flag di ottimizzazione, non troverai alcuna differenza di prestazioni.
Una risposta meta:
Ci sono alcune lezioni è utile prendere in consegna in C da linguaggi funzionali: l'uso di piccole funzioni, funzioni d'uso che non mutano né globali o argomenti di input, non abbiate paura di puntatori di funzioni. Ma c'è un limite a ciò che si può ragionevolmente fare qui, e fare affidamento sull'eliminazione di chiamata di coda ('ottimizzazione di coda ' non è proprio il termine giusto) è probabilmente al di là di ciò che è utile. Non è possibile forzare il compilatore a utilizzare questa strategia, e anche se fosse possibile, la risultante C sarebbe estremamente unidiomatica e difficile da leggere per gli altri, incluso il proprio sé futuro.
Utilizzare le lingue per i loro punti di forza. C è buono per alcune cose, quindi usalo per quelli, in buono stile C. Se vuoi diversi punti di forza, o se vuoi usare uno stile funzionale (ottima decisione!), Usa un linguaggio funzionale.
Se in realtà è una coda, un ciclo while o un goto non appariranno molto diversi da una chiamata ricorsiva. Basta aggiornare tutte le variabili invece di passarle come parametri. AFAIK questo è l'unico modo multipiattaforma in C per controllare l'utilizzo dello stack a tutti i livelli di ottimizzazione. Può anche essere più leggibile poiché hai una funzione con inizializzazione seguita dal ciclo, che è piuttosto idiomatica. La versione ricorsiva della coda richiede due funzioni, una per l'inizializzazione e una per la parte ricorsiva.
Il compilatore è probabilmente piuttosto intelligente a questo proposito, fidatevi. Non c'è bisogno di hack * non-portatili *. –
Cosa vuoi che succeda nei casi in cui pensi che l'ottimizzazione della coda dovrebbe verificarsi ma il compilatore non è in grado di farlo (per qualsiasi ragione)? –
@ Michael mi aspettavo un errore di compilazione se l'ottimizzazione forzata delle chiamate tail è impossibile. – Eonil