To help along cases where begin and end are passed on to another function
and then uses std::distance on them. In the case of the testcases added,
std::lexicographical_compare_three_way (for C++20). We now able to opimize
`vector < known empty vector` to a constant where before we would need to load
begin() and end() and do a comparison of them.

Note for C++20+ at -O1 we still don't optimize it to a constant but that is
due to not doing copy propagation for aggregates.

v2 change: Use __OPTIMIZE__ as requested.

Bootstrapped and tested on x86_64-linux-gnu.

        PR libstdc++/111499

libstdc++-v3/ChangeLog:

        * include/bits/stl_vector.h (vector::begin(), vector::end(),
        vector::cbegin(), vector::cend()):  Add __builtin_unreachable call to
        announce that _M_finish is greater than or equal to _M_start.

gcc/testsuite/ChangeLog:

        * g++.dg/tree-ssa/pr111499-1.C: New test.
        * g++.dg/tree-ssa/pr111499.C: New test.

Signed-off-by: Andrew Pinski <quic_apin...@quicinc.com>
---
 gcc/testsuite/g++.dg/tree-ssa/pr111499-1.C | 16 ++++++++
 gcc/testsuite/g++.dg/tree-ssa/pr111499.C   | 15 +++++++
 libstdc++-v3/include/bits/stl_vector.h     | 48 +++++++++++++++++++---
 3 files changed, 73 insertions(+), 6 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/tree-ssa/pr111499-1.C
 create mode 100644 gcc/testsuite/g++.dg/tree-ssa/pr111499.C

diff --git a/gcc/testsuite/g++.dg/tree-ssa/pr111499-1.C 
b/gcc/testsuite/g++.dg/tree-ssa/pr111499-1.C
new file mode 100644
index 00000000000..737f6673301
--- /dev/null
+++ b/gcc/testsuite/g++.dg/tree-ssa/pr111499-1.C
@@ -0,0 +1,16 @@
+// { dg-do compile }
+// { dg-options "-O1 -fdump-tree-optimized -Wextra -Wall" }
+#include <vector>
+
+bool f(const std::vector<unsigned char> &v)
+{
+  std::vector<unsigned char> w;
+  return v < w;
+}
+// This should compile to empty function; check that no size of
+// vector is determined and there is no allocation
+// For C++20+, at -O1 there is a missed optimization dealing with copy 
propagation for aggregates
+// { dg-final { scan-tree-dump-not "_M_start" "optimized" { xfail c++20 } } }
+// { dg-final { scan-tree-dump-not "delete" "optimized" } }
+// { dg-final { scan-tree-dump-not " = MEM" "optimized" } }
+// { dg-final { scan-tree-dump "return 0" "optimized" { xfail c++20 } } }
diff --git a/gcc/testsuite/g++.dg/tree-ssa/pr111499.C 
b/gcc/testsuite/g++.dg/tree-ssa/pr111499.C
new file mode 100644
index 00000000000..faa38299d4d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/tree-ssa/pr111499.C
@@ -0,0 +1,15 @@
+// { dg-do compile }
+// { dg-options "-O2 -fdump-tree-optimized -Wextra -Wall" }
+#include <vector>
+
+bool f(const std::vector<unsigned char> &v)
+{
+  std::vector<unsigned char> w;
+  return v < w;
+}
+// This should compile to empty function; check that no size of
+// vector is determined and there is no allocation
+// { dg-final { scan-tree-dump-not "_M_start" "optimized" } }
+// { dg-final { scan-tree-dump-not "delete" "optimized" } }
+// { dg-final { scan-tree-dump-not " = MEM" "optimized" } }
+// { dg-final { scan-tree-dump "return 0" "optimized" } }
diff --git a/libstdc++-v3/include/bits/stl_vector.h 
b/libstdc++-v3/include/bits/stl_vector.h
index 458adc987da..a4b1d1bda79 100644
--- a/libstdc++-v3/include/bits/stl_vector.h
+++ b/libstdc++-v3/include/bits/stl_vector.h
@@ -996,7 +996,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
       _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
       iterator
       begin() _GLIBCXX_NOEXCEPT
-      { return iterator(this->_M_impl._M_start); }
+      {
+#ifdef __OPTIMIZE__
+       if (this->_M_impl._M_start > this->_M_impl._M_finish)
+         __builtin_unreachable();
+#endif
+       return iterator(this->_M_impl._M_start);
+      }
 
       /**
        *  Returns a read-only (constant) iterator that points to the
@@ -1006,7 +1012,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
       _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
       const_iterator
       begin() const _GLIBCXX_NOEXCEPT
-      { return const_iterator(this->_M_impl._M_start); }
+      {
+#ifdef __OPTIMIZE__
+       if (this->_M_impl._M_start > this->_M_impl._M_finish)
+         __builtin_unreachable();
+#endif
+       return const_iterator(this->_M_impl._M_start);
+      }
 
       /**
        *  Returns a read/write iterator that points one past the last
@@ -1016,7 +1028,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
       _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
       iterator
       end() _GLIBCXX_NOEXCEPT
-      { return iterator(this->_M_impl._M_finish); }
+      {
+#ifdef __OPTIMIZE__
+       if (this->_M_impl._M_start > this->_M_impl._M_finish)
+         __builtin_unreachable();
+#endif
+       return iterator(this->_M_impl._M_finish);
+      }
 
       /**
        *  Returns a read-only (constant) iterator that points one past
@@ -1026,7 +1044,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
       _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
       const_iterator
       end() const _GLIBCXX_NOEXCEPT
-      { return const_iterator(this->_M_impl._M_finish); }
+      {
+#ifdef __OPTIMIZE__
+       if (this->_M_impl._M_start > this->_M_impl._M_finish)
+         __builtin_unreachable();
+#endif
+       return const_iterator(this->_M_impl._M_finish);
+      }
 
       /**
        *  Returns a read/write reverse iterator that points to the
@@ -1077,7 +1101,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
       [[__nodiscard__]] _GLIBCXX20_CONSTEXPR
       const_iterator
       cbegin() const noexcept
-      { return const_iterator(this->_M_impl._M_start); }
+      {
+#ifdef __OPTIMIZE__
+       if (this->_M_impl._M_start > this->_M_impl._M_finish)
+         __builtin_unreachable();
+#endif
+       return const_iterator(this->_M_impl._M_start);
+      }
 
       /**
        *  Returns a read-only (constant) iterator that points one past
@@ -1087,7 +1117,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
       [[__nodiscard__]] _GLIBCXX20_CONSTEXPR
       const_iterator
       cend() const noexcept
-      { return const_iterator(this->_M_impl._M_finish); }
+      {
+#ifdef __OPTIMIZE__
+       if (this->_M_impl._M_start > this->_M_impl._M_finish)
+         __builtin_unreachable();
+#endif
+       return const_iterator(this->_M_impl._M_finish);
+      }
 
       /**
        *  Returns a read-only (constant) reverse iterator that points
-- 
2.43.0

Reply via email to