# LLVM/Clang 9 und der Kernel

## schmidicom

Seit LLVM/Clang 9 soll es offenbar möglich sein damit den Linux-Kernel ohne große Verrenkungen zu bauen.

https://www.golem.de/news/compiler-llvm-9-baut-x86-linux-kernel-1909-143986.html

Hat das schon mal einer ausprobiert?

Was könnte einem das bringen?

----------

## forrestfunk81

Bei Phoronix haben sie einige Benchmarks durchgeführt. Aber das sind Fullstack Benchmarks und zeigen erwartungsgemäß nur geringe Unterschiede im Ergebnis. Leider trifft Phoronix auch keine Aussage über die Compile Zeit oder die Binary Größe. Gerade die Compile Zeit wäre interessant, da Clang darauf angeblich besonderen Wert legt.

----------

## mike155

 *schmidicom wrote:*   

> Hat das schon mal einer ausprobiert?
> 
> Was könnte einem das bringen?

 

Ich glaube nicht, dass der Kernel besser wird, wenn man ihn mit LLVM/Clang compiliert.   :Smile: 

Aber darum geht es auch nicht. Viel wichtiger ist, dass es jetzt einen zweiten vollwertigen und sehr guten C/C++ Compiler gibt! Davon haben wir alle etwas:

Ab jetzt haben wir sowohl für den Kernel, als auch für (fast) alle anderen Pakete die Wahl zwischen GCC und LLVM/Clang. Das wird insbesondere wichtig, wenn mal einer der Compiler Probleme haben sollte.

Die Konkurrenz zwischen GCC und LLVM/Clang wird beide Projekte voranbringen. Die Entwickler untersuchen natürlich sehr genau, wo das andere Produkt besser oder schlechter ist. Beispielsweise haben die GCC Entwickler gesehen, dass Clang deutlich bessere Meldungen ausgibt - und daraufhin die Meldungen von GCC in den letzten Releases deutlich verbessert. Ein anderes Beispiel: die GCC Entwickler überlegen, den GCC weiter zu modularisieren.

Wenn ich es richtig verstehe, sind die GCC Entwickler nicht traurig über die Konkurrenz und nehmen sie sportlich. Den GCC Entwicklern (allen voran Richard Stallman) bleibt auf jeden Fall der Verdienst, Linux und große Teile von Open Source überhaupt erst möglich gemacht zu haben. Dafür werde ich ihnen ewig dankbar sein!

----------

## toralf

 *mike155 wrote:*   

> Den GCC Entwicklern (allen voran Richard Stallman) bleibt auf jeden Fall der Verdienst, Linux und große Teile von Open Source überhaupt erst möglich gemacht zu haben. Dafür werde ich ihnen ewig dankbar sein!

 Hört sich ja ein bißchen wie ein Nachruf an  :Very Happy: 

----------

## mike155

 *toralf wrote:*   

> Hört sich ja ein bißchen wie ein Nachruf an 

 

"Nachruf" wäre übertrieben. Aber den Status als "der" C-Compiler unter Linux hat GCC sicherlich eingebüßt. 

Ich muss gestehen, das ich am Anfang einige Gewissensbisse hatte, clang/LLVM zu verwenden. Es hat sich irgendwie illoyal angefühlt. Nicht nur aus Gewohnheitsgründen, sondern auch wegen der unterschiedlichen Lizenzen. Clang/LLVM ist nicht nur ein weiterer Compiler - es ist auch ein Angriff auf die GPL und das GNU Projekt. Ich bin mir aber noch nicht sicher, was das bedeutet und ob bzw. wie ich darauf reagieren soll.

Jedenfalls verwende ich zurzeit regelmäßig sowohl GCC als auch clang und ich bin mit beiden sehr zufrieden.

----------

## schmidicom

Ich habe jetzt mal auf meinem Laptop den neusten Kernel (5.3.2) mit clang gebaut und gebootet, beides hat problemlos funktioniert.

Spürbare Unterschiede kann ich bis jetzt keine feststellen, außer dass das neue Kernel-Image 0.2M kleiner ist als von 5.3.1 (was natürlich nicht zwingend nur mit clang zu tun haben muss).

----------

## mike155

Das ist interessant, schmidicom! Bitte berichte weiter von Deinen Erfahrungen.

Das Problem ist nicht, den Kernel mit einem anderen Compiler zu übersetzen. 

Das Problem ist, dass der Kernel in den letzten 27 Jahren bewusst und häufig auch unbewusst auf den GCC optimiert wurde. D.h. clang muss nicht nur den Code compilieren, sondern er muss auch die vielen dokumentierten und nicht dokumentierten Eigenheiten des GCC nachbauen. Sonst funktioniert der Kernel anders als gewünscht.

Ich denke da beispielsweise an Posts auf der LKML, wo jemand eine Änderung des Quellcodes an einer kritischen Stelle vorschlägt. Die Entwickler schauen sich dann den von GCC generierten Assembler-Code an und ändern den Source-Code so lange, bis der generierte Assembler-Code passt. Hier ist es wahrscheinlich, dass clang ganz anderen Assembler-Code generiert - und ein mit clang compilierter Kernel Dinge macht, die die Entwickler gar nicht so wollen. Das ist dann aber kein Fehler von clang. Sondern eine zu starke Optimierung des Quellcodes an den GCC.

Ein anderes Beispiel ist, dass die Kerrnel-Entwickler gelegentlich Fehler im GCC finden. Der GCC wird dann typischerweise angepasst und dadurch besser. Dieser Prozess hat in clang/LLVM noch nicht stattgefunden. Ich kann mir gut vorstellen, dass in clang/LLVM noch ein paar Fehler schlummern, die noch nicht entdeckt wurden - und die zu Fehlfunktionen im Kernel führen.

----------

## schmidicom

Inzwischen konnte ich das ganze mal etwas ausgedehnter ausprobieren und hier mal ein kleines Fazit dazu:

Auf meinem Desktop oder Laptop merke ich zwischen einem Kernel der mit clang-9 und einem der mit GCC kompiliert wurde kaum einen Unterschied. Nur bei einem Server für Samba-Freigaben konnte ich, und inzwischen auch andere, einen Unterschied bemerken. Auf diesen greifen tagtäglich um die 200 Clients (hauptsächlich Windows aber auch ein paar wenige Macs) zu und der reagiert jetzt beim Auflisten des Inhalts eines Ordners (vor allem Ordner mit sehr vielen Dateien/Unterordnern) deutlich schneller.

----------

## mike155

 *Quote:*   

> und der reagiert jetzt beim Auflisten des Inhalts eines Ordners (vor allem Ordner mit sehr vielen Dateien/Unterordnern) deutlich schneller.

 

Hast Du schon eine Erklärung dafür? Oder zumindest eine Vermutung?

Wenn Anwender etwas merken, müssen die entsprechenden Funktionen im Kernel um mindestens 20-30% schneller geworden sein. Das würde mich sehr wundern.

----------

## Max Steel

[quote="mike155"] *Quote:*   

> Wenn Anwender etwas merken, müssen die entsprechenden Funktionen im Kernel um mindestens 20-30% schneller geworden sein. Das würde mich sehr wundern.

 

Nicht zwangsläufig, eine Ordnerstruktur mit einigen tausend Einträgen ruft auch bestimmte Funktionen einige tausend mal auf. Eine Verbesserung hierin könnte Lastabhängig schon eine deutliche Verbesserung bringen. Ist aber zugleich auch ein fieser Corner-Case.

Oder die Stromsparmechanismen der Festplatten funktionieren in der Version eben nicht und die Platten müssen nicht laufend (oder am Morgen) frisch anfahren.

----------

## schmidicom

 *mike155 wrote:*   

>  *Quote:*   und der reagiert jetzt beim Auflisten des Inhalts eines Ordners (vor allem Ordner mit sehr vielen Dateien/Unterordnern) deutlich schneller. 
> 
> Hast Du schon eine Erklärung dafür? Oder zumindest eine Vermutung?
> 
> Wenn Anwender etwas merken, müssen die entsprechenden Funktionen im Kernel um mindestens 20-30% schneller geworden sein. Das würde mich sehr wundern.

 

Nö so richtig erklären kann ich mir das nicht, aber der Unterschied ist recht deutlich.

Vorher konnte man dem Windows-Explorer beim Zugriff auf die Samba-Freigabe des Servers dabei zusehen wie die Liste an Dateien und Ordner aufgebaut wurde (man erkannte sogar das diese nicht alphabetisch aufgebaut wurde) und jetzt wird sie gleich ohne erkennbare Verzögerung vollständig angezeigt. Die reine Datentransferrate jedoch (z. B. beim kopieren einer großen Datei) hat sich nicht verändert.

Info am Rande:

Der Server ist eine VM auf einem VMWare-ESXi mit XFS als Dateisystem.

----------

## ChrisJumper

Hmm. Wieso und warum sollte man llvm nehmen? Kann mich da mal jemand aufklären kurz Zusammengefasst was da der Vorteil sein sollte?

----------

## schmidicom

 *ChrisJumper wrote:*   

> Hmm. Wieso und warum sollte man llvm nehmen? Kann mich da mal jemand aufklären kurz Zusammengefasst was da der Vorteil sein sollte?

 

https://clang.llvm.org/comparison.html

Letztendlich wird wohl jeder seine eigenen Gründe haben warum er lieber den einen oder anderen Compiler benutzt.

----------

## schmidicom

 *mike155 wrote:*   

> Ich denke da beispielsweise an Posts auf der LKML, wo jemand eine Änderung des Quellcodes an einer kritischen Stelle vorschlägt. Die Entwickler schauen sich dann den von GCC generierten Assembler-Code an und ändern den Source-Code so lange, bis der generierte Assembler-Code passt. Hier ist es wahrscheinlich, dass clang ganz anderen Assembler-Code generiert - und ein mit clang compilierter Kernel Dinge macht, die die Entwickler gar nicht so wollen. Das ist dann aber kein Fehler von clang. Sondern eine zu starke Optimierung des Quellcodes an den GCC.

 

Zu dieser Sache scheint es jetzt was neues zu geben:

 *https://www.pro-linux.de/news/1/27944/erste-vorschau-auf-linux-kernel-57.html wrote:*   

> Der Kernel kann nun ganz einfach mit der Kommandozeilenoption LLVM=1 mit Clang statt GCC compiliert werden. Um auch den integrierten Assembler zu verwenden, muss man zusätzlich LLVM_IAS=1 angeben.

 

Ich vermute daher einfach mal das ein "make CC=/usr/lib/llvm/10/bin/clang -j5" den Assembler-Code aus dem Kernel nicht mit LLVM compiliert hat.

----------

## l3u

Jedenfalls haut clang immer mal (sinnvolle) Warnungen beim Kompilieren raus, die man mit dem gcc nicht bekommt. Ich bau mein eines Projekt immer mal mit clang, damit ich die dann bekomm, und bisher hab ich mir immer gedacht "cleverer clang" ;-)

----------

## schmidicom

Der Kernel 5.7.0 ist ja jetzt draußen und wie angekündigt kann man jetzt LLVM und LLVM_IAS benutzen um das ganze mit den Compilern von LLVM zu bauen.

Aber...

Wenn LLVM_IAS auf 1, also aktiv, gesetzt wird passiert zumindest bei mir das:

```
...

  AS [M]  arch/x86/crypto/chacha-avx512vl-x86_64.o

  AS [M]  arch/x86/crypto/aesni-intel_asm.o

<instantiation>:15:74: error: too many positional arguments

 PRECOMPUTE 8*3+8(%rsp), %xmm1, %xmm2, %xmm3, %xmm4, %xmm5, %xmm6, %xmm7,

                                                                         ^

arch/x86/crypto/aesni-intel_asm.S:1598:2: note: while in macro instantiation

 GCM_INIT %r9, 8*3 +8(%rsp), 8*3 +16(%rsp), 8*3 +24(%rsp)

 ^

<instantiation>:47:2: error: unknown use of instruction mnemonic without a size suffix

 GHASH_4_ENCRYPT_4_PARALLEL_dec %xmm9, %xmm10, %xmm11, %xmm12, %xmm13, %xmm14, %xmm0, %xmm1, %xmm2, %xmm3, %xmm4, %xmm5, %xmm6, %xmm7, %xmm8, enc

 ^

arch/x86/crypto/aesni-intel_asm.S:1599:2: note: while in macro instantiation

 GCM_ENC_DEC dec

 ^

<instantiation>:15:74: error: too many positional arguments

 PRECOMPUTE 8*3+8(%rsp), %xmm1, %xmm2, %xmm3, %xmm4, %xmm5, %xmm6, %xmm7,

                                                                         ^

arch/x86/crypto/aesni-intel_asm.S:1686:2: note: while in macro instantiation

 GCM_INIT %r9, 8*3 +8(%rsp), 8*3 +16(%rsp), 8*3 +24(%rsp)

 ^

<instantiation>:47:2: error: unknown use of instruction mnemonic without a size suffix

 GHASH_4_ENCRYPT_4_PARALLEL_enc %xmm9, %xmm10, %xmm11, %xmm12, %xmm13, %xmm14, %xmm0, %xmm1, %xmm2, %xmm3, %xmm4, %xmm5, %xmm6, %xmm7, %xmm8, enc

 ^

arch/x86/crypto/aesni-intel_asm.S:1687:2: note: while in macro instantiation

 GCM_ENC_DEC enc

 ^

<instantiation>:15:67: error: too many positional arguments

 PRECOMPUTE %rcx, %xmm1, %xmm2, %xmm3, %xmm4, %xmm5, %xmm6, %xmm7,

                                                                  ^

arch/x86/crypto/aesni-intel_asm.S:1707:2: note: while in macro instantiation

 GCM_INIT %rdx, %rcx,%r8, %r9

 ^

<instantiation>:47:2: error: unknown use of instruction mnemonic without a size suffix

 GHASH_4_ENCRYPT_4_PARALLEL_enc %xmm9, %xmm10, %xmm11, %xmm12, %xmm13, %xmm14, %xmm0, %xmm1, %xmm2, %xmm3, %xmm4, %xmm5, %xmm6, %xmm7, %xmm8, enc

 ^

arch/x86/crypto/aesni-intel_asm.S:1722:2: note: while in macro instantiation

 GCM_ENC_DEC enc

 ^

<instantiation>:47:2: error: unknown use of instruction mnemonic without a size suffix

 GHASH_4_ENCRYPT_4_PARALLEL_dec %xmm9, %xmm10, %xmm11, %xmm12, %xmm13, %xmm14, %xmm0, %xmm1, %xmm2, %xmm3, %xmm4, %xmm5, %xmm6, %xmm7, %xmm8, enc

 ^

arch/x86/crypto/aesni-intel_asm.S:1737:2: note: while in macro instantiation

 GCM_ENC_DEC dec

 ^

make[2]: *** [scripts/Makefile.build:349: arch/x86/crypto/aesni-intel_asm.o] Fehler 1

make[1]: *** [scripts/Makefile.build:488: arch/x86/crypto] Fehler 2

make[1]: *** Es wird auf noch nicht beendete Prozesse gewartet....

  CC      arch/x86/mm/numa_64.o

  CC      fs/notify/notification.o

  CC      arch/x86/kernel/cpu/mtrr/generic.o

...
```

Der Assembler-Code des Kernels ist offensichtlich noch nicht mit LLVM kompilierbar aber der C-Code schon.

----------

