Seite 1 von 1

Clang lld-link führt keine LTO/Inlining durch

Verfasst: 14.03.2020, 14:14
von Krishty
Windows. Clang 9.0.0 kompiliert mein Programm, linkt es, optimiert … und das Ergebnis ist eine einzige Katastrophe – von der Leistung her weit hinter Visual C++.

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.
    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.
    Entferne ich den -flto-Schalter, wird das Kompilat eklatant größer, trotz -O2 oder -Os. Es scheint also durchaus globale Optimierung stattzufinden.
Was läuft schief?

Re: Clang lld-link führt keine LTO/Inlining durch

Verfasst: 14.03.2020, 18:02
von Krishty
Die LLVM-Webseite bietet für LLVM 9.0.1 keinen Windoze-Download an. Wenn man sich den Quelltext anschaut, existiert durchaus ein Link, ist aber auskommentiert. Ohne Erklärung.

Ich habe das mal heruntergeladen und installiert; keine Änderung.

Der Link führt ins github-Repo, und dort findet man dann auch viel frischere Binaries – etwa den 10.0.0 rc3.

Der bringt volle C++’20-Unterstützung und ist etwas strikter mit static bzw. inline auf constexpr auf namespace-Level, also musste ich ein Bisschen was anpassen.

clang++ beschwert sich auch, dass -MT und -Os nicht mehr unterstützt werden(?!?). Also habe ich die entfernt.

Das Ergebnis ist jedoch – zumindest an den Stellen, die ich verglichen habe – gleich.

Ich habe eben sichergestellt, dass Clang auch tatsächlich Bitcode-Dateien ausspuckt, denn das setzt LTO voraus. Die Dateien beginnen alle mit den Bytes BC.

Irgendwas mache ich total falsch. Nun schaue ich erstmal, wo die Optimierungsoptionen hingewandert sind.

Re: Clang lld-link führt keine LTO/Inlining durch

Verfasst: 14.03.2020, 21:14
von Schrompf
Ich bin überhaupt damit gescheitert, ein hinreichend komplexes Projekt mit -flto zu kompilieren. Du bist bereits deutlich weiter gekommen als ich. Sorry, kann Dir da nicht helfen. Außer vielleicht Dir ein wenig Zeitverschwendung zu ersparen: deren User-MailingList bounced bei dem Versuch, sich dafür zu registrieren. Verdammte Profis.

Re: Clang lld-link führt keine LTO/Inlining durch

Verfasst: 14.03.2020, 21:40
von Krishty
Schrompf hat geschrieben: 14.03.2020, 21:14Außer vielleicht Dir ein wenig Zeitverschwendung zu ersparen: deren User-MailingList bounced bei dem Versuch, sich dafür zu registrieren. Verdammte Profis.
Jetzt wo du es sagst: Da wollte ich mich vor zehn Jahren oder so mal registrieren, und da war die Registrierung überhaupt nicht möglich (Spam oder so).

Als jemand, der es in den letzten 15 Jahren nicht geschafft hat, mal substantiell was an ZFX zu verbessern, stimme ich dir zu: Verdammte Profis.

Re: Clang lld-link führt keine LTO/Inlining durch

Verfasst: 15.03.2020, 01:48
von Krishty
Irgendwas hat sich geändert – und das, obwohl meine Befehle exakt die selben sind wie zuvor. WTF.

Ich hatte ein wenig mit /opt:lldlto=3 und /opt:lldltojobs=8 experimentiert.

Nun wird definitiv geinlined und über Funktionsgrenzen optimiert. Ich habe aber dennoch viele Dutzend Funktionen mit nur einem oder zwei Befehlen Länge, und das Gesamtkompilat ist rund 70 % länger als Visual C++’. Alles fishy.