Stack und Parameterliste
-
Hi,
mich würde interessieren ob man sich den Stack und die Parameterliste
(also das gepushte) anschauen kann.In erster Linie würde mich interessieren, ob nicht verwendete
variablen auf dem Stack wegoptimiert werden können, auch wenn sie
eine Überladene Funktion selektiert haben...Also Konkret funktioniert die Funktionsauflösung überladener Funktionen anhand der Parameterliste zur Compilezeit.???
Nachdem die funktion selektiert worden ist, kann sie dann einen nicht verwendeten Parameter wegoptimieren.
z.B.:
func(int a) { std::cout <<"\n ich bin eine tolle funtion die a ausgiebt\t" << a; } func(int a, double b) { std::cout <<"\n ich bin auch eine tolle funktion die a ausgiebt und b nicht benutzt\t" << a; }Könnte da b wegoptimiert werden obwohl je nach dem ob func(10) oder func(10,0.2) aufgerufen worden ist die richtige funktion selektiert wurde ??
-
AlexanderKiebler schrieb:
func(int a) { std::cout <<"\n ich bin eine tolle funtion die a ausgiebt\t" << a; } func(int a, double b) { std::cout <<"\n ich bin auch eine tolle funktion die a ausgiebt und b nicht benutzt\t" << a; }Könnte da b wegoptimiert werden ??
Alles ist möglich, mein Sohn. In deinem Fall gibt das Warnungen, und die solltest du einfach gleich befolgen ohne über sie zu spekulieren.
- Pastor Hacker
Im Klartext: Ja. Aber ich hoffe diese Frage war aus reinem Wissensdurst gestellt?
-
AlexanderKiebler schrieb:
Also Konkret funktioniert die Funktionsauflösung überladener Funktionen anhand der Parameterliste zur Compilezeit.???
Ja.
Nachdem die funktion selektiert worden ist, kann sie dann einen nicht verwendeten Parameter wegoptimieren.
Innerhalb der Funktion ja, für den Call selber aber nicht. Denn der Aufrufer kennt nur die Signatur und muss daher seine Parameter brav übergeben. Das ändert sich natürlich, wenn die Funktionsdefinition vorliegt, dann kann der Compiler anfangen, wild zu optimieren. Das läuft bei Compileroptimierungen oft unter Namen wie "Interprozedurale Optimierung". Daher ist es bei mittelalten Compilern oftmals so günstig, kleine Funktionen inline im Header zu definieren, weil das dann sehr viel Optimierung bringen kann. Das muss man aber oftmals explizit aktivieren oder es kommt erst mit den höchsten Optimierungsstufen, weil ein Funktionsaufruf an sich doch eine recht starke Optimierungshürde ist. Neuerdings kommt auch immer mehr in Mode, die Optimierungen zur Linkzeit durchzuführen. Das hat die gleichen Vorteile, aber der Programmierer braucht die Grenzen seiner Module nicht so sehr aufzuweichen.
-
Hmm okay....
*Also zu den Extern gelinkten Symbolen gibt es eine Signatur (Wenn das Symbol eine Funktion ist)
*Anhand der Signatur wird die Implementierung gewählt (Bei überladung)
*Nachdem der Compiler die Implementierung übersetzt hat, kann er feststellen,
dass die Signatur nicht vollständig benötigt wird. Die information wird gespeichert
*Der Linker kann dann den Aufrufer optimieren, so dass er auch den aufruf mit weniger werten machen kann und trotzdem die richtige Implementierung erwischt.Hab ich das so richtig verstanden ??
Hmm inline... okay... inline würde das lösen da dort die Implementierung direkt ersetzt wird und es keinen funktionsaufruf gibt.Würds mir trotzdem gerne irgendwie anschauen. Haben GCC und Visual studio linker files wo angeben wo der stack so ist ??
Das Problem dass ich mir den stack anschauen muss wird mich so oder so noch viele male einholen.
-
AlexanderKiebler schrieb:
Hmm okay....
*Also zu den Extern gelinkten Symbolen gibt es eine Signatur (Wenn das Symbol eine Funktion ist)
Ja.
*Anhand der Signatur wird die Implementierung gewählt (Bei überladung)
Ja.
*Nachdem der Compiler die Implementierung übersetzt hat, kann er feststellen,
dass die Signatur nicht vollständig benötigt wird. Die information wird gespeichertNein, wird sie nicht.
*Der Linker kann dann den Aufrufer optimieren, so dass er auch den aufruf mit weniger werten machen kann und trotzdem die richtige Implementierung erwischt.
Nein, der Linker linkt nur, der ändert nichts mehr am Code. Außer du machst wilde Sachen wie Optimierung zur Linkzeit, aber dann passt der klassische Ablaufplan von Compilierung, Assemblierung und Linken nicht mehr.
Hmm inline... okay... inline würde das lösen da dort die Implementierung direkt ersetzt wird und es keinen funktionsaufruf gibt.
Das ist möglich, aber das nicht das was der Hauptanwendungszweck von inline ist. Inline beeinflusst in erster Linie die Linkage, wodurch es überhaupt möglich ist, Funktionen in Headerdateien zu definieren.
Würds mir trotzdem gerne irgendwie anschauen. Haben GCC und Visual studio linker files wo angeben wo der stack so ist ??
Häh was? Der Stack entsteht erst zur Laufzeit. Den kannst du dir gerne im Debugger angucken. Du kannst dir die Funktionsaufrufe auch im fertigen Programm angucken, da kannst du sehen, welche Parameter erst gepusht werden, bevor eine Funktion aufgerufen wird.
Ich habe das Gefühl, du benutzt das Wort Stack nicht richtig.
-
Nein, der Linker linkt nur, der ändert nichts mehr am Code. Außer du machst wilde Sachen wie Optimierung zur Linkzeit, aber dann passt der klassische Ablaufplan von Compilierung, Assemblierung und Linken nicht mehr.
Ja als ich das geschrieben habe ist mir das auch aufgefallen. In dem Fall würde der Linker ein bischen compilieren .... damit wäre die Trennung nicht mehr sauber das stimmt.
Ja du hast Recht, auf den stack müssen ja die Register, welche vom Unterprogramm benutzt werden könnten. Ich hatte irgendwo noch im Kopf, dass auch die Parameterliste auf den stack kommt..... Bin ich da auf dem Holzweg ??
Ich muss nachschauen verdammt...
-
Also was alles gemacht werden könnte, und was real von irgendeiner Implementierung gemacht wird, sind zwei paar Schuhe.
Unbenutzte Parameter mit Typen die trivial zu kopieren und zerstören sind könnten theoretisch wegoptimiert werden ("as if").
Mit Inlining können das auch sicher viele Implementierungen.Ohne Inlining kann es vermutlich aber keine Implementierungen.
-
AlexanderKiebler schrieb:
Nein, der Linker linkt nur, der ändert nichts mehr am Code. Außer du machst wilde Sachen wie Optimierung zur Linkzeit, aber dann passt der klassische Ablaufplan von Compilierung, Assemblierung und Linken nicht mehr.
Ja als ich das geschrieben habe ist mir das auch aufgefallen. In dem Fall würde der Linker ein bischen compilieren .... damit wäre die Trennung nicht mehr sauber das stimmt.
Macht ja nix, viele Compiler bieten mittlerweile die Option dass die gesamte Code-Generierung im Linker gemacht wird (MSVC nennt es LTCG, GCC nennt es LTO).
Wenn dadurch eine Funktion inline erweitert wird, kannst du auch davon ausgehen dass viele unnötige Dinge die nacht "as if" entfernt werden können auch entfernt werden.
Wenn auch mit LTCG/LTO ein echter Funktionsaufruf übrigbleibt gehe ich davon aus dass unbenützte Parameter nicht optimiert werden.Ja du hast Recht, auf den stack müssen ja die Register, welche vom Unterprogramm benutzt werden könnten. Ich hatte irgendwo noch im Kopf, dass auch die Parameterliste auf den stack kommt..... Bin ich da auf dem Holzweg ??
Ich muss nachschauen verdammt...Das Sichern von Registern, Parameterübergabe etc. ist alles implementierungsabhängig.
Üblich ist dass Register auf den Stack gesichert werden, dann die ersten paar Parameter in Registern übergeben werden, und der Rest auf dem Stack landet.