Ursache scheint zu sein, dass der Linker während der Link Time Optimization kein Inlining von nicht-inline-Funktionen durchführt. Beispielsweise habe ich in endian.cpp ein Dutzend Funktionen littleEndian(), die nichts anderes tun, als ihren Parameter direkt wieder zurückzugeben – weil sie pure Abstraktionshelfer sind. Visual C++ optimiert diese Aufrufe komplett weg. Clang nicht:
mov eax, ecx
call littleEndian
…
littleEndian(x):
push rax
mov dword ptr [rsp+4],ecx
mov eax,dword ptr [rsp+4]
pop rcx
ret
What the fuck! Das sieht wie Debug-Code aus!
Die naheliegende Frage ist natürlich: Wie kompiliere ich?
Die C++-Quellen kompiliere ich mit
clang++ -c -std=c++2a -fno-ms-compatibility -fno-ms-extensions -Wall -Wextra -Wpedantic -Wno-#pragma-messages -fno-exceptions -finline-functions -finline-hint-functions -MT -Os -flto -fmerge-all-constants -fvisibility=hidden -ffunction-sections -fdata-sections -gfull -gcodeview "foo.cpp" -o "foo.o"
Dann linke ich sie mit
lld-link /debug /pdb:"foo.pdb" /subsystem:WINDOWS /out:"foo.exe" "foo.o" /opt:REF /opt:ICF
Ich beobachte folgendes:
- Ersetze ich -Os durch -O0, wird der Code rapide größer. Durch -O2 oder -O3 ändert sich fast nix. Optimierung scheint also stattzufinden.
- Ich setze extra -fvisibility=hidden damit Clang nicht mit irgendwelchem Linux-Shared-Object-Verhalten anfängt und nicht-statische, nicht-inline Funktionen nur noch durch explizite Aufrufe ansteuert. Das Flag ändert aber nichts am Kompilat.
- Es gibt keine klare Dokumentation, wie LTO aktiviert wird.
Entferne ich den -flto-Schalter, wird das Kompilat eklatant größer, trotz -O2 oder -Os. Es scheint also durchaus globale Optimierung stattzufinden.https://lld.llvm.org/ hat geschrieben:Link-time optimization (LTO) is supported by default. Essentially, all you have to do to do LTO is to pass the -flto option to clang. Then clang creates object files not in the native object file format but in LLVM bitcode format. LLD reads bitcode object files, compiles them using LLVM and emit an output file. Because in this way LLD can see the entire program, it can do the whole program optimization.