Optimierung: Was macht der Compiler hier?
-
Das hat ja nun eine Diskussion ausgelöst
Das mit dem Haltepunkt setzen wäre eine Idee, werde dann über das Resultat berichten. Im Disassembly mit einem externen Disassembler fand ich (bei optimiertem Code ohnehin) kaum je meinen eigenen Code wieder, daher ist das eine Idee; bin ich noch nicht drauf gekommen.
EDIT: Hier das Resultat:
register DWORD dwPos=(DWORD)atoi(spos); 004F7689 lea eax,[spos] 004F768F push eax 004F7690 call @ILT+41830(_atoi) (4E036Bh) 004F7695 add esp,4 004F7698 mov dword ptr [dwPos],eax __asm{ mov eax, dwPos 004F769E mov eax,dword ptr [dwPos] mov ecx, 1000 004F76A4 mov ecx,3E8h mov ebx, 60 004F76A9 mov ebx,3Ch Xor edx, edx
und in der Release-Version:
__asm{ mov eax, dwPos 00431248 mov eax,dword ptr [esp+18h] mov ecx, 1000 0043124C mov ecx,3E8h mov ebx, 60 00431251 mov ebx,3Ch Xor edx, edx
Also die Register-Anweisung wird definitiv ignoriert.
Ja, ich verwende Visual Studio 2005, mit MFC, und das Programm ist lauffähig.
Zum CastDWORD dwPos=(DWORD)atoi(spos);
nehme ich mal an da ein int sowieso ein DWORD ist wird kein zusätzlicher Code erzeugt, ist dieser Cast nur um den Compiler zu befriedigen?
-
Wahrscheinlich. Das hast du bei C-artigen Sprachen sehr oft, dass casts praktisch gar nichts bewirken, ausser Warnings beim compilieren zu vermeiden.
-
Der Code sieht jedenfalls auch ganz danach aus. Ausser bei Cast von int zu String und umgekehrt etc. natürlich. Hoffentlich auch, gäbe ja einigen zusätzlichen Code, bei den vielen Casts welche manchmal nötig sind.
-
mov eax,dword ptr [esp+18h] mov ecx,3E8h mov ebx,3Ch
Also die Register-Anweisung wird definitiv ignoriert.
Die Sache ist die, dass Dein Assembler-Code 1:1 vom Compiler uebernommen wird und dabei kein Versuch unternommen wird, diesen sinnvoll in den bestehenden Code einzubetten.
Da Du fuer den Inline-Assembler eax (scheinbar) aus einer Variablen laedst, stellt der Compiler zuvor sicher, dass da auch der entsprechende Wert drin zu finden ist; das laesst sich mit der Register-Anweisung eben nicht vereinbaren.
Eine Alternative waere eventuell den Return-Wert von atoi in eax zu erwarten.
-
hellihjb schrieb:
Die Sache ist die, dass Dein Assembler-Code 1:1 vom Compiler uebernommen wird und dabei kein Versuch unternommen wird, diesen sinnvoll in den bestehenden Code einzubetten.
Wahrscheinlich eher im Gegenteil; der Assemblerblock dürfte den Optimierer gewaltig ausbremsen.
-
Wahrscheinlich eher im Gegenteil
Genau genommen ist es genau so wie ich schrieb; fuehrt in letzter Instanz aber auch zu Deiner Schlussfolgerung.
-
Ja, so meinte ich das auch, sorry. Das Gegenteil war auf den Versuch der sinnvollen Einbettung gemünzt.
-
gibt es auch schon compiler, die eigenen assemblercode auf wunsch auch optimieren? (wenn man nur z.b. rol/ror oder so verwenden will, aber dazu noch mov davor/dahinter einbaut, dass diese dann wegoptimiert werden)
-
Beim GCC kann man dem Inline-Assembler mitteilen, in welchen Registern Variablen und Returnwert angenommen werden sollen, genauso bei Open Watcom.
Der eigentliche Code wird aber auch da nicht angefasst, sonst koennte man es ja auch gleich als C/C++ formulieren.
-
Das hab ich fast angenommen, dass da der Assemblercode Vorrang hat gegenüber der Register-Anweisung.
Auf das Laden der Variable kommt es auch nicht wirklich an, aber wie würde das gehen den Rückgabewert von atoi direkt im eax zu haben?Die ganze Berechnung in asm hätte in C auch nicht viel ausgemacht, aber vielleicht ist's etwas schneller falls C++ den Coprozessor verwenden würde. Wäre auch noch interessant ob der Compiler den Code auf den Wertebereich und Fliesskommazahlen prüft und dann je nach dem die CPU oder FPU benützt.
-
vielleicht ist's etwas schneller falls C++ den Coprozessor verwenden würde
FPU fuer atoi ?
wie würde das gehen den Rückgabewert von atoi direkt im eax zu haben
Integer-Returnwerte werden immer in eax angenommen:
int res; atoi("-12345"); _asm { mov res,eax } printf("%d \n", res);
Aber nach dem Aufruf einer Funktion (teuer) und dem Parsen eines Strings (noch teurer) kannst Du mit so'm Integer eigentlich nicht mehr viel anstellen dass irgendwie performancerelevant waere...
Was hast Du denn ueberhaupt vor?
-
Nein nicht für atoi die FPU sondern die Berechnung (Umrechnung von Sekunden) die danach kommt, welche ich in Assembler geschrieben habe. Und ob dafür die FPU genommen würde, das wäre sicherlich langsamer mit allem drum und dran (die Methode wird 2 Mal in der Sekunde ausgeführt).
Es kommt eigentlich nicht so drauf an, 2 Mal in der Sekunde ist ja nicht soo viel aber ich dachte ich schreibe das mal in Assembler, so einfach wie möglich schadet sicher nicht
Ah ja klar wie Windows-Funktionen ebenfalls unter Assembler den Wert in EAX zurückgeben.
-
die "register" anweisung wird übrigens inzwischen von so gut wie allen vompilern komplett ignoriert - ob mit inline-asm oder ohne.
-
Ach so, hoffentlich wird bei einer Schleife im Stil von (int i=0; i==...usw...) wenigstens die Zählvariable gleich im Register angelegt
-
wenn der compiler dies für sinnvolll hält, schon. also wenns nich noch zig verschachtelte for's sind, dann wird er das machen bei eingeschalteter optimierung.
-
Ah super, immerhin
-
hellihjb schrieb:
Der eigentliche Code wird aber auch da nicht angefasst, sonst koennte man es ja auch gleich als C/C++ formulieren.
nein, c++ hat kein ror/rol/lsb/...
-
nein, c++ hat kein ror/rol/lsb/...
Man muss es nur etwas komplizierter formulieren:
unsigned int ror(unsigned int a, unsigned char bits) { return (a>>bits)|(a<<(32-bits)); } // testloop damit der compiler ueberhaupt code erzeugt und keine konstante hinschreibt: for (int i=0;i<10;i++) { unsigned int x= ror(0x12345678, i); printf("%d \n ", x); }
Disassembly:
00401010 movzx ecx,bl 00401013 mov eax,12345678h 00401018 ror eax,cl ; qed 0040101A push eax 0040101B push offset string "%d \n" (4020E4h) 0040101E call esi ; printf
-
Welche Kompiler können das?@ror
-
In diesem Fall war's der C++ Compiler von Visual-Studio 2005, andere werden aber aehnlichen Code produzieren.
Der Befehlssatz der Zielplattform ist dem Compiler ja bekannt und er sollte feststellen koennen, dass das Ergebnis aequivalent mit dem des ror Befehls ist.