Hi

    I abandon the idea of providing Debug algos, it would be too much code to add and maintain. However I haven't quit on reducing Debug mode performance impact.

    So this patch make use of the existing std::__niter_base to get rid of the debug layer around __gnu_debug::vector<>::iterator so that __builtin_memmove replacement can take place.

    As _Safe_iterator<> do not have a constructor taking a pointer I change algos implementation so that we do not try to instantiate the iterator type ourselves but rather rely on its operators + or -.

    The small drawback is that for std::equal algo where we can't use the __glibcxx_can_increment we need to keep the debug layer to make sure we don't reach past-the-end iterator. So I had to remove usage of __niter_base when in Debug mode, doing so it also disable potential usage of __builtin_memcmp when calling std::equal on std::__cxx1998::vector<> iterators. A rather rare situation I think.

    Note that I don't know how to test that __builtin_memmove has been indeed used. So I've been through some debug sessions to check that.

    I am not really happy with ChangeLog entry I came up with, I'll try to improve it before this patch is validated.


    * include/bits/stl_algobase.h
    (__copy_move<_IsMove, _IsSimple, random_access_iterator_tag>
    ::__copy_impl): New.
    (__copy_move<_IsMove, _IsSimple, random_access_iterator_tag>
    ::__copy_m): Use latter.
    (__copy_move<_IsMove, true, random_access_iterator_tag>::__copy_m):
    Add __base_res parameter.
    (__copy_move<_IsMove, true, random_access_iterator_tag>::__copy_m): Add
    __res_base parameter and use it to call __builtin_memmove.
    (__copy_move_a): Adapt.
    (__copy_move_a2): Adapt.
    (__copy_move_backward<_IsMove, _IsSimple, random_access_iterator_tag>
    ::__copy_b_impl): New.
    (__copy_move_backward<_IsMove, _IsSimple, random_access_iterator_tag>
    ::__copy_move_b): Use latter.
    (__copy_move_backward<_IsMove, true, random_access_iterator_tag>
    ::__copy_move_b): Add __res_base parameter and use it to call
    __builtin_memmove.
    (__copy_move_backward_a): Adapt.
    (__copy_move_backward_a2): Adapt.
    (__fill_n_a): Add _OI template parameter.
    (std::equal<>(_II1, _II1, _II2)): Remove usage of __niter_base on
    __first2 in _GLIBCXX_DEBUG mode.
    * include/debug/stl_iterator.h
    (std::__niter_base(const __gnu_cxx::_Safe_iterator<
    __gnu_cxx::__normal_iterator<>, _Sequence>&)): New declaration.
    * include/debug/vector (__niter_base(const __gnu_cxx::_Safe_iterator<
    __gnu_cxx::__normal_iterator<>, _Sequence>&)): New.

Tested under x86_64 linux.

Ok to commit ?

François

diff --git a/libstdc++-v3/include/bits/stl_algobase.h b/libstdc++-v3/include/bits/stl_algobase.h
index d429943..100676b 100644
--- a/libstdc++-v3/include/bits/stl_algobase.h
+++ b/libstdc++-v3/include/bits/stl_algobase.h
@@ -286,9 +286,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template<bool, bool, typename>
     struct __copy_move
     {
-      template<typename _II, typename _OI>
+      template<typename _II, typename _OI, typename _OIBase>
 	static _OI
-	__copy_m(_II __first, _II __last, _OI __result)
+	__copy_m(_II __first, _II __last, _OI __result, _OIBase)
 	{
 	  for (; __first != __last; ++__result, (void)++__first)
 	    *__result = *__first;
@@ -300,9 +300,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template<typename _Category>
     struct __copy_move<true, false, _Category>
     {
-      template<typename _II, typename _OI>
+      template<typename _II, typename _OI, typename _OIBase>
 	static _OI
-	__copy_m(_II __first, _II __last, _OI __result)
+	__copy_m(_II __first, _II __last, _OI __result, _OIBase)
 	{
 	  for (; __first != __last; ++__result, (void)++__first)
 	    *__result = std::move(*__first);
@@ -314,9 +314,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template<>
     struct __copy_move<false, false, random_access_iterator_tag>
     {
+    private:
       template<typename _II, typename _OI>
 	static _OI
-	__copy_m(_II __first, _II __last, _OI __result)
+	__copy_impl(_II __first, _II __last, _OI __result)
 	{
 	  typedef typename iterator_traits<_II>::difference_type _Distance;
 	  for (_Distance __n = __last - __first; __n > 0; --__n)
@@ -327,15 +328,30 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	    }
 	  return __result;
 	}
+
+    public:
+      template<typename _II, typename _OI>
+	static _OI
+	__copy_m(_II __first, _II __last, _OI __result, _OI)
+	{ return __copy_impl(__first, __last, __result); }
+
+      template<typename _II, typename _OI, typename _OIBase>
+	static _OI
+	__copy_m(_II __first, _II __last, _OI __result, _OIBase __res_base)
+	{
+	  _OIBase __end = __copy_impl(__first, __last, __res_base);
+	  return __result + (__end - __res_base);
+	}
     };
 
 #if __cplusplus >= 201103L
   template<>
     struct __copy_move<true, false, random_access_iterator_tag>
     {
+    private:
       template<typename _II, typename _OI>
 	static _OI
-	__copy_m(_II __first, _II __last, _OI __result)
+	__copy_impl(_II __first, _II __last, _OI __result)
 	{
 	  typedef typename iterator_traits<_II>::difference_type _Distance;
 	  for (_Distance __n = __last - __first; __n > 0; --__n)
@@ -346,15 +362,30 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	    }
 	  return __result;
 	}
+
+    public:
+      template<typename _II, typename _OI>
+	static _OI
+	__copy_m(_II __first, _II __last, _OI __result, _OI)
+	{ return __copy_impl(__first, __last, __result); }
+
+      template<typename _II, typename _OI, typename _OIBase>
+	static _OI
+	__copy_m(_II __first, _II __last, _OI __result, _OIBase __res_base)
+	{
+	  _OIBase __end = __copy_impl(__first, __last, __res_base);
+	  return __result + (__end - __res_base);
+	}
     };
 #endif
 
   template<bool _IsMove>
     struct __copy_move<_IsMove, true, random_access_iterator_tag>
     {
-      template<typename _Tp>
-	static _Tp*
-	__copy_m(const _Tp* __first, const _Tp* __last, _Tp* __result)
+      template<typename _Tp, typename _OI>
+	static _OI
+        __copy_m(const _Tp* __first, const _Tp* __last, _OI __result,
+		 _Tp* __res_base)
 	{
 #if __cplusplus >= 201103L
 	  using __assignable = conditional<_IsMove,
@@ -365,25 +396,25 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 #endif
 	  const ptrdiff_t _Num = __last - __first;
 	  if (_Num)
-	    __builtin_memmove(__result, __first, sizeof(_Tp) * _Num);
+	    __builtin_memmove(__res_base, __first, sizeof(_Tp) * _Num);
 	  return __result + _Num;
 	}
     };
 
-  template<bool _IsMove, typename _II, typename _OI>
+  template<bool _IsMove, typename _II, typename _OI, typename _OIBase>
     inline _OI
-    __copy_move_a(_II __first, _II __last, _OI __result)
+    __copy_move_a(_II __first, _II __last, _OI __result, _OIBase __res_base)
     {
       typedef typename iterator_traits<_II>::value_type _ValueTypeI;
-      typedef typename iterator_traits<_OI>::value_type _ValueTypeO;
+      typedef typename iterator_traits<_OIBase>::value_type _ValueTypeO;
       typedef typename iterator_traits<_II>::iterator_category _Category;
       const bool __simple = (__is_trivial(_ValueTypeI)
 			     && __is_pointer<_II>::__value
-			     && __is_pointer<_OI>::__value
+			     && __is_pointer<_OIBase>::__value
 			     && __are_same<_ValueTypeI, _ValueTypeO>::__value);
 
-      return std::__copy_move<_IsMove, __simple,
-			      _Category>::__copy_m(__first, __last, __result);
+      return std::__copy_move<_IsMove, __simple, _Category>
+	::__copy_m(__first, __last, __result, __res_base);
     }
 
   // Helpers for streambuf iterators (either istream or ostream).
@@ -419,9 +450,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     inline _OI
     __copy_move_a2(_II __first, _II __last, _OI __result)
     {
-      return _OI(std::__copy_move_a<_IsMove>(std::__niter_base(__first),
+      return std::__copy_move_a<_IsMove>(std::__niter_base(__first),
 					 std::__niter_base(__last),
-					     std::__niter_base(__result)));
+					 __result,
+					 std::__niter_base(__result));
     }
 
   /**
@@ -495,9 +527,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template<bool, bool, typename>
     struct __copy_move_backward
     {
-      template<typename _BI1, typename _BI2>
+      template<typename _BI1, typename _BI2, typename _BI2Base>
 	static _BI2
-	__copy_move_b(_BI1 __first, _BI1 __last, _BI2 __result)
+	__copy_move_b(_BI1 __first, _BI1 __last, _BI2 __result, _BI2Base)
 	{
 	  while (__first != __last)
 	    *--__result = *--__last;
@@ -509,9 +541,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template<typename _Category>
     struct __copy_move_backward<true, false, _Category>
     {
-      template<typename _BI1, typename _BI2>
+      template<typename _BI1, typename _BI2, typename _BI2Base>
 	static _BI2
-	__copy_move_b(_BI1 __first, _BI1 __last, _BI2 __result)
+	__copy_move_b(_BI1 __first, _BI1 __last, _BI2 __result, _BI2Base)
 	{
 	  while (__first != __last)
 	    *--__result = std::move(*--__last);
@@ -523,39 +555,72 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template<>
     struct __copy_move_backward<false, false, random_access_iterator_tag>
     {
+    private:
       template<typename _BI1, typename _BI2>
 	static _BI2
-	__copy_move_b(_BI1 __first, _BI1 __last, _BI2 __result)
+	__copy_b_impl(_BI1 __first, _BI1 __last, _BI2 __result)
 	{
 	  typename iterator_traits<_BI1>::difference_type __n;
 	  for (__n = __last - __first; __n > 0; --__n)
 	    *--__result = *--__last;
 	  return __result;
 	}
+
+    public:
+      template<typename _BI1, typename _BI2>
+	static _BI2
+	__copy_move_b(_BI1 __first, _BI1 __last, _BI2 __result, _BI2)
+	{ return __copy_b_impl(__first, __last, __result); }
+
+      template<typename _BI1, typename _BI2, typename _BI2Base>
+	static _BI2
+	__copy_move_b(_BI1 __first, _BI1 __last, _BI2 __result,
+		      _BI2Base __res_base)
+	{
+	  _BI2Base __rend = __copy_b_impl(__first, __last, __res_base);
+	  return __result + (__rend - __res_base);
+	}
     };
 
 #if __cplusplus >= 201103L
   template<>
     struct __copy_move_backward<true, false, random_access_iterator_tag>
     {
+    private:
       template<typename _BI1, typename _BI2>
 	static _BI2
-	__copy_move_b(_BI1 __first, _BI1 __last, _BI2 __result)
+	__copy_b_impl(_BI1 __first, _BI1 __last, _BI2 __result)
 	{
 	  typename iterator_traits<_BI1>::difference_type __n;
 	  for (__n = __last - __first; __n > 0; --__n)
 	    *--__result = std::move(*--__last);
 	  return __result;
 	}
+
+    public:
+      template<typename _BI1, typename _BI2>
+	static _BI2
+	__copy_move_b(_BI1 __first, _BI1 __last, _BI2 __result, _BI2)
+	{ return __copy_b_impl(__first, __last, __result); }
+
+      template<typename _BI1, typename _BI2, typename _BI2Base>
+	static _BI2
+	__copy_move_b(_BI1 __first, _BI1 __last, _BI2 __result,
+		      _BI2Base __res_base)
+	{
+	  _BI2Base __rend = __copy_b_impl(__first, __last, __res_base);
+	  return __result + (__rend - __res_base);
+	}
     };
 #endif
 
   template<bool _IsMove>
     struct __copy_move_backward<_IsMove, true, random_access_iterator_tag>
     {
-      template<typename _Tp>
-	static _Tp*
-	__copy_move_b(const _Tp* __first, const _Tp* __last, _Tp* __result)
+      template<typename _Tp, typename _BI2>
+	static _BI2
+	__copy_move_b(const _Tp* __first, const _Tp* __last, _BI2 __result,
+		      _Tp* __res_base)
 	{
 #if __cplusplus >= 201103L
 	  using __assignable = conditional<_IsMove,
@@ -566,36 +631,35 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 #endif
 	  const ptrdiff_t _Num = __last - __first;
 	  if (_Num)
-	    __builtin_memmove(__result - _Num, __first, sizeof(_Tp) * _Num);
+	    __builtin_memmove(__res_base - _Num, __first, sizeof(_Tp) * _Num);
 	  return __result - _Num;
 	}
     };
 
-  template<bool _IsMove, typename _BI1, typename _BI2>
+  template<bool _IsMove, typename _BI1, typename _BI2, typename _BI2Base>
     inline _BI2
-    __copy_move_backward_a(_BI1 __first, _BI1 __last, _BI2 __result)
+    __copy_move_backward_a(_BI1 __first, _BI1 __last, _BI2 __result,
+			   _BI2Base __res_base)
     {
       typedef typename iterator_traits<_BI1>::value_type _ValueType1;
-      typedef typename iterator_traits<_BI2>::value_type _ValueType2;
+      typedef typename iterator_traits<_BI2Base>::value_type _ValueType2;
       typedef typename iterator_traits<_BI1>::iterator_category _Category;
       const bool __simple = (__is_trivial(_ValueType1)
 			     && __is_pointer<_BI1>::__value
-			     && __is_pointer<_BI2>::__value
+			     && __is_pointer<_BI2Base>::__value
 			     && __are_same<_ValueType1, _ValueType2>::__value);
 
-      return std::__copy_move_backward<_IsMove, __simple,
-				       _Category>::__copy_move_b(__first,
-								 __last,
-								 __result);
+      return std::__copy_move_backward<_IsMove, __simple, _Category>
+	::__copy_move_b(__first, __last, __result, __res_base);
     }
 
   template<bool _IsMove, typename _BI1, typename _BI2>
     inline _BI2
     __copy_move_backward_a2(_BI1 __first, _BI1 __last, _BI2 __result)
     {
-      return _BI2(std::__copy_move_backward_a<_IsMove>
+      return std::__copy_move_backward_a<_IsMove>
 	      (std::__niter_base(__first), std::__niter_base(__last),
-		   std::__niter_base(__result)));
+	       __result, std::__niter_base(__result));
     }
 
   /**
@@ -749,10 +813,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 		    __value);
     }
 
-  template<typename _OutputIterator, typename _Size, typename _Tp>
+  template<typename _OutputIterator, typename _OI, typename _Size, typename _Tp>
     inline typename
     __gnu_cxx::__enable_if<!__is_scalar<_Tp>::__value, _OutputIterator>::__type
-    __fill_n_a(_OutputIterator __first, _Size __n, const _Tp& __value)
+    __fill_n_a(_OutputIterator __first, _Size __n, const _Tp& __value, _OI)
     {
       for (__decltype(__n + 0) __niter = __n;
 	   __niter > 0; --__niter, (void) ++__first)
@@ -760,10 +824,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       return __first;
     }
 
-  template<typename _OutputIterator, typename _Size, typename _Tp>
+  template<typename _OutputIterator, typename _OI, typename _Size, typename _Tp>
     inline typename
     __gnu_cxx::__enable_if<__is_scalar<_Tp>::__value, _OutputIterator>::__type
-    __fill_n_a(_OutputIterator __first, _Size __n, const _Tp& __value)
+    __fill_n_a(_OutputIterator __first, _Size __n, const _Tp& __value, _OI)
     {
       const _Tp __tmp = __value;
       for (__decltype(__n + 0) __niter = __n;
@@ -772,12 +836,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       return __first;
     }
 
-  template<typename _Size, typename _Tp>
+  template<typename _OutputIterator, typename _Size, typename _Tp>
     inline typename
-    __gnu_cxx::__enable_if<__is_byte<_Tp>::__value, _Tp*>::__type
-    __fill_n_a(_Tp* __first, _Size __n, const _Tp& __c)
+    __gnu_cxx::__enable_if<__is_byte<_Tp>::__value, _OutputIterator>::__type
+    __fill_n_a(_OutputIterator __first, _Size __n, const _Tp& __c, _Tp* __res)
     {
-      std::__fill_a(__first, __first + __n, __c);
+      std::__fill_a(__res, __res + __n, __c);
       return __first + __n;
     }
 
@@ -804,7 +868,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       __glibcxx_function_requires(_OutputIteratorConcept<_OI, _Tp>)
       __glibcxx_requires_can_increment(__first, __n);
 
-      return _OI(std::__fill_n_a(std::__niter_base(__first), __n, __value));
+      return std::__fill_n_a(__first, __n, __value, std::__niter_base(__first));
     }
 
   template<bool _BoolType>
@@ -1066,7 +1130,11 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
 
       return std::__equal_aux(std::__niter_base(__first1),
 			      std::__niter_base(__last1),
+#if _GLIBCXX_DEBUG
+			      __first2);
+#else
 			      std::__niter_base(__first2));
+#endif
     }
 
   /**
diff --git a/libstdc++-v3/include/debug/stl_iterator.h b/libstdc++-v3/include/debug/stl_iterator.h
index a6a2a76..eca7203 100644
--- a/libstdc++-v3/include/debug/stl_iterator.h
+++ b/libstdc++-v3/include/debug/stl_iterator.h
@@ -120,4 +120,19 @@ namespace __gnu_debug
 #endif
 }
 
+#if __cplusplus >= 201103L
+namespace std
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+template<typename _Iterator, typename _Container, typename _Sequence>
+    _Iterator
+    __niter_base(const __gnu_debug::_Safe_iterator<
+		 __gnu_cxx::__normal_iterator<_Iterator, _Container>,
+		 _Sequence>&);
+
+_GLIBCXX_END_NAMESPACE_VERSION
+}
+#endif
+
 #endif
diff --git a/libstdc++-v3/include/debug/vector b/libstdc++-v3/include/debug/vector
index 8d60da3..40a991f 100644
--- a/libstdc++-v3/include/debug/vector
+++ b/libstdc++-v3/include/debug/vector
@@ -783,6 +783,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       { return std::hash<_GLIBCXX_STD_C::vector<bool, _Alloc>>()(__b); }
     };
 
+ template<typename _Iterator, typename _Container, typename _Sequence>
+    _Iterator
+    __niter_base(const __gnu_debug::_Safe_iterator<
+		 __gnu_cxx::__normal_iterator<_Iterator, _Container>,
+		 _Sequence>& __it)
+    { return std::__niter_base(__it.base()); }
+
 _GLIBCXX_END_NAMESPACE_VERSION
 #endif
 

Reply via email to