https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89825
Bug ID: 89825 Summary: Jump table for variant visitation could be shortened for never empty variants 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 `__do_cookie` computation in `_Multi_array` seems suboptimal. There are variant types that are never empty, so they never need the cookie value at all. `_Variant_storage<true, _Types...>::_M_valid()` already use that knowledge to always return `true`. The same logic could be used for the `__do_cookie`. Pseudo-code: + template<typename _Variant> + struct _Never_empty; + template<typename... _Types> + struct _Never_empty<variant<_Types...>> + { + static constexpr bool _S_value = (is_trivially_copyable_v<_Types> && ...); + }; template<typename _Ret, typename _Visitor, typename... _Variants, size_t __first, size_t... __rest> struct _Multi_array<_Ret(*)(_Visitor, _Variants...), __first, __rest...> { + static constexpr size_t __index = sizeof...(_Variants) - sizeof...(__rest) - 1; + using _Variant_current = __remove_cvref_t<typename _Nth_type<__index, _Variants...>::type>; static constexpr int __do_cookie = - is_same_v<_Ret, __variant_cookie> ? 1 : 0; + is_same_v<_Ret, __variant_cookie> && _Never_empty<_Variant_current>::_S_value ? 1 : 0; using _Tp = _Ret(*)(_Visitor, _Variants...); template<typename... _Args> constexpr const _Tp& _M_access(size_t __first_index, _Args... __rest_indices) const { return _M_arr[__first_index + __do_cookie]._M_access(__rest_indices...); } _Multi_array<_Tp, __rest...> _M_arr[__first + __do_cookie]; }; template<size_t... __var_indices> static constexpr void _S_apply_all_alts(_Array_type& __vtable, std::index_sequence<__var_indices...>) { - if constexpr (is_same_v<_Result_type, __variant_cookie>) + if constexpr (is_same_v<_Result_type, __variant_cookie> + && !_Never_empty<remove_cv_t<_Next>>::_S_value) (_S_apply_single_alt<true, __var_indices>( __vtable._M_arr[__var_indices + 1], &(__vtable._M_arr[0])), ...); else (_S_apply_single_alt<false, __var_indices>( __vtable._M_arr[__var_indices]), ...); } The above patch reduces jump table size on up to 2*sizeof...(_Types) for binary visitations.