https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109631
Bug ID: 109631 Summary: Simple std::optional types returned on stack, not registers Product: gcc Version: unknown Status: UNCONFIRMED Severity: normal Priority: P3 Component: libstdc++ Assignee: unassigned at gcc dot gnu.org Reporter: david at westcontrol dot com Target Milestone: --- A std::optional<T> is fundamentally like a std::pair<T, bool>, but with nice access features, type safety, etc. But for simple functions it is significantly less efficient, because in gcc it is returned on the stack even when T fits in a single register. <https://godbolt.org/z/6hx6vxaG7> On targets such as x86-64 and AARCH64, simple structs and pairs that fit in two registers, are returned in two registers - there is no need for the caller to reserve stack space and pass a hidden pointer to the callee function. On clang with its standard library, this also applies to std::optional<T> for suitable types T such as "int", but on gcc and its standard C++ library, the stack is used for returning the std::optional<int>. Since both clang and gcc follow the same calling conventions, this must (I believe) be a result of different implementations of std::optional<> in the C++ libraries. (I note that code for std::pair<bool, T> is more efficient here than using std::pair<T, bool>. But perhaps the details of std::optional<> require that the contained element comes first.) #include <optional> #include <utility> using A = std::optional<int>; using B = std::pair<int, bool>; using C = std::pair<bool, int>; A foo_A(int x) { return x; } B foo_b(int x) { B y { x, true }; return y; } C foo_c(int x) { C y { true, x }; return y; }