Warum einige Compiler if (a0) und nicht if (* (& a) 0) optimieren?

8

Nehmen wir an, ich habe im globalen Geltungsbereich deklariert:

%Vor%

Und in der Hauptfunktion habe ich folgende Bedingung:

%Vor%

Eine peinliche Sache, die ich bemerkt habe, ist, dass der RVDS -Compiler die if -Anweisung fallen lässt und es keine Verzweigung / jmp in der Objektdatei gibt.

aber Wenn ich schreibe:

%Vor%

Das if ( cmp und branch ) befindet sich in der kompilierten Objektdatei.

Im Gegensatz dazu optimiert GCC beide mit ( -O1 oder -O2 oder -O3 ):

%Vor%

mit -O3 kompiliert:

%Vor%

Und für

%Vor%

gibt Folgendes:

%Vor%

GCC behandelt beide als gleich (wie es sein sollte) und RVDS nicht?

Ich habe versucht, den Effekt der Verwendung von volatile zu untersuchen, und im RVDS hat er die if(a>333) fallengelassen, gcc aber nicht:

%Vor%

Wahrscheinlich gibt es einige Fehler in der Compiler-Version von RVDS.

    
0x90 20.06.2013, 17:10
quelle

2 Antworten

4

Optimierungen sind Implementierungsdetails der Compiler. Es erfordert Zeit und Mühe, sie zu implementieren, und Compiler-Autoren konzentrieren sich gewöhnlich auf die allgemeinen Sprachverwendungen (d. H. Die Rendite der Investition von optimiertem Code, der sehr selten ist, ist nahezu nichts).

Davon abgesehen gibt es einen wichtigen Unterschied in beiden Code-Stücken. Im ersten Fall wird a nicht odr-verwendet, sondern nur als rvalue verwendet, was bedeutet, dass es als Kompilierzeitkonstante verarbeitet werden kann. Das heißt, wenn a direkt verwendet wird (keine Adresse, keine an sie gebundenen Referenzen), ersetzen Compiler sofort den Wert in. Der Wert muss dem Compiler bekannt sein, ohne auf die Variable zuzugreifen, da er in Kontexten verwendet werden könnte konstante Ausdrücke sind erforderlich (dh die Größe eines Arrays wird definiert).

Wenn im zweiten Fall a odr-used ist, wird die Adresse genommen und der Wert an dieser Stelle gelesen. Der Compiler muss Code erstellen, der diese Schritte ausführt, bevor das Ergebnis an das Optimierungsprogramm übergeben wird. Der Optimierer kann wiederum erkennen, dass es sich um eine Konstante handelt, und die gesamte Operation durch den Wert ersetzen. Dies ist jedoch etwas komplizierter als im vorherigen Fall, in dem der Compiler den Wert selbst eingegeben hat.

    
David Rodríguez - dribeas 20.06.2013, 19:14
quelle
11

Der Komplexitätsgrad, den der Compiler durchlaufen wird, um herauszufinden, "das ist etwas, was ich herausfinden kann, was der tatsächliche Wert ist", ist nicht unbegrenzt. Wenn Sie eine ausreichend komplexe Aussage schreiben, sagt der Compiler einfach "Ich weiß nicht, was der Wert ist, ich werde Code generieren, um ihn zu berechnen".

Dies ist für einen Compiler durchaus möglich, um herauszufinden, dass es sich nicht ändern wird. Aber es ist auch möglich, dass einige Compiler "aufgeben" - es kann auch davon abhängen, wo in der Kompilierungskette diese Analyse durchgeführt wird.

Dies ist wahrscheinlich ein ziemlich typisches Beispiel für eine "als-ob" -Regel - der Compiler darf jede Optimierung durchführen, die das Ergebnis "als-ob" erzeugt, wenn dies ausgeführt wurde.

Nachdem das alles gesagt wurde, sollte dies ziemlich trivial sein (und laut den Kommentaren sollte der Compiler *(&a) genauso wie a ), so dass es merkwürdig erscheint, dass es dann den Vergleich nicht los wird.

    
Mats Petersson 20.06.2013 17:18
quelle