https://gcc.gnu.org/bugzilla/show_bug.cgi?id=117764
Jan Hubicka <hubicka at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- Summary|cddce should handle |[15 Regression] cddce |__builtin_unreachable |should handle |guards |__builtin_unreachable | |guards CC| |mjambor at suse dot cz --- Comment #1 from Jan Hubicka <hubicka at gcc dot gnu.org> --- This is a regression, since I introduced the __builtin_unreachable guards to std::vector::size. I wonder if reasonable heuristics would be to mark the conditionals guarding __builtin_unreachable as live provided that their control-dependency block is already live for other reason. This will allow removal of unnecesary loops. We may however need to do something about ipa-sra as well. If inlining failed, it is not a best idea to keep dead argument just because we know its range. Jonathan's reverted patch: diff --git a/libstdc++-v3/include/bits/stl_vector.h b/libstdc++-v3/include/bits/stl_vector.h index acb29396d264..e593be443bc2 100644 --- a/libstdc++-v3/include/bits/stl_vector.h +++ b/libstdc++-v3/include/bits/stl_vector.h @@ -388,6 +388,24 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER } protected: + + __attribute__((__always_inline__)) + _GLIBCXX20_CONSTEXPR void + _M_invariant() const + { +#if __OPTIMIZE__ + if (this->_M_impl._M_finish < this->_M_impl._M_start) + __builtin_unreachable(); + if (this->_M_impl._M_finish > this->_M_impl._M_end_of_storage) + __builtin_unreachable(); + + size_t __sz = this->_M_impl._M_finish - this->_M_impl._M_start; + size_t __cap = this->_M_impl._M_end_of_storage - this->_M_impl._M_start; + if (__sz > __cap) + __builtin_unreachable(); +#endif + } + _GLIBCXX20_CONSTEXPR void _M_create_storage(size_t __n) @@ -987,7 +1005,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR size_type size() const _GLIBCXX_NOEXCEPT - { return size_type(this->_M_impl._M_finish - this->_M_impl._M_start); } + { + _Base::_M_invariant(); + return size_type(this->_M_impl._M_finish - this->_M_impl._M_start); + } /** Returns the size() of the largest possible %vector. */ _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR shows that people may do such things. Here _M_invariant is empty, but Jonathan clearly assumed that we will always inline it to every size() invokation and then FRE multiple loads from _M_finish, M_start and friends and then after inlining use this to derive useful value ranges for live code... We may declare this as impossible, but I wonder what are the options :) Also ipa-modref can detect the parameter as effectively unused...