2016-04-22 35 views
5

Sto lavorando su una cassa di ruggine che cambia la modalità di arrotondamento (+ inf, -inf, più vicino o troncato).Quali pass LLVM sono responsabili delle ottimizzazioni in virgola mobile?

Le funzioni che cambiano la modalità di arrotondamento sono scritti utilizzando assembly inline:

fn upward() { 
    let cw: u32 = 0; 
    unsafe { 
    asm!("stmxcsr $0; 
      mov $0, %eax; 
      or $$0x4000, %eax; 
      mov %eax, $0; 
      ldmxcsr $0;" 
      : "=*m"(&cw) 
      : "*m"(&cw) 
      : "{eax}" 
     ); 
    } 
} 

Quando compilo il codice in modalità debug funziona come previsto, ottengo ,3333333333337 per un terzo quando si aggira verso l'infinito positivo, ma quando compilo in modalità di rilascio ottengo lo stesso risultato, indipendentemente dalla modalità di arrotondamento impostata. Immagino che questo comportamento sia dovuto alle ottimizzazioni fatte dal backend LLVM.

Se sapessi quali pass LLVM sono responsabili di questa ottimizzazione, posso disabilitarli poiché non vedo altre soluzioni al momento.

+0

Ho paura che questa informazione possa dipendere molto dalla versione di LLVM (che è gratuita per aggiungere/rimuovere passaggi), e come risultato legato alla versione di 'rustc'. Quale versione di 'rustc' stai usando? Ti dispiace se questo si rompe durante l'aggiornamento? –

+0

Sto usando Rust 1.10 ogni notte. Non mi dispiace se si rompe. Se capisco che cosa sta causando questo comportamento, posso fare un po 'di fatica con un po' di duro lavoro. –

+1

Dopo alcune letture penso che ci siano dei passaggi di programmazione che stanno spostando l'istruzione di divisione prima della chiamata di funzione verso l'alto(). (solo una supposizione), correggimi se sbaglio. –

risposta

4

Fondamentalmente, non è possibile farlo. LLVM presuppone che tutte le operazioni in virgola mobile utilizzino la modalità di arrotondamento predefinita e che il registro di controllo a virgola mobile non venga mai letto o modificato.

C'è stato some discussion of this issue recently on the LLVM-dev mailing list, se sei interessato.

Nel frattempo, l'unica soluzione affidabile consiste nell'utilizzare l'assemblaggio in linea, come asm!("addsd $0, $1".

La libreria standard di Rust presuppone inoltre di non modificare la modalità di arrotondamento (in particolare, il codice per la conversione tra virgola mobile e le stringhe è sensibile a questo).

+0

Se ho capito bene, quando si usa l'assembly inline la modalità di arrotondamento impostata nei registri mxcsr o fctrl viene presa in considerazione dal calcolo in asm! macro? –

+1

Sì. A quel punto, in pratica si sta semplicemente scrivendo un assembly grezzo, quindi la semantica di Rust o LLVM IR non ha importanza. –

+0

Sì, l'ottimizzazione di LLVM è fatta sull'IR, grazie. –