Since the number of registers depends on the architecture, is a generic pre-compiled binary targeted for the worst case (least number of available registers)?
Non esiste davvero un binario precompilato generico. I binari compilati sono necessariamente destinati a una specifica Architettura dell'insieme di istruzioni e a uno specifico Interfaccia binaria di applicazione . Lo stesso binario non verrà eseguito su un ISA diverso o su un ABI diverso, dovrà essere ricompilato per questo.
È l'ISA che definisce il set di registri hardware disponibile; l'ABI definisce come il software può utilizzare i registri, specialmente quando si tratta di chiamate di funzione.
Durante la compilazione, l'ISA e l'ABI vengono selezionati scegliendo il compilatore appropriato o, a volte, le opzioni del compilatore.
Ad esempio, x86 è un'Intel Set Architecture a 32 bit intel che specifica ~ 8 registri a 32 bit (senza contare alcun registro in virgola mobile o xmm).
x64, dall'altra ha avuto ~ 16 registri a 64 bit. E ci sono anche altri processori.
Un binario compilato per x86 di solito esegue in modalità di compatibilità a 32 bit come una caratteristica di un processore x64 , tuttavia, un x64 compilato-binario non verrà eseguito su un x86. (Quando un processore x64 esegue un binario x86 che binario viene eseguito con le risorse dell'architettura dell'insieme di istruzioni a 32 bit, vale a dire che è limitato ai registri ~ 8 a 32 bit e ha anche un limite di spazio di indirizzi di 4 GB; non ha accesso ai 16 registri a 64 bit o agli indirizzi più grandi.)
Inoltre, un file binario compilato per Windows non verrà eseguito su Linux e viceversa a causa delle differenze ABI, anche per lo stesso ISA.
Is the loop unrolling one of the examples of this “targeted” compilation?
Tutta la compilation "pre" è mirata a una coppia ISA e ABI esatta.
As in, a software compiled for a processor with more registers than the generic case will utilize ALL those registers for its loops?
Sì, fino a un certo punto. Ma direi che non esiste un caso generico, ci sono casi specifici.
C'è un'area di compilazione che è più dinamica, e questa è Just in Time Compiling o JITing in breve. Sia Java che C # utilizzano entrambi un modulo binario intermedio chiamato codice byte (diverso per ciascuno, ovviamente), quindi eseguono la compilazione finale sul computer di destinazione in fase di runtime. Poiché il runtime conosce meglio l'attuale processore su cui è in esecuzione, può fare un lavoro migliore di gestione della compilazione non solo per ISA e ABI specifici, ma anche per il processore specifico. Questo include i registri e influisce sull'uso di funzioni opzionali del processore, come i registri XMM. Ad esempio, in C # è possibile scrivere codice che utilizza le estensioni del processore SIMD e, se tale hardware è presente (cioè è attualmente in esecuzione su un processore più costoso o più moderno), il JIT genererà il codice per utilizzarli e se l'hardware non è presente, non lo farà.
In un ambiente "pre" compilato, dovresti creare due binari precompilati separati per questo.