Cppreference and this documentation do not state explicitly that likelihood attributes won't work with a single if
statement. Or, I just do not understand what is meant by alternative path of execution. So that's my question, will the attribute, say, [[unlikely]]
, work in the case below?
if (condition) [[unlikely]] {
do_stuff();
}
Yes, it makes sense. The alternative, [[likely]]
, path is the one where the condition is false
, that is, the path not calling do_stuff();
. That becomes the path it'll try to optimize for.
Example:
#include <iostream>
inline void do_stuff() {
std::cout << "Surprise!\n";
}
int main(int argc, char**) {
if (argc == 0) [[likely]] {
do_stuff();
}
}
Assembler with [[likely]]
:
.LC0:
.string "Surprise!\n"
main:
test edi, edi
jne .L4
sub rsp, 8
mov edx, 10
mov esi, OFFSET FLAT:.LC0
mov edi, OFFSET FLAT:_ZSt4cout
call std::basic_ostream<char, std::char_traits<char> >& std::__ostream_insert<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*, long)
xor eax, eax
add rsp, 8
ret
.L4:
xor eax, eax
ret
_GLOBAL__sub_I_main:
sub rsp, 8
mov edi, OFFSET FLAT:_ZStL8__ioinit
call std::ios_base::Init::Init() [complete object constructor]
mov edx, OFFSET FLAT:__dso_handle
mov esi, OFFSET FLAT:_ZStL8__ioinit
mov edi, OFFSET FLAT:_ZNSt8ios_base4InitD1Ev
add rsp, 8
jmp __cxa_atexit
With [[unlikely]]
(and without attribute at all):
.LC0:
.string "Surprise!\n"
main:
test edi, edi
je .L8
xor eax, eax
ret
.L8:
push rax
mov edx, 10
mov esi, OFFSET FLAT:.LC0
mov edi, OFFSET FLAT:_ZSt4cout
call std::basic_ostream<char, std::char_traits<char> >& std::__ostream_insert<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*, long)
xor eax, eax
pop rdx
ret
_GLOBAL__sub_I_main:
sub rsp, 8
mov edi, OFFSET FLAT:_ZStL8__ioinit
call std::ios_base::Init::Init() [complete object constructor]
mov edx, OFFSET FLAT:__dso_handle
mov esi, OFFSET FLAT:_ZStL8__ioinit
mov edi, OFFSET FLAT:_ZNSt8ios_base4InitD1Ev
add rsp, 8
jmp __cxa_atexit
Those are two slightly different outcomes and without knowing too much about assembler, I'd say the effect of putting [[likely]]
there is clear. It looks to me that putting [[likely]]
there made it inline the function while [[unlikely]]
left it as a function call.