https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89819
Bug ID: 89819 Summary: [9 Regression] std::variant operators regressed since GCC 8.3 Product: gcc Version: 9.0 Status: UNCONFIRMED Keywords: missed-optimization Severity: normal Priority: P3 Component: libstdc++ Assignee: unassigned at gcc dot gnu.org Reporter: antoshkka at gmail dot com Target Milestone: --- The following code #include <variant> struct my_type{}; bool operator==(const my_type&, const my_type&) noexcept; using V1 = std::variant<int, float, long, double, my_type>; auto test1(const V1& v) { return v == v; } Was producing a jump table of size 5 on GCC 8.3. GCC 9 produces huge jump tables with over 30 entries. This leads to ~15 times bigger binaries with GCC 9 and ~25% compilation slowdown. https://godbolt.org/z/yoAIrP This could be fixed by changing the `_VARIANT_RELATION_FUNCTION_TEMPLATE` from binary visitation to unary via first checking the `index()` of `__lhs` + `__rhs` and doing the visitation only if they match (hold the same type). Pseudo-code: #define _VARIANT_RELATION_FUNCTION_TEMPLATE(__OP, __NAME) \ template<typename... _Types> \ constexpr bool operator __OP(const variant<_Types...>& __lhs, \ const variant<_Types...>& __rhs) \ { \ bool __ret = true; \ if ((__lhs.index() + 1) != (__rhs.index() + 1)) { \ return (__lhs.index() + 1) __OP (__rhs.index() + 1); \ } \ __do_visit([&__ret, &__lhs] \ (auto&& __rhs_mem) mutable \ -> __detail::__variant::__variant_cookie \ { \ using __Type = remove_reference_t<decltype(__rhs_mem)>; \ if constexpr (!is_same_v< \ __Type, \ __detail::__variant::__variant_cookie>) \ __ret = __detail::__variant::__get<__detail::__variant::__index_of_v<__Type, _Types...>>(__this_mem) __OP __rhs_mem; \ return {}; \ }, __rhs); \ return __ret; \ } \ \ constexpr bool operator __OP(monostate, monostate) noexcept \ { return 0 __OP 0; }