2

I took below example from https://kernelnewbies.org/FAQ/LikelyUnlikely

#include <stdio.h>
#define likely(x)    __builtin_expect(!!(x), 1)
#define unlikely(x)  __builtin_expect(!!(x), 0)

int main(char *argv[], int argc)
{
   int a;

   /* Get the value from somewhere GCC can't optimize */
   a = atoi (argv[1]);

   if (likely (a == 2))
      a++;
   else
      a--;

   printf ("%d\n", a);

   return 0;
}

and compiled it https://godbolt.org/z/IC0aif with arm gcc 8.2 compiler.

In the original link, they have tested it for X86 and the assembly output is different if likely(in the if condition in above code) is replaced with unlikely, which shows the optimisation performed by compiler for branch prediction.

But when I compile the above code for ARM (arm-gcc -O2), I don't see any difference in assembly code. Below is the output of ARM assembly in both the case - likely and unlikely

main:
        push    {r4, lr}
        ldr     r0, [r0, #4]
        bl      atoi
        cmp     r0, #2
        subne   r1, r0, #1
        moveq   r1, #3
        ldr     r0, .L6
        bl      printf
        mov     r0, #0
        pop     {r4, pc}
.L6:
        .word   .LC0
.LC0:
        .ascii  "%d\012\000"

Why doesn't the compiler optimize for branch prediction in case of ARM ?

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
bornfree
  • 2,308
  • 1
  • 23
  • 33
  • This could depend on the exact ARM CPU targeted, as some have shallow pipelines and no branch-prediction units. – Some programmer dude Jun 01 '19 at 06:52
  • 3
    There is no branch prediction because there is no branch. ARM lets you put a condition on most instructions. For example, `subne` does the subtraction only if the last comparison was "not equal" while `moveq` only moves the literal value if the last comparison was "equal". – rici Jun 01 '19 at 08:04
  • @rici - so likely/unlikely is not so useful in case of ARM ? – bornfree Jun 01 '19 at 08:07
  • 2
    I didn't say that. Here, the conditional actions are very simple. For more complicated conditionals, branching will be required and likely/unlikely will probably affect code generation. How much difference that actually makes (on any platform) is another question. – rici Jun 01 '19 at 12:45
  • @rici - Thanks. Got it. – bornfree Jun 01 '19 at 15:31
  • 1
    1) there is no reason to assume that this will improve the code output for any target. 2) there is no reason to assume that a compiler cant figure this out. – old_timer Jun 01 '19 at 17:13
  • This is to some extent ghee whiz trying to mess with the language. And also falls into premature optimization. Also with something like gcc or clang it has a time limit, might work on the day on the machine on that compiler and version for that target that it was written. But over time if not already in a version not yet on that computer that day, the compiler can figure this out with improvements or sometimes accidents. Likewise improvements or accidents can cause this optimization to fail. – old_timer Jun 01 '19 at 17:16
  • It doesnt hurt to re-organize the if and else to improve a warm fuzzy feeling inside the programmer, but no reason to assume it will make a difference and more important no reason to expect it will always make a difference for any platform much less a specific one. – old_timer Jun 01 '19 at 17:17
  • 3
    Why downvote the question? The question is genuine and clear. – bornfree Jun 01 '19 at 17:28

1 Answers1

2

As @rici said, your code is simple enough that it can be realized by conditional instructions. You can see a difference, e.g., if you call functions which are implemented in a different compilation unit:

#define likely(x)    __builtin_expect(!!(x), 1)
#define unlikely(x)  __builtin_expect(!!(x), 0)

// only forward declarations:
void foo();
void bar();

int main(char *argv[], int argc)
{
   if (likely (argc == 2))
      foo();
   else
      bar();
}

Changing likely to unlikely switches the order of the if and else branch, for ARM and x86: https://godbolt.org/z/UDzvf0. If this really makes a difference likely depends on the hardware you are running on, whether you call the function the first time (otherwise, the CPU-internal branch prediction likely has a higher influence than the order of the instructions), and probably many other things.

chtz
  • 17,329
  • 4
  • 26
  • 56