2016-04-22 10 views
5

Ich arbeite an einer Rust-Kiste, die den Rundungsmodus ändert (+ inf, -inf, nearest oder trunkate).Welche LLVM-Pässe sind verantwortlich für Gleitkomma-Optimierungen?

Die Funktionen, die den Rundungsmodus ändern mit Inline-Assembler geschrieben:

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}" 
     ); 
    } 
} 

Wenn ich den Code im Debug-Modus funktioniert wie beabsichtigt zu kompilieren, bekomme ich ,3333333333337 für ein Drittel, wenn in Richtung positive Unendlichkeit Rundung, aber wenn ich im Freigabemodus kompiliere, bekomme ich das gleiche Ergebnis, egal welchen Rundungsmodus ich einstelle. Ich vermute, dass dieses Verhalten auf die Optimierungen zurückzuführen ist, die das LLVM-Backend durchführt.

Wenn ich wüsste, welche LLVM Pässe für diese Optimierung verantwortlich sind, kann ich sie deaktivieren, da ich im Moment keine andere Problemumgehung sehe.

+0

Ich fürchte, dass diese Informationen sehr von der Version von LLVM (die frei ist, um hinzuzufügen/zu entfernen) hängt, und als Ergebnis an die Version von 'rustc' gebunden ist. Welche Version von 'rustc' benutzt du? Stört es dich, wenn das beim Upgrade kaputt geht? –

+0

Ich benutze Rust 1.10 allabendlich. Es macht mir nichts aus, wenn es kaputt geht. Wenn ich verstehe, was dieses Verhalten verursacht, kann ich mit ein bisschen harter Arbeit Abhilfe schaffen. –

+1

Nach einigem Lesen denke ich, dass es einige Scheduling-Pässe gibt, die den Divide-Befehl vor dem Funktionsaufruf upward() bewegen. (nur eine Vermutung), korrigieren Sie mich, wenn ich falsch liege. –

Antwort

4

Grundsätzlich können Sie dies nicht tun. LLVM nimmt an, dass alle Gleitkommaoperationen den Standardrundungsmodus verwenden und dass das Gleitkomma-Steuerregister niemals gelesen oder geändert wird.

Es gab some discussion of this issue recently on the LLVM-dev mailing list, wenn Sie interessiert sind.

In der Zwischenzeit ist die einzige zuverlässige Problemumgehung, Inline-Assembly wie asm!("addsd $0, $1" zu verwenden.

Die Rust-Standardbibliothek setzt außerdem voraus, dass Sie den Rundungsmodus nicht ändern (insbesondere der Code zum Konvertieren zwischen Fließkomma und Zeichenfolgen ist dafür empfindlich).

+0

Wenn ich Sie richtig verstehe, wird bei Verwendung der Inline-Assembly der im mxcsr- oder im fctrl-Register eingestellte Rundungsmodus durch die Berechnung in der asm! Makro? –

+1

Ja. An diesem Punkt schreiben Sie im Grunde nur rohe Assembly, also spielt die Semantik von Rust oder LLVM IR keine Rolle. –

+0

Yes ofc, LLVM Optimierung sind auf der IR gemacht, danke. –