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.

Reply via email to