Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Simple example where [[likely]] and [[unlikely]] affect program assembly?

C++20 introduced the attributes [[likely]] and [[unlikely]] to the language, which can be used to allow the compiler to optimize for the case where one execution path is either much more likely or much less likely than the other ones.

Given the cost of an incorrect branch prediction, this seems like a feature that's potentially extremely useful in performance-critical sections of code, but I don't know what it would actually cause the compiler to do.

Is there a simple piece of code for which adding [[likely]] and [[unlikely]] attributes changes the assembly output by the compiler? And perhaps more importantly, what do these changes do?

I created a simple example for my own understanding to see if there was any difference in the assembly, but it appears that this example is too simple to actually show any changes to the assembly:

void true_path();
void false_path();

void foo(int i) {
    if(i) {
        true_path();
    } else {
        false_path();
    }
}
void bar(int i) {
    if(i) [[likely]] {
        true_path();
    } else [[unlikely]] {
        false_path();
    }
}

View the compiled assembly here.

like image 290
Alecto Irene Perez Avatar asked Jun 05 '20 18:06

Alecto Irene Perez


People also ask

What is the use of likely and unlikely macros in Linux kernel?

Assisting the compiler in optimizing if conditions A look at the Linux kernel code will show many if conditions enclosed in likely and unlikely macros. These macros invoke compiler directives that give the compiler a hint on the code leg that should be optimized for performance.

What is __ Builtin_expect?

You can use the __builtin_expect built-in function to indicate that an expression is likely to evaluate to a specified value. The compiler can use this knowledge to direct optimizations. This built-in function is portable with the GNU C/C++ __builtin_expect function.

What is assembly programming?

Assembly Programming Tutorial. Assembly language is a low-level programming language for a computer or other programmable device specific to a particular computer architecture in contrast to most high-level programming languages, which are generally portable across multiple systems.

What are conditions in assembly language?

Assembly - Conditions. Conditional execution in assembly language is accomplished by several looping and branching instructions. These instructions can change the flow of control in a program.

How is assembly language converted into executable machine code?

Assembly language is converted into executable machine code by a utility program referred to as an assembler like NASM, MASM, etc.

What is the use of likely and unlikely attributes in Java?

likely and unlikely attributes is our way of saying to the compiler that which code is most likely to be executed so compiler can schedule accordingly and result in a overall faster code execution. We should be cautious using likely and unlikely if we are not very sure because otherwise we would have serious performance degradations.


1 Answers

As it seems, there is a bug in gcc. If you have two functions which are the same, besides [[likely]] attributes, gcc folds them incorrectly.

But if you use just one function, and switch between [[likely]]/[[unlikely]], assembly changes.

So, this function:

void bar(int i) {
    if(i) [[unlikely]] {
        true_path();
    } else [[likely]] {
        false_path();
    }
}

compiles to:

bar(int):
        test    edi, edi
        jne     .L4
        jmp     false_path()
.L4:
        jmp     true_path()

And this:

void bar(int i) {
    if(i) [[likely]] {
        true_path();
    } else [[unlikely]] {
        false_path();
    }
}

compiles to:

bar(int):
        test    edi, edi
        je      .L2
        jmp     true_path()
.L2:
        jmp     false_path()

Notice, that the condition has changed: the first version jumps, if i is non-zero, while the second one jumps if i is zero.

This is in agreement with the attributes: gcc generates code, where the conditional jump happens in the unlikely path.

like image 70
geza Avatar answered Oct 29 '22 17:10

geza