Warum verwendet gcc movl anstelle von Push-to-Pass-Funktionsargumenten?
Lesezeit: 3 Minuten
Puuh
achte auf diesen Code:
#include <stdio.h>
void a(int a, int b, int c)
{
char buffer1[5];
char buffer2[10];
}
int main()
{
a(1,2,3);
}
danach :
gcc -S a.c
Dieser Befehl zeigt unseren Quellcode in Assembly.
Jetzt können wir in der Hauptfunktion sehen, dass wir niemals den Befehl “push” verwenden, um die Argumente der a-Funktion in den Stapel zu schieben. und es wurde stattdessen “movel” verwendet
-mpush-args
-mno-push-args
Use PUSH operations to store outgoing parameters. This method is shorter and usually
equally fast as method using SUB/MOV operations and is enabled by default.
In some cases disabling it may improve performance because of improved scheduling
and reduced dependencies.
-maccumulate-outgoing-args
If enabled, the maximum amount of space required for outgoing arguments will be
computed in the function prologue. This is faster on most modern CPUs because of
reduced dependencies, improved scheduling and reduced stack usage when preferred
stack boundary is not equal to 2. The drawback is a notable increase in code size.
This switch implies -mno-push-args.
Offenbar -maccumulate-outgoing-args ist standardmäßig aktiviert und überschreibt -mpush-args. Explizit kompilieren mit -mno-accumulate-outgoing-args kehrt zu zurück PUSH Methode, hier.
2019-Aktualisierung: Moderne CPUs haben seit ungefähr Pentium M einen effizienten Push / Pop. -mno-accumulate-outgoing-args (und die Verwendung von Push) wurde schließlich zum Standard für -mtune=generic im Januar 2014.
Eine viel bessere Frage wäre, warum diese aufblähende Option -maccumulate-outgoing-args wird nicht automatisch durch deaktiviert -Os.
– R.. GitHub HÖR AUF, EIS ZU HELFEN
28. Dezember 2010 um 4:32 Uhr
@R.. Also weißt du warum?
– Toni
25. März 2015 um 12:49 Uhr
@ Tony: Offensichtlich, denn bei der Entscheidung, welche der vielen (~ 200) Optimierungs-Flags für jede spezifische -O-Option aktiviert / deaktiviert werden sollen, rutschen manchmal Dinge durch die Ritzen.
– ninjalj
27. Juli 2015 um 21:06 Uhr
Aktualisieren: -maccumulate-outgoing-args war standardmäßig deaktiviert -mtune=generic im Januar 2014, jetzt, wo CPUs ohne Stack-Engines sehr selten sind. (Wahrscheinlich hätte man das früher machen sollen).
– Peter Cordes
30. August 2016 um 23:44 Uhr
Ben Zotto
Dieser Code setzt die Konstanten (1, 2, 3) einfach direkt an Offset-Positionen vom (aktualisierten) Stapelzeiger (esp). Der Compiler entscheidet sich dafür, den “Push” manuell mit dem gleichen Ergebnis durchzuführen.
“push” setzt die Daten und aktualisiert den Stapelzeiger. In diesem Fall reduziert der Compiler dies auf nur eine Aktualisierung des Stapelzeigers (gegenüber drei). Ein interessantes Experiment wäre es, zu versuchen, die Funktion “a” zu ändern, um nur ein Argument zu nehmen, und zu sehen, ob sich das Befehlsmuster ändert.
Warum müssen Sie die Konstante zuerst in ein Register schreiben? x86 unterstützt das Pushen von unmittelbaren Konstanten
– Nekrolis
26. Dezember 2010 um 19:50 Uhr
gcc führt alle Arten von Optimierungen durch, einschließlich der Auswahl von Anweisungen basierend auf der Ausführungsgeschwindigkeit der jeweiligen CPU, für die optimiert wird. Sie werden feststellen, dass Dinge wie x *= n wird oft durch eine Mischung aus SHL, ADD und/oder SUB ersetzt, besonders wenn n eine Konstante ist; während MUL nur verwendet wird, wenn die durchschnittliche Laufzeit (und Cache-/etc.-Footprints) der Kombination von SHL-ADD-SUB die von MUL überschreiten würde, oder n ist keine Konstante (und daher wäre die Verwendung von Schleifen mit shl-add-sub teurer).
Im Falle von Funktionsargumenten: MOV kann durch Hardware parallelisiert werden, während PUSH dies nicht kann. (Der zweite PUSH muss wegen der Aktualisierung des esp-Registers auf das Ende des ersten PUSH warten.) Im Fall von Funktionsargumenten können MOVs parallel ausgeführt werden.
Ist das zufällig unter OS X? Ich habe irgendwo gelesen, dass der Stapelzeiger an 16-Byte-Grenzen ausgerichtet sein muss. Das könnte möglicherweise diese Art der Codegenerierung erklären.