diff options
author | Jonathan Wakely <jwakely@redhat.com> | 2019-09-23 16:54:16 +0100 |
---|---|---|
committer | Jonathan Wakely <redi@gcc.gnu.org> | 2019-09-23 16:54:16 +0100 |
commit | 1e8822d360a3fe5beb693de84fd986ec8c52a2f0 (patch) | |
tree | f2728a5feaa677602146900700f9c827342cfb1d | |
parent | fa87544ca13000e62982d3005edb47a53401cfe7 (diff) | |
download | gcc-1e8822d360a3fe5beb693de84fd986ec8c52a2f0.zip gcc-1e8822d360a3fe5beb693de84fd986ec8c52a2f0.tar.gz gcc-1e8822d360a3fe5beb693de84fd986ec8c52a2f0.tar.bz2 |
PR libstdc++/91788 improve codegen for std::variant<T...>::index()
If __index_type is a smaller type than size_t, then the result of
size_t(__index_type(-1)) is not equal to size_t(-1), but to an incorrect
value such as size_t(255) or size_t(65535). The old implementation of
variant<T...>::index() uses (size_t(__index_type(_M_index + 1)) - 1)
which is always correct, but generates suboptimal code for many common
cases.
When the __index_type is size_t or valueless variants are not possible
we can just return the value directly.
When the number of alternatives is sufficiently small the result of
converting the _M_index value to the corresponding signed type will be
either non-negative or -1. In those cases converting to the signed type
and then to size_t will either produce the correct positive value or
will sign extend -1 to (size_t)-1 as desired.
For the remaining case we keep the existing arithmetic operations to
ensure the correct result.
PR libstdc++/91788 (partial)
* include/std/variant (variant::index()): Improve codegen for cases
where conversion to size_t already works correctly.
From-SVN: r276056
-rw-r--r-- | libstdc++-v3/ChangeLog | 6 | ||||
-rw-r--r-- | libstdc++-v3/include/std/variant | 12 |
2 files changed, 17 insertions, 1 deletions
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 545247e..54fe95f 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,9 @@ +2019-09-23 Jonathan Wakely <jwakely@redhat.com> + + PR libstdc++/91788 (partial) + * include/std/variant (variant::index()): Improve codegen for cases + where conversion to size_t already works correctly. + 2019-09-23 Andreas Schwab <schwab@suse.de> * config/abi/post/riscv64-linux-gnu/baseline_symbols.txt: Update. diff --git a/libstdc++-v3/include/std/variant b/libstdc++-v3/include/std/variant index d93ea86..c004324 100644 --- a/libstdc++-v3/include/std/variant +++ b/libstdc++-v3/include/std/variant @@ -1518,7 +1518,17 @@ namespace __variant { return !this->_M_valid(); } constexpr size_t index() const noexcept - { return size_t(typename _Base::__index_type(this->_M_index + 1)) - 1; } + { + using __index_type = typename _Base::__index_type; + if constexpr (is_same_v<__index_type, size_t>) + return this->_M_index; + else if constexpr (__detail::__variant::__never_valueless<_Types...>()) + return this->_M_index; + else if constexpr (sizeof...(_Types) <= __index_type(-1) / 2) + return make_signed_t<__index_type>(this->_M_index); + else + return size_t(__index_type(this->_M_index + 1)) - 1; + } void swap(variant& __rhs) |