Hallo zusammen, ich versuche, die Code Size meines Binaries möglichst klein zu halten und würde deshalb gerne auch virtuelle Funktionen (C++), die nicht benutzt werden, aus dem Binary schmeißen. Für normale Funktionen gibt es ja Dead Code Elimination des Linkers, aber die greift aufgrund der VTables bei virtuellen Funktionen nicht. Stattdessen gibt es anscheinend VFE (https://developer.arm.com/documentation/dui0474/m/linker-command-line-options/--vfemode-mode), was laut Link wohl auch standardmäßig schon aktiviert ist. Jedoch finden alle virtuellen Funktionen obwohl ganz klar nicht genutzt, ihren Weg ins fertig Binary und verdoppeln dort die Codesize. Compiler: ARM GCC 9.3.1, STM32CubeIDE V1.8.0 kompiliert wird mit: -Os -ffunction-sections -fdata-sections -Wl,--gc-sections -nostartfiles -nodefaultlibs -nostdlib Ich habe auch bereits folgende Optionen ohne Erfolg probiert: -fwhole-program -flto -fdevirtualize-at-ltrans Hat jemand eine Idee, was ich tun muss, um die virtuellen Funktionen rauszubekommen (außer, keine zu benutzen...) Grüße
Hast du mal -O3 mit -flto probiert? Wenn damit Compiler und Linker das auch nicht machen, dann gehts vermutlich nicht besser. Oliver
Leopold N. schrieb: > Hat jemand eine Idee, was ich tun muss, um die virtuellen Funktionen > rauszubekommen (außer, keine zu benutzen...) Keine zu benutzen, ist natürlich Quatsch. Die bestmögliche Lösung ist, nur die Funktionen virtuell zu machen, die man auch zu nutzen gedenkt und zwar tatsächlich als virtuelle Funktionen. Denn logischerweise bringt es nix, eine virtuelle Funktion zu deklarieren, die entweder garnicht genutzt wird oder auch nur nirgendwo überschrieben wird.
Zeig mal Beispielcode, prinzipiell kann GCC Optimizer Devirtualization (das brauchst du hier efefktiv), aber manchmal weigert er sich. Vielleicht ist Amalgation notwendig, obwohl -fwhole-program das gleiche bringen sollte.
Hier als Beispiel mal der LTDC. Der LTDC wird nur in der Klasse STM32H753BIT6 verwendet, und zwar ist er ein Member. Es werden nur die Funktionen LTDC::startup und LTDC::LTDC aufgerufen, die restlichen Funktionen landen aber trotzdem aufgrund der VTables im Binary.
Oliver S. schrieb: > Hast du mal -O3 mit -flto probiert? Wenn damit Compiler und Linker das > auch nicht machen, dann gehts vermutlich nicht besser. > > Oliver Probiert, aber ohne Erfolg
Leopold N. schrieb: > Oliver S. schrieb: >> Hast du mal -O3 mit -flto probiert? Wenn damit Compiler und Linker das >> auch nicht machen, dann gehts vermutlich nicht besser. >> >> Oliver > > Probiert, aber ohne Erfolg Dann wirst du wohl damit leben müssen, wie es ist, oder du wirfst die nicht benötigten Funktionen halt aus dem Sourcecode raus. Oliver
Hier mal ein STM32CubeIDE Project, mit dem ich das ganze mal ausprobiert hab. Wenn ich bei DerivedClass die Vererbung wegnehme (: public BaseClass auskommentieren und override löschen) verschwindet die Funktion DerivedClass::foo aus dem Binary, da sie ja auch nicht aufgerufen wird. Die Funktion DerivedClass::bar bleibt natürlich. Sobald DerivedClass aber von BaseClass erbt, wird DerivedClass::foo immer mit in die Binaries geschleppt, obwohl main() sie nicht aufruft. Jemand eine Idee?
Leopold N. schrieb: > Jemand eine Idee? Haste mal gegoogelt? Wenn dir das keine neuen Ansätze liefert (was es nicht tun wird, obwohl die Frage durchaus häufig gestellt wird), gehts halt nicht. Einzige Lösung, die sich dort abzeichnet: Geh zurück auf gcc 3.x. Da gabs eine Compileroption für das Problem. Der Erfolg ist nicht garantiert, da gcc die ab Version 4 wegen "Nicht-Wartbarkeit" (Euphemismus für "funzt nicht wirklich") aufgegeben hat. Oliver
Habe gerade gefühlt zwei Tage mit googlen verbracht... auf GCC 3.x zurückzugehen ist keine Option. Ich kann bloß nicht glauben, dass es 2021 (fast 22) keine Möglichkeit geben soll, Dead Code zu eliminieren, nur weil ein paar VTables sich darauf referenzieren, welche selbst aber nicht gebraucht werden. Und ich versteh nicht, warum VFE als Compileroption zwar im Handbuch steht, aber nix tut, bzw. vom Compiler sogar explizit nicht erkannt wird.
Leopold N. schrieb: > Hier als Beispiel mal der LTDC. Wir brauchen ein MWE, damit können wir nichts anfangen, weil zu komplex und kompiliert nicht. Leopold N. schrieb: > Hier mal ein STM32CubeIDE Project, mit dem ich das ganze mal ausprobiert > hab. > [...] > Jemand eine Idee? Ja, -flto (GCC9) optimiert das sauber wie erhofft: Es verbleibt nur DerivedClass::foo(). Konstruktor, Destruktor und vtable werden komplett eliminiert.
Ups, ich hatte die Namen vertauscht. Die vtable wird eliminiert, aber DerivedClass::foo() ist weiterhin vorhanden, obwohl ungenutzt.
Ja, -flto hatte ich auch schon probiert...habe allerdings Sorgen bei dieser Option, da sie wohl Bugs haben soll (oder mal gehabt hatte in früheren Versionen von GCC).
Leopold N. schrieb: > Ja, -flto hatte ich auch schon probiert...habe allerdings Sorgen > bei > dieser Option, da sie wohl Bugs haben soll (oder mal gehabt hatte in > früheren Versionen von GCC). Der Schwippschwager des Onkel meines Bruders Hundesitter kennt jemanden, der hat mal gehört, daß… Debuggen wird damit natürlich nicht einfacher, aber sonstige Sorgen braucht man da schon lange nicht mehr zu haben. Oliver
Leopold N. schrieb: > Ja, -flto hatte ich auch schon probiert...habe allerdings Sorgen bei > dieser Option, da sie wohl Bugs haben soll (oder mal gehabt hatte in > früheren Versionen von GCC). Wenn ich den Inhalt von derivedClass.cpp in main.cpp kopiere, klappt es. Dann gibt es derivedClass gar nicht mehr im Binary. Vollte Optimierung bekommt man leider erst mit Amalgation. Soll der TE das mal probieren. LTO bringt grundsätzlich nicht mehr Bugs als GCC sowieso hat, bis auf die bekannte Geschichte mit weak linking von interrupts.
Devirtualization schrieb: > Amalgation Devirtualization schrieb: > Amalgation Was du für Wörter kennst… Ähnlichkeiten mit Amalgamation sind vermutlich beabsichtigt. Oliver
Devirtualization schrieb: > Wenn ich den Inhalt von derivedClass.cpp in main.cpp kopiere, klappt es. > Dann gibt es derivedClass gar nicht mehr im Binary. > Vollte Optimierung bekommt man leider erst mit Amalgation. Soll der TE > das mal probieren. Das Problem ist leider, dass ich die virtuellen Klassen und deren Ableitungen in verschiedenen Bibliotheken habe und main() davon erst mal nichts sieht... Drum geht das mit dem amalgamamatieren leider nicht :)
Ich hasb mal probiert: In meinem Testprogramm fliegt die unbenutze virtuelle Funktion func1 auch mit Almagamation nicht raus. Es hätte mich auch gewundert, wenns da zwischen lto und und "alles in einer Datei" wesentliche Unterschiede gegeben hätte. https://godbolt.org/z/v6WvbaooY Oliver
Also Fazit: Keiner hier hat ne Ahnung wie man diesen Overhead wegbekommt... Schade, hatte gehofft, dass ich zu blöd zum googlen bin :/ Falls noch jemand ne Idee hat, immer gern, ansonsten könnte man den Thread schließen.
Leopold N. schrieb: > Schade, hatte gehofft, dass ich zu blöd zum googlen bin :/ Biste halt. Sonst hättest du den passenden Kommentar zu der Frage auf gcc.org gefunden. Ich zitier mal für dich: >> So what can I do? > Nothing (well, improve GCC!). In diesem Sinne… Oliver
:
Bearbeitet durch User
Oliver S. schrieb: > Biste halt. > > Sonst hättest du den passenden Kommentar zu der Frage auf gcc.org > gefunden. :) Den Thread hatte ich auch schon durch, mehrmals sogar in der Hoffnung was übersehen zu haben xD Schönen Abend noch ;)
> Das Problem ist leider, dass ich die virtuellen Klassen > und deren Ableitungen in verschiedenen Bibliotheken habe Falls das der Wahrheit entspricht und es sich um Objektcode-Bibliotheken handelt, wirst du doch nicht ernsthaft erwarten daß der Compiler da was optimieren kann. Der bekommt den Maschinencode ja nichtmal in die Finger.
Du kannst in Godbolt nicht erkennen, ob der Compiler/Linker Funktionen raushaut, oder nicht. Überlege doch mal: Das Standard-Template ist int square(int num) { return num*num;} was von exakt niemanden aufgerufen wird! Und trotzdem ist es im Disassembly - egal bei welcher Optimierung usw. Merkste selbst? ;-) Der Thread stürzt sich hier auf das falsche tool: der Compiler ist überhaupt nicht dafür zuständig, Sachen aus dem Programm zu schmeißen! Das macht der Linker.
HörNichtAufMich schrieb: > Der Thread stürzt sich hier auf das falsche tool: der Compiler ist > überhaupt nicht dafür zuständig, Sachen aus dem Programm zu schmeißen! > Das macht der Linker. Dann muss der arm-clang den Linker integriert haben?
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.