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...