2016-04-11 18 views
8

Ich habe diese beiden Compiler in verschiedenen Projekten verwendet.Unterschied zwischen clang und gcc

Wie unterscheiden sie sich hinsichtlich Codeverarbeitung und Ausgabegenerationen? Zum Beispiel haben sowohl gcc als auch clang-O2 Optionen für die Optimierung. Arbeiten sie in Bezug auf die Code-Optimierung auf die gleiche Weise (High-Level)? Ich habe einen kleinen Test, zum Beispiel, wenn ich den folgenden Code haben:

int foo(int num) { 
    if(num % 2 == 1) 
     return num * num; 
    else 
     return num * num +1; 
} 

die folgenden sind die Ausgabebaugruppen mit Klappern und gcc mit -O2:

----gcc 5.3.0-----        ----clang 3.8.0---- 
foo(int):          foo(int): 
     movl %edi, %edx        movl %edi, %eax 
     shrl $31, %edx        shrl $31, %eax 
     leal (%rdi,%rdx), %eax      addl %edi, %eax 
     andl $1, %eax        andl $-2, %eax 
     subl %edx, %eax        movl %edi, %ecx 
     cmpl $1, %eax        subl %eax, %ecx 
     je  .L5          imull %edi, %edi 
     imull %edi, %edi        cmpl $1, %ecx 
     leal 1(%rdi), %eax       setne %al 
     ret            movzbl %al, %eax 
.L5:             addl %edi, %eax 
     movl %edi, %eax        retq 
     imull %edi, %eax 
     ret 

wie es die Ausgabe zu sehen ist hat andere Anweisungen. Also meine Frage ist, hat einer von ihnen Vorteile gegenüber anderen in verschiedenen Projekten?

+2

Sie könnten Ihren Code verbessern, indem Sie stattdessen 'int foo (int num) {Rückkehrnummer * num + ~ num & 1;}' schreiben. – fuz

+1

@FUZxxl: toller Punkt, dass [macht viel besseren Code] (https://godbolt.org/g/Y1RZuj), aber Sie brauchen Parens 'int foo (int num) {zurück Nummer * num + (~ num & 1);} 'weil' & 'eine niedrigere Priorität als * und + hat. Das hat auch ein anderes Verhalten für negative Zahlen. In C ist' -1% 2' '-1', also ist das if falsch. Der Code von gcc ist dafür verantwortlich wenn Sie 'n * n + (n% 2)' schreiben. –

+0

@FUZxxl danke für den Hinweis, es ist nur ein einfacher Test zu sehen, welche Compiler was ausgeben – Pooya

Antwort

12

Ja. Und nein.

Das ist wie die Frage, ob ein Audi Auto einen Vorteil gegenüber einem Mercedes hat. Wie sie sind die beiden Compiler zwei verschiedene Projekte, die dasselbe tun sollen. In einigen Fällen wird gcc besseren Code ausgeben, in anderen Fällen wird es clang sein.

Wenn Sie wissen müssen, müssen Sie Ihren Code mit beiden kompilieren und dann messen.

Es gibt ein Argument here und etwas weniger verwandt here.

10

In diesem Fall ist der Clang-Ausgang besser, weil er nicht verzweigt; stattdessen lädt es den Wert von num % 2 == 1 zu al Der von gcc generierte Code verwendet Sprünge. Wenn num erwartungsgemäß gerade/ungerade mit 50% Chancen und ohne sich wiederholende Muster ist, wird der von GCC generierte Code susceptible to branch prediction failure sein.


auch immer Sie den Code artig durch

tun als auch auf GCC machen mehr
int foo(int num) { 
    return num * num + (num % 2 != 1); 
} 

Auch so, wie es, dass Ihr Algorithmus scheint wirklich für Zahlen ohne Vorzeichen nur definiert ist, sollten Sie unsigned int (sie sind unterschiedlich für negative Zahlen) - Sie tatsächlich eine große Beschleunigung erhalten, indem unsigned int für das Argument verwendet wird, wie jetzt GCC/Clang optimieren num % 2-num & 1:

unsigned int foo(unsigned int num) { 
    return num * num + (num % 2 != 1); 
} 

Der resultierende Code erzeugt durch gcc -O2

movl %edi, %edx 
imull %edi, %edi 
andl $1, %edx 
xorl $1, %edx 
leal (%rdi,%rdx), %eax 
ret 

ist viel besser als der Code für Ihre ursprüngliche Funktion entweder durch Compiler erzeugt. Ein Compiler ist also nicht so wichtig wie ein Programmierer, der weiß, was er tut.

+1

hmm Ich hätte einen Fehler gemacht, hätte natürlich '! = 1' oder' == 0' sein sollen –

Verwandte Themen