Optimiert der Compiler so etwas weg?



  • int x;
    int y;
    cin >> x;
    cin >> y;
    
    if(x != 0){
      y = x+y;
    }
    

    Mit geht es um die If Anweisung, prinzipiell ist die hier nämlich unnötig.
    Denn wenn x 0 ist, dann ändert sich y nicht, wenn man x zu y addieren würde.



  • Wäre doof, wenn nicht.



  • Mit "y += x" baut der Compiler Dir garantiert optimalen Code und es ist lesbarer. Was soll denn so eine "Optimierung" bezwecken? Im Zweifelsfall einfach ausprobieren, ob er das wegoptimiert.



  • Beachte, dass die Umformung schon bei Fließkommazahlen nicht mehr äquivalent ist (siehe NaN). Da der Code terminiert, darf bei Fließkommazahlen also nicht optimiert werden.



  • Sagen wir mal so, es würde mich brennend interessieren, wenn das ein Compiler optimieren würde. Noch wichtiger: Wie er das macht. Soll er die Bedingung negieren, den Code damit instanziieren und schauen, ob er den gleichen Effekt hat? Das scheint mir alles hochgradig nichttrivial zu sein und bis auf Spezialfälle keinen Nutzen zu haben.



  • Michael E. schrieb:

    Beachte, dass die Umformung schon bei Fließkommazahlen nicht mehr äquivalent ist (siehe NaN). Da der Code terminiert, darf bei Fließkommazahlen also nicht optimiert werden.

    Kannst du das näher erläutern?

    Es sollte doch keinen Unterschied machen, wenn zu einem
    double Wert eine 0.0 hinzuaddiert wird.

    @ Walli
    Eine unnötige IF Abfrage ist sicher langsamer als eine einfache Wertzuweisung.

    Das hier, liefert nämlich genau das gleiche Ergebnis:

    int x;
    int y;
    cin >> x;
    cin >> y;
    
    y = x+y;
    

    Oder eben mit y += x;

    int x;
    int y;
    cin >> x;
    cin >> y;
    
    y += x;
    

    Wie der obige code im ersten Posting.



  • Optimizer Frage schrieb:

    Kannst du das näher erläutern?

    double x = 0.0;
    double y = signaling_NaN;
    
    // 1. Variante
    if(x != 0.0)
        y += x;    // wird nicht ausgeführt => kein Laufzeitfehler
    
    // 2. Variante
    y += x;    // wird ausgeführt => Laufzeitfehler
    

    Edit: Ich weiß nicht, ob aus einer direkten Usereingabe Signaling NaN folgen kann. Aber im Allgemeinen sind die beiden Varianten wie eben gesagt nicht äquivalent.



  • Michael E. schrieb:

    Optimizer Frage schrieb:

    Kannst du das näher erläutern?

    double x = 0.0;
    double y = signaling_NaN;
    
    // 1. Variante
    if(x != 0.0)
        y += x;    // wird nicht ausgeführt => kein Laufzeitfehler
    
    // 2. Variante
    y += x;    // wird ausgeführt => Laufzeitfehler
    

    Edit: Ich weiß nicht, ob aus einer direkten Usereingabe Signaling NaN folgen kann. Aber im Allgemeinen sind die beiden Varianten wie eben gesagt nicht äquivalent.

    Wenn y = signaling_NaN ist, dann kommt es aber trotzdem zu einem Laufzeitfehler wenn x nicht 0 ist.
    Isofern wäre dann auch die 2. Variante ein Laufzeitfehler, da es egal wäre, was x ist. (also 0.0 oder eine andere Zahl)

    Wenn man also davon ausgeht, daß y = signaling_Nan sein könnte, dann sollte man vielleicht besser y in einer If Abfrage prüfen, bevor man irgendwas weiterrechnet.
    Sprich, das mit dem signaling_Nan geht an der Problemstellung eigentlich vorbei.



  • Optimizer Frage schrieb:

    Wenn y = signaling_NaN ist, dann kommt es aber trotzdem zu einem Laufzeitfehler wenn x nicht 0 ist.

    Ja, aber für Äquivalenz reicht es nicht, wenn es in Spezialfällen hinhaut. Ansonsten könnte ich x^2 = 25 zu x = 5 umformen, weil es manchmal stimmt :p

    Isofern wäre dann auch die 2. Variante ein Laufzeitfehler, da es egal wäre, was x ist. (also 0.0 oder eine andere Zahl)

    Den Satz verstehe ich nicht. [Edit: Habs jetzt nochmal gelesen und den Satz verstanden. Zum Inhalt siehe oben.]

    Wenn man also davon ausgeht, daß y = signaling_Nan sein könnte, dann sollte man vielleicht besser y in einer If Abfrage prüfen, bevor man irgendwas weiterrechnet.
    Sprich, das mit dem signaling_Nan geht an der Problemstellung eigentlich vorbei.

    Wenn man auf Signaling NaN prüfen wollte, würde man das sicherlich anders implementieren. Hier geht es aber darum, ob ein Compiler eine Optimierung vornehmen darf. Dies darf er nicht, weil er nicht äquivalenten Code erzeugen würde.



  • Habs mal ausprobiert mit vc10 release mode.

    if(x != 0)
    { 
       y = x+y; 
    }
    

    Wird restlos gestrichen, weils nicht verwendet wird.
    Wenn ich danach noch eine Ausgabe einfüge, dann siehts so aus:

    Vollständiger Code:

    #include <iostream>
    using namespace std;
    
    int main(int argc, char* argv[])
    {
    	int x; 
    	int y; 
    	cin >> x; 
    	cin >> y; 
    
    	if(x != 0){ 
    		y = x+y; 
    	}
    
    	cout << y << endl;
    }
    
    if(x != 0){ 
    00FC1026  mov         eax,dword ptr [x]  
    00FC1029  test        eax,eax  
    00FC102B  je          main+30h (0FC1030h)  
    		y = x+y; 
    00FC102D  add         dword ptr [y],eax  
    	}
    

    Das if wird also nicht rausoptimiert!



  • Der gcc (4.6.1 mit -O3) optimiert das übrigens auch mit ints nicht.



  • gcc tut's nicht, clang tut's nicht, MSVC tut's nicht, Borland tut's nicht.
    Ist evtl. auch Absicht, da solcher Code meist erst bei Mikrooptimierungsversuchen entsteht.



  • Vielleicht ist gar kein Code-Optimierer gefragt, sondern ein Fragen-Optimierer hier im Forum? 😕 Einen solchen habe ich in plattdeutscher Version im Kopf und der sagt: "Diene Sorgen un Otje sien Geld!" 😃


Anmelden zum Antworten