[1/3] libstdc++: Fold some ranges algo subroutines into their only caller
diff mbox series

Message ID 20200214153547.2390767-1-ppalka@redhat.com
State New
Headers show
Series
  • [1/3] libstdc++: Fold some ranges algo subroutines into their only caller
Related show

Commit Message

Patrick Palka Feb. 14, 2020, 3:35 p.m. UTC
These subroutines have only a single call site, so it might be best and simplest
to eliminate them before we convert the algos into function objects.

libstdc++-v3/ChangeLog:

	* include/bits/ranges_algo.h (ranges::__find_end): Fold into ...
	(ranges::find_end): ... here.
	(ranges::__lexicographical_compare): Fold into ...
	(ranges::lexicographical_compare): ... here.
	* include/bits/ranges_algobase.h (ranges::__equal): Fold into ...
	(ranges::equal): ... here.
---
 libstdc++-v3/include/bits/ranges_algo.h     | 104 ++++++++------------
 libstdc++-v3/include/bits/ranges_algobase.h |  33 +++----
 2 files changed, 55 insertions(+), 82 deletions(-)

Comments

Jonathan Wakely Feb. 15, 2020, 1:47 a.m. UTC | #1
On 14/02/20 10:35 -0500, Patrick Palka wrote:
>These subroutines have only a single call site, so it might be best and simplest
>to eliminate them before we convert the algos into function objects.
>
>libstdc++-v3/ChangeLog:
>
>	* include/bits/ranges_algo.h (ranges::__find_end): Fold into ...
>	(ranges::find_end): ... here.
>	(ranges::__lexicographical_compare): Fold into ...
>	(ranges::lexicographical_compare): ... here.
>	* include/bits/ranges_algobase.h (ranges::__equal): Fold into ...
>	(ranges::equal): ... here.

OK for master, but please note the two comments below.


> libstdc++-v3/include/bits/ranges_algo.h     | 104 ++++++++------------
> libstdc++-v3/include/bits/ranges_algobase.h |  33 +++----
> 2 files changed, 55 insertions(+), 82 deletions(-)
>
>diff --git a/libstdc++-v3/include/bits/ranges_algo.h b/libstdc++-v3/include/bits/ranges_algo.h
>index 84a02cabb80..6b6f4defdf5 100644
>--- a/libstdc++-v3/include/bits/ranges_algo.h
>+++ b/libstdc++-v3/include/bits/ranges_algo.h
>@@ -513,40 +513,7 @@ namespace ranges
> 			      std::move(__pred), std::move(__proj));
>     }
>
>-  template<forward_iterator _Iter1, sentinel_for<_Iter1> _Sent1,
>-	   forward_iterator _Iter2, sentinel_for<_Iter2> _Sent2,
>-	   typename _Pred = ranges::equal_to,
>-	   typename _Proj1 = identity, typename _Proj2 = identity>
>-    requires indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2>
>-    constexpr subrange<_Iter1>
>-    __find_end(_Iter1 __first1, _Sent1 __last1,
>-	       _Iter2 __first2, _Sent2 __last2,
>-	       _Pred __pred, _Proj1 __proj1, _Proj2 __proj2)
>-    {
>-      auto __i = ranges::next(__first1, __last1);
>-      if (__first2 == __last2)
>-	return {__i, __i};
>
>-      auto __result_begin = __i;
>-      auto __result_end = __i;
>-      for (;;)
>-	{
>-	  auto __new_range = ranges::search(__first1, __last1,
>-					    __first2, __last2,
>-					    __pred, __proj1, __proj2);
>-	  auto __new_result_begin = ranges::begin(__new_range);
>-	  auto __new_result_end = ranges::end(__new_range);
>-	  if (__new_result_begin == __last1)
>-	    return {__result_begin, __result_end};
>-	  else
>-	    {
>-	      __result_begin = __new_result_begin;
>-	      __result_end = __new_result_end;
>-	      __first1 = __result_begin;
>-	      ++__first1;
>-	    }
>-	}
>-    }
>
>   template<forward_iterator _Iter1, sentinel_for<_Iter1> _Sent1,
> 	   forward_iterator _Iter2, sentinel_for<_Iter2> _Sent2,
>@@ -578,9 +545,31 @@ namespace ranges
> 	    return {__result_first, __result_last};
> 	}
>       else
>-	return ranges::__find_end(__first1, __last1, __first2, __last2,
>-				  std::move(__pred),
>-				  std::move(__proj1), std::move(__proj2));
>+	{
>+	  auto __i = ranges::next(__first1, __last1);
>+	  if (__first2 == __last2)
>+	    return {__i, __i};
>+
>+	  auto __result_begin = __i;
>+	  auto __result_end = __i;
>+	  for (;;)
>+	    {
>+	      auto __new_range = ranges::search(__first1, __last1,
>+						__first2, __last2,
>+						__pred, __proj1, __proj2);
>+	      auto __new_result_begin = ranges::begin(__new_range);
>+	      auto __new_result_end = ranges::end(__new_range);
>+	      if (__new_result_begin == __last1)
>+		return {__result_begin, __result_end};
>+	      else
>+		{
>+		  __result_begin = __new_result_begin;
>+		  __result_end = __new_result_end;
>+		  __first1 = __result_begin;
>+		  ++__first1;
>+		}
>+	    }
>+	}
>     }
>
>   template<forward_range _Range1, forward_range _Range2,
>@@ -2908,14 +2897,26 @@ namespace ranges
>
>   template<input_iterator _Iter1, sentinel_for<_Iter1> _Sent1,
> 	   input_iterator _Iter2, sentinel_for<_Iter2> _Sent2,
>-	   typename _Proj1, typename _Proj2,
>+	   typename _Proj1 = identity, typename _Proj2 = identity,
> 	   indirect_strict_weak_order<projected<_Iter1, _Proj1>,
>-				      projected<_Iter2, _Proj2>> _Comp>
>+				      projected<_Iter2, _Proj2>>
>+	     _Comp = ranges::less>
>     constexpr bool
>-    __lexicographical_compare(_Iter1 __first1, _Sent1 __last1,
>-			      _Iter2 __first2, _Sent2 __last2,
>-			      _Comp __comp, _Proj1 __proj1, _Proj2 __proj2)
>+    lexicographical_compare(_Iter1 __first1, _Sent1 __last1,
>+			    _Iter2 __first2, _Sent2 __last2,
>+			    _Comp __comp = {},
>+			    _Proj1 __proj1 = {}, _Proj2 __proj2 = {})
>     {
>+      if constexpr (__detail::__is_normal_iterator<_Iter1>
>+		    || __detail::__is_normal_iterator<_Iter2>)
>+	return ranges::lexicographical_compare
>+		 (std::__niter_base(std::move(__first1)),
>+		  std::__niter_base(std::move(__last1)),
>+		  std::__niter_base(std::move(__first2)),
>+		  std::__niter_base(std::move(__last2)),
>+		  std::move(__comp),
>+		  std::move(__proj1), std::move(__proj2));
>+

I think we want "else {" here, so the lines following are not
instantiated when we unpack normal iterators.

That can be done in a separate patch later though.

>       constexpr bool __sized_iters
> 	= (sized_sentinel_for<_Sent1, _Iter1>
> 	   && sized_sentinel_for<_Sent2, _Iter2>);
>@@ -2976,27 +2977,6 @@ namespace ranges
>       return __first1 == __last1 && __first2 != __last2;
>     }
>
>-  template<input_iterator _Iter1, sentinel_for<_Iter1> _Sent1,
>-	   input_iterator _Iter2, sentinel_for<_Iter2> _Sent2,
>-	   typename _Proj1 = identity, typename _Proj2 = identity,
>-	   indirect_strict_weak_order<projected<_Iter1, _Proj1>,
>-				      projected<_Iter2, _Proj2>>
>-	     _Comp = ranges::less>
>-    constexpr bool
>-    lexicographical_compare(_Iter1 __first1, _Sent1 __last1,
>-			    _Iter2 __first2, _Sent2 __last2,
>-			    _Comp __comp = {},
>-			    _Proj1 __proj1 = {}, _Proj2 __proj2 = {})
>-    {
>-      return (ranges::__lexicographical_compare
>-	      (std::__niter_base(std::move(__first1)),
>-	       std::__niter_base(std::move(__last1)),
>-	       std::__niter_base(std::move(__first2)),
>-	       std::__niter_base(std::move(__last2)),
>-	       std::move(__comp),
>-	       std::move(__proj1), std::move(__proj2)));
>-    }
>-
>   template<input_range _Range1, input_range _Range2, typename _Proj1 = identity,
> 	   typename _Proj2 = identity,
> 	   indirect_strict_weak_order<projected<iterator_t<_Range1>, _Proj1>,
>diff --git a/libstdc++-v3/include/bits/ranges_algobase.h b/libstdc++-v3/include/bits/ranges_algobase.h
>index f63c032cf0b..813a5096ae0 100644
>--- a/libstdc++-v3/include/bits/ranges_algobase.h
>+++ b/libstdc++-v3/include/bits/ranges_algobase.h
>@@ -73,14 +73,24 @@ namespace ranges
>
>   template<input_iterator _Iter1, sentinel_for<_Iter1> _Sent1,
> 	   input_iterator _Iter2, sentinel_for<_Iter2> _Sent2,
>-	   typename _Pred, typename _Proj1, typename _Proj2>
>+	   typename _Pred = ranges::equal_to,
>+	   typename _Proj1 = identity, typename _Proj2 = identity>
>     requires indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2>
>     constexpr bool
>-    __equal(_Iter1 __first1, _Sent1 __last1, _Iter2 __first2, _Sent2 __last2,
>-	    _Pred __pred, _Proj1 __proj1, _Proj2 __proj2)
>+    equal(_Iter1 __first1, _Sent1 __last1, _Iter2 __first2, _Sent2 __last2,
>+	  _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {})
>     {
>       // TODO: implement more specializations to at least have parity with
>       // std::equal.
>+      if constexpr (__detail::__is_normal_iterator<_Iter1>
>+		    || __detail::__is_normal_iterator<_Iter2>)
>+	return ranges::equal(std::__niter_base(std::move(__first1)),
>+			     std::__niter_base(std::move(__last1)),
>+			     std::__niter_base(std::move(__first2)),
>+			     std::__niter_base(std::move(__last2)),
>+			     std::move(__pred),
>+			     std::move(__proj1), std::move(__proj2));
>+

Same thing here.

>       constexpr bool __sized_iters
> 	= (sized_sentinel_for<_Sent1, _Iter1>
> 	   && sized_sentinel_for<_Sent2, _Iter2>);
>@@ -129,23 +139,6 @@ namespace ranges
> 	}
>     }
>
>-  template<input_iterator _Iter1, sentinel_for<_Iter1> _Sent1,
>-	   input_iterator _Iter2, sentinel_for<_Iter2> _Sent2,
>-	   typename _Pred = ranges::equal_to,
>-	   typename _Proj1 = identity, typename _Proj2 = identity>
>-    requires indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2>
>-    constexpr bool
>-    equal(_Iter1 __first1, _Sent1 __last1, _Iter2 __first2, _Sent2 __last2,
>-	  _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {})
>-    {
>-      return ranges::__equal(std::__niter_base(std::move(__first1)),
>-			     std::__niter_base(std::move(__last1)),
>-			     std::__niter_base(std::move(__first2)),
>-			     std::__niter_base(std::move(__last2)),
>-			     std::move(__pred),
>-			     std::move(__proj1), std::move(__proj2));
>-    }
>-
>   template<input_range _Range1, input_range _Range2,
> 	   typename _Pred = ranges::equal_to,
> 	   typename _Proj1 = identity, typename _Proj2 = identity>
>-- 
>2.25.0.232.gd8437c57fa
>
Patrick Palka Feb. 15, 2020, 4:20 p.m. UTC | #2
On Sat, 15 Feb 2020, Jonathan Wakely wrote:

> On 14/02/20 10:35 -0500, Patrick Palka wrote:
> > These subroutines have only a single call site, so it might be best and
> > simplest
> > to eliminate them before we convert the algos into function objects.
> > 
> > libstdc++-v3/ChangeLog:
> > 
> > 	* include/bits/ranges_algo.h (ranges::__find_end): Fold into ...
> > 	(ranges::find_end): ... here.
> > 	(ranges::__lexicographical_compare): Fold into ...
> > 	(ranges::lexicographical_compare): ... here.
> > 	* include/bits/ranges_algobase.h (ranges::__equal): Fold into ...
> > 	(ranges::equal): ... here.
> 
> OK for master, but please note the two comments below.
> 
> 
> > libstdc++-v3/include/bits/ranges_algo.h     | 104 ++++++++------------
> > libstdc++-v3/include/bits/ranges_algobase.h |  33 +++----
> > 2 files changed, 55 insertions(+), 82 deletions(-)
> > 
> > diff --git a/libstdc++-v3/include/bits/ranges_algo.h
> > b/libstdc++-v3/include/bits/ranges_algo.h
> > index 84a02cabb80..6b6f4defdf5 100644
> > --- a/libstdc++-v3/include/bits/ranges_algo.h
> > +++ b/libstdc++-v3/include/bits/ranges_algo.h
> > @@ -513,40 +513,7 @@ namespace ranges
> > 			      std::move(__pred), std::move(__proj));
> >     }
> > 
> > -  template<forward_iterator _Iter1, sentinel_for<_Iter1> _Sent1,
> > -	   forward_iterator _Iter2, sentinel_for<_Iter2> _Sent2,
> > -	   typename _Pred = ranges::equal_to,
> > -	   typename _Proj1 = identity, typename _Proj2 = identity>
> > -    requires indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2>
> > -    constexpr subrange<_Iter1>
> > -    __find_end(_Iter1 __first1, _Sent1 __last1,
> > -	       _Iter2 __first2, _Sent2 __last2,
> > -	       _Pred __pred, _Proj1 __proj1, _Proj2 __proj2)
> > -    {
> > -      auto __i = ranges::next(__first1, __last1);
> > -      if (__first2 == __last2)
> > -	return {__i, __i};
> > 
> > -      auto __result_begin = __i;
> > -      auto __result_end = __i;
> > -      for (;;)
> > -	{
> > -	  auto __new_range = ranges::search(__first1, __last1,
> > -					    __first2, __last2,
> > -					    __pred, __proj1, __proj2);
> > -	  auto __new_result_begin = ranges::begin(__new_range);
> > -	  auto __new_result_end = ranges::end(__new_range);
> > -	  if (__new_result_begin == __last1)
> > -	    return {__result_begin, __result_end};
> > -	  else
> > -	    {
> > -	      __result_begin = __new_result_begin;
> > -	      __result_end = __new_result_end;
> > -	      __first1 = __result_begin;
> > -	      ++__first1;
> > -	    }
> > -	}
> > -    }
> > 
> >   template<forward_iterator _Iter1, sentinel_for<_Iter1> _Sent1,
> > 	   forward_iterator _Iter2, sentinel_for<_Iter2> _Sent2,
> > @@ -578,9 +545,31 @@ namespace ranges
> > 	    return {__result_first, __result_last};
> > 	}
> >       else
> > -	return ranges::__find_end(__first1, __last1, __first2, __last2,
> > -				  std::move(__pred),
> > -				  std::move(__proj1), std::move(__proj2));
> > +	{
> > +	  auto __i = ranges::next(__first1, __last1);
> > +	  if (__first2 == __last2)
> > +	    return {__i, __i};
> > +
> > +	  auto __result_begin = __i;
> > +	  auto __result_end = __i;
> > +	  for (;;)
> > +	    {
> > +	      auto __new_range = ranges::search(__first1, __last1,
> > +						__first2, __last2,
> > +						__pred, __proj1, __proj2);
> > +	      auto __new_result_begin = ranges::begin(__new_range);
> > +	      auto __new_result_end = ranges::end(__new_range);
> > +	      if (__new_result_begin == __last1)
> > +		return {__result_begin, __result_end};
> > +	      else
> > +		{
> > +		  __result_begin = __new_result_begin;
> > +		  __result_end = __new_result_end;
> > +		  __first1 = __result_begin;
> > +		  ++__first1;
> > +		}
> > +	    }
> > +	}
> >     }
> > 
> >   template<forward_range _Range1, forward_range _Range2,
> > @@ -2908,14 +2897,26 @@ namespace ranges
> > 
> >   template<input_iterator _Iter1, sentinel_for<_Iter1> _Sent1,
> > 	   input_iterator _Iter2, sentinel_for<_Iter2> _Sent2,
> > -	   typename _Proj1, typename _Proj2,
> > +	   typename _Proj1 = identity, typename _Proj2 = identity,
> > 	   indirect_strict_weak_order<projected<_Iter1, _Proj1>,
> > -				      projected<_Iter2, _Proj2>> _Comp>
> > +				      projected<_Iter2, _Proj2>>
> > +	     _Comp = ranges::less>
> >     constexpr bool
> > -    __lexicographical_compare(_Iter1 __first1, _Sent1 __last1,
> > -			      _Iter2 __first2, _Sent2 __last2,
> > -			      _Comp __comp, _Proj1 __proj1, _Proj2 __proj2)
> > +    lexicographical_compare(_Iter1 __first1, _Sent1 __last1,
> > +			    _Iter2 __first2, _Sent2 __last2,
> > +			    _Comp __comp = {},
> > +			    _Proj1 __proj1 = {}, _Proj2 __proj2 = {})
> >     {
> > +      if constexpr (__detail::__is_normal_iterator<_Iter1>
> > +		    || __detail::__is_normal_iterator<_Iter2>)
> > +	return ranges::lexicographical_compare
> > +		 (std::__niter_base(std::move(__first1)),
> > +		  std::__niter_base(std::move(__last1)),
> > +		  std::__niter_base(std::move(__first2)),
> > +		  std::__niter_base(std::move(__last2)),
> > +		  std::move(__comp),
> > +		  std::move(__proj1), std::move(__proj2));
> > +
> 
> I think we want "else {" here, so the lines following are not
> instantiated when we unpack normal iterators.
> 
> That can be done in a separate patch later though.
> 
> >       constexpr bool __sized_iters
> > 	= (sized_sentinel_for<_Sent1, _Iter1>
> > 	   && sized_sentinel_for<_Sent2, _Iter2>);
> > @@ -2976,27 +2977,6 @@ namespace ranges
> >       return __first1 == __last1 && __first2 != __last2;
> >     }
> > 
> > -  template<input_iterator _Iter1, sentinel_for<_Iter1> _Sent1,
> > -	   input_iterator _Iter2, sentinel_for<_Iter2> _Sent2,
> > -	   typename _Proj1 = identity, typename _Proj2 = identity,
> > -	   indirect_strict_weak_order<projected<_Iter1, _Proj1>,
> > -				      projected<_Iter2, _Proj2>>
> > -	     _Comp = ranges::less>
> > -    constexpr bool
> > -    lexicographical_compare(_Iter1 __first1, _Sent1 __last1,
> > -			    _Iter2 __first2, _Sent2 __last2,
> > -			    _Comp __comp = {},
> > -			    _Proj1 __proj1 = {}, _Proj2 __proj2 = {})
> > -    {
> > -      return (ranges::__lexicographical_compare
> > -	      (std::__niter_base(std::move(__first1)),
> > -	       std::__niter_base(std::move(__last1)),
> > -	       std::__niter_base(std::move(__first2)),
> > -	       std::__niter_base(std::move(__last2)),
> > -	       std::move(__comp),
> > -	       std::move(__proj1), std::move(__proj2)));
> > -    }
> > -
> >   template<input_range _Range1, input_range _Range2, typename _Proj1 =
> > identity,
> > 	   typename _Proj2 = identity,
> > 	   indirect_strict_weak_order<projected<iterator_t<_Range1>, _Proj1>,
> > diff --git a/libstdc++-v3/include/bits/ranges_algobase.h
> > b/libstdc++-v3/include/bits/ranges_algobase.h
> > index f63c032cf0b..813a5096ae0 100644
> > --- a/libstdc++-v3/include/bits/ranges_algobase.h
> > +++ b/libstdc++-v3/include/bits/ranges_algobase.h
> > @@ -73,14 +73,24 @@ namespace ranges
> > 
> >   template<input_iterator _Iter1, sentinel_for<_Iter1> _Sent1,
> > 	   input_iterator _Iter2, sentinel_for<_Iter2> _Sent2,
> > -	   typename _Pred, typename _Proj1, typename _Proj2>
> > +	   typename _Pred = ranges::equal_to,
> > +	   typename _Proj1 = identity, typename _Proj2 = identity>
> >     requires indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2>
> >     constexpr bool
> > -    __equal(_Iter1 __first1, _Sent1 __last1, _Iter2 __first2, _Sent2
> > __last2,
> > -	    _Pred __pred, _Proj1 __proj1, _Proj2 __proj2)
> > +    equal(_Iter1 __first1, _Sent1 __last1, _Iter2 __first2, _Sent2 __last2,
> > +	  _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {})
> >     {
> >       // TODO: implement more specializations to at least have parity with
> >       // std::equal.
> > +      if constexpr (__detail::__is_normal_iterator<_Iter1>
> > +		    || __detail::__is_normal_iterator<_Iter2>)
> > +	return ranges::equal(std::__niter_base(std::move(__first1)),
> > +			     std::__niter_base(std::move(__last1)),
> > +			     std::__niter_base(std::move(__first2)),
> > +			     std::__niter_base(std::move(__last2)),
> > +			     std::move(__pred),
> > +			     std::move(__proj1), std::move(__proj2));
> > +
> 
> Same thing here.

Thanks for the review.  I committed the series, and will post a followup
patch that makes this adjustment.

Patch
diff mbox series

diff --git a/libstdc++-v3/include/bits/ranges_algo.h b/libstdc++-v3/include/bits/ranges_algo.h
index 84a02cabb80..6b6f4defdf5 100644
--- a/libstdc++-v3/include/bits/ranges_algo.h
+++ b/libstdc++-v3/include/bits/ranges_algo.h
@@ -513,40 +513,7 @@  namespace ranges
 			      std::move(__pred), std::move(__proj));
     }
 
-  template<forward_iterator _Iter1, sentinel_for<_Iter1> _Sent1,
-	   forward_iterator _Iter2, sentinel_for<_Iter2> _Sent2,
-	   typename _Pred = ranges::equal_to,
-	   typename _Proj1 = identity, typename _Proj2 = identity>
-    requires indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2>
-    constexpr subrange<_Iter1>
-    __find_end(_Iter1 __first1, _Sent1 __last1,
-	       _Iter2 __first2, _Sent2 __last2,
-	       _Pred __pred, _Proj1 __proj1, _Proj2 __proj2)
-    {
-      auto __i = ranges::next(__first1, __last1);
-      if (__first2 == __last2)
-	return {__i, __i};
 
-      auto __result_begin = __i;
-      auto __result_end = __i;
-      for (;;)
-	{
-	  auto __new_range = ranges::search(__first1, __last1,
-					    __first2, __last2,
-					    __pred, __proj1, __proj2);
-	  auto __new_result_begin = ranges::begin(__new_range);
-	  auto __new_result_end = ranges::end(__new_range);
-	  if (__new_result_begin == __last1)
-	    return {__result_begin, __result_end};
-	  else
-	    {
-	      __result_begin = __new_result_begin;
-	      __result_end = __new_result_end;
-	      __first1 = __result_begin;
-	      ++__first1;
-	    }
-	}
-    }
 
   template<forward_iterator _Iter1, sentinel_for<_Iter1> _Sent1,
 	   forward_iterator _Iter2, sentinel_for<_Iter2> _Sent2,
@@ -578,9 +545,31 @@  namespace ranges
 	    return {__result_first, __result_last};
 	}
       else
-	return ranges::__find_end(__first1, __last1, __first2, __last2,
-				  std::move(__pred),
-				  std::move(__proj1), std::move(__proj2));
+	{
+	  auto __i = ranges::next(__first1, __last1);
+	  if (__first2 == __last2)
+	    return {__i, __i};
+
+	  auto __result_begin = __i;
+	  auto __result_end = __i;
+	  for (;;)
+	    {
+	      auto __new_range = ranges::search(__first1, __last1,
+						__first2, __last2,
+						__pred, __proj1, __proj2);
+	      auto __new_result_begin = ranges::begin(__new_range);
+	      auto __new_result_end = ranges::end(__new_range);
+	      if (__new_result_begin == __last1)
+		return {__result_begin, __result_end};
+	      else
+		{
+		  __result_begin = __new_result_begin;
+		  __result_end = __new_result_end;
+		  __first1 = __result_begin;
+		  ++__first1;
+		}
+	    }
+	}
     }
 
   template<forward_range _Range1, forward_range _Range2,
@@ -2908,14 +2897,26 @@  namespace ranges
 
   template<input_iterator _Iter1, sentinel_for<_Iter1> _Sent1,
 	   input_iterator _Iter2, sentinel_for<_Iter2> _Sent2,
-	   typename _Proj1, typename _Proj2,
+	   typename _Proj1 = identity, typename _Proj2 = identity,
 	   indirect_strict_weak_order<projected<_Iter1, _Proj1>,
-				      projected<_Iter2, _Proj2>> _Comp>
+				      projected<_Iter2, _Proj2>>
+	     _Comp = ranges::less>
     constexpr bool
-    __lexicographical_compare(_Iter1 __first1, _Sent1 __last1,
-			      _Iter2 __first2, _Sent2 __last2,
-			      _Comp __comp, _Proj1 __proj1, _Proj2 __proj2)
+    lexicographical_compare(_Iter1 __first1, _Sent1 __last1,
+			    _Iter2 __first2, _Sent2 __last2,
+			    _Comp __comp = {},
+			    _Proj1 __proj1 = {}, _Proj2 __proj2 = {})
     {
+      if constexpr (__detail::__is_normal_iterator<_Iter1>
+		    || __detail::__is_normal_iterator<_Iter2>)
+	return ranges::lexicographical_compare
+		 (std::__niter_base(std::move(__first1)),
+		  std::__niter_base(std::move(__last1)),
+		  std::__niter_base(std::move(__first2)),
+		  std::__niter_base(std::move(__last2)),
+		  std::move(__comp),
+		  std::move(__proj1), std::move(__proj2));
+
       constexpr bool __sized_iters
 	= (sized_sentinel_for<_Sent1, _Iter1>
 	   && sized_sentinel_for<_Sent2, _Iter2>);
@@ -2976,27 +2977,6 @@  namespace ranges
       return __first1 == __last1 && __first2 != __last2;
     }
 
-  template<input_iterator _Iter1, sentinel_for<_Iter1> _Sent1,
-	   input_iterator _Iter2, sentinel_for<_Iter2> _Sent2,
-	   typename _Proj1 = identity, typename _Proj2 = identity,
-	   indirect_strict_weak_order<projected<_Iter1, _Proj1>,
-				      projected<_Iter2, _Proj2>>
-	     _Comp = ranges::less>
-    constexpr bool
-    lexicographical_compare(_Iter1 __first1, _Sent1 __last1,
-			    _Iter2 __first2, _Sent2 __last2,
-			    _Comp __comp = {},
-			    _Proj1 __proj1 = {}, _Proj2 __proj2 = {})
-    {
-      return (ranges::__lexicographical_compare
-	      (std::__niter_base(std::move(__first1)),
-	       std::__niter_base(std::move(__last1)),
-	       std::__niter_base(std::move(__first2)),
-	       std::__niter_base(std::move(__last2)),
-	       std::move(__comp),
-	       std::move(__proj1), std::move(__proj2)));
-    }
-
   template<input_range _Range1, input_range _Range2, typename _Proj1 = identity,
 	   typename _Proj2 = identity,
 	   indirect_strict_weak_order<projected<iterator_t<_Range1>, _Proj1>,
diff --git a/libstdc++-v3/include/bits/ranges_algobase.h b/libstdc++-v3/include/bits/ranges_algobase.h
index f63c032cf0b..813a5096ae0 100644
--- a/libstdc++-v3/include/bits/ranges_algobase.h
+++ b/libstdc++-v3/include/bits/ranges_algobase.h
@@ -73,14 +73,24 @@  namespace ranges
 
   template<input_iterator _Iter1, sentinel_for<_Iter1> _Sent1,
 	   input_iterator _Iter2, sentinel_for<_Iter2> _Sent2,
-	   typename _Pred, typename _Proj1, typename _Proj2>
+	   typename _Pred = ranges::equal_to,
+	   typename _Proj1 = identity, typename _Proj2 = identity>
     requires indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2>
     constexpr bool
-    __equal(_Iter1 __first1, _Sent1 __last1, _Iter2 __first2, _Sent2 __last2,
-	    _Pred __pred, _Proj1 __proj1, _Proj2 __proj2)
+    equal(_Iter1 __first1, _Sent1 __last1, _Iter2 __first2, _Sent2 __last2,
+	  _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {})
     {
       // TODO: implement more specializations to at least have parity with
       // std::equal.
+      if constexpr (__detail::__is_normal_iterator<_Iter1>
+		    || __detail::__is_normal_iterator<_Iter2>)
+	return ranges::equal(std::__niter_base(std::move(__first1)),
+			     std::__niter_base(std::move(__last1)),
+			     std::__niter_base(std::move(__first2)),
+			     std::__niter_base(std::move(__last2)),
+			     std::move(__pred),
+			     std::move(__proj1), std::move(__proj2));
+
       constexpr bool __sized_iters
 	= (sized_sentinel_for<_Sent1, _Iter1>
 	   && sized_sentinel_for<_Sent2, _Iter2>);
@@ -129,23 +139,6 @@  namespace ranges
 	}
     }
 
-  template<input_iterator _Iter1, sentinel_for<_Iter1> _Sent1,
-	   input_iterator _Iter2, sentinel_for<_Iter2> _Sent2,
-	   typename _Pred = ranges::equal_to,
-	   typename _Proj1 = identity, typename _Proj2 = identity>
-    requires indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2>
-    constexpr bool
-    equal(_Iter1 __first1, _Sent1 __last1, _Iter2 __first2, _Sent2 __last2,
-	  _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {})
-    {
-      return ranges::__equal(std::__niter_base(std::move(__first1)),
-			     std::__niter_base(std::move(__last1)),
-			     std::__niter_base(std::move(__first2)),
-			     std::__niter_base(std::move(__last2)),
-			     std::move(__pred),
-			     std::move(__proj1), std::move(__proj2));
-    }
-
   template<input_range _Range1, input_range _Range2,
 	   typename _Pred = ranges::equal_to,
 	   typename _Proj1 = identity, typename _Proj2 = identity>