https://gcc.gnu.org/bugzilla/show_bug.cgi?id=117935
Bug ID: 117935 Summary: [[likely]] attribute not propagated from function body to callers Product: gcc Version: 15.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: middle-end Assignee: unassigned at gcc dot gnu.org Reporter: redi at gcc dot gnu.org Target Milestone: --- Given: struct optional { union { int val; }; bool has_val = false; bool has_value(bool b) const { #ifdef HINT return __builtin_expect(b,1); #else if (b) #ifdef LIKELY [[likely]] #endif return true; else return false; #endif } int value_or(int def) const { if (has_value(has_val)) return val; else return def; } }; int f(optional const& o) { return o.value_or(0); } This compiles to: f(optional const&): xor eax, eax cmp BYTE PTR [rdi+4], 0 je .L1 mov eax, DWORD PTR [rdi] .L1: ret Defining LIKELY doesn't change anything, so the [[likely]] attribute inside the has_value() function doesn't seem to do anything. But defining HINT gives this different code: f(optional const&): cmp BYTE PTR [rdi+4], 0 je .L3 mov eax, DWORD PTR [rdi] ret .L3: xor eax, eax ret It looks like the value_or function uses the __builtin_expect hint so that the xor is moved into the unlikely path. The gimple for -DHINT looks like: bool optional::has_value (const struct optional * const this, bool b) { bool D.2871; # DEBUG BEGIN_STMT _1 = (long int) b; _2 = __builtin_expect (_1, 1); D.2871 = _2 != 0; return D.2871; } And for -DLIKELY it looks like: bool optional::has_value (const struct optional * const this, bool b) { bool D.2873; # DEBUG BEGIN_STMT if (b != 0) goto <D.2871>; else goto <D.2872>; <D.2871>: # DEBUG BEGIN_STMT // predicted likely by hot label predictor. D.2873 = 1; // predicted unlikely by early return (on trees) predictor. return D.2873; <D.2872>: # DEBUG BEGIN_STMT D.2873 = 0; // predicted unlikely by early return (on trees) predictor. return D.2873; __builtin_unreachable (); } Is it expected that the hot label predictor has no effect on the callers?