Difference between clang and gcc

19,650

Solution 1

Yes. And no.

This is like asking whether an Audi car has an advantage over a Mercedes car. Like them, the two compilers are two different projects aiming to do the same thing. In some cases, gcc will emit better code, in others it will be clang.

When you need to know, you have to compile your code with both and then measure it.

There is an argument here and somewhat less related here.

Solution 2

In this case the Clang output is better, because it does not branch; instead it loads the value of num % 2 == 1 to al the code generated by gcc uses jumps. If num is expected to be even/odd with 50 % chances, and with no repeating patterns, the code generated by GCC will be susceptible to branch prediction failure.


However you can make the code well-behaved on GCC as well by doing

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

Even more so, as it seems that your algorithm is really defined for unsigned numbers only, you should use unsigned int (they're different for negative numbers) - actually you get a major speedup by using unsigned int for the argument, as now GCC/Clang can optimize num % 2 to num & 1:

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

The resulting code generated by gcc -O2

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

is much better than the code for your original function generated by either compiler. Thus a compiler does not matter as much as does a programmer who knows what he's doing.

Share:
19,650

Related videos on Youtube

Pooya
Author by

Pooya

I have M.Sc in Computer Architecture and have over 10 years of work experience on embedded systems, hardware-software co-design, back-end web development and mobile software development. I have experiences in C/C++, Java, PHP and Android. I'm a lifelong learner and eager to learn new things everyday.

Updated on June 22, 2022

Comments

  • Pooya
    Pooya 6 months

    I used both of these compilers in different projects.

    How they are different in terms of code processing and output generations? For example both gcc and clang has -O2 options for optimization. Are they operating the same way (high level) in terms of optimizing code? I did a little test , for example if I have the following code:

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

    the following are the output assemblies with clang and gcc with -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
    

    as it can be seen the output has different instructions. So my question is does one of them has advantage over another in different projects?

    • fuz
      fuz over 6 years
      You could improve your code by writing int foo(int num) { return num * num + ~num & 1; } instead.
    • Peter Cordes
      Peter Cordes over 6 years
      @FUZxxl: great point, that makes much better code, but you need parens int foo(int num) { return num * num + (~num & 1); } because & has lower precedence than * and +. Also, that does have different behaviour for negative numbers. In C, -1 % 2 is -1, so the if is false. gcc's code accounts for this if you write n*n + (n%2).
    • user1135541
      user1135541 over 6 years
      @FUZxxl return num * num + ~num & 1; are you kidding me? That code is confusing, you made a mistake in a single line, original code is safer for larger pool of people to maintain.