[PATCH] Changes to std::variant to reduce code size

Jonathan Wakely jwakely@redhat.com
Thu May 16 11:29:00 GMT 2019


These two changes both result in smaller code for std::variant.

The first one means smaller tables of function pointers, because we
don't generate an instantiation for the valueless state. Instead we do
a runtime branch, marked [[unlikely]] to make _M_reset() a no-op if
it's already valueless. In a microbenchmark I couldn't measure any
performance difference due to the extra branch, so the code size
reduction seems worthwhile.

The second one removes a branch from the index() member by relying on
unsigned arithmetic. That also results in smaller code and I can't see
any downside.

	* include/std/variant (_Variant_storage<false, _Types...>::_M_reset):
	Replace raw visitation with a runtime check for the valueless state
	and a non-raw visitor.
	(_Variant_storage<false, _Types...>::_M_reset_impl): Remove.
	(variant::index()): Remove branch.

Tested powerpc64le-linux, any objections?


-------------- next part --------------
commit a36ecd71f2e7ce95b479d4c06597f2ee0dfe27b1
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Wed May 15 22:33:31 2019 +0100

    Changes to std::variant to reduce code size
    
            * include/std/variant (_Variant_storage<false, _Types...>::_M_reset):
            Replace raw visitation with a runtime check for the valueless state
            and a non-raw visitor.
            (_Variant_storage<false, _Types...>::_M_reset_impl): Remove.
            (variant::index()): Remove branch.

diff --git a/libstdc++-v3/include/std/variant b/libstdc++-v3/include/std/variant
index 8c710c30de5..8844c54913f 100644
--- a/libstdc++-v3/include/std/variant
+++ b/libstdc++-v3/include/std/variant
@@ -396,19 +396,16 @@ namespace __variant
 	_M_index(_Np)
 	{ }
 
-      constexpr void _M_reset_impl()
-      {
-	__variant::__raw_visit([](auto&& __this_mem) mutable
-	  {
-	    if constexpr (!is_same_v<remove_reference_t<decltype(__this_mem)>,
-			  __variant_cookie>)
-	      std::_Destroy(std::__addressof(__this_mem));
-	  }, __variant_cast<_Types...>(*this));
-      }
-
       void _M_reset()
       {
-	_M_reset_impl();
+	if (!_M_valid()) [[unlikely]]
+	  return;
+
+	std::__do_visit<void>([](auto&& __this_mem) mutable
+	  {
+	    std::_Destroy(std::__addressof(__this_mem));
+	  }, __variant_cast<_Types...>(*this));
+
 	_M_index = variant_npos;
       }
 
@@ -1485,12 +1482,7 @@ namespace __variant
       { return !this->_M_valid(); }
 
       constexpr size_t index() const noexcept
-      {
-	if (this->_M_index ==
-	    typename _Base::__index_type(variant_npos))
-	  return variant_npos;
-	return this->_M_index;
-      }
+      { return size_t(typename _Base::__index_type(this->_M_index + 1)) - 1; }
 
       void
       swap(variant& __rhs)


More information about the Gcc-patches mailing list