public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH] libstdc++: Synchronize PSTL with upstream
@ 2023-04-20  3:39 Thomas Rodgers
  2023-05-17 19:31 ` Jonathan Wakely
  0 siblings, 1 reply; 6+ messages in thread
From: Thomas Rodgers @ 2023-04-20  3:39 UTC (permalink / raw)
  To: libstdc++, gcc Patches


[-- Attachment #1.1: Type: text/plain, Size: 1 bytes --]



[-- Attachment #2: 0001-libstdc-Synchronize-PSTL-with-upstream.patch --]
[-- Type: text/x-patch, Size: 680886 bytes --]

From d8c7e3866668de8432ab1348325cf1b6355b60e4 Mon Sep 17 00:00:00 2001
From: Thomas Rodgers <trodgers@redhat.com>
Date: Mon, 10 Apr 2023 19:34:55 -0700
Subject: [PATCH] libstdc++: Synchronize PSTL with upstream

This patch rebases the C++17 parallel algorithms implementation (pstl)
against the current upstream version, commit 843c12d6a.

This version does not currently include the recently added OpenMP
backend, that will be considered for a future version.

libstdc++-v3/ChangeLog:
	* include/pstl/algorithm_fwd.h: Synchronize with upstream.
	* include/pstl/algorithm_impl.h: Likewise.
	* include/pstl/execution_defs.h: Likewise.
	* include/pstl/execution_impl.h: Likewise.
	* include/pstl/glue_algorithms_impl.h: Likewise.
	* include/pstl/glue_execution_defs.h: Likewise.
	* include/pstl/glue_memory_impl.h: Likewise.
	* include/pstl/glue_numeric_impl.h: Likewise.
	* include/pstl/memory_impl.h: Likewise.
	* include/pstl/numeric_fwd.h: Likewise.
	* include/pstl/numeric_impl.h: Likewise.
	* include/pstl/parallel_backend.h: Likewise.
	* include/pstl/parallel_backend_serial.h: Likewise.
	* include/pstl/parallel_backend_tbb.h: Likewise.
	* include/pstl/parallel_impl.h: Likewise.
	* include/pstl/pstl_config.h: Likewise.
	* include/pstl/unseq_backend_simd.h: Likewise.
	* include/pstl/utils.h: Likewise.
	* testsuite/20_util/specialized_algorithms/pstl/uninitialized_construct.cc:
	Likewise.
	* testsuite/20_util/specialized_algorithms/pstl/uninitialized_copy_move.cc:
	Likewise.
	* testsuite/20_util/specialized_algorithms/pstl/uninitialized_fill_destroy.cc:
	Likewise.
	* testsuite/25_algorithms/pstl/alg_merge/inplace_merge.cc:
	Likewise.
	* testsuite/25_algorithms/pstl/alg_merge/merge.cc: Likewise.
	* testsuite/25_algorithms/pstl/alg_modifying_operations/copy_if.cc:
	Likewise.
	* testsuite/25_algorithms/pstl/alg_modifying_operations/copy_move.cc:
	Likewise.
	* testsuite/25_algorithms/pstl/alg_modifying_operations/fill.cc:
	Likewise.
	* testsuite/25_algorithms/pstl/alg_modifying_operations/generate.cc:
	Likewise.
	* testsuite/25_algorithms/pstl/alg_modifying_operations/is_partitioned.cc:
	Likewise.
	* testsuite/25_algorithms/pstl/alg_modifying_operations/partition.cc:
	Likewise.
	* testsuite/25_algorithms/pstl/alg_modifying_operations/partition_copy.cc:
	Likewise.
	* testsuite/25_algorithms/pstl/alg_modifying_operations/remove.cc:
	Likewise.
	* testsuite/25_algorithms/pstl/alg_modifying_operations/remove_copy.cc:
	Likewise.
	* testsuite/25_algorithms/pstl/alg_modifying_operations/replace.cc:
	Likewise.
	* testsuite/25_algorithms/pstl/alg_modifying_operations/replace_copy.cc:
	Likewise.
	* testsuite/25_algorithms/pstl/alg_modifying_operations/rotate.cc:
	Likewise.
	* testsuite/25_algorithms/pstl/alg_modifying_operations/rotate_copy.cc:
	Likewise.
	* testsuite/25_algorithms/pstl/alg_modifying_operations/swap_ranges.cc:
	Likewise.
	* testsuite/25_algorithms/pstl/alg_modifying_operations/transform_binary.cc:
	Likewise.
	* testsuite/25_algorithms/pstl/alg_modifying_operations/transform_unary.cc:
	Likewise.
	* testsuite/25_algorithms/pstl/alg_modifying_operations/unique.cc:
	Likewise.
	* testsuite/25_algorithms/pstl/alg_modifying_operations/unique_copy_equal.cc:
	Likewise.
	* testsuite/25_algorithms/pstl/alg_nonmodifying/adjacent_find.cc:
	Likewise.
	* testsuite/25_algorithms/pstl/alg_nonmodifying/all_of.cc:
	Likewise.
	* testsuite/25_algorithms/pstl/alg_nonmodifying/any_of.cc:
	Likewise.
	* testsuite/25_algorithms/pstl/alg_nonmodifying/count.cc:
	Likewise.
	* testsuite/25_algorithms/pstl/alg_nonmodifying/equal.cc:
	Likewise.
	* testsuite/25_algorithms/pstl/alg_nonmodifying/find.cc:
	Likewise.
	* testsuite/25_algorithms/pstl/alg_nonmodifying/find_end.cc:
	Likewise.
	* testsuite/25_algorithms/pstl/alg_nonmodifying/find_first_of.cc:
	Likewise.
	* testsuite/25_algorithms/pstl/alg_nonmodifying/find_if.cc:
	Likewise.
	* testsuite/25_algorithms/pstl/alg_nonmodifying/for_each.cc:
	Likewise.
	* testsuite/25_algorithms/pstl/alg_nonmodifying/mismatch.cc:
	Likewise.
	* testsuite/25_algorithms/pstl/alg_nonmodifying/none_of.cc:
	Likewise.
	* testsuite/25_algorithms/pstl/alg_nonmodifying/nth_element.cc:
	Likewise.
	* testsuite/25_algorithms/pstl/alg_nonmodifying/reverse.cc:
	Likewise.
	* testsuite/25_algorithms/pstl/alg_nonmodifying/reverse_copy.cc:
	Likewise.
	* testsuite/25_algorithms/pstl/alg_nonmodifying/search_n.cc:
	Likewise.
	* testsuite/25_algorithms/pstl/alg_sorting/includes.cc:
	Likewise.
	* testsuite/25_algorithms/pstl/alg_sorting/is_heap.cc:
	Likewise.
	* testsuite/25_algorithms/pstl/alg_sorting/is_sorted.cc:
	Likewise.
	* testsuite/25_algorithms/pstl/alg_sorting/lexicographical_compare.cc:
	Likewise.
	* testsuite/25_algorithms/pstl/alg_sorting/minmax_element.cc:
	Likewise.
	* testsuite/25_algorithms/pstl/alg_sorting/partial_sort.cc:
	Likewise.
	* testsuite/25_algorithms/pstl/alg_sorting/partial_sort_copy.cc:
	Likewise.
	* testsuite/25_algorithms/pstl/alg_sorting/set.cc:
	Likewise.
	* testsuite/25_algorithms/pstl/alg_sorting/sort.cc:
	Likewise.
	* testsuite/26_numerics/pstl/numeric_ops/adjacent_difference.cc:
	Likewise.
	* testsuite/26_numerics/pstl/numeric_ops/reduce.cc:
	Likewise.
	* testsuite/26_numerics/pstl/numeric_ops/scan.cc:
	Likewise.
	* testsuite/26_numerics/pstl/numeric_ops/transform_reduce.cc:
	Likewise.
	* testsuite/26_numerics/pstl/numeric_ops/transform_scan.cc:
	Likewise.
	* testsuite/util/pstl/test_utils.h:
	Likewise.
---
 libstdc++-v3/include/pstl/algorithm_fwd.h     |  979 +++---
 libstdc++-v3/include/pstl/algorithm_impl.h    | 2840 +++++++++--------
 libstdc++-v3/include/pstl/execution_defs.h    |   76 +-
 libstdc++-v3/include/pstl/execution_impl.h    |  181 +-
 .../include/pstl/glue_algorithm_impl.h        |  545 ++--
 .../include/pstl/glue_execution_defs.h        |    4 +-
 libstdc++-v3/include/pstl/glue_memory_impl.h  |  293 +-
 libstdc++-v3/include/pstl/glue_numeric_impl.h |   83 +-
 libstdc++-v3/include/pstl/memory_impl.h       |   20 +-
 libstdc++-v3/include/pstl/numeric_fwd.h       |   94 +-
 libstdc++-v3/include/pstl/numeric_impl.h      |  309 +-
 libstdc++-v3/include/pstl/parallel_backend.h  |    6 +
 .../include/pstl/parallel_backend_serial.h    |   29 +-
 .../include/pstl/parallel_backend_tbb.h       |   30 +-
 libstdc++-v3/include/pstl/parallel_impl.h     |   19 +-
 libstdc++-v3/include/pstl/pstl_config.h       |   83 +-
 .../include/pstl/unseq_backend_simd.h         |   20 +-
 libstdc++-v3/include/pstl/utils.h             |   65 +-
 .../pstl/uninitialized_construct.cc           |    4 +-
 .../pstl/uninitialized_copy_move.cc           |   14 +-
 .../pstl/uninitialized_fill_destroy.cc        |    2 +-
 .../pstl/alg_merge/inplace_merge.cc           |   22 +-
 .../25_algorithms/pstl/alg_merge/merge.cc     |    8 +-
 .../pstl/alg_modifying_operations/copy_if.cc  |   10 +-
 .../alg_modifying_operations/copy_move.cc     |   37 +-
 .../pstl/alg_modifying_operations/fill.cc     |    4 +-
 .../pstl/alg_modifying_operations/generate.cc |   15 +-
 .../is_partitioned.cc                         |   12 +-
 .../alg_modifying_operations/partition.cc     |   19 +-
 .../partition_copy.cc                         |   19 +-
 .../pstl/alg_modifying_operations/remove.cc   |   31 +-
 .../alg_modifying_operations/remove_copy.cc   |   11 +-
 .../pstl/alg_modifying_operations/replace.cc  |   15 +-
 .../alg_modifying_operations/replace_copy.cc  |    8 +-
 .../pstl/alg_modifying_operations/rotate.cc   |   14 +-
 .../alg_modifying_operations/rotate_copy.cc   |   10 +-
 .../alg_modifying_operations/swap_ranges.cc   |    4 +-
 .../transform_binary.cc                       |   11 +-
 .../transform_unary.cc                        |    2 +-
 .../pstl/alg_modifying_operations/unique.cc   |   22 +-
 .../unique_copy_equal.cc                      |   16 +-
 .../pstl/alg_nonmodifying/adjacent_find.cc    |   14 +-
 .../pstl/alg_nonmodifying/all_of.cc           |    6 +-
 .../pstl/alg_nonmodifying/any_of.cc           |    6 +-
 .../pstl/alg_nonmodifying/count.cc            |    6 +-
 .../pstl/alg_nonmodifying/equal.cc            |    6 +-
 .../pstl/alg_nonmodifying/find.cc             |   14 +-
 .../pstl/alg_nonmodifying/find_end.cc         |  110 +-
 .../pstl/alg_nonmodifying/find_first_of.cc    |   14 +-
 .../pstl/alg_nonmodifying/find_if.cc          |   12 +-
 .../pstl/alg_nonmodifying/for_each.cc         |    4 +-
 .../pstl/alg_nonmodifying/mismatch.cc         |    4 +-
 .../pstl/alg_nonmodifying/none_of.cc          |    6 +-
 .../pstl/alg_nonmodifying/nth_element.cc      |   13 +-
 .../pstl/alg_nonmodifying/reverse.cc          |   14 +-
 .../pstl/alg_nonmodifying/reverse_copy.cc     |   13 +-
 .../pstl/alg_nonmodifying/search_n.cc         |   14 +-
 .../pstl/alg_sorting/includes.cc              |    7 +-
 .../25_algorithms/pstl/alg_sorting/is_heap.cc |   15 +-
 .../pstl/alg_sorting/is_sorted.cc             |    4 +-
 .../alg_sorting/lexicographical_compare.cc    |    4 +-
 .../pstl/alg_sorting/minmax_element.cc        |    2 +-
 .../pstl/alg_sorting/partial_sort.cc          |   20 +-
 .../pstl/alg_sorting/partial_sort_copy.cc     |   19 +-
 .../25_algorithms/pstl/alg_sorting/set.cc     |  155 +-
 .../25_algorithms/pstl/alg_sorting/sort.cc    |   10 +-
 .../pstl/numeric_ops/adjacent_difference.cc   |   38 +-
 .../26_numerics/pstl/numeric_ops/reduce.cc    |    4 +-
 .../26_numerics/pstl/numeric_ops/scan.cc      |   13 +-
 .../pstl/numeric_ops/transform_reduce.cc      |   33 +-
 .../pstl/numeric_ops/transform_scan.cc        |   24 +-
 libstdc++-v3/testsuite/util/pstl/test_utils.h |   94 +-
 72 files changed, 3366 insertions(+), 3318 deletions(-)

diff --git a/libstdc++-v3/include/pstl/algorithm_fwd.h b/libstdc++-v3/include/pstl/algorithm_fwd.h
index e85125c4dc7..1ba9555e2a0 100644
--- a/libstdc++-v3/include/pstl/algorithm_fwd.h
+++ b/libstdc++-v3/include/pstl/algorithm_fwd.h
@@ -10,6 +10,7 @@
 #ifndef _PSTL_ALGORITHM_FWD_H
 #define _PSTL_ALGORITHM_FWD_H
 
+#include <iterator>
 #include <type_traits>
 #include <utility>
 
@@ -27,20 +28,18 @@ bool
 __brick_any_of(const _ForwardIterator, const _ForwardIterator, _Pred,
                /*__is_vector=*/std::false_type) noexcept;
 
-template <class _ForwardIterator, class _Pred>
+template <class _RandomAccessIterator, class _Pred>
 bool
-__brick_any_of(const _ForwardIterator, const _ForwardIterator, _Pred,
+__brick_any_of(const _RandomAccessIterator, const _RandomAccessIterator, _Pred,
                /*__is_vector=*/std::true_type) noexcept;
 
-template <class _ExecutionPolicy, class _ForwardIterator, class _Pred, class _IsVector>
+template <class _Tag, class _ExecutionPolicy, class _ForwardIterator, class _Pred>
 bool
-__pattern_any_of(_ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _Pred, _IsVector,
-                 /*parallel=*/std::false_type) noexcept;
+__pattern_any_of(_Tag, _ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _Pred) noexcept;
 
-template <class _ExecutionPolicy, class _ForwardIterator, class _Pred, class _IsVector>
+template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _Pred>
 bool
-__pattern_any_of(_ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _Pred, _IsVector,
-                 /*parallel=*/std::true_type);
+__pattern_any_of(__parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator, _Pred);
 
 //------------------------------------------------------------------------
 // walk1 (pseudo)
@@ -56,25 +55,22 @@ template <class _RandomAccessIterator, class _Function>
 void __brick_walk1(_RandomAccessIterator, _RandomAccessIterator, _Function,
                    /*vector=*/std::true_type) noexcept;
 
-template <class _ExecutionPolicy, class _ForwardIterator, class _Function, class _IsVector>
+template <class _Tag, class _ExecutionPolicy, class _ForwardIterator, class _Function>
 void
-__pattern_walk1(_ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _Function, _IsVector,
-                /*parallel=*/std::false_type) noexcept;
+__pattern_walk1(_Tag, _ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _Function) noexcept;
 
-template <class _ExecutionPolicy, class _ForwardIterator, class _Function, class _IsVector>
+template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _Function>
 void
-__pattern_walk1(_ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _Function, _IsVector,
-                /*parallel=*/std::true_type);
+__pattern_walk1(__parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator, _Function);
 
-template <class _ExecutionPolicy, class _ForwardIterator, class _Brick>
+template <class _Tag, class _ExecutionPolicy, class _ForwardIterator, class _Brick>
 void
-__pattern_walk_brick(_ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _Brick,
-                     /*parallel=*/std::false_type) noexcept;
+__pattern_walk_brick(_Tag, _ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _Brick) noexcept;
 
-template <class _ExecutionPolicy, class _ForwardIterator, class _Brick>
+template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _Brick>
 void
-__pattern_walk_brick(_ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _Brick,
-                     /*parallel=*/std::true_type);
+__pattern_walk_brick(__parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator,
+                     _Brick);
 
 //------------------------------------------------------------------------
 // walk1_n
@@ -88,25 +84,21 @@ template <class _RandomAccessIterator, class _DifferenceType, class _Function>
 _RandomAccessIterator __brick_walk1_n(_RandomAccessIterator, _DifferenceType, _Function,
                                       /*vectorTag=*/std::true_type) noexcept;
 
-template <class _ExecutionPolicy, class _ForwardIterator, class _Size, class _Function, class _IsVector>
+template <class _Tag, class _ExecutionPolicy, class _ForwardIterator, class _Size, class _Function>
 _ForwardIterator
-__pattern_walk1_n(_ExecutionPolicy&&, _ForwardIterator, _Size, _Function, _IsVector,
-                  /*is_parallel=*/std::false_type) noexcept;
+__pattern_walk1_n(_Tag, _ExecutionPolicy&&, _ForwardIterator, _Size, _Function) noexcept;
 
-template <class _ExecutionPolicy, class _RandomAccessIterator, class _Size, class _Function, class _IsVector>
+template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _Size, class _Function>
 _RandomAccessIterator
-__pattern_walk1_n(_ExecutionPolicy&&, _RandomAccessIterator, _Size, _Function, _IsVector,
-                  /*is_parallel=*/std::true_type);
+__pattern_walk1_n(__parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator, _Size, _Function);
 
-template <class _ExecutionPolicy, class _ForwardIterator, class _Size, class _Brick>
+template <class _Tag, class _ExecutionPolicy, class _ForwardIterator, class _Size, class _Brick>
 _ForwardIterator
-__pattern_walk_brick_n(_ExecutionPolicy&&, _ForwardIterator, _Size, _Brick,
-                       /*is_parallel=*/std::false_type) noexcept;
+__pattern_walk_brick_n(_Tag, _ExecutionPolicy&&, _ForwardIterator, _Size, _Brick) noexcept;
 
-template <class _ExecutionPolicy, class _RandomAccessIterator, class _Size, class _Brick>
+template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _Size, class _Brick>
 _RandomAccessIterator
-__pattern_walk_brick_n(_ExecutionPolicy&&, _RandomAccessIterator, _Size, _Brick,
-                       /*is_parallel=*/std::true_type);
+__pattern_walk_brick_n(__parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator, _Size, _Brick);
 
 //------------------------------------------------------------------------
 // walk2 (pseudo)
@@ -118,60 +110,60 @@ template <class _ForwardIterator1, class _ForwardIterator2, class _Function>
 _ForwardIterator2 __brick_walk2(_ForwardIterator1, _ForwardIterator1, _ForwardIterator2, _Function,
                                 /*vector=*/std::false_type) noexcept;
 
-template <class _ForwardIterator1, class _ForwardIterator2, class _Function>
-_ForwardIterator2 __brick_walk2(_ForwardIterator1, _ForwardIterator1, _ForwardIterator2, _Function,
-                                /*vector=*/std::true_type) noexcept;
+template <class _RandomAccessIterator1, class _RandomAccessIterator2, class _Function>
+_RandomAccessIterator2 __brick_walk2(_RandomAccessIterator1, _RandomAccessIterator1, _RandomAccessIterator2, _Function,
+                                     /*vector=*/std::true_type) noexcept;
 
 template <class _ForwardIterator1, class _Size, class _ForwardIterator2, class _Function>
 _ForwardIterator2 __brick_walk2_n(_ForwardIterator1, _Size, _ForwardIterator2, _Function,
                                   /*vector=*/std::false_type) noexcept;
 
-template <class _ForwardIterator1, class _Size, class _ForwardIterator2, class _Function>
-_ForwardIterator2 __brick_walk2_n(_ForwardIterator1, _Size, _ForwardIterator2, _Function,
-                                  /*vector=*/std::true_type) noexcept;
+template <class _RandomAccessIterator1, class _Size, class _RandomAccessIterator2, class _Function>
+_RandomAccessIterator2 __brick_walk2_n(_RandomAccessIterator1, _Size, _RandomAccessIterator2, _Function,
+                                       /*vector=*/std::true_type) noexcept;
 
-template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _Function, class _IsVector>
+template <class _Tag, class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _Function>
 _ForwardIterator2
-__pattern_walk2(_ExecutionPolicy&&, _ForwardIterator1, _ForwardIterator1, _ForwardIterator2, _Function, _IsVector,
-                /*parallel=*/std::false_type) noexcept;
+__pattern_walk2(_Tag, _ExecutionPolicy&&, _ForwardIterator1, _ForwardIterator1, _ForwardIterator2, _Function) noexcept;
 
-template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _Function, class _IsVector>
-_ForwardIterator2
-__pattern_walk2(_ExecutionPolicy&&, _ForwardIterator1, _ForwardIterator1, _ForwardIterator2, _Function, _IsVector,
-                /*parallel=*/std::true_type);
-
-template <class _ExecutionPolicy, class _ForwardIterator1, class _Size, class _ForwardIterator2, class _Function,
-          class _IsVector>
-_ForwardIterator2
-__pattern_walk2_n(_ExecutionPolicy&&, _ForwardIterator1, _Size, _ForwardIterator2, _Function, _IsVector,
-                  /*parallel=*/std::false_type) noexcept;
-
-template <class _ExecutionPolicy, class _RandomAccessIterator1, class _Size, class _RandomAccessIterator2,
-          class _Function, class _IsVector>
+template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator1, class _RandomAccessIterator2,
+          class _Function>
 _RandomAccessIterator2
-__pattern_walk2_n(_ExecutionPolicy&&, _RandomAccessIterator1, _Size, _RandomAccessIterator2, _Function, _IsVector,
-                  /*parallel=*/std::true_type);
+__pattern_walk2(__parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator1, _RandomAccessIterator1,
+                _RandomAccessIterator2, _Function);
 
-template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _Brick>
+template <class _Tag, class _ExecutionPolicy, class _ForwardIterator1, class _Size, class _ForwardIterator2,
+          class _Function>
 _ForwardIterator2
-__pattern_walk2_brick(_ExecutionPolicy&&, _ForwardIterator1, _ForwardIterator1, _ForwardIterator2, _Brick,
-                      /*parallel=*/std::false_type) noexcept;
+__pattern_walk2_n(_Tag, _ExecutionPolicy&&, _ForwardIterator1, _Size, _ForwardIterator2, _Function) noexcept;
 
-template <class _ExecutionPolicy, class _RandomAccessIterator1, class _RandomAccessIterator2, class _Brick>
+template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator1, class _Size,
+          class _RandomAccessIterator2, class _Function>
 _RandomAccessIterator2
-__pattern_walk2_brick(_ExecutionPolicy&&, _RandomAccessIterator1, _RandomAccessIterator1, _RandomAccessIterator2,
-                      _Brick,
-                      /*parallel=*/std::true_type);
+__pattern_walk2_n(__parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator1, _Size, _RandomAccessIterator2,
+                  _Function);
 
-template <class _ExecutionPolicy, class _ForwardIterator1, class _Size, class _ForwardIterator2, class _Brick>
+template <class _Tag, class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _Brick>
 _ForwardIterator2
-__pattern_walk2_brick_n(_ExecutionPolicy&&, _ForwardIterator1, _Size, _ForwardIterator2, _Brick,
-                        /*parallel=*/std::false_type) noexcept;
+__pattern_walk2_brick(_Tag, _ExecutionPolicy&&, _ForwardIterator1, _ForwardIterator1, _ForwardIterator2,
+                      _Brick) noexcept;
 
-template <class _ExecutionPolicy, class _RandomAccessIterator1, class _Size, class _RandomAccessIterator2, class _Brick>
+template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator1, class _RandomAccessIterator2,
+          class _Brick>
 _RandomAccessIterator2
-__pattern_walk2_brick_n(_ExecutionPolicy&&, _RandomAccessIterator1, _Size, _RandomAccessIterator2, _Brick,
-                        /*parallel=*/std::true_type);
+__pattern_walk2_brick(__parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator1, _RandomAccessIterator1,
+                      _RandomAccessIterator2, _Brick);
+
+template <class _Tag, class _ExecutionPolicy, class _ForwardIterator1, class _Size, class _ForwardIterator2,
+          class _Brick>
+_ForwardIterator2
+__pattern_walk2_brick_n(_Tag, _ExecutionPolicy&&, _ForwardIterator1, _Size, _ForwardIterator2, _Brick) noexcept;
+
+template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator1, class _Size,
+          class _RandomAccessIterator2, class _Brick>
+_RandomAccessIterator2
+__pattern_walk2_brick_n(__parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator1, _Size,
+                        _RandomAccessIterator2, _Brick);
 
 //------------------------------------------------------------------------
 // walk3 (pseudo)
@@ -188,18 +180,17 @@ _RandomAccessIterator3 __brick_walk3(_RandomAccessIterator1, _RandomAccessIterat
                                      _RandomAccessIterator3, _Function,
                                      /*vector=*/std::true_type) noexcept;
 
-template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _ForwardIterator3,
-          class _Function, class _IsVector>
+template <class _Tag, class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _ForwardIterator3,
+          class _Function>
 _ForwardIterator3
-__pattern_walk3(_ExecutionPolicy&&, _ForwardIterator1, _ForwardIterator1, _ForwardIterator2, _ForwardIterator3,
-                _Function, _IsVector,
-                /*parallel=*/std::false_type) noexcept;
+__pattern_walk3(_Tag, _ExecutionPolicy&&, _ForwardIterator1, _ForwardIterator1, _ForwardIterator2, _ForwardIterator3,
+                _Function) noexcept;
 
-template <class _ExecutionPolicy, class _RandomAccessIterator1, class _RandomAccessIterator2,
-          class _RandomAccessIterator3, class _Function, class _IsVector>
+template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator1, class _RandomAccessIterator2,
+          class _RandomAccessIterator3, class _Function>
 _RandomAccessIterator3
-__pattern_walk3(_ExecutionPolicy&&, _RandomAccessIterator1, _RandomAccessIterator1, _RandomAccessIterator2,
-                _RandomAccessIterator3, _Function, _IsVector, /*parallel=*/std::true_type);
+__pattern_walk3(__parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator1, _RandomAccessIterator1,
+                _RandomAccessIterator2, _RandomAccessIterator3, _Function);
 
 //------------------------------------------------------------------------
 // equal
@@ -213,17 +204,16 @@ template <class _RandomAccessIterator1, class _RandomAccessIterator2, class _Bin
 bool __brick_equal(_RandomAccessIterator1, _RandomAccessIterator1, _RandomAccessIterator2, _BinaryPredicate,
                    /* is_vector = */ std::true_type) noexcept;
 
-template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate,
-          class _IsVector>
+template <class _Tag, class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate>
 bool
-__pattern_equal(_ExecutionPolicy&&, _ForwardIterator1, _ForwardIterator1, _ForwardIterator2, _BinaryPredicate,
-                _IsVector, /* is_parallel = */ std::false_type) noexcept;
+__pattern_equal(_Tag, _ExecutionPolicy&&, _ForwardIterator1, _ForwardIterator1, _ForwardIterator2,
+                _BinaryPredicate) noexcept;
 
-template <class _ExecutionPolicy, class _RandomAccessIterator1, class _RandomAccessIterator2, class _BinaryPredicate,
-          class _IsVector>
+template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator1, class _RandomAccessIterator2,
+          class _BinaryPredicate>
 bool
-__pattern_equal(_ExecutionPolicy&&, _RandomAccessIterator1, _RandomAccessIterator1, _RandomAccessIterator2,
-                _BinaryPredicate, _IsVector, /* is_parallel = */ std::true_type);
+__pattern_equal(__parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator1, _RandomAccessIterator1,
+                _RandomAccessIterator2, _BinaryPredicate);
 
 template <class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate>
 bool __brick_equal(_ForwardIterator1, _ForwardIterator1, _ForwardIterator2, _ForwardIterator2, _BinaryPredicate,
@@ -233,17 +223,16 @@ template <class _RandomAccessIterator1, class _RandomAccessIterator2, class _Bin
 bool __brick_equal(_RandomAccessIterator1, _RandomAccessIterator1, _RandomAccessIterator2, _RandomAccessIterator2,
                    _BinaryPredicate, /* is_vector = */ std::true_type) noexcept;
 
-template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate,
-          class _IsVector>
+template <class _Tag, class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate>
 bool
-__pattern_equal(_ExecutionPolicy&&, _ForwardIterator1, _ForwardIterator1, _ForwardIterator2, _ForwardIterator2,
-                _BinaryPredicate, _IsVector, /* is_parallel = */ std::false_type) noexcept;
+__pattern_equal(_Tag, _ExecutionPolicy&&, _ForwardIterator1, _ForwardIterator1, _ForwardIterator2, _ForwardIterator2,
+                _BinaryPredicate) noexcept;
 
-template <class _ExecutionPolicy, class _RandomAccessIterator1, class _RandomAccessIterator2, class _BinaryPredicate,
-          class _IsVector>
+template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator1, class _RandomAccessIterator2,
+          class _BinaryPredicate>
 bool
-__pattern_equal(_ExecutionPolicy&&, _RandomAccessIterator1, _RandomAccessIterator1, _RandomAccessIterator2,
-                _RandomAccessIterator2, _BinaryPredicate, _IsVector, /* is_parallel = */ std::true_type);
+__pattern_equal(__parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator1, _RandomAccessIterator1,
+                _RandomAccessIterator2, _RandomAccessIterator2, _BinaryPredicate);
 
 //------------------------------------------------------------------------
 // find_if
@@ -257,15 +246,14 @@ template <class _RandomAccessIterator, class _Predicate>
 _RandomAccessIterator __brick_find_if(_RandomAccessIterator, _RandomAccessIterator, _Predicate,
                                       /*is_vector=*/std::true_type) noexcept;
 
-template <class _ExecutionPolicy, class _ForwardIterator, class _Predicate, class _IsVector>
+template <class _Tag, class _ExecutionPolicy, class _ForwardIterator, class _Predicate>
 _ForwardIterator
-__pattern_find_if(_ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _Predicate, _IsVector,
-                  /*is_parallel=*/std::false_type) noexcept;
+__pattern_find_if(_Tag, _ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _Predicate) noexcept;
 
-template <class _ExecutionPolicy, class _ForwardIterator, class _Predicate, class _IsVector>
-_ForwardIterator
-__pattern_find_if(_ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _Predicate, _IsVector,
-                  /*is_parallel=*/std::true_type);
+template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _Predicate>
+_RandomAccessIterator
+__pattern_find_if(__parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator,
+                  _Predicate);
 
 //------------------------------------------------------------------------
 // find_end
@@ -276,24 +264,21 @@ _ForwardIterator1 __brick_find_end(_ForwardIterator1, _ForwardIterator1, _Forwar
                                    _BinaryPredicate,
                                    /*__is_vector=*/std::false_type) noexcept;
 
-template <class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate>
-_ForwardIterator1 __brick_find_end(_ForwardIterator1, _ForwardIterator1, _ForwardIterator2, _ForwardIterator2,
-                                   _BinaryPredicate,
-                                   /*__is_vector=*/std::true_type) noexcept;
+template <class _RandomAccessIterator1, class _RandomAccessIterator2, class _BinaryPredicate>
+_RandomAccessIterator1 __brick_find_end(_RandomAccessIterator1, _RandomAccessIterator1, _RandomAccessIterator2,
+                                        _RandomAccessIterator2, _BinaryPredicate,
+                                        /*__is_vector=*/std::true_type) noexcept;
 
-template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate,
-          class _IsVector>
+template <class _Tag, class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate>
 _ForwardIterator1
-__pattern_find_end(_ExecutionPolicy&&, _ForwardIterator1, _ForwardIterator1, _ForwardIterator2, _ForwardIterator2,
-                   _BinaryPredicate, _IsVector,
-                   /*is_parallel=*/std::false_type) noexcept;
+__pattern_find_end(_Tag, _ExecutionPolicy&&, _ForwardIterator1, _ForwardIterator1, _ForwardIterator2, _ForwardIterator2,
+                   _BinaryPredicate) noexcept;
 
-template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate,
-          class _IsVector>
-_ForwardIterator1
-__pattern_find_end(_ExecutionPolicy&&, _ForwardIterator1, _ForwardIterator1, _ForwardIterator2, _ForwardIterator2,
-                   _BinaryPredicate, _IsVector,
-                   /*is_parallel=*/std::true_type) noexcept;
+template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator1, class _RandomAccessIterator2,
+          class _BinaryPredicate>
+_RandomAccessIterator1
+__pattern_find_end(__parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator1, _RandomAccessIterator1,
+                   _RandomAccessIterator2, _RandomAccessIterator2, _BinaryPredicate) noexcept;
 
 //------------------------------------------------------------------------
 // find_first_of
@@ -304,22 +289,21 @@ _ForwardIterator1 __brick_find_first_of(_ForwardIterator1, _ForwardIterator1, _F
                                         _BinaryPredicate,
                                         /*__is_vector=*/std::false_type) noexcept;
 
-template <class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate>
-_ForwardIterator1 __brick_find_first_of(_ForwardIterator1, _ForwardIterator1, _ForwardIterator2, _ForwardIterator2,
-                                        _BinaryPredicate,
-                                        /*__is_vector=*/std::true_type) noexcept;
+template <class _RandomAccessIterator1, class _RandomAccessIterator2, class _BinaryPredicate>
+_RandomAccessIterator1 __brick_find_first_of(_RandomAccessIterator1, _RandomAccessIterator1, _RandomAccessIterator2,
+                                             _RandomAccessIterator2, _BinaryPredicate,
+                                             /*__is_vector=*/std::true_type) noexcept;
 
-template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate,
-          class _IsVector>
+template <class _Tag, class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate>
 _ForwardIterator1
-__pattern_find_first_of(_ExecutionPolicy&&, _ForwardIterator1, _ForwardIterator1, _ForwardIterator2, _ForwardIterator2,
-                        _BinaryPredicate, _IsVector, /*is_parallel=*/std::false_type) noexcept;
+__pattern_find_first_of(_Tag, _ExecutionPolicy&&, _ForwardIterator1, _ForwardIterator1, _ForwardIterator2,
+                        _ForwardIterator2, _BinaryPredicate) noexcept;
 
-template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate,
-          class _IsVector>
-_ForwardIterator1
-__pattern_find_first_of(_ExecutionPolicy&&, _ForwardIterator1, _ForwardIterator1, _ForwardIterator2, _ForwardIterator2,
-                        _BinaryPredicate, _IsVector, /*is_parallel=*/std::true_type) noexcept;
+template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator1, class _RandomAccessIterator2,
+          class _BinaryPredicate>
+_RandomAccessIterator1
+__pattern_find_first_of(__parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator1, _RandomAccessIterator1,
+                        _RandomAccessIterator2, _RandomAccessIterator2, _BinaryPredicate) noexcept;
 
 //------------------------------------------------------------------------
 // search
@@ -330,24 +314,21 @@ _ForwardIterator1 __brick_search(_ForwardIterator1, _ForwardIterator1, _ForwardI
                                  _BinaryPredicate,
                                  /*vector=*/std::false_type) noexcept;
 
-template <class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate>
-_ForwardIterator1 __brick_search(_ForwardIterator1, _ForwardIterator1, _ForwardIterator2, _ForwardIterator2,
-                                 _BinaryPredicate,
-                                 /*vector=*/std::true_type) noexcept;
+template <class _RandomAccessIterator1, class _RandomAccessIterator2, class _BinaryPredicate>
+_RandomAccessIterator1 __brick_search(_RandomAccessIterator1, _RandomAccessIterator1, _RandomAccessIterator2,
+                                      _RandomAccessIterator2, _BinaryPredicate,
+                                      /*vector=*/std::true_type) noexcept;
 
-template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate,
-          class _IsVector>
+template <class _Tag, class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate>
 _ForwardIterator1
-__pattern_search(_ExecutionPolicy&&, _ForwardIterator1, _ForwardIterator1, _ForwardIterator2, _ForwardIterator2,
-                 _BinaryPredicate, _IsVector,
-                 /*is_parallel=*/std::false_type) noexcept;
+__pattern_search(_Tag, _ExecutionPolicy&&, _ForwardIterator1, _ForwardIterator1, _ForwardIterator2, _ForwardIterator2,
+                 _BinaryPredicate) noexcept;
 
-template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate,
-          class _IsVector>
-_ForwardIterator1
-__pattern_search(_ExecutionPolicy&&, _ForwardIterator1, _ForwardIterator1, _ForwardIterator2, _ForwardIterator2,
-                 _BinaryPredicate, _IsVector,
-                 /*is_parallel=*/std::true_type) noexcept;
+template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator1, class _RandomAccessIterator2,
+          class _BinaryPredicate>
+_RandomAccessIterator1
+__pattern_search(__parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator1, _RandomAccessIterator1,
+                 _RandomAccessIterator2, _RandomAccessIterator2, _BinaryPredicate) noexcept;
 
 //------------------------------------------------------------------------
 // search_n
@@ -358,24 +339,21 @@ _ForwardIterator
 __brick_search_n(_ForwardIterator, _ForwardIterator, _Size, const _Tp&, _BinaryPredicate,
                  /*vector=*/std::false_type) noexcept;
 
-template <class _ForwardIterator, class _Size, class _Tp, class _BinaryPredicate>
-_ForwardIterator
-__brick_search_n(_ForwardIterator, _ForwardIterator, _Size, const _Tp&, _BinaryPredicate,
+template <class _RandomAccessIterator, class _Size, class _Tp, class _BinaryPredicate>
+_RandomAccessIterator
+__brick_search_n(_RandomAccessIterator, _RandomAccessIterator, _Size, const _Tp&, _BinaryPredicate,
                  /*vector=*/std::true_type) noexcept;
 
-template <class _ExecutionPolicy, class _ForwardIterator, class _Size, class _Tp, class _BinaryPredicate,
-          class _IsVector>
+template <class _Tag, class _ExecutionPolicy, class _ForwardIterator, class _Size, class _Tp, class _BinaryPredicate>
 _ForwardIterator
-__pattern_search_n(_ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _Size, const _Tp&, _BinaryPredicate,
-		   _IsVector,
-                   /*is_parallel=*/std::false_type) noexcept;
+__pattern_search_n(_Tag, _ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _Size, const _Tp&,
+                   _BinaryPredicate) noexcept;
 
-template <class _ExecutionPolicy, class _RandomAccessIterator, class _Size, class _Tp, class _BinaryPredicate,
-          class _IsVector>
+template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _Size, class _Tp,
+          class _BinaryPredicate>
 _RandomAccessIterator
-__pattern_search_n(_ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator, _Size, const _Tp&,
-                   _BinaryPredicate, _IsVector,
-                   /*is_parallel=*/std::true_type) noexcept;
+__pattern_search_n(__parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator, _Size,
+                   const _Tp&, _BinaryPredicate) noexcept;
 
 //------------------------------------------------------------------------
 // copy_n
@@ -385,8 +363,8 @@ template <class _ForwardIterator, class _Size, class _OutputIterator>
 _OutputIterator __brick_copy_n(_ForwardIterator, _Size, _OutputIterator,
                                /*vector=*/std::false_type) noexcept;
 
-template <class _ForwardIterator, class _Size, class _OutputIterator>
-_OutputIterator __brick_copy_n(_ForwardIterator, _Size, _OutputIterator,
+template <class _RandomAccessIterator, class _Size, class _OutputIterator>
+_OutputIterator __brick_copy_n(_RandomAccessIterator, _Size, _OutputIterator,
                                /*vector=*/std::true_type) noexcept;
 
 //------------------------------------------------------------------------
@@ -417,14 +395,12 @@ _OutputIterator __brick_move(_RandomAccessIterator, _RandomAccessIterator, _Outp
 // swap_ranges
 //------------------------------------------------------------------------
 template <class _ForwardIterator, class _OutputIterator>
-_OutputIterator
-__brick_swap_ranges(_ForwardIterator __first, _ForwardIterator __last, _OutputIterator __result,
-                    /*vector=*/std::false_type) noexcept;
+_OutputIterator __brick_swap_ranges(_ForwardIterator, _ForwardIterator, _OutputIterator,
+                                    /*vector=*/std::false_type) noexcept;
 
-template <class _ForwardIterator, class _OutputIterator>
-_OutputIterator
-__brick_swap_ranges(_ForwardIterator __first, _ForwardIterator __last, _OutputIterator __result,
-                    /*vector=*/std::true_type) noexcept;
+template <class _RandomAccessIterator, class _OutputIterator>
+_OutputIterator __brick_swap_ranges(_RandomAccessIterator, _RandomAccessIterator, _OutputIterator,
+                                    /*vector=*/std::true_type) noexcept;
 
 //------------------------------------------------------------------------
 // copy_if
@@ -434,8 +410,8 @@ template <class _ForwardIterator, class _OutputIterator, class _UnaryPredicate>
 _OutputIterator __brick_copy_if(_ForwardIterator, _ForwardIterator, _OutputIterator, _UnaryPredicate,
                                 /*vector=*/std::false_type) noexcept;
 
-template <class _ForwardIterator, class _OutputIterator, class _UnaryPredicate>
-_OutputIterator __brick_copy_if(_ForwardIterator, _ForwardIterator, _OutputIterator, _UnaryPredicate,
+template <class _RandomAccessIterator, class _OutputIterator, class _UnaryPredicate>
+_OutputIterator __brick_copy_if(_RandomAccessIterator, _RandomAccessIterator, _OutputIterator, _UnaryPredicate,
                                 /*vector=*/std::true_type) noexcept;
 
 template <class _DifferenceType, class _ForwardIterator, class _UnaryPredicate>
@@ -452,9 +428,9 @@ void
 __brick_copy_by_mask(_ForwardIterator, _ForwardIterator, _OutputIterator, bool*,
                      /*vector=*/std::false_type) noexcept;
 
-template <class _ForwardIterator, class _OutputIterator>
+template <class _RandomAccessIterator, class _OutputIterator>
 void
-__brick_copy_by_mask(_ForwardIterator, _ForwardIterator, _OutputIterator, bool* __restrict,
+__brick_copy_by_mask(_RandomAccessIterator, _RandomAccessIterator, _OutputIterator, bool* __restrict,
                      /*vector=*/std::true_type) noexcept;
 
 template <class _ForwardIterator, class _OutputIterator1, class _OutputIterator2>
@@ -467,24 +443,24 @@ void
 __brick_partition_by_mask(_RandomAccessIterator, _RandomAccessIterator, _OutputIterator1, _OutputIterator2, bool*,
                           /*vector=*/std::true_type) noexcept;
 
-template <class _ExecutionPolicy, class _ForwardIterator, class _OutputIterator, class _UnaryPredicate, class _IsVector>
+template <class _Tag, class _ExecutionPolicy, class _ForwardIterator, class _OutputIterator, class _UnaryPredicate>
 _OutputIterator
-__pattern_copy_if(_ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _OutputIterator, _UnaryPredicate, _IsVector,
-                  /*parallel=*/std::false_type) noexcept;
+__pattern_copy_if(_Tag, _ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _OutputIterator,
+                  _UnaryPredicate) noexcept;
 
-template <class _ExecutionPolicy, class _RandomAccessIterator, class _OutputIterator, class _UnaryPredicate,
-          class _IsVector>
+template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _OutputIterator,
+          class _UnaryPredicate>
 _OutputIterator
-__pattern_copy_if(_ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator, _OutputIterator, _UnaryPredicate,
-                  _IsVector, /*parallel=*/std::true_type);
+__pattern_copy_if(__parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator,
+                  _OutputIterator, _UnaryPredicate);
 
 //------------------------------------------------------------------------
 // count
 //------------------------------------------------------------------------
 
-template <class _ForwardIterator, class _Predicate>
-typename std::iterator_traits<_ForwardIterator>::difference_type
-    __brick_count(_ForwardIterator, _ForwardIterator, _Predicate,
+template <class _RandomAccessIterator, class _Predicate>
+typename std::iterator_traits<_RandomAccessIterator>::difference_type
+    __brick_count(_RandomAccessIterator, _RandomAccessIterator, _Predicate,
                   /* is_vector = */ std::true_type) noexcept;
 
 template <class _ForwardIterator, class _Predicate>
@@ -492,15 +468,14 @@ typename std::iterator_traits<_ForwardIterator>::difference_type
     __brick_count(_ForwardIterator, _ForwardIterator, _Predicate,
                   /* is_vector = */ std::false_type) noexcept;
 
-template <class _ExecutionPolicy, class _ForwardIterator, class _Predicate, class _IsVector>
+template <class _Tag, class _ExecutionPolicy, class _ForwardIterator, class _Predicate>
 typename std::iterator_traits<_ForwardIterator>::difference_type
-__pattern_count(_ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _Predicate,
-                /* is_parallel */ std::false_type, _IsVector) noexcept;
+__pattern_count(_Tag, _ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _Predicate) noexcept;
 
-template <class _ExecutionPolicy, class _ForwardIterator, class _Predicate, class _IsVector>
-typename std::iterator_traits<_ForwardIterator>::difference_type
-__pattern_count(_ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _Predicate,
-                /* is_parallel */ std::true_type, _IsVector);
+template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _Predicate>
+typename std::iterator_traits<_RandomAccessIterator>::difference_type
+__pattern_count(__parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator,
+                _Predicate);
 
 //------------------------------------------------------------------------
 // unique
@@ -510,37 +485,35 @@ template <class _ForwardIterator, class _BinaryPredicate>
 _ForwardIterator __brick_unique(_ForwardIterator, _ForwardIterator, _BinaryPredicate,
                                 /*is_vector=*/std::false_type) noexcept;
 
-template <class _ForwardIterator, class _BinaryPredicate>
-_ForwardIterator __brick_unique(_ForwardIterator, _ForwardIterator, _BinaryPredicate,
-                                /*is_vector=*/std::true_type) noexcept;
+template <class _RandomAccessIterator, class _BinaryPredicate>
+_RandomAccessIterator __brick_unique(_RandomAccessIterator, _RandomAccessIterator, _BinaryPredicate,
+                                     /*is_vector=*/std::true_type) noexcept;
 
-template <class _ExecutionPolicy, class _ForwardIterator, class _BinaryPredicate, class _IsVector>
+template <class _Tag, class _ExecutionPolicy, class _ForwardIterator, class _BinaryPredicate>
 _ForwardIterator
-__pattern_unique(_ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _BinaryPredicate, _IsVector,
-                 /*is_parallel=*/std::false_type) noexcept;
+__pattern_unique(_Tag, _ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _BinaryPredicate) noexcept;
 
-template <class _ExecutionPolicy, class _ForwardIterator, class _BinaryPredicate, class _IsVector>
-_ForwardIterator
-__pattern_unique(_ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _BinaryPredicate, _IsVector,
-                 /*is_parallel=*/std::true_type) noexcept;
+template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _BinaryPredicate>
+_RandomAccessIterator
+__pattern_unique(__parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator,
+                 _BinaryPredicate) noexcept;
 
 //------------------------------------------------------------------------
 // unique_copy
 //------------------------------------------------------------------------
 
 template <class _ForwardIterator, class _OutputIterator, class _BinaryPredicate>
-  _OutputIterator __brick_unique_copy(_ForwardIterator, _ForwardIterator, _OutputIterator, _BinaryPredicate,
+_OutputIterator __brick_unique_copy(_ForwardIterator, _ForwardIterator, _OutputIterator, _BinaryPredicate,
                                    /*vector=*/std::false_type) noexcept;
 
 template <class _RandomAccessIterator, class _OutputIterator, class _BinaryPredicate>
 _OutputIterator __brick_unique_copy(_RandomAccessIterator, _RandomAccessIterator, _OutputIterator, _BinaryPredicate,
                                     /*vector=*/std::true_type) noexcept;
 
-template <class _ExecutionPolicy, class _ForwardIterator, class _OutputIterator, class _BinaryPredicate,
-          class _IsVector>
+template <class _Tag, class _ExecutionPolicy, class _ForwardIterator, class _OutputIterator, class _BinaryPredicate>
 _OutputIterator
-__pattern_unique_copy(_ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _OutputIterator, _BinaryPredicate,
-                      _IsVector, /*parallel=*/std::false_type) noexcept;
+__pattern_unique_copy(_Tag, _ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _OutputIterator,
+                      _BinaryPredicate) noexcept;
 
 template <class _ExecutionPolicy, class _DifferenceType, class _RandomAccessIterator, class _BinaryPredicate>
 _DifferenceType
@@ -552,11 +525,11 @@ _DifferenceType
 __brick_calc_mask_2(_RandomAccessIterator, _RandomAccessIterator, bool* __restrict, _BinaryPredicate,
                     /*vector=*/std::true_type) noexcept;
 
-template <class _ExecutionPolicy, class _RandomAccessIterator, class _OutputIterator, class _BinaryPredicate,
-          class _IsVector>
+template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _OutputIterator,
+          class _BinaryPredicate>
 _OutputIterator
-__pattern_unique_copy(_ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator, _OutputIterator,
-                      _BinaryPredicate, _IsVector, /*parallel=*/std::true_type);
+__pattern_unique_copy(__parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator,
+                      _OutputIterator, _BinaryPredicate);
 
 //------------------------------------------------------------------------
 // reverse
@@ -566,27 +539,25 @@ template <class _BidirectionalIterator>
 void __brick_reverse(_BidirectionalIterator, _BidirectionalIterator,
                      /*__is_vector=*/std::false_type) noexcept;
 
-template <class _BidirectionalIterator>
-void __brick_reverse(_BidirectionalIterator, _BidirectionalIterator,
+template <class _RandomAccessIterator>
+void __brick_reverse(_RandomAccessIterator, _RandomAccessIterator,
                      /*__is_vector=*/std::true_type) noexcept;
 
 template <class _BidirectionalIterator>
 void __brick_reverse(_BidirectionalIterator, _BidirectionalIterator, _BidirectionalIterator,
                      /*is_vector=*/std::false_type) noexcept;
 
-template <class _BidirectionalIterator>
-void __brick_reverse(_BidirectionalIterator, _BidirectionalIterator, _BidirectionalIterator,
+template <class _RandomAccessIterator>
+void __brick_reverse(_RandomAccessIterator, _RandomAccessIterator, _RandomAccessIterator,
                      /*is_vector=*/std::true_type) noexcept;
 
-template <class _ExecutionPolicy, class _BidirectionalIterator, class _IsVector>
+template <class _Tag, class _ExecutionPolicy, class _BidirectionalIterator>
 void
-__pattern_reverse(_ExecutionPolicy&&, _BidirectionalIterator, _BidirectionalIterator, _IsVector,
-                  /*is_parallel=*/std::false_type) noexcept;
+__pattern_reverse(_Tag, _ExecutionPolicy&&, _BidirectionalIterator, _BidirectionalIterator) noexcept;
 
-template <class _ExecutionPolicy, class _BidirectionalIterator, class _IsVector>
+template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator>
 void
-__pattern_reverse(_ExecutionPolicy&&, _BidirectionalIterator, _BidirectionalIterator, _IsVector,
-                  /*is_parallel=*/std::true_type);
+__pattern_reverse(__parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator);
 
 //------------------------------------------------------------------------
 // reverse_copy
@@ -596,19 +567,19 @@ template <class _BidirectionalIterator, class _OutputIterator>
 _OutputIterator __brick_reverse_copy(_BidirectionalIterator, _BidirectionalIterator, _OutputIterator,
                                      /*is_vector=*/std::false_type) noexcept;
 
-template <class _BidirectionalIterator, class _OutputIterator>
-_OutputIterator __brick_reverse_copy(_BidirectionalIterator, _BidirectionalIterator, _OutputIterator,
+template <class _RandomAccessIterator, class _OutputIterator>
+_OutputIterator __brick_reverse_copy(_RandomAccessIterator, _RandomAccessIterator, _OutputIterator,
                                      /*is_vector=*/std::true_type) noexcept;
 
-template <class _ExecutionPolicy, class _BidirectionalIterator, class _OutputIterator, class _IsVector>
+template <class _Tag, class _ExecutionPolicy, class _BidirectionalIterator, class _OutputIterator>
 _OutputIterator
-__pattern_reverse_copy(_ExecutionPolicy&&, _BidirectionalIterator, _BidirectionalIterator, _OutputIterator, _IsVector,
-                       /*is_parallel=*/std::false_type) noexcept;
+__pattern_reverse_copy(_Tag, _ExecutionPolicy&&, _BidirectionalIterator, _BidirectionalIterator,
+                       _OutputIterator) noexcept;
 
-template <class _ExecutionPolicy, class _BidirectionalIterator, class _OutputIterator, class _IsVector>
+template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _OutputIterator>
 _OutputIterator
-__pattern_reverse_copy(_ExecutionPolicy&&, _BidirectionalIterator, _BidirectionalIterator, _OutputIterator, _IsVector,
-                       /*is_parallel=*/std::true_type);
+__pattern_reverse_copy(__parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator,
+                       _OutputIterator);
 
 //------------------------------------------------------------------------
 // rotate
@@ -618,19 +589,18 @@ template <class _ForwardIterator>
 _ForwardIterator __brick_rotate(_ForwardIterator, _ForwardIterator, _ForwardIterator,
                                 /*is_vector=*/std::false_type) noexcept;
 
-template <class _ForwardIterator>
-_ForwardIterator __brick_rotate(_ForwardIterator, _ForwardIterator, _ForwardIterator,
-                                /*is_vector=*/std::true_type) noexcept;
+template <class _RandomAccessIterator>
+_RandomAccessIterator __brick_rotate(_RandomAccessIterator, _RandomAccessIterator, _RandomAccessIterator,
+                                     /*is_vector=*/std::true_type) noexcept;
 
-template <class _ExecutionPolicy, class _ForwardIterator, class _IsVector>
+template <class _Tag, class _ExecutionPolicy, class _ForwardIterator>
 _ForwardIterator
-__pattern_rotate(_ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _ForwardIterator, _IsVector,
-                 /*is_parallel=*/std::false_type) noexcept;
+__pattern_rotate(_Tag, _ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _ForwardIterator) noexcept;
 
-template <class _ExecutionPolicy, class _ForwardIterator, class _IsVector>
-_ForwardIterator
-__pattern_rotate(_ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _ForwardIterator, _IsVector,
-                 /*is_parallel=*/std::true_type);
+template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator>
+_RandomAccessIterator
+__pattern_rotate(__parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator,
+                 _RandomAccessIterator);
 
 //------------------------------------------------------------------------
 // rotate_copy
@@ -640,21 +610,20 @@ template <class _ForwardIterator, class _OutputIterator>
 _OutputIterator __brick_rotate_copy(_ForwardIterator, _ForwardIterator, _ForwardIterator, _OutputIterator,
                                     /*__is_vector=*/std::false_type) noexcept;
 
-template <class _ForwardIterator, class _OutputIterator>
-_OutputIterator __brick_rotate_copy(_ForwardIterator, _ForwardIterator, _ForwardIterator, _OutputIterator,
+template <class _RandomAccessIterator, class _OutputIterator>
+_OutputIterator __brick_rotate_copy(_RandomAccessIterator, _RandomAccessIterator, _RandomAccessIterator,
+                                    _OutputIterator,
                                     /*__is_vector=*/std::true_type) noexcept;
 
-template <class _ExecutionPolicy, class _ForwardIterator, class _OutputIterator, class _IsVector>
+template <class _Tag, class _ExecutionPolicy, class _ForwardIterator, class _OutputIterator>
 _OutputIterator
-__pattern_rotate_copy(_ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _ForwardIterator, _OutputIterator,
-                      _IsVector,
-                      /*is_parallel=*/std::false_type) noexcept;
+__pattern_rotate_copy(_Tag, _ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _ForwardIterator,
+                      _OutputIterator) noexcept;
 
-template <class _ExecutionPolicy, class _ForwardIterator, class _OutputIterator, class _IsVector>
+template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _OutputIterator>
 _OutputIterator
-__pattern_rotate_copy(_ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _ForwardIterator, _OutputIterator,
-                      _IsVector,
-                      /*is_parallel=*/std::true_type);
+__pattern_rotate_copy(__parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator,
+                      _RandomAccessIterator, _OutputIterator);
 
 //------------------------------------------------------------------------
 // is_partitioned
@@ -664,19 +633,18 @@ template <class _ForwardIterator, class _UnaryPredicate>
 bool __brick_is_partitioned(_ForwardIterator, _ForwardIterator, _UnaryPredicate,
                             /*is_vector=*/std::false_type) noexcept;
 
-template <class _ForwardIterator, class _UnaryPredicate>
-bool __brick_is_partitioned(_ForwardIterator, _ForwardIterator, _UnaryPredicate,
+template <class _RandomAccessIterator, class _UnaryPredicate>
+bool __brick_is_partitioned(_RandomAccessIterator, _RandomAccessIterator, _UnaryPredicate,
                             /*is_vector=*/std::true_type) noexcept;
 
-template <class _ExecutionPolicy, class _ForwardIterator, class _UnaryPredicate, class _IsVector>
+template <class _Tag, class _ExecutionPolicy, class _ForwardIterator, class _UnaryPredicate>
 bool
-__pattern_is_partitioned(_ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _UnaryPredicate, _IsVector,
-                         /*is_parallel=*/std::false_type) noexcept;
+__pattern_is_partitioned(_Tag, _ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _UnaryPredicate) noexcept;
 
-template <class _ExecutionPolicy, class _ForwardIterator, class _UnaryPredicate, class _IsVector>
+template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _UnaryPredicate>
 bool
-__pattern_is_partitioned(_ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _UnaryPredicate, _IsVector,
-                         /*is_parallel=*/std::true_type);
+__pattern_is_partitioned(__parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator,
+                         _UnaryPredicate);
 
 //------------------------------------------------------------------------
 // partition
@@ -686,19 +654,18 @@ template <class _ForwardIterator, class _UnaryPredicate>
 _ForwardIterator __brick_partition(_ForwardIterator, _ForwardIterator, _UnaryPredicate,
                                    /*is_vector=*/std::false_type) noexcept;
 
-template <class _ForwardIterator, class _UnaryPredicate>
-_ForwardIterator __brick_partition(_ForwardIterator, _ForwardIterator, _UnaryPredicate,
-                                   /*is_vector=*/std::true_type) noexcept;
+template <class _RandomAccessIterator, class _UnaryPredicate>
+_RandomAccessIterator __brick_partition(_RandomAccessIterator, _RandomAccessIterator, _UnaryPredicate,
+                                        /*is_vector=*/std::true_type) noexcept;
 
-template <class _ExecutionPolicy, class _ForwardIterator, class _UnaryPredicate, class _IsVector>
+template <class _Tag, class _ExecutionPolicy, class _ForwardIterator, class _UnaryPredicate>
 _ForwardIterator
-__pattern_partition(_ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _UnaryPredicate, _IsVector,
-                    /*is_parallel=*/std::false_type) noexcept;
+__pattern_partition(_Tag, _ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _UnaryPredicate) noexcept;
 
-template <class _ExecutionPolicy, class _ForwardIterator, class _UnaryPredicate, class _IsVector>
-_ForwardIterator
-__pattern_partition(_ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _UnaryPredicate, _IsVector,
-                    /*is_parallel=*/std::true_type);
+template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _UnaryPredicate>
+_RandomAccessIterator
+__pattern_partition(__parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator,
+                    _UnaryPredicate);
 
 //------------------------------------------------------------------------
 // stable_partition
@@ -708,21 +675,19 @@ template <class _BidirectionalIterator, class _UnaryPredicate>
 _BidirectionalIterator __brick_stable_partition(_BidirectionalIterator, _BidirectionalIterator, _UnaryPredicate,
                                                 /*__is_vector=*/std::false_type) noexcept;
 
-template <class _BidirectionalIterator, class _UnaryPredicate>
-_BidirectionalIterator __brick_stable_partition(_BidirectionalIterator, _BidirectionalIterator, _UnaryPredicate,
-                                                /*__is_vector=*/std::true_type) noexcept;
+template <class _RandomAccessIterator, class _UnaryPredicate>
+_RandomAccessIterator __brick_stable_partition(_RandomAccessIterator, _RandomAccessIterator, _UnaryPredicate,
+                                               /*__is_vector=*/std::true_type) noexcept;
 
-template <class _ExecutionPolicy, class _BidirectionalIterator, class _UnaryPredicate, class _IsVector>
+template <class _Tag, class _ExecutionPolicy, class _BidirectionalIterator, class _UnaryPredicate>
 _BidirectionalIterator
-__pattern_stable_partition(_ExecutionPolicy&&, _BidirectionalIterator, _BidirectionalIterator, _UnaryPredicate,
-                           _IsVector,
-                           /*is_parallelization=*/std::false_type) noexcept;
+__pattern_stable_partition(_Tag, _ExecutionPolicy&&, _BidirectionalIterator, _BidirectionalIterator,
+                           _UnaryPredicate) noexcept;
 
-template <class _ExecutionPolicy, class _BidirectionalIterator, class _UnaryPredicate, class _IsVector>
-_BidirectionalIterator
-__pattern_stable_partition(_ExecutionPolicy&&, _BidirectionalIterator, _BidirectionalIterator, _UnaryPredicate,
-                           _IsVector,
-                           /*is_parallelization=*/std::true_type) noexcept;
+template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _UnaryPredicate>
+_RandomAccessIterator
+__pattern_stable_partition(__parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator,
+                           _UnaryPredicate) noexcept;
 
 //------------------------------------------------------------------------
 // partition_copy
@@ -733,134 +698,123 @@ std::pair<_OutputIterator1, _OutputIterator2>
     __brick_partition_copy(_ForwardIterator, _ForwardIterator, _OutputIterator1, _OutputIterator2, _UnaryPredicate,
                            /*is_vector=*/std::false_type) noexcept;
 
-template <class _ForwardIterator, class _OutputIterator1, class _OutputIterator2, class _UnaryPredicate>
-std::pair<_OutputIterator1, _OutputIterator2>
-    __brick_partition_copy(_ForwardIterator, _ForwardIterator, _OutputIterator1, _OutputIterator2, _UnaryPredicate,
-                           /*is_vector=*/std::true_type) noexcept;
+template <class _RandomAccessIterator, class _OutputIterator1, class _OutputIterator2, class _UnaryPredicate>
+std::pair<_OutputIterator1, _OutputIterator2> __brick_partition_copy(_RandomAccessIterator, _RandomAccessIterator,
+                                                                     _OutputIterator1, _OutputIterator2,
+                                                                     _UnaryPredicate,
+                                                                     /*is_vector=*/std::true_type) noexcept;
 
-template <class _ExecutionPolicy, class _ForwardIterator, class _OutputIterator1, class _OutputIterator2,
-          class _UnaryPredicate, class _IsVector>
+template <class _Tag, class _ExecutionPolicy, class _ForwardIterator, class _OutputIterator1, class _OutputIterator2,
+          class _UnaryPredicate>
 std::pair<_OutputIterator1, _OutputIterator2>
-__pattern_partition_copy(_ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _OutputIterator1, _OutputIterator2,
-                         _UnaryPredicate, _IsVector,
-                         /*is_parallelization=*/std::false_type) noexcept;
+__pattern_partition_copy(_Tag, _ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _OutputIterator1,
+                         _OutputIterator2, _UnaryPredicate) noexcept;
 
-template <class _ExecutionPolicy, class _RandomAccessIterator, class _OutputIterator1, class _OutputIterator2,
-          class _UnaryPredicate, class _IsVector>
+template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _OutputIterator1,
+          class _OutputIterator2, class _UnaryPredicate>
 std::pair<_OutputIterator1, _OutputIterator2>
-__pattern_partition_copy(_ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator, _OutputIterator1,
-                         _OutputIterator2, _UnaryPredicate, _IsVector,
-                         /*is_parallelization=*/std::true_type);
+__pattern_partition_copy(__parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator,
+                         _OutputIterator1, _OutputIterator2, _UnaryPredicate);
 
 //------------------------------------------------------------------------
 // sort
 //------------------------------------------------------------------------
 
-template <class _ExecutionPolicy, class _RandomAccessIterator, class _Compare, class _IsVector,
-          class _IsMoveConstructible>
+template <class _Tag, class _ExecutionPolicy, class _RandomAccessIterator, class _Compare, class _IsMoveConstructible>
 void
-__pattern_sort(_ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator, _Compare, _IsVector /*is_vector*/,
-               /*is_parallel=*/std::false_type, _IsMoveConstructible) noexcept;
+__pattern_sort(_Tag, _ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator, _Compare,
+               _IsMoveConstructible) noexcept;
 
-template <class _ExecutionPolicy, class _RandomAccessIterator, class _Compare, class _IsVector>
+template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _Compare>
 void
-__pattern_sort(_ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator, _Compare, _IsVector /*is_vector*/,
-               /*is_parallel=*/std::true_type,
+__pattern_sort(__parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator, _Compare,
                /*is_move_constructible=*/std::true_type);
 
 //------------------------------------------------------------------------
 // stable_sort
 //------------------------------------------------------------------------
 
-template <class _ExecutionPolicy, class _RandomAccessIterator, class _Compare, class _IsVector>
+template <class _Tag, class _ExecutionPolicy, class _RandomAccessIterator, class _Compare>
 void
-__pattern_stable_sort(_ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator, _Compare,
-                      _IsVector /*is_vector*/,
-                      /*is_parallel=*/std::false_type) noexcept;
+__pattern_stable_sort(_Tag, _ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator, _Compare) noexcept;
 
-template <class _ExecutionPolicy, class _RandomAccessIterator, class _Compare, class _IsVector>
+template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _Compare>
 void
-__pattern_stable_sort(_ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator, _Compare,
-                      _IsVector /*is_vector*/,
-                      /*is_parallel=*/std::true_type);
+__pattern_stable_sort(__parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator,
+                      _Compare);
 
 //------------------------------------------------------------------------
 // partial_sort
 //------------------------------------------------------------------------
 
-template <class _ExecutionPolicy, class _RandomAccessIterator, class _Compare, class _IsVector>
+template <class _Tag, class _ExecutionPolicy, class _RandomAccessIterator, class _Compare>
 void
-__pattern_partial_sort(_ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator, _RandomAccessIterator,
-                       _Compare, _IsVector,
-                       /*is_parallel=*/std::false_type) noexcept;
+__pattern_partial_sort(_Tag, _ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator, _RandomAccessIterator,
+                       _Compare) noexcept;
 
-template <class _ExecutionPolicy, class _RandomAccessIterator, class _Compare, class _IsVector>
+template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _Compare>
 void
-__pattern_partial_sort(_ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator, _RandomAccessIterator,
-                       _Compare, _IsVector,
-                       /*is_parallel=*/std::true_type);
+__pattern_partial_sort(__parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator,
+                       _RandomAccessIterator, _Compare);
 
 //------------------------------------------------------------------------
 // partial_sort_copy
 //------------------------------------------------------------------------
 
-template <class _ExecutionPolicy, class _ForwardIterator, class _RandomAccessIterator, class _Compare, class _IsVector>
-_RandomAccessIterator
-__pattern_partial_sort_copy(_ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _RandomAccessIterator,
-                            _RandomAccessIterator, _Compare, _IsVector,
-                            /*is_parallel=*/std::false_type) noexcept;
+template <class _Tag, class _ExecutionPolicy, class _RandomAccessIterator1, class _RandomAccessIterator2,
+          class _Compare>
+_RandomAccessIterator2
+__pattern_partial_sort_copy(_Tag, _ExecutionPolicy&&, _RandomAccessIterator1, _RandomAccessIterator1,
+                            _RandomAccessIterator2, _RandomAccessIterator2, _Compare) noexcept;
 
-template <class _ExecutionPolicy, class _ForwardIterator, class _RandomAccessIterator, class _Compare, class _IsVector>
-_RandomAccessIterator
-__pattern_partial_sort_copy(_ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _RandomAccessIterator,
-                            _RandomAccessIterator, _Compare, _IsVector,
-                            /*is_parallel=*/std::true_type);
+template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator1, class _RandomAccessIterator2,
+          class _Compare>
+_RandomAccessIterator2
+__pattern_partial_sort_copy(__parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator1,
+                            _RandomAccessIterator1, _RandomAccessIterator2, _RandomAccessIterator2, _Compare);
 
 //------------------------------------------------------------------------
 // adjacent_find
 //------------------------------------------------------------------------
 
-template <class _ForwardIterator, class _BinaryPredicate>
-_ForwardIterator
-__brick_adjacent_find(_ForwardIterator, _ForwardIterator, _BinaryPredicate,
-                      /* _IsVector = */ std::true_type, bool) noexcept;
-
-template <class _ForwardIterator, class _BinaryPredicate>
-_ForwardIterator
-__brick_adjacent_find(_ForwardIterator, _ForwardIterator, _BinaryPredicate,
-                      /* _IsVector = */ std::false_type, bool) noexcept;
-
-template <class _ExecutionPolicy, class _ForwardIterator, class _BinaryPredicate, class _IsVector>
-_ForwardIterator
-__pattern_adjacent_find(_ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _BinaryPredicate,
-                        /* is_parallel */ std::false_type, _IsVector, bool) noexcept;
-
-template <class _ExecutionPolicy, class _RandomAccessIterator, class _BinaryPredicate, class _IsVector>
+template <class _RandomAccessIterator, class _BinaryPredicate>
 _RandomAccessIterator
-__pattern_adjacent_find(_ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator, _BinaryPredicate,
-                        /* is_parallel */ std::true_type, _IsVector, bool);
+__brick_adjacent_find(_RandomAccessIterator, _RandomAccessIterator, _BinaryPredicate,
+                      /* IsVector = */ std::true_type, bool) noexcept;
+
+template <class _ForwardIterator, class _BinaryPredicate>
+_ForwardIterator
+__brick_adjacent_find(_ForwardIterator, _ForwardIterator, _BinaryPredicate,
+                      /* IsVector = */ std::false_type, bool) noexcept;
+
+template <class _Tag, class _ExecutionPolicy, class _ForwardIterator, class _BinaryPredicate>
+_ForwardIterator
+__pattern_adjacent_find(_Tag, _ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _BinaryPredicate, bool) noexcept;
+
+template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _BinaryPredicate>
+_RandomAccessIterator
+__pattern_adjacent_find(__parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator,
+                        _BinaryPredicate, bool);
 
 //------------------------------------------------------------------------
 // nth_element
 //------------------------------------------------------------------------
-template <class _ExecutionPolicy, class _RandomAccessIterator, class _Compare, class _IsVector>
+template <class _Tag, class _ExecutionPolicy, class _RandomAccessIterator, class _Compare>
 void
-__pattern_nth_element(_ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator, _RandomAccessIterator, _Compare,
-                      _IsVector,
-                      /*is_parallel=*/std::false_type) noexcept;
+__pattern_nth_element(_Tag, _ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator, _RandomAccessIterator,
+                      _Compare) noexcept;
 
-template <class _ExecutionPolicy, class _RandomAccessIterator, class _Compare, class _IsVector>
+template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _Compare>
 void
-__pattern_nth_element(_ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator, _RandomAccessIterator, _Compare,
-                      _IsVector,
-                      /*is_parallel=*/std::true_type) noexcept;
+__pattern_nth_element(__parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator,
+                      _RandomAccessIterator, _Compare) noexcept;
 
 //------------------------------------------------------------------------
 // fill, fill_n
 //------------------------------------------------------------------------
-template <class _ForwardIterator, class _Tp>
+template <class _RandomAccessIterator, class _Tp>
 void
-__brick_fill(_ForwardIterator, _ForwardIterator, const _Tp&,
+__brick_fill(_RandomAccessIterator, _RandomAccessIterator, const _Tp&,
              /* __is_vector = */ std::true_type) noexcept;
 
 template <class _ForwardIterator, class _Tp>
@@ -868,19 +822,17 @@ void
 __brick_fill(_ForwardIterator, _ForwardIterator, const _Tp&,
              /* __is_vector = */ std::false_type) noexcept;
 
-template <class _ExecutionPolicy, class _ForwardIterator, class _Tp, class _IsVector>
+template <class _Tag, class _ExecutionPolicy, class _ForwardIterator, class _Tp>
 void
-__pattern_fill(_ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, const _Tp&,
-               /*is_parallel=*/std::false_type, _IsVector) noexcept;
+__pattern_fill(_Tag, _ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, const _Tp&) noexcept;
 
-template <class _ExecutionPolicy, class _ForwardIterator, class _Tp, class _IsVector>
-_ForwardIterator
-__pattern_fill(_ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, const _Tp&,
-               /*is_parallel=*/std::true_type, _IsVector);
+template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _Tp>
+_RandomAccessIterator
+__pattern_fill(__parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator, const _Tp&);
 
-template <class _OutputIterator, class _Size, class _Tp>
-_OutputIterator
-__brick_fill_n(_OutputIterator, _Size, const _Tp&,
+template <class _RandomAccessIterator, class _Size, class _Tp>
+_RandomAccessIterator
+__brick_fill_n(_RandomAccessIterator, _Size, const _Tp&,
                /* __is_vector = */ std::true_type) noexcept;
 
 template <class _OutputIterator, class _Size, class _Tp>
@@ -888,15 +840,13 @@ _OutputIterator
 __brick_fill_n(_OutputIterator, _Size, const _Tp&,
                /* __is_vector = */ std::false_type) noexcept;
 
-template <class _ExecutionPolicy, class _OutputIterator, class _Size, class _Tp, class _IsVector>
+template <class _Tag, class _ExecutionPolicy, class _OutputIterator, class _Size, class _Tp>
 _OutputIterator
-__pattern_fill_n(_ExecutionPolicy&&, _OutputIterator, _Size, const _Tp&,
-                 /*is_parallel=*/std::false_type, _IsVector) noexcept;
+__pattern_fill_n(_Tag, _ExecutionPolicy&&, _OutputIterator, _Size, const _Tp&) noexcept;
 
-template <class _ExecutionPolicy, class _OutputIterator, class _Size, class _Tp, class _IsVector>
-_OutputIterator
-__pattern_fill_n(_ExecutionPolicy&&, _OutputIterator, _Size, const _Tp&,
-                 /*is_parallel=*/std::true_type, _IsVector);
+template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _Size, class _Tp>
+_RandomAccessIterator
+__pattern_fill_n(__parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator, _Size, const _Tp&);
 
 //------------------------------------------------------------------------
 // generate, generate_n
@@ -910,33 +860,30 @@ template <class _ForwardIterator, class _Generator>
 void __brick_generate(_ForwardIterator, _ForwardIterator, _Generator,
                       /* is_vector = */ std::false_type) noexcept;
 
-template <class _ExecutionPolicy, class _ForwardIterator, class _Generator, class _IsVector>
+template <class _Tag, class _ExecutionPolicy, class _ForwardIterator, class _Generator>
 void
-__pattern_generate(_ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _Generator,
-                   /*is_parallel=*/std::false_type, _IsVector) noexcept;
+__pattern_generate(_Tag, _ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _Generator) noexcept;
 
-template <class _ExecutionPolicy, class _ForwardIterator, class _Generator, class _IsVector>
-_ForwardIterator
-__pattern_generate(_ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _Generator,
-                   /*is_parallel=*/std::true_type, _IsVector);
+template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _Generator>
+_RandomAccessIterator
+__pattern_generate(__parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator,
+                   _Generator);
+
+template <class _RandomAccessIterator, class _Size, class _Generator>
+_RandomAccessIterator __brick_generate_n(_RandomAccessIterator, _Size, _Generator,
+                                         /* is_vector = */ std::true_type) noexcept;
 
 template <class _OutputIterator, class _Size, class _Generator>
-  _OutputIterator __brick_generate_n(_OutputIterator, _Size, _Generator,
-                                  /* is_vector = */ std::true_type) noexcept;
-
-template <class _OutputIterator, class _Size, class _Generator>
-  _OutputIterator __brick_generate_n(_OutputIterator, _Size, _Generator,
+_OutputIterator __brick_generate_n(_OutputIterator, _Size, _Generator,
                                   /* is_vector = */ std::false_type) noexcept;
 
-template <class _ExecutionPolicy, class _OutputIterator, class _Size, class _Generator, class _IsVector>
-  _OutputIterator
-__pattern_generate_n(_ExecutionPolicy&&, _OutputIterator, _Size, _Generator,
-                     /*is_parallel=*/std::false_type, _IsVector) noexcept;
+template <class _Tag, class _ExecutionPolicy, class _OutputIterator, class _Size, class _Generator>
+_OutputIterator
+__pattern_generate_n(_Tag, _ExecutionPolicy&&, _OutputIterator, _Size, _Generator) noexcept;
 
-template <class _ExecutionPolicy, class _OutputIterator, class _Size, class _Generator, class _IsVector>
-  _OutputIterator
-__pattern_generate_n(_ExecutionPolicy&&, _OutputIterator, _Size, _Generator,
-                     /*is_parallel=*/std::true_type, _IsVector);
+template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _Size, class _Generator>
+_RandomAccessIterator
+__pattern_generate_n(__parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator, _Size, _Generator);
 
 //------------------------------------------------------------------------
 // remove
@@ -949,15 +896,14 @@ template <class _RandomAccessIterator, class _UnaryPredicate>
 _RandomAccessIterator __brick_remove_if(_RandomAccessIterator, _RandomAccessIterator, _UnaryPredicate,
                                         /* __is_vector = */ std::true_type) noexcept;
 
-template <class _ExecutionPolicy, class _ForwardIterator, class _UnaryPredicate, class _IsVector>
+template <class _Tag, class _ExecutionPolicy, class _ForwardIterator, class _UnaryPredicate>
 _ForwardIterator
-__pattern_remove_if(_ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _UnaryPredicate, _IsVector,
-                    /*is_parallel*/ std::false_type) noexcept;
+__pattern_remove_if(_Tag, _ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _UnaryPredicate) noexcept;
 
-template <class _ExecutionPolicy, class _ForwardIterator, class _UnaryPredicate, class _IsVector>
-_ForwardIterator
-__pattern_remove_if(_ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _UnaryPredicate, _IsVector,
-                    /*is_parallel*/ std::true_type) noexcept;
+template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _UnaryPredicate>
+_RandomAccessIterator
+__pattern_remove_if(__parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator,
+                    _UnaryPredicate) noexcept;
 
 //------------------------------------------------------------------------
 // merge
@@ -968,23 +914,22 @@ _OutputIterator __brick_merge(_ForwardIterator1, _ForwardIterator1, _ForwardIter
                               _OutputIterator, _Compare,
                               /* __is_vector = */ std::false_type) noexcept;
 
-template <class _ForwardIterator1, class _ForwardIterator2, class _OutputIterator, class _Compare>
-_OutputIterator __brick_merge(_ForwardIterator1, _ForwardIterator1, _ForwardIterator2, _ForwardIterator2,
-                              _OutputIterator, _Compare,
+template <class _RandomAccessIterator1, class _RandomAccessIterator2, class _OutputIterator, class _Compare>
+_OutputIterator __brick_merge(_RandomAccessIterator1, _RandomAccessIterator1, _RandomAccessIterator2,
+                              _RandomAccessIterator2, _OutputIterator, _Compare,
                               /* __is_vector = */ std::true_type) noexcept;
 
-template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _OutputIterator,
-          class _Compare, class _IsVector>
+template <class _Tag, class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _OutputIterator,
+          class _Compare>
 _OutputIterator
-__pattern_merge(_ExecutionPolicy&&, _ForwardIterator1, _ForwardIterator1, _ForwardIterator2, _ForwardIterator2,
-                _OutputIterator, _Compare, _IsVector, /* is_parallel = */ std::false_type) noexcept;
+__pattern_merge(_Tag, _ExecutionPolicy&&, _ForwardIterator1, _ForwardIterator1, _ForwardIterator2, _ForwardIterator2,
+                _OutputIterator, _Compare) noexcept;
 
-template <class _ExecutionPolicy, class _RandomAccessIterator1, class _RandomAccessIterator2, class _OutputIterator,
-          class _Compare, class _IsVector>
+template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator1, class _RandomAccessIterator2,
+          class _OutputIterator, class _Compare>
 _OutputIterator
-__pattern_merge(_ExecutionPolicy&&, _RandomAccessIterator1, _RandomAccessIterator1, _RandomAccessIterator2,
-                _RandomAccessIterator2, _OutputIterator, _Compare, _IsVector,
-                /* is_parallel = */ std::true_type);
+__pattern_merge(__parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator1, _RandomAccessIterator1,
+                _RandomAccessIterator2, _RandomAccessIterator2, _OutputIterator, _Compare);
 
 //------------------------------------------------------------------------
 // inplace_merge
@@ -994,37 +939,34 @@ template <class _BidirectionalIterator, class _Compare>
 void __brick_inplace_merge(_BidirectionalIterator, _BidirectionalIterator, _BidirectionalIterator, _Compare,
                            /* __is_vector = */ std::false_type) noexcept;
 
-template <class _BidirectionalIterator, class _Compare>
-void __brick_inplace_merge(_BidirectionalIterator, _BidirectionalIterator, _BidirectionalIterator, _Compare,
+template <class _RandomAccessIterator, class _Compare>
+void __brick_inplace_merge(_RandomAccessIterator, _RandomAccessIterator, _RandomAccessIterator, _Compare,
                            /* __is_vector = */ std::true_type) noexcept;
 
-template <class _ExecutionPolicy, class _BidirectionalIterator, class _Compare, class _IsVector>
+template <class _Tag, class _ExecutionPolicy, class _BidirectionalIterator, class _Compare>
 void
-__pattern_inplace_merge(_ExecutionPolicy&&, _BidirectionalIterator, _BidirectionalIterator, _BidirectionalIterator,
-                        _Compare, _IsVector,
-                        /* is_parallel = */ std::false_type) noexcept;
+__pattern_inplace_merge(_Tag, _ExecutionPolicy&&, _BidirectionalIterator, _BidirectionalIterator,
+                        _BidirectionalIterator, _Compare) noexcept;
 
-template <class _ExecutionPolicy, class _BidirectionalIterator, class _Compare, class _IsVector>
+template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _Compare>
 void
-__pattern_inplace_merge(_ExecutionPolicy&&, _BidirectionalIterator, _BidirectionalIterator, _BidirectionalIterator,
-                        _Compare, _IsVector,
-                        /*is_parallel=*/std::true_type);
+__pattern_inplace_merge(__parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator,
+                        _RandomAccessIterator, _Compare);
 
 //------------------------------------------------------------------------
 // includes
 //------------------------------------------------------------------------
 
-template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _Compare, class _IsVector>
+template <class _Tag, class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _Compare>
 bool
-__pattern_includes(_ExecutionPolicy&&, _ForwardIterator1, _ForwardIterator1, _ForwardIterator2, _ForwardIterator2,
-                   _Compare, _IsVector,
-                   /*is_parallel=*/std::false_type) noexcept;
+__pattern_includes(_Tag, _ExecutionPolicy&&, _ForwardIterator1, _ForwardIterator1, _ForwardIterator2, _ForwardIterator2,
+                   _Compare) noexcept;
 
-template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _Compare, class _IsVector>
+template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator1, class _RandomAccessIterator2,
+          class _Compare>
 bool
-__pattern_includes(_ExecutionPolicy&&, _ForwardIterator1, _ForwardIterator1, _ForwardIterator2, _ForwardIterator2,
-                   _Compare, _IsVector,
-                   /*is_parallel=*/std::true_type);
+__pattern_includes(__parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator1, _RandomAccessIterator1,
+                   _RandomAccessIterator2, _RandomAccessIterator2, _Compare);
 
 //------------------------------------------------------------------------
 // set_union
@@ -1035,22 +977,22 @@ _OutputIterator __brick_set_union(_ForwardIterator1, _ForwardIterator1, _Forward
                                   _OutputIterator, _Compare,
                                   /*__is_vector=*/std::false_type) noexcept;
 
-template <class _ForwardIterator1, class _ForwardIterator2, class _OutputIterator, class _Compare>
-_OutputIterator __brick_set_union(_ForwardIterator1, _ForwardIterator1, _ForwardIterator2, _ForwardIterator2,
-                                  _OutputIterator, _Compare,
+template <class _RandomAccessIterator1, class _RandomAccessIterator2, class _OutputIterator, class _Compare>
+_OutputIterator __brick_set_union(_RandomAccessIterator1, _RandomAccessIterator1, _RandomAccessIterator2,
+                                  _RandomAccessIterator2, _OutputIterator, _Compare,
                                   /*__is_vector=*/std::true_type) noexcept;
 
-template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _OutputIterator,
-          class _Compare, class _IsVector>
+template <class _Tag, class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _OutputIterator,
+          class _Compare>
 _OutputIterator
-__pattern_set_union(_ExecutionPolicy&&, _ForwardIterator1, _ForwardIterator1, _ForwardIterator2, _ForwardIterator2,
-                    _OutputIterator, _Compare, _IsVector, /*is_parallel=*/std::false_type) noexcept;
+__pattern_set_union(_Tag, _ExecutionPolicy&&, _ForwardIterator1, _ForwardIterator1, _ForwardIterator2,
+                    _ForwardIterator2, _OutputIterator, _Compare) noexcept;
 
-template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _OutputIterator,
-          class _Compare, class _IsVector>
+template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator1, class _RandomAccessIterator2,
+          class _OutputIterator, class _Compare>
 _OutputIterator
-__pattern_set_union(_ExecutionPolicy&&, _ForwardIterator1, _ForwardIterator1, _ForwardIterator2, _ForwardIterator2,
-                    _OutputIterator, _Compare, _IsVector, /*is_parallel=*/std::true_type);
+__pattern_set_union(__parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator1, _RandomAccessIterator1,
+                    _RandomAccessIterator2, _RandomAccessIterator2, _OutputIterator, _Compare);
 
 //------------------------------------------------------------------------
 // set_intersection
@@ -1061,23 +1003,23 @@ _OutputIterator __brick_set_intersection(_ForwardIterator1, _ForwardIterator1, _
                                          _OutputIterator, _Compare,
                                          /*__is_vector=*/std::false_type) noexcept;
 
-template <class _ForwardIterator1, class _ForwardIterator2, class _OutputIterator, class _Compare>
-_OutputIterator __brick_set_intersection(_ForwardIterator1, _ForwardIterator1, _ForwardIterator2, _ForwardIterator2,
-                                         _OutputIterator, _Compare,
+template <class _RandomAccessIterator1, class _RandomAccessIterator2, class _OutputIterator, class _Compare>
+_OutputIterator __brick_set_intersection(_RandomAccessIterator1, _RandomAccessIterator1, _RandomAccessIterator2,
+                                         _RandomAccessIterator2, _OutputIterator, _Compare,
                                          /*__is_vector=*/std::true_type) noexcept;
 
-template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _OutputIterator,
-          class _Compare, class _IsVector>
+template <class _Tag, class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _OutputIterator,
+          class _Compare>
 _OutputIterator
-__pattern_set_intersection(_ExecutionPolicy&&, _ForwardIterator1, _ForwardIterator1, _ForwardIterator2,
-                           _ForwardIterator2, _OutputIterator, _Compare, _IsVector,
-                           /*is_parallel=*/std::false_type) noexcept;
+__pattern_set_intersection(_Tag, _ExecutionPolicy&&, _ForwardIterator1, _ForwardIterator1, _ForwardIterator2,
+                           _ForwardIterator2, _OutputIterator, _Compare) noexcept;
 
-template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _OutputIterator,
-          class _Compare, class _IsVector>
+template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator1, class _RandomAccessIterator2,
+          class _OutputIterator, class _Compare>
 _OutputIterator
-__pattern_set_intersection(_ExecutionPolicy&&, _ForwardIterator1, _ForwardIterator1, _ForwardIterator2,
-                           _ForwardIterator2, _OutputIterator, _Compare, _IsVector, /*is_parallel=*/std::true_type);
+__pattern_set_intersection(__parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator1,
+                           _RandomAccessIterator1, _RandomAccessIterator2, _RandomAccessIterator2, _OutputIterator,
+                           _Compare);
 
 //------------------------------------------------------------------------
 // set_difference
@@ -1088,22 +1030,22 @@ _OutputIterator __brick_set_difference(_ForwardIterator1, _ForwardIterator1, _Fo
                                        _OutputIterator, _Compare,
                                        /*__is_vector=*/std::false_type) noexcept;
 
-template <class _ForwardIterator1, class _ForwardIterator2, class _OutputIterator, class _Compare>
-_OutputIterator __brick_set_difference(_ForwardIterator1, _ForwardIterator1, _ForwardIterator2, _ForwardIterator2,
-                                       _OutputIterator, _Compare,
+template <class _RandomAccessIterator1, class _RandomAccessIterator2, class _OutputIterator, class _Compare>
+_OutputIterator __brick_set_difference(_RandomAccessIterator1, _RandomAccessIterator1, _RandomAccessIterator2,
+                                       _RandomAccessIterator2, _OutputIterator, _Compare,
                                        /*__is_vector=*/std::true_type) noexcept;
 
-template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _OutputIterator,
-          class _Compare, class _IsVector>
+template <class _Tag, class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _OutputIterator,
+          class _Compare>
 _OutputIterator
-__pattern_set_difference(_ExecutionPolicy&&, _ForwardIterator1, _ForwardIterator1, _ForwardIterator2, _ForwardIterator2,
-                         _OutputIterator, _Compare, _IsVector, /*is_parallel=*/std::false_type) noexcept;
+__pattern_set_difference(_Tag, _ExecutionPolicy&&, _ForwardIterator1, _ForwardIterator1, _ForwardIterator2,
+                         _ForwardIterator2, _OutputIterator, _Compare) noexcept;
 
-template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _OutputIterator,
-          class _Compare, class _IsVector>
+template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator1, class _RandomAccessIterator2,
+          class _OutputIterator, class _Compare>
 _OutputIterator
-__pattern_set_difference(_ExecutionPolicy&&, _ForwardIterator1, _ForwardIterator1, _ForwardIterator2, _ForwardIterator2,
-                         _OutputIterator, _Compare, _IsVector, /*is_parallel=*/std::true_type);
+__pattern_set_difference(__parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator1, _RandomAccessIterator1,
+                         _RandomAccessIterator2, _RandomAccessIterator2, _OutputIterator, _Compare);
 
 //------------------------------------------------------------------------
 // set_symmetric_difference
@@ -1114,24 +1056,23 @@ _OutputIterator __brick_set_symmetric_difference(_ForwardIterator1, _ForwardIter
                                                  _ForwardIterator2, _OutputIterator, _Compare,
                                                  /*__is_vector=*/std::false_type) noexcept;
 
-template <class _ForwardIterator1, class _ForwardIterator2, class _OutputIterator, class _Compare>
-_OutputIterator __brick_set_symmetric_difference(_ForwardIterator1, _ForwardIterator1, _ForwardIterator2,
-                                                 _ForwardIterator2, _OutputIterator, _Compare,
+template <class _RandomAccessIterator1, class _RandomAccessIterator2, class _OutputIterator, class _Compare>
+_OutputIterator __brick_set_symmetric_difference(_RandomAccessIterator1, _RandomAccessIterator1, _RandomAccessIterator2,
+                                                 _RandomAccessIterator2, _OutputIterator, _Compare,
                                                  /*__is_vector=*/std::true_type) noexcept;
 
-template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _OutputIterator,
-          class _Compare, class _IsVector>
+template <class _Tag, class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _OutputIterator,
+          class _Compare>
 _OutputIterator
-__pattern_set_symmetric_difference(_ExecutionPolicy&&, _ForwardIterator1, _ForwardIterator1, _ForwardIterator2,
-                                   _ForwardIterator2, _OutputIterator, _Compare, _IsVector,
-                                   /*is_parallel=*/std::false_type) noexcept;
+__pattern_set_symmetric_difference(_Tag, _ExecutionPolicy&&, _ForwardIterator1, _ForwardIterator1, _ForwardIterator2,
+                                   _ForwardIterator2, _OutputIterator, _Compare) noexcept;
 
-template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _OutputIterator,
-          class _Compare, class _IsVector>
+template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator1, class _RandomAccessIterator2,
+          class _OutputIterator, class _Compare>
 _OutputIterator
-__pattern_set_symmetric_difference(_ExecutionPolicy&&, _ForwardIterator1, _ForwardIterator1, _ForwardIterator2,
-                                   _ForwardIterator2, _OutputIterator, _Compare, _IsVector,
-                                   /*is_parallel=*/std::true_type);
+__pattern_set_symmetric_difference(__parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator1,
+                                   _RandomAccessIterator1, _RandomAccessIterator2, _RandomAccessIterator2,
+                                   _OutputIterator, _Compare);
 
 //------------------------------------------------------------------------
 // is_heap_until
@@ -1145,15 +1086,14 @@ template <class _RandomAccessIterator, class _Compare>
 _RandomAccessIterator __brick_is_heap_until(_RandomAccessIterator, _RandomAccessIterator, _Compare,
                                             /* __is_vector = */ std::true_type) noexcept;
 
-template <class _ExecutionPolicy, class _RandomAccessIterator, class _Compare, class _IsVector>
+template <class _Tag, class _ExecutionPolicy, class _RandomAccessIterator, class _Compare>
 _RandomAccessIterator
-__pattern_is_heap_until(_ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator, _Compare, _IsVector,
-                        /* is_parallel = */ std::false_type) noexcept;
+__pattern_is_heap_until(_Tag, _ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator, _Compare) noexcept;
 
-template <class _ExecutionPolicy, class _RandomAccessIterator, class _Compare, class _IsVector>
+template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _Compare>
 _RandomAccessIterator
-__pattern_is_heap_until(_ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator, _Compare, _IsVector,
-                        /* is_parallel = */ std::true_type) noexcept;
+__pattern_is_heap_until(__parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator,
+                        _Compare) noexcept;
 
 //------------------------------------------------------------------------
 // min_element
@@ -1163,19 +1103,18 @@ template <typename _ForwardIterator, typename _Compare>
 _ForwardIterator __brick_min_element(_ForwardIterator, _ForwardIterator, _Compare,
                                      /* __is_vector = */ std::false_type) noexcept;
 
-template <typename _ForwardIterator, typename _Compare>
-_ForwardIterator __brick_min_element(_ForwardIterator, _ForwardIterator, _Compare,
-                                     /* __is_vector = */ std::true_type) noexcept;
+template <typename _RandomAccessIterator, typename _Compare>
+_RandomAccessIterator __brick_min_element(_RandomAccessIterator, _RandomAccessIterator, _Compare,
+                                          /* __is_vector = */ std::true_type) noexcept;
 
-template <typename _ExecutionPolicy, typename _ForwardIterator, typename _Compare, typename _IsVector>
+template <typename _Tag, typename _ExecutionPolicy, typename _ForwardIterator, typename _Compare>
 _ForwardIterator
-__pattern_min_element(_ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _Compare, _IsVector,
-                      /* is_parallel = */ std::false_type) noexcept;
+__pattern_min_element(_Tag, _ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _Compare) noexcept;
 
-template <typename _ExecutionPolicy, typename _RandomAccessIterator, typename _Compare, typename _IsVector>
+template <typename _IsVector, typename _ExecutionPolicy, typename _RandomAccessIterator, typename _Compare>
 _RandomAccessIterator
-__pattern_min_element(_ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator, _Compare, _IsVector,
-                      /* is_parallel = */ std::true_type);
+__pattern_min_element(__parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator,
+                      _Compare);
 
 //------------------------------------------------------------------------
 // minmax_element
@@ -1185,19 +1124,19 @@ template <typename _ForwardIterator, typename _Compare>
 std::pair<_ForwardIterator, _ForwardIterator> __brick_minmax_element(_ForwardIterator, _ForwardIterator, _Compare,
                                                                      /* __is_vector = */ std::false_type) noexcept;
 
-template <typename _ForwardIterator, typename _Compare>
-std::pair<_ForwardIterator, _ForwardIterator> __brick_minmax_element(_ForwardIterator, _ForwardIterator, _Compare,
-                                                                     /* __is_vector = */ std::true_type) noexcept;
+template <typename _RandomAccessIterator, typename _Compare>
+std::pair<_RandomAccessIterator, _RandomAccessIterator>
+    __brick_minmax_element(_RandomAccessIterator, _RandomAccessIterator, _Compare,
+                           /* __is_vector = */ std::true_type) noexcept;
 
-template <typename _ExecutionPolicy, typename _ForwardIterator, typename _Compare, typename _IsVector>
+template <typename _Tag, typename _ExecutionPolicy, typename _ForwardIterator, typename _Compare>
 std::pair<_ForwardIterator, _ForwardIterator>
-__pattern_minmax_element(_ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _Compare, _IsVector,
-                         /* is_parallel = */ std::false_type) noexcept;
+__pattern_minmax_element(_Tag, _ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _Compare) noexcept;
 
-template <typename _ExecutionPolicy, typename _ForwardIterator, typename _Compare, typename _IsVector>
-std::pair<_ForwardIterator, _ForwardIterator>
-__pattern_minmax_element(_ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _Compare, _IsVector,
-                         /* is_parallel = */ std::true_type);
+template <typename _IsVector, typename _ExecutionPolicy, typename _RandomAccessIterator, typename _Compare>
+std::pair<_RandomAccessIterator, _RandomAccessIterator>
+__pattern_minmax_element(__parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator,
+                         _Compare);
 
 //------------------------------------------------------------------------
 // mismatch
@@ -1208,22 +1147,22 @@ std::pair<_ForwardIterator1, _ForwardIterator2> __brick_mismatch(_ForwardIterato
                                                                  _ForwardIterator2, _ForwardIterator2, _Predicate,
                                                                  /* __is_vector = */ std::false_type) noexcept;
 
-template <class _ForwardIterator1, class _ForwardIterator2, class _Predicate>
-std::pair<_ForwardIterator1, _ForwardIterator2> __brick_mismatch(_ForwardIterator1, _ForwardIterator1,
-                                                                 _ForwardIterator2, _ForwardIterator2, _Predicate,
-                                                                 /* __is_vector = */ std::true_type) noexcept;
-
-template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _Predicate, class _IsVector>
-std::pair<_ForwardIterator1, _ForwardIterator2>
-__pattern_mismatch(_ExecutionPolicy&&, _ForwardIterator1, _ForwardIterator1, _ForwardIterator2, _ForwardIterator2,
-                   _Predicate, _IsVector,
-                   /* is_parallel = */ std::false_type) noexcept;
-
-template <class _ExecutionPolicy, class _RandomAccessIterator1, class _RandomAccessIterator2, class _Predicate,
-          class _IsVector>
+template <class _RandomAccessIterator1, class _RandomAccessIterator2, class _Predicate>
 std::pair<_RandomAccessIterator1, _RandomAccessIterator2>
-__pattern_mismatch(_ExecutionPolicy&&, _RandomAccessIterator1, _RandomAccessIterator1, _RandomAccessIterator2,
-                   _RandomAccessIterator2, _Predicate, _IsVector, /* is_parallel = */ std::true_type) noexcept;
+    __brick_mismatch(_RandomAccessIterator1, _RandomAccessIterator1, _RandomAccessIterator2, _RandomAccessIterator2,
+                     _Predicate,
+                     /* __is_vector = */ std::true_type) noexcept;
+
+template <class _Tag, class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _Predicate>
+std::pair<_ForwardIterator1, _ForwardIterator2>
+__pattern_mismatch(_Tag, _ExecutionPolicy&&, _ForwardIterator1, _ForwardIterator1, _ForwardIterator2, _ForwardIterator2,
+                   _Predicate) noexcept;
+
+template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator1, class _RandomAccessIterator2,
+          class _Predicate>
+std::pair<_RandomAccessIterator1, _RandomAccessIterator2>
+__pattern_mismatch(__parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator1, _RandomAccessIterator1,
+                   _RandomAccessIterator2, _RandomAccessIterator2, _Predicate) noexcept;
 
 //------------------------------------------------------------------------
 // lexicographical_compare
@@ -1234,20 +1173,22 @@ bool __brick_lexicographical_compare(_ForwardIterator1, _ForwardIterator1, _Forw
                                      _Compare,
                                      /* __is_vector = */ std::false_type) noexcept;
 
-template <class _ForwardIterator1, class _ForwardIterator2, class _Compare>
-bool __brick_lexicographical_compare(_ForwardIterator1, _ForwardIterator1, _ForwardIterator2, _ForwardIterator2,
-                                     _Compare,
+template <class _RandomAccessIterator1, class _RandomAccessIterator2, class _Compare>
+bool __brick_lexicographical_compare(_RandomAccessIterator1, _RandomAccessIterator1, _RandomAccessIterator2,
+                                     _RandomAccessIterator2, _Compare,
                                      /* __is_vector = */ std::true_type) noexcept;
 
-template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _Compare, class _IsVector>
+template <class _Tag, class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _Compare>
 bool
-__pattern_lexicographical_compare(_ExecutionPolicy&&, _ForwardIterator1, _ForwardIterator1, _ForwardIterator2,
-                                  _ForwardIterator2, _Compare, _IsVector, /* is_parallel = */ std::false_type) noexcept;
+__pattern_lexicographical_compare(_Tag, _ExecutionPolicy&&, _ForwardIterator1, _ForwardIterator1, _ForwardIterator2,
+                                  _ForwardIterator2, _Compare) noexcept;
 
-template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _Compare, class _IsVector>
+template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator1, class _RandomAccessIterator2,
+          class _Compare>
 bool
-__pattern_lexicographical_compare(_ExecutionPolicy&&, _ForwardIterator1, _ForwardIterator1, _ForwardIterator2,
-                                  _ForwardIterator2, _Compare, _IsVector, /* is_parallel = */ std::true_type) noexcept;
+__pattern_lexicographical_compare(__parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator1,
+                                  _RandomAccessIterator1, _RandomAccessIterator2, _RandomAccessIterator2,
+                                  _Compare) noexcept;
 
 } // namespace __internal
 } // namespace __pstl
diff --git a/libstdc++-v3/include/pstl/algorithm_impl.h b/libstdc++-v3/include/pstl/algorithm_impl.h
index 32c19990ed0..a30d6b5f0e3 100644
--- a/libstdc++-v3/include/pstl/algorithm_impl.h
+++ b/libstdc++-v3/include/pstl/algorithm_impl.h
@@ -41,33 +41,35 @@ __brick_any_of(const _ForwardIterator __first, const _ForwardIterator __last, _P
     return std::any_of(__first, __last, __pred);
 };
 
-template <class _ForwardIterator, class _Pred>
+template <class _RandomAccessIterator, class _Pred>
 bool
-__brick_any_of(const _ForwardIterator __first, const _ForwardIterator __last, _Pred __pred,
+__brick_any_of(const _RandomAccessIterator __first, const _RandomAccessIterator __last, _Pred __pred,
                /*__is_vector=*/std::true_type) noexcept
 {
     return __unseq_backend::__simd_or(__first, __last - __first, __pred);
 };
 
-template <class _ExecutionPolicy, class _ForwardIterator, class _Pred, class _IsVector>
+template <class _Tag, class _ExecutionPolicy, class _ForwardIterator, class _Pred>
 bool
-__pattern_any_of(_ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last, _Pred __pred,
-                 _IsVector __is_vector, /*parallel=*/std::false_type) noexcept
+__pattern_any_of(_Tag, _ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last, _Pred __pred) noexcept
 {
-    return __internal::__brick_any_of(__first, __last, __pred, __is_vector);
+    return __internal::__brick_any_of(__first, __last, __pred, typename _Tag::__is_vector{});
 }
 
-template <class _ExecutionPolicy, class _ForwardIterator, class _Pred, class _IsVector>
+template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _Pred>
 bool
-__pattern_any_of(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _Pred __pred,
-                 _IsVector __is_vector, /*parallel=*/std::true_type)
+__pattern_any_of(__parallel_tag<_IsVector> __tag, _ExecutionPolicy&& __exec, _RandomAccessIterator __first,
+                 _RandomAccessIterator __last, _Pred __pred)
 {
-    return __internal::__except_handler([&]() {
-        return __internal::__parallel_or(std::forward<_ExecutionPolicy>(__exec), __first, __last,
-                                         [__pred, __is_vector](_ForwardIterator __i, _ForwardIterator __j) {
-                                             return __internal::__brick_any_of(__i, __j, __pred, __is_vector);
-                                         });
-    });
+    using __backend_tag = typename decltype(__tag)::__backend_tag;
+
+    return __internal::__except_handler(
+        [&]()
+        {
+            return __internal::__parallel_or(__backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __first, __last,
+                                             [__pred](_RandomAccessIterator __i, _RandomAccessIterator __j)
+                                             { return __internal::__brick_any_of(__i, __j, __pred, _IsVector{}); });
+        });
 }
 
 // [alg.foreach]
@@ -102,46 +104,51 @@ __brick_walk1(_RandomAccessIterator __first, _RandomAccessIterator __last, _Func
     __unseq_backend::__simd_walk_1(__first, __last - __first, __f);
 }
 
-template <class _ExecutionPolicy, class _ForwardIterator, class _Function, class _IsVector>
+template <class _Tag, class _ExecutionPolicy, class _ForwardIterator, class _Function>
 void
-__pattern_walk1(_ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last, _Function __f,
-                _IsVector __is_vector,
-                /*parallel=*/std::false_type) noexcept
+__pattern_walk1(_Tag, _ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last, _Function __f) noexcept
 {
-    __internal::__brick_walk1(__first, __last, __f, __is_vector);
+    __internal::__brick_walk1(__first, __last, __f, typename _Tag::__is_vector{});
 }
 
-template <class _ExecutionPolicy, class _ForwardIterator, class _Function, class _IsVector>
+template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _Function>
 void
-__pattern_walk1(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _Function __f,
-                _IsVector __is_vector,
-                /*parallel=*/std::true_type)
+__pattern_walk1(__parallel_tag<_IsVector> __tag, _ExecutionPolicy&& __exec, _RandomAccessIterator __first,
+                _RandomAccessIterator __last, _Function __f)
 {
-    __internal::__except_handler([&]() {
-        __par_backend::__parallel_for(std::forward<_ExecutionPolicy>(__exec), __first, __last,
-                                      [__f, __is_vector](_ForwardIterator __i, _ForwardIterator __j) {
-                                          __internal::__brick_walk1(__i, __j, __f, __is_vector);
-                                      });
-    });
+    using __backend_tag = typename decltype(__tag)::__backend_tag;
+
+    __internal::__except_handler(
+        [&]()
+        {
+            __par_backend::__parallel_for(__backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __first, __last,
+                                          [__f](_RandomAccessIterator __i, _RandomAccessIterator __j)
+                                          { __internal::__brick_walk1(__i, __j, __f, _IsVector{}); });
+        });
 }
 
-template <class _ExecutionPolicy, class _ForwardIterator, class _Brick>
+template <class _Tag, class _ExecutionPolicy, class _ForwardIterator, class _Brick>
 void
-__pattern_walk_brick(_ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last, _Brick __brick,
-                     /*parallel=*/std::false_type) noexcept
+__pattern_walk_brick(_Tag, _ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last,
+                     _Brick __brick) noexcept
 {
     __brick(__first, __last);
 }
 
-template <class _ExecutionPolicy, class _ForwardIterator, class _Brick>
+template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _Brick>
 void
-__pattern_walk_brick(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _Brick __brick,
-                     /*parallel=*/std::true_type)
+__pattern_walk_brick(__parallel_tag<_IsVector> __tag, _ExecutionPolicy&& __exec, _RandomAccessIterator __first,
+                     _RandomAccessIterator __last, _Brick __brick)
 {
-    __internal::__except_handler([&]() {
-        __par_backend::__parallel_for(std::forward<_ExecutionPolicy>(__exec), __first, __last,
-                                      [__brick](_ForwardIterator __i, _ForwardIterator __j) { __brick(__i, __j); });
-    });
+    using __backend_tag = typename decltype(__tag)::__backend_tag;
+
+    __internal::__except_handler(
+        [&]()
+        {
+            __par_backend::__parallel_for(__backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __first, __last,
+                                          [__brick](_RandomAccessIterator __i, _RandomAccessIterator __j)
+                                          { __brick(__i, __j); });
+        });
 }
 
 //------------------------------------------------------------------------
@@ -163,44 +170,45 @@ __brick_walk1_n(_RandomAccessIterator __first, _DifferenceType __n, _Function __
     return __unseq_backend::__simd_walk_1(__first, __n, __f);
 }
 
-template <class _ExecutionPolicy, class _ForwardIterator, class _Size, class _Function, class _IsVector>
+template <class _Tag, class _ExecutionPolicy, class _ForwardIterator, class _Size, class _Function>
 _ForwardIterator
-__pattern_walk1_n(_ExecutionPolicy&&, _ForwardIterator __first, _Size __n, _Function __f, _IsVector __is_vector,
-                  /*is_parallel=*/std::false_type) noexcept
+__pattern_walk1_n(_Tag, _ExecutionPolicy&&, _ForwardIterator __first, _Size __n, _Function __f) noexcept
 {
-    return __internal::__brick_walk1_n(__first, __n, __f, __is_vector);
+    return __internal::__brick_walk1_n(__first, __n, __f, typename _Tag::__is_vector{});
 }
 
-template <class _ExecutionPolicy, class _RandomAccessIterator, class _Size, class _Function, class _IsVector>
+template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _Size, class _Function>
 _RandomAccessIterator
-__pattern_walk1_n(_ExecutionPolicy&& __exec, _RandomAccessIterator __first, _Size __n, _Function __f,
-                  _IsVector __is_vector,
-                  /*is_parallel=*/std::true_type)
+__pattern_walk1_n(__parallel_tag<_IsVector> __tag, _ExecutionPolicy&& __exec, _RandomAccessIterator __first, _Size __n,
+                  _Function __f)
 {
-    __internal::__pattern_walk1(std::forward<_ExecutionPolicy>(__exec), __first, __first + __n, __f, __is_vector,
-                                std::true_type());
+    __internal::__pattern_walk1(__tag, std::forward<_ExecutionPolicy>(__exec), __first, __first + __n, __f);
+
     return __first + __n;
 }
 
-template <class _ExecutionPolicy, class _ForwardIterator, class _Size, class _Brick>
+template <class _Tag, class _ExecutionPolicy, class _ForwardIterator, class _Size, class _Brick>
 _ForwardIterator
-__pattern_walk_brick_n(_ExecutionPolicy&&, _ForwardIterator __first, _Size __n, _Brick __brick,
-                       /*is_parallel=*/std::false_type) noexcept
+__pattern_walk_brick_n(_Tag, _ExecutionPolicy&&, _ForwardIterator __first, _Size __n, _Brick __brick) noexcept
 {
     return __brick(__first, __n);
 }
 
-template <class _ExecutionPolicy, class _RandomAccessIterator, class _Size, class _Brick>
+template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _Size, class _Brick>
 _RandomAccessIterator
-__pattern_walk_brick_n(_ExecutionPolicy&& __exec, _RandomAccessIterator __first, _Size __n, _Brick __brick,
-                       /*is_parallel=*/std::true_type)
+__pattern_walk_brick_n(__parallel_tag<_IsVector> __tag, _ExecutionPolicy&& __exec, _RandomAccessIterator __first,
+                       _Size __n, _Brick __brick)
 {
-    return __internal::__except_handler([&]() {
-        __par_backend::__parallel_for(
-            std::forward<_ExecutionPolicy>(__exec), __first, __first + __n,
-            [__brick](_RandomAccessIterator __i, _RandomAccessIterator __j) { __brick(__i, __j - __i); });
-        return __first + __n;
-    });
+    using __backend_tag = typename decltype(__tag)::__backend_tag;
+
+    return __internal::__except_handler(
+        [&]()
+        {
+            __par_backend::__parallel_for(
+                __backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __first, __first + __n,
+                [__brick](_RandomAccessIterator __i, _RandomAccessIterator __j) { __brick(__i, __j - __i); });
+            return __first + __n;
+        });
 }
 
 //------------------------------------------------------------------------
@@ -218,9 +226,10 @@ __brick_walk2(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIte
     return __first2;
 }
 
-template <class _ForwardIterator1, class _ForwardIterator2, class _Function>
-_ForwardIterator2
-__brick_walk2(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2, _Function __f,
+template <class _RandomAccessIterator1, class _RandomAccessIterator2, class _Function>
+_RandomAccessIterator2
+__brick_walk2(_RandomAccessIterator1 __first1, _RandomAccessIterator1 __last1, _RandomAccessIterator2 __first2,
+              _Function __f,
               /*vector=*/std::true_type) noexcept
 {
     return __unseq_backend::__simd_walk_2(__first1, __last1 - __first1, __first2, __f);
@@ -236,102 +245,115 @@ __brick_walk2_n(_ForwardIterator1 __first1, _Size __n, _ForwardIterator2 __first
     return __first2;
 }
 
-template <class _ForwardIterator1, class _Size, class _ForwardIterator2, class _Function>
-_ForwardIterator2
-__brick_walk2_n(_ForwardIterator1 __first1, _Size __n, _ForwardIterator2 __first2, _Function __f,
+template <class _RandomAccessIterator1, class _Size, class _RandomAccessIterator2, class _Function>
+_RandomAccessIterator2
+__brick_walk2_n(_RandomAccessIterator1 __first1, _Size __n, _RandomAccessIterator2 __first2, _Function __f,
                 /*vector=*/std::true_type) noexcept
 {
     return __unseq_backend::__simd_walk_2(__first1, __n, __first2, __f);
 }
 
-template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _Function, class _IsVector>
+template <class _Tag, class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _Function>
 _ForwardIterator2
-__pattern_walk2(_ExecutionPolicy&&, _ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2,
-                _Function __f, _IsVector __is_vector, /*parallel=*/std::false_type) noexcept
+__pattern_walk2(_Tag, _ExecutionPolicy&&, _ForwardIterator1 __first1, _ForwardIterator1 __last1,
+                _ForwardIterator2 __first2, _Function __f) noexcept
 {
-    return __internal::__brick_walk2(__first1, __last1, __first2, __f, __is_vector);
+    return __internal::__brick_walk2(__first1, __last1, __first2, __f, typename _Tag::__is_vector{});
 }
 
-template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _Function, class _IsVector>
-_ForwardIterator2
-__pattern_walk2(_ExecutionPolicy&& __exec, _ForwardIterator1 __first1, _ForwardIterator1 __last1,
-                _ForwardIterator2 __first2, _Function __f, _IsVector __is_vector, /*parallel=*/std::true_type)
-{
-    return __internal::__except_handler([&]() {
-        __par_backend::__parallel_for(
-            std::forward<_ExecutionPolicy>(__exec), __first1, __last1,
-            [__f, __first1, __first2, __is_vector](_ForwardIterator1 __i, _ForwardIterator1 __j) {
-                __internal::__brick_walk2(__i, __j, __first2 + (__i - __first1), __f, __is_vector);
-            });
-        return __first2 + (__last1 - __first1);
-    });
-}
-
-template <class _ExecutionPolicy, class _ForwardIterator1, class _Size, class _ForwardIterator2, class _Function,
-          class _IsVector>
-_ForwardIterator2
-__pattern_walk2_n(_ExecutionPolicy&&, _ForwardIterator1 __first1, _Size __n, _ForwardIterator2 __first2, _Function __f,
-                  _IsVector __is_vector, /*parallel=*/std::false_type) noexcept
-{
-    return __internal::__brick_walk2_n(__first1, __n, __first2, __f, __is_vector);
-}
-
-template <class _ExecutionPolicy, class _RandomAccessIterator1, class _Size, class _RandomAccessIterator2,
-          class _Function, class _IsVector>
+template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator1, class _RandomAccessIterator2,
+          class _Function>
 _RandomAccessIterator2
-__pattern_walk2_n(_ExecutionPolicy&& __exec, _RandomAccessIterator1 __first1, _Size __n, _RandomAccessIterator2 __first2,
-                  _Function __f, _IsVector __is_vector, /*parallel=*/std::true_type)
+__pattern_walk2(__parallel_tag<_IsVector> __tag, _ExecutionPolicy&& __exec, _RandomAccessIterator1 __first1,
+                _RandomAccessIterator1 __last1, _RandomAccessIterator2 __first2, _Function __f)
 {
-    return __internal::__pattern_walk2(std::forward<_ExecutionPolicy>(__exec), __first1, __first1 + __n, __first2, __f,
-                                       __is_vector, std::true_type());
+    using __backend_tag = typename decltype(__tag)::__backend_tag;
+
+    return __internal::__except_handler(
+        [&]()
+        {
+            __par_backend::__parallel_for(
+                __backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __first1, __last1,
+                [__f, __first1, __first2](_RandomAccessIterator1 __i, _RandomAccessIterator1 __j)
+                { __internal::__brick_walk2(__i, __j, __first2 + (__i - __first1), __f, _IsVector{}); });
+            return __first2 + (__last1 - __first1);
+        });
 }
 
-template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _Brick>
+template <class _Tag, class _ExecutionPolicy, class _ForwardIterator1, class _Size, class _ForwardIterator2,
+          class _Function>
 _ForwardIterator2
-__pattern_walk2_brick(_ExecutionPolicy&&, _ForwardIterator1 __first1, _ForwardIterator1 __last1,
-                      _ForwardIterator2 __first2, _Brick __brick, /*parallel=*/std::false_type) noexcept
+__pattern_walk2_n(_Tag, _ExecutionPolicy&&, _ForwardIterator1 __first1, _Size __n, _ForwardIterator2 __first2,
+                  _Function __f) noexcept
+{
+    return __internal::__brick_walk2_n(__first1, __n, __first2, __f, typename _Tag::__is_vector{});
+}
+
+template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator1, class _Size,
+          class _RandomAccessIterator2, class _Function>
+_RandomAccessIterator2
+__pattern_walk2_n(__parallel_tag<_IsVector> __tag, _ExecutionPolicy&& __exec, _RandomAccessIterator1 __first1,
+                  _Size __n, _RandomAccessIterator2 __first2, _Function __f)
+{
+    return __internal::__pattern_walk2(__tag, std::forward<_ExecutionPolicy>(__exec), __first1, __first1 + __n,
+                                       __first2, __f);
+}
+
+template <class _Tag, class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _Brick>
+_ForwardIterator2
+__pattern_walk2_brick(_Tag, _ExecutionPolicy&&, _ForwardIterator1 __first1, _ForwardIterator1 __last1,
+                      _ForwardIterator2 __first2, _Brick __brick) noexcept
 {
     return __brick(__first1, __last1, __first2);
 }
 
-template <class _ExecutionPolicy, class _RandomAccessIterator1, class _RandomAccessIterator2, class _Brick>
+template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator1, class _RandomAccessIterator2,
+          class _Brick>
 _RandomAccessIterator2
-__pattern_walk2_brick(_ExecutionPolicy&& __exec, _RandomAccessIterator1 __first1, _RandomAccessIterator1 __last1,
-                      _RandomAccessIterator2 __first2, _Brick __brick, /*parallel=*/std::true_type)
+__pattern_walk2_brick(__parallel_tag<_IsVector> __tag, _ExecutionPolicy&& __exec, _RandomAccessIterator1 __first1,
+                      _RandomAccessIterator1 __last1, _RandomAccessIterator2 __first2, _Brick __brick)
 {
-    return __internal::__except_handler([&]() {
-        __par_backend::__parallel_for(
-            std::forward<_ExecutionPolicy>(__exec), __first1, __last1,
-            [__first1, __first2, __brick](_RandomAccessIterator1 __i, _RandomAccessIterator1 __j) {
-                __brick(__i, __j, __first2 + (__i - __first1));
-            });
-        return __first2 + (__last1 - __first1);
-    });
+    using __backend_tag = typename decltype(__tag)::__backend_tag;
+
+    return __internal::__except_handler(
+        [&]()
+        {
+            __par_backend::__parallel_for(
+                __backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __first1, __last1,
+                [__first1, __first2, __brick](_RandomAccessIterator1 __i, _RandomAccessIterator1 __j)
+                { __brick(__i, __j, __first2 + (__i - __first1)); });
+            return __first2 + (__last1 - __first1);
+        });
 }
 
-template <class _ExecutionPolicy, class _RandomAccessIterator1, class _Size, class _RandomAccessIterator2, class _Brick>
-_RandomAccessIterator2
-__pattern_walk2_brick_n(_ExecutionPolicy&& __exec, _RandomAccessIterator1 __first1, _Size __n,
-                        _RandomAccessIterator2 __first2, _Brick __brick, /*parallel=*/std::true_type)
-{
-    return __internal::__except_handler([&]() {
-        __par_backend::__parallel_for(
-            std::forward<_ExecutionPolicy>(__exec), __first1, __first1 + __n,
-            [__first1, __first2, __brick](_RandomAccessIterator1 __i, _RandomAccessIterator1 __j) {
-                __brick(__i, __j - __i, __first2 + (__i - __first1));
-            });
-        return __first2 + __n;
-    });
-}
-
-template <class _ExecutionPolicy, class _ForwardIterator1, class _Size, class _ForwardIterator2, class _Brick>
+template <class _Tag, class _ExecutionPolicy, class _ForwardIterator1, class _Size, class _ForwardIterator2,
+          class _Brick>
 _ForwardIterator2
-__pattern_walk2_brick_n(_ExecutionPolicy&&, _ForwardIterator1 __first1, _Size __n, _ForwardIterator2 __first2,
-                        _Brick __brick, /*parallel=*/std::false_type) noexcept
+__pattern_walk2_brick_n(_Tag, _ExecutionPolicy&&, _ForwardIterator1 __first1, _Size __n, _ForwardIterator2 __first2,
+                        _Brick __brick) noexcept
 {
     return __brick(__first1, __n, __first2);
 }
 
+template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator1, class _Size,
+          class _RandomAccessIterator2, class _Brick>
+_RandomAccessIterator2
+__pattern_walk2_brick_n(__parallel_tag<_IsVector> __tag, _ExecutionPolicy&& __exec, _RandomAccessIterator1 __first1,
+                        _Size __n, _RandomAccessIterator2 __first2, _Brick __brick)
+{
+    using __backend_tag = typename decltype(__tag)::__backend_tag;
+
+    return __internal::__except_handler(
+        [&]()
+        {
+            __par_backend::__parallel_for(
+                __backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __first1, __first1 + __n,
+                [__first1, __first2, __brick](_RandomAccessIterator1 __i, _RandomAccessIterator1 __j)
+                { __brick(__i, __j - __i, __first2 + (__i - __first1)); });
+            return __first2 + __n;
+        });
+}
+
 //------------------------------------------------------------------------
 // walk3 (pseudo)
 //
@@ -355,31 +377,35 @@ __brick_walk3(_RandomAccessIterator1 __first1, _RandomAccessIterator1 __last1, _
     return __unseq_backend::__simd_walk_3(__first1, __last1 - __first1, __first2, __first3, __f);
 }
 
-template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _ForwardIterator3,
-          class _Function, class _IsVector>
+template <class _Tag, class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _ForwardIterator3,
+          class _Function>
 _ForwardIterator3
-__pattern_walk3(_ExecutionPolicy&&, _ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2,
-                _ForwardIterator3 __first3, _Function __f, _IsVector __is_vector, /*parallel=*/std::false_type) noexcept
+__pattern_walk3(_Tag, _ExecutionPolicy&&, _ForwardIterator1 __first1, _ForwardIterator1 __last1,
+                _ForwardIterator2 __first2, _ForwardIterator3 __first3, _Function __f) noexcept
 {
-    return __internal::__brick_walk3(__first1, __last1, __first2, __first3, __f, __is_vector);
+    return __internal::__brick_walk3(__first1, __last1, __first2, __first3, __f, typename _Tag::__is_vector{});
 }
 
-template <class _ExecutionPolicy, class _RandomAccessIterator1, class _RandomAccessIterator2,
-          class _RandomAccessIterator3, class _Function, class _IsVector>
+template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator1, class _RandomAccessIterator2,
+          class _RandomAccessIterator3, class _Function>
 _RandomAccessIterator3
-__pattern_walk3(_ExecutionPolicy&& __exec, _RandomAccessIterator1 __first1, _RandomAccessIterator1 __last1,
-                _RandomAccessIterator2 __first2, _RandomAccessIterator3 __first3, _Function __f, _IsVector __is_vector,
-                /*parallel=*/std::true_type)
+__pattern_walk3(__parallel_tag<_IsVector> __tag, _ExecutionPolicy&& __exec, _RandomAccessIterator1 __first1,
+                _RandomAccessIterator1 __last1, _RandomAccessIterator2 __first2, _RandomAccessIterator3 __first3,
+                _Function __f)
 {
-    return __internal::__except_handler([&]() {
-        __par_backend::__parallel_for(
-            std::forward<_ExecutionPolicy>(__exec), __first1, __last1,
-            [__f, __first1, __first2, __first3, __is_vector](_RandomAccessIterator1 __i, _RandomAccessIterator1 __j) {
-                __internal::__brick_walk3(__i, __j, __first2 + (__i - __first1), __first3 + (__i - __first1), __f,
-                                          __is_vector);
-            });
-        return __first3 + (__last1 - __first1);
-    });
+    using __backend_tag = typename decltype(__tag)::__backend_tag;
+
+    return __internal::__except_handler(
+        [&]()
+        {
+            __par_backend::__parallel_for(
+                __backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __first1, __last1,
+                [__f, __first1, __first2, __first3](_RandomAccessIterator1 __i, _RandomAccessIterator1 __j) {
+                    __internal::__brick_walk3(__i, __j, __first2 + (__i - __first1), __first3 + (__i - __first1), __f,
+                                              _IsVector{});
+                });
+            return __first3 + (__last1 - __first1);
+        });
 }
 
 //------------------------------------------------------------------------
@@ -405,34 +431,37 @@ __brick_equal(_RandomAccessIterator1 __first1, _RandomAccessIterator1 __last1, _
     return __unseq_backend::__simd_first(__first1, __last1 - __first1, __first2, std::not_fn(__p)).first == __last1;
 }
 
-template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate,
-          class _IsVector>
+template <class _Tag, class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate>
 bool
-__pattern_equal(_ExecutionPolicy&&, _ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2,
-                _ForwardIterator2 __last2, _BinaryPredicate __p, _IsVector __is_vector, /* is_parallel = */
-                std::false_type) noexcept
+__pattern_equal(_Tag, _ExecutionPolicy&&, _ForwardIterator1 __first1, _ForwardIterator1 __last1,
+                _ForwardIterator2 __first2, _ForwardIterator2 __last2, _BinaryPredicate __p) noexcept
 {
-    return __internal::__brick_equal(__first1, __last1, __first2, __last2, __p, __is_vector);
+    return __internal::__brick_equal(__first1, __last1, __first2, __last2, __p, typename _Tag::__is_vector{});
 }
 
-template <class _ExecutionPolicy, class _RandomAccessIterator1, class _RandomAccessIterator2, class _BinaryPredicate,
-          class _IsVector>
+template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator1, class _RandomAccessIterator2,
+          class _BinaryPredicate>
 bool
-__pattern_equal(_ExecutionPolicy&& __exec, _RandomAccessIterator1 __first1, _RandomAccessIterator1 __last1,
-                _RandomAccessIterator2 __first2, _RandomAccessIterator2 __last2, _BinaryPredicate __p,
-                _IsVector __is_vector, /*is_parallel=*/std::true_type)
+__pattern_equal(__parallel_tag<_IsVector> __tag, _ExecutionPolicy&& __exec, _RandomAccessIterator1 __first1,
+                _RandomAccessIterator1 __last1, _RandomAccessIterator2 __first2, _RandomAccessIterator2 __last2,
+                _BinaryPredicate __p)
 {
+    using __backend_tag = typename decltype(__tag)::__backend_tag;
+
     if (__last1 - __first1 != __last2 - __first2)
         return false;
 
-    return __internal::__except_handler([&]() {
-        return !__internal::__parallel_or(
-            std::forward<_ExecutionPolicy>(__exec), __first1, __last1,
-            [__first1, __first2, __p, __is_vector](_RandomAccessIterator1 __i, _RandomAccessIterator1 __j) {
-                return !__internal::__brick_equal(__i, __j, __first2 + (__i - __first1), __first2 + (__j - __first1),
-                                                  __p, __is_vector);
-            });
-    });
+    return __internal::__except_handler(
+        [&]()
+        {
+            return !__internal::__parallel_or(
+                __backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __first1, __last1,
+                [__first1, __first2, __p](_RandomAccessIterator1 __i, _RandomAccessIterator1 __j)
+                {
+                    return !__internal::__brick_equal(__i, __j, __first2 + (__i - __first1),
+                                                      __first2 + (__j - __first1), __p, _IsVector{});
+                });
+        });
 }
 
 //------------------------------------------------------------------------
@@ -455,29 +484,30 @@ __brick_equal(_RandomAccessIterator1 __first1, _RandomAccessIterator1 __last1, _
     return __unseq_backend::__simd_first(__first1, __last1 - __first1, __first2, std::not_fn(__p)).first == __last1;
 }
 
-template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate,
-          class _IsVector>
+template <class _Tag, class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate>
 bool
-__pattern_equal(_ExecutionPolicy&&, _ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2,
-                _BinaryPredicate __p, _IsVector __is_vector, /* is_parallel = */ std::false_type) noexcept
+__pattern_equal(_Tag, _ExecutionPolicy&&, _ForwardIterator1 __first1, _ForwardIterator1 __last1,
+                _ForwardIterator2 __first2, _BinaryPredicate __p) noexcept
 {
-    return __internal::__brick_equal(__first1, __last1, __first2, __p, __is_vector);
+    return __internal::__brick_equal(__first1, __last1, __first2, __p, typename _Tag::__is_vector{});
 }
 
-template <class _ExecutionPolicy, class _RandomAccessIterator1, class _RandomAccessIterator2, class _BinaryPredicate,
-          class _IsVector>
+template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator1, class _RandomAccessIterator2,
+          class _BinaryPredicate>
 bool
-__pattern_equal(_ExecutionPolicy&& __exec, _RandomAccessIterator1 __first1, _RandomAccessIterator1 __last1,
-                _RandomAccessIterator2 __first2, _BinaryPredicate __p, _IsVector __is_vector,
-                /*is_parallel=*/std::true_type)
+__pattern_equal(__parallel_tag<_IsVector> __tag, _ExecutionPolicy&& __exec, _RandomAccessIterator1 __first1,
+                _RandomAccessIterator1 __last1, _RandomAccessIterator2 __first2, _BinaryPredicate __p)
 {
-    return __internal::__except_handler([&]() {
-        return !__internal::__parallel_or(
-            std::forward<_ExecutionPolicy>(__exec), __first1, __last1,
-            [__first1, __first2, __p, __is_vector](_RandomAccessIterator1 __i, _RandomAccessIterator1 __j) {
-                return !__internal::__brick_equal(__i, __j, __first2 + (__i - __first1), __p, __is_vector);
-            });
-    });
+    using __backend_tag = typename decltype(__tag)::__backend_tag;
+
+    return __internal::__except_handler(
+        [&]()
+        {
+            return !__internal::__parallel_or(
+                __backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __first1, __last1,
+                [__first1, __first2, __p](_RandomAccessIterator1 __i, _RandomAccessIterator1 __j)
+                { return !__internal::__brick_equal(__i, __j, __first2 + (__i - __first1), __p, _IsVector{}); });
+        });
 }
 
 //------------------------------------------------------------------------
@@ -502,30 +532,31 @@ __brick_find_if(_RandomAccessIterator __first, _RandomAccessIterator __last, _Pr
         [&__pred](_RandomAccessIterator __it, _SizeType __i) { return __pred(__it[__i]); });
 }
 
-template <class _ExecutionPolicy, class _ForwardIterator, class _Predicate, class _IsVector>
+template <class _Tag, class _ExecutionPolicy, class _ForwardIterator, class _Predicate>
 _ForwardIterator
-__pattern_find_if(_ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last, _Predicate __pred,
-                  _IsVector __is_vector,
-                  /*is_parallel=*/std::false_type) noexcept
+__pattern_find_if(_Tag __tag, _ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last,
+                  _Predicate __pred) noexcept
 {
-    return __internal::__brick_find_if(__first, __last, __pred, __is_vector);
+    return __internal::__brick_find_if(__first, __last, __pred, typename _Tag::__is_vector{});
 }
 
-template <class _ExecutionPolicy, class _ForwardIterator, class _Predicate, class _IsVector>
-_ForwardIterator
-__pattern_find_if(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _Predicate __pred,
-                  _IsVector __is_vector,
-                  /*is_parallel=*/std::true_type)
+template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _Predicate>
+_RandomAccessIterator
+__pattern_find_if(__parallel_tag<_IsVector> __tag, _ExecutionPolicy&& __exec, _RandomAccessIterator __first,
+                  _RandomAccessIterator __last, _Predicate __pred)
 {
-    return __internal::__except_handler([&]() {
-        return __internal::__parallel_find(
-            std::forward<_ExecutionPolicy>(__exec), __first, __last,
-            [__pred, __is_vector](_ForwardIterator __i, _ForwardIterator __j) {
-                return __internal::__brick_find_if(__i, __j, __pred, __is_vector);
-            },
-            std::less<typename std::iterator_traits<_ForwardIterator>::difference_type>(),
-            /*is_first=*/true);
-    });
+    using __backend_tag = typename decltype(__tag)::__backend_tag;
+
+    return __internal::__except_handler(
+        [&]()
+        {
+            return __internal::__parallel_find(
+                __backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __first, __last,
+                [__pred](_RandomAccessIterator __i, _RandomAccessIterator __j)
+                { return __internal::__brick_find_if(__i, __j, __pred, _IsVector{}); },
+                std::less<typename std::iterator_traits<_RandomAccessIterator>::difference_type>(),
+                /*is_first=*/true);
+        });
 }
 
 //------------------------------------------------------------------------
@@ -632,48 +663,51 @@ __brick_find_end(_ForwardIterator1 __first, _ForwardIterator1 __last, _ForwardIt
     return std::find_end(__first, __last, __s_first, __s_last, __pred);
 }
 
-template <class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate>
-_ForwardIterator1
-__brick_find_end(_ForwardIterator1 __first, _ForwardIterator1 __last, _ForwardIterator2 __s_first,
-                 _ForwardIterator2 __s_last, _BinaryPredicate __pred, /*__is_vector=*/std::true_type) noexcept
+template <class _RandomAccessIterator1, class _RandomAccessIterator2, class _BinaryPredicate>
+_RandomAccessIterator1
+__brick_find_end(_RandomAccessIterator1 __first, _RandomAccessIterator1 __last, _RandomAccessIterator2 __s_first,
+                 _RandomAccessIterator2 __s_last, _BinaryPredicate __pred, /*__is_vector=*/std::true_type) noexcept
 {
     return __find_subrange(__first, __last, __last, __s_first, __s_last, __pred, false, std::true_type());
 }
 
-template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate,
-          class _IsVector>
+template <class _Tag, class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate>
 _ForwardIterator1
-__pattern_find_end(_ExecutionPolicy&&, _ForwardIterator1 __first, _ForwardIterator1 __last, _ForwardIterator2 __s_first,
-                   _ForwardIterator2 __s_last, _BinaryPredicate __pred, _IsVector __is_vector,
-                   /*is_parallel=*/std::false_type) noexcept
+__pattern_find_end(_Tag, _ExecutionPolicy&&, _ForwardIterator1 __first, _ForwardIterator1 __last,
+                   _ForwardIterator2 __s_first, _ForwardIterator2 __s_last, _BinaryPredicate __pred) noexcept
 {
-    return __internal::__brick_find_end(__first, __last, __s_first, __s_last, __pred, __is_vector);
+    return __internal::__brick_find_end(__first, __last, __s_first, __s_last, __pred, typename _Tag::__is_vector{});
 }
 
-template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate,
-          class _IsVector>
-_ForwardIterator1
-__pattern_find_end(_ExecutionPolicy&& __exec, _ForwardIterator1 __first, _ForwardIterator1 __last,
-                   _ForwardIterator2 __s_first, _ForwardIterator2 __s_last, _BinaryPredicate __pred,
-                   _IsVector __is_vector, /*is_parallel=*/std::true_type) noexcept
+template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator1, class _RandomAccessIterator2,
+          class _BinaryPredicate>
+_RandomAccessIterator1
+__pattern_find_end(__parallel_tag<_IsVector> __tag, _ExecutionPolicy&& __exec, _RandomAccessIterator1 __first,
+                   _RandomAccessIterator1 __last, _RandomAccessIterator2 __s_first, _RandomAccessIterator2 __s_last,
+                   _BinaryPredicate __pred) noexcept
 {
+    using __backend_tag = typename decltype(__tag)::__backend_tag;
+
     if (__last - __first == __s_last - __s_first)
     {
-        const bool __res = __internal::__pattern_equal(std::forward<_ExecutionPolicy>(__exec), __first, __last,
-                                                       __s_first, __pred, __is_vector, std::true_type());
+        const bool __res = __internal::__pattern_equal(__tag, std::forward<_ExecutionPolicy>(__exec), __first, __last,
+                                                       __s_first, __pred);
         return __res ? __first : __last;
     }
     else
     {
-        return __internal::__except_handler([&]() {
-            return __internal::__parallel_find(
-                std::forward<_ExecutionPolicy>(__exec), __first, __last,
-                [__last, __s_first, __s_last, __pred, __is_vector](_ForwardIterator1 __i, _ForwardIterator1 __j) {
-                    return __internal::__find_subrange(__i, __j, __last, __s_first, __s_last, __pred, false,
-                                                       __is_vector);
-                },
-                std::greater<typename std::iterator_traits<_ForwardIterator1>::difference_type>(), /*is_first=*/false);
-        });
+        return __internal::__except_handler(
+            [&]()
+            {
+                return __internal::__parallel_find(
+                    __backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __first, __last,
+                    [__last, __s_first, __s_last, __pred](_RandomAccessIterator1 __i, _RandomAccessIterator1 __j) {
+                        return __internal::__find_subrange(__i, __j, __last, __s_first, __s_last, __pred, false,
+                                                           _IsVector{});
+                    },
+                    std::greater<typename std::iterator_traits<_RandomAccessIterator1>::difference_type>(),
+                    /*is_first=*/false);
+            });
     }
 }
 
@@ -688,95 +722,99 @@ __brick_find_first_of(_ForwardIterator1 __first, _ForwardIterator1 __last, _Forw
     return std::find_first_of(__first, __last, __s_first, __s_last, __pred);
 }
 
-template <class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate>
-_ForwardIterator1
-__brick_find_first_of(_ForwardIterator1 __first, _ForwardIterator1 __last, _ForwardIterator2 __s_first,
-                      _ForwardIterator2 __s_last, _BinaryPredicate __pred, /*__is_vector=*/std::true_type) noexcept
+template <class _RandomAccessIterator1, class _RandomAccessIterator2, class _BinaryPredicate>
+_RandomAccessIterator1
+__brick_find_first_of(_RandomAccessIterator1 __first, _RandomAccessIterator1 __last, _RandomAccessIterator2 __s_first,
+                      _RandomAccessIterator2 __s_last, _BinaryPredicate __pred, /*__is_vector=*/std::true_type) noexcept
 {
     return __unseq_backend::__simd_find_first_of(__first, __last, __s_first, __s_last, __pred);
 }
 
-template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate,
-          class _IsVector>
+template <class _Tag, class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate>
 _ForwardIterator1
-__pattern_find_first_of(_ExecutionPolicy&&, _ForwardIterator1 __first, _ForwardIterator1 __last,
-                        _ForwardIterator2 __s_first, _ForwardIterator2 __s_last, _BinaryPredicate __pred,
-                        _IsVector __is_vector, /*is_parallel=*/std::false_type) noexcept
+__pattern_find_first_of(_Tag, _ExecutionPolicy&&, _ForwardIterator1 __first, _ForwardIterator1 __last,
+                        _ForwardIterator2 __s_first, _ForwardIterator2 __s_last, _BinaryPredicate __pred) noexcept
 {
-    return __internal::__brick_find_first_of(__first, __last, __s_first, __s_last, __pred, __is_vector);
+    return __internal::__brick_find_first_of(__first, __last, __s_first, __s_last, __pred,
+                                             typename _Tag::__is_vector{});
 }
 
-template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate,
-          class _IsVector>
-_ForwardIterator1
-__pattern_find_first_of(_ExecutionPolicy&& __exec, _ForwardIterator1 __first, _ForwardIterator1 __last,
-                        _ForwardIterator2 __s_first, _ForwardIterator2 __s_last, _BinaryPredicate __pred,
-                        _IsVector __is_vector, /*is_parallel=*/std::true_type) noexcept
+template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator1, class _RandomAccessIterator2,
+          class _BinaryPredicate>
+_RandomAccessIterator1
+__pattern_find_first_of(__parallel_tag<_IsVector> __tag, _ExecutionPolicy&& __exec, _RandomAccessIterator1 __first,
+                        _RandomAccessIterator1 __last, _RandomAccessIterator2 __s_first,
+                        _RandomAccessIterator2 __s_last, _BinaryPredicate __pred) noexcept
 {
-    return __internal::__except_handler([&]() {
-        return __internal::__parallel_find(
-            std::forward<_ExecutionPolicy>(__exec), __first, __last,
-            [__s_first, __s_last, __pred, __is_vector](_ForwardIterator1 __i, _ForwardIterator1 __j) {
-                return __internal::__brick_find_first_of(__i, __j, __s_first, __s_last, __pred, __is_vector);
-            },
-            std::less<typename std::iterator_traits<_ForwardIterator1>::difference_type>(), /*is_first=*/true);
-    });
+    using __backend_tag = typename decltype(__tag)::__backend_tag;
+
+    return __internal::__except_handler(
+        [&]()
+        {
+            return __internal::__parallel_find(
+                __backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __first, __last,
+                [__s_first, __s_last, __pred](_RandomAccessIterator1 __i, _RandomAccessIterator1 __j)
+                { return __internal::__brick_find_first_of(__i, __j, __s_first, __s_last, __pred, _IsVector{}); },
+                std::less<typename std::iterator_traits<_RandomAccessIterator1>::difference_type>(), /*is_first=*/true);
+        });
 }
 
 //------------------------------------------------------------------------
 // search
 //------------------------------------------------------------------------
-template <class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate>
-_ForwardIterator1
-__brick_search(_ForwardIterator1 __first, _ForwardIterator1 __last, _ForwardIterator2 __s_first,
-               _ForwardIterator2 __s_last, _BinaryPredicate __pred, /*vector=*/std::false_type) noexcept
+template <class _RandomAccessIterator1, class _RandomAccessIterator2, class _BinaryPredicate>
+_RandomAccessIterator1
+__brick_search(_RandomAccessIterator1 __first, _RandomAccessIterator1 __last, _RandomAccessIterator2 __s_first,
+               _RandomAccessIterator2 __s_last, _BinaryPredicate __pred, /*vector=*/std::false_type) noexcept
 {
     return std::search(__first, __last, __s_first, __s_last, __pred);
 }
 
-template <class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate>
-_ForwardIterator1
-__brick_search(_ForwardIterator1 __first, _ForwardIterator1 __last, _ForwardIterator2 __s_first,
-               _ForwardIterator2 __s_last, _BinaryPredicate __pred, /*vector=*/std::true_type) noexcept
+template <class _RandomAccessIterator1, class _RandomAccessIterator2, class _BinaryPredicate>
+_RandomAccessIterator1
+__brick_search(_RandomAccessIterator1 __first, _RandomAccessIterator1 __last, _RandomAccessIterator2 __s_first,
+               _RandomAccessIterator2 __s_last, _BinaryPredicate __pred, /*vector=*/std::true_type) noexcept
 {
     return __internal::__find_subrange(__first, __last, __last, __s_first, __s_last, __pred, true, std::true_type());
 }
 
-template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate,
-          class _IsVector>
+template <class _Tag, class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate>
 _ForwardIterator1
-__pattern_search(_ExecutionPolicy&&, _ForwardIterator1 __first, _ForwardIterator1 __last, _ForwardIterator2 __s_first,
-                 _ForwardIterator2 __s_last, _BinaryPredicate __pred, _IsVector __is_vector,
-                 /*is_parallel=*/std::false_type) noexcept
+__pattern_search(_Tag, _ExecutionPolicy&&, _ForwardIterator1 __first, _ForwardIterator1 __last,
+                 _ForwardIterator2 __s_first, _ForwardIterator2 __s_last, _BinaryPredicate __pred) noexcept
 {
-    return __internal::__brick_search(__first, __last, __s_first, __s_last, __pred, __is_vector);
+    return __internal::__brick_search(__first, __last, __s_first, __s_last, __pred, typename _Tag::__is_vector{});
 }
 
-template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate,
-          class _IsVector>
-_ForwardIterator1
-__pattern_search(_ExecutionPolicy&& __exec, _ForwardIterator1 __first, _ForwardIterator1 __last,
-                 _ForwardIterator2 __s_first, _ForwardIterator2 __s_last, _BinaryPredicate __pred,
-                 _IsVector __is_vector,
-                 /*is_parallel=*/std::true_type) noexcept
+template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator1, class _RandomAccessIterator2,
+          class _BinaryPredicate>
+_RandomAccessIterator1
+__pattern_search(__parallel_tag<_IsVector> __tag, _ExecutionPolicy&& __exec, _RandomAccessIterator1 __first,
+                 _RandomAccessIterator1 __last, _RandomAccessIterator2 __s_first, _RandomAccessIterator2 __s_last,
+                 _BinaryPredicate __pred) noexcept
 {
+    using __backend_tag = typename decltype(__tag)::__backend_tag;
+
     if (__last - __first == __s_last - __s_first)
     {
-        const bool __res = __internal::__pattern_equal(std::forward<_ExecutionPolicy>(__exec), __first, __last,
-                                                       __s_first, __pred, __is_vector, std::true_type());
+        const bool __res = __internal::__pattern_equal(__tag, std::forward<_ExecutionPolicy>(__exec), __first, __last,
+                                                       __s_first, __pred);
         return __res ? __first : __last;
     }
     else
     {
-        return __internal::__except_handler([&]() {
-            return __internal::__parallel_find(
-                std::forward<_ExecutionPolicy>(__exec), __first, __last,
-                [__last, __s_first, __s_last, __pred, __is_vector](_ForwardIterator1 __i, _ForwardIterator1 __j) {
-                    return __internal::__find_subrange(__i, __j, __last, __s_first, __s_last, __pred, true,
-                                                       __is_vector);
-                },
-                std::less<typename std::iterator_traits<_ForwardIterator1>::difference_type>(), /*is_first=*/true);
-        });
+        return __internal::__except_handler(
+            [&]()
+            {
+                return __internal::__parallel_find(
+                    __backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __first, __last,
+                    [__last, __s_first, __s_last, __pred](_RandomAccessIterator1 __i, _RandomAccessIterator1 __j) {
+                        return __internal::__find_subrange(__i, __j, __last, __s_first, __s_last, __pred, true,
+                                                           _IsVector{});
+                    },
+                    std::less<typename std::iterator_traits<_RandomAccessIterator1>::difference_type>(),
+                    /*is_first=*/true);
+            });
     }
 }
 
@@ -791,49 +829,49 @@ __brick_search_n(_ForwardIterator __first, _ForwardIterator __last, _Size __coun
     return std::search_n(__first, __last, __count, __value, __pred);
 }
 
-template <class _ForwardIterator, class _Size, class _Tp, class _BinaryPredicate>
-_ForwardIterator
-__brick_search_n(_ForwardIterator __first, _ForwardIterator __last, _Size __count, const _Tp& __value,
+template <class _RandomAccessIterator, class _Size, class _Tp, class _BinaryPredicate>
+_RandomAccessIterator
+__brick_search_n(_RandomAccessIterator __first, _RandomAccessIterator __last, _Size __count, const _Tp& __value,
                  _BinaryPredicate __pred, /*vector=*/std::true_type) noexcept
 {
     return __internal::__find_subrange(__first, __last, __last, __count, __value, __pred, std::true_type());
 }
 
-template <class _ExecutionPolicy, class _ForwardIterator, class _Size, class _Tp, class _BinaryPredicate,
-          class _IsVector>
+template <class _Tag, class _ExecutionPolicy, class _ForwardIterator, class _Size, class _Tp, class _BinaryPredicate>
 _ForwardIterator
-__pattern_search_n(_ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last, _Size __count,
-                   const _Tp& __value, _BinaryPredicate __pred, _IsVector __is_vector,
-                   /*is_parallel=*/std::false_type) noexcept
+__pattern_search_n(_Tag, _ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last, _Size __count,
+                   const _Tp& __value, _BinaryPredicate __pred) noexcept
 {
-    return __internal::__brick_search_n(__first, __last, __count, __value, __pred, __is_vector);
+    return __internal::__brick_search_n(__first, __last, __count, __value, __pred, typename _Tag::__is_vector{});
 }
 
-template <class _ExecutionPolicy, class _RandomAccessIterator, class _Size, class _Tp, class _BinaryPredicate,
-          class _IsVector>
+template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _Size, class _Tp,
+          class _BinaryPredicate>
 _RandomAccessIterator
-__pattern_search_n(_ExecutionPolicy&& __exec, _RandomAccessIterator __first, _RandomAccessIterator __last,
-                   _Size __count, const _Tp& __value, _BinaryPredicate __pred, _IsVector __is_vector,
-                   /*is_parallel=*/std::true_type) noexcept
+__pattern_search_n(__parallel_tag<_IsVector> __tag, _ExecutionPolicy&& __exec, _RandomAccessIterator __first,
+                   _RandomAccessIterator __last, _Size __count, const _Tp& __value, _BinaryPredicate __pred) noexcept
 {
+    using __backend_tag = typename decltype(__tag)::__backend_tag;
+
     if (static_cast<_Size>(__last - __first) == __count)
     {
-        const bool __result = !__internal::__pattern_any_of(
-            std::forward<_ExecutionPolicy>(__exec), __first, __last,
-            [&__value, &__pred](const _Tp& __val) { return !__pred(__val, __value); }, __is_vector,
-            /*is_parallel*/ std::true_type());
+        const bool __result =
+            !__internal::__pattern_any_of(__tag, std::forward<_ExecutionPolicy>(__exec), __first, __last,
+                                          [&__value, &__pred](const _Tp& __val) { return !__pred(__val, __value); });
         return __result ? __first : __last;
     }
     else
     {
-        return __internal::__except_handler([&__exec, __first, __last, __count, &__value, __pred, __is_vector]() {
-            return __internal::__parallel_find(
-                std::forward<_ExecutionPolicy>(__exec), __first, __last,
-                [__last, __count, &__value, __pred, __is_vector](_RandomAccessIterator __i, _RandomAccessIterator __j) {
-                    return __internal::__find_subrange(__i, __j, __last, __count, __value, __pred, __is_vector);
-                },
-                std::less<typename std::iterator_traits<_RandomAccessIterator>::difference_type>(), /*is_first=*/true);
-        });
+        return __internal::__except_handler(
+            [&__exec, __first, __last, __count, &__value, __pred]()
+            {
+                return __internal::__parallel_find(
+                    __backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __first, __last,
+                    [__last, __count, &__value, __pred](_RandomAccessIterator __i, _RandomAccessIterator __j)
+                    { return __internal::__find_subrange(__i, __j, __last, __count, __value, __pred, _IsVector{}); },
+                    std::less<typename std::iterator_traits<_RandomAccessIterator>::difference_type>(),
+                    /*is_first=*/true);
+            });
     }
 }
 
@@ -848,12 +886,14 @@ __brick_copy_n(_ForwardIterator __first, _Size __n, _OutputIterator __result, /*
     return std::copy_n(__first, __n, __result);
 }
 
-template <class _ForwardIterator, class _Size, class _OutputIterator>
-_OutputIterator
-__brick_copy_n(_ForwardIterator __first, _Size __n, _OutputIterator __result, /*vector=*/std::true_type) noexcept
+template <class _RandomAccessIterator1, class _Size, class _RandomAccessIterator2>
+_RandomAccessIterator2
+__brick_copy_n(_RandomAccessIterator1 __first, _Size __n, _RandomAccessIterator2 __result,
+               /*vector=*/std::true_type) noexcept
 {
     return __unseq_backend::__simd_assign(
-        __first, __n, __result, [](_ForwardIterator __first, _OutputIterator __result) { *__result = *__first; });
+        __first, __n, __result,
+        [](_RandomAccessIterator1 __first, _RandomAccessIterator2 __result) { *__result = *__first; });
 }
 
 //------------------------------------------------------------------------
@@ -867,14 +907,14 @@ __brick_copy(_ForwardIterator __first, _ForwardIterator __last, _OutputIterator
     return std::copy(__first, __last, __result);
 }
 
-template <class _RandomAccessIterator, class _OutputIterator>
-_OutputIterator
-__brick_copy(_RandomAccessIterator __first, _RandomAccessIterator __last, _OutputIterator __result,
+template <class _RandomAccessIterator1, class _RandomAccessIterator2>
+_RandomAccessIterator2
+__brick_copy(_RandomAccessIterator1 __first, _RandomAccessIterator1 __last, _RandomAccessIterator2 __result,
              /*vector=*/std::true_type) noexcept
 {
     return __unseq_backend::__simd_assign(
         __first, __last - __first, __result,
-        [](_RandomAccessIterator __first, _OutputIterator __result) { *__result = *__first; });
+        [](_RandomAccessIterator1 __first, _RandomAccessIterator2 __result) { *__result = *__first; });
 }
 
 //------------------------------------------------------------------------
@@ -888,36 +928,38 @@ __brick_move(_ForwardIterator __first, _ForwardIterator __last, _OutputIterator
     return std::move(__first, __last, __result);
 }
 
-template <class _RandomAccessIterator, class _OutputIterator>
-_OutputIterator
-__brick_move(_RandomAccessIterator __first, _RandomAccessIterator __last, _OutputIterator __result,
+template <class _RandomAccessIterator1, class _RandomAccessIterator2>
+_RandomAccessIterator2
+__brick_move(_RandomAccessIterator1 __first, _RandomAccessIterator1 __last, _RandomAccessIterator2 __result,
              /*vector=*/std::true_type) noexcept
 {
     return __unseq_backend::__simd_assign(
         __first, __last - __first, __result,
-        [](_RandomAccessIterator __first, _OutputIterator __result) { *__result = std::move(*__first); });
+        [](_RandomAccessIterator1 __first, _RandomAccessIterator2 __result) { *__result = std::move(*__first); });
 }
 
 struct __brick_move_destroy
 {
-    template <typename _Iterator, typename _OutputIterator>
-    _OutputIterator
-    operator()(_Iterator __first, _Iterator __last, _OutputIterator __result, /*vec*/ std::true_type) const
+    template <typename _RandomAccessIterator1, typename _RandomAccessIterator2>
+    _RandomAccessIterator2
+    operator()(_RandomAccessIterator1 __first, _RandomAccessIterator1 __last, _RandomAccessIterator2 __result,
+               /*vec*/ std::true_type) const
     {
-        using _IteratorValueType = typename std::iterator_traits<_Iterator>::value_type;
+        using _IteratorValueType = typename std::iterator_traits<_RandomAccessIterator1>::value_type;
 
         return __unseq_backend::__simd_assign(__first, __last - __first, __result,
-                                              [](_Iterator __first, _OutputIterator __result) {
+                                              [](_RandomAccessIterator1 __first, _RandomAccessIterator2 __result) {
                                                   *__result = std::move(*__first);
                                                   (*__first).~_IteratorValueType();
                                               });
     }
 
-    template <typename _Iterator, typename _OutputIterator>
-    _OutputIterator
-    operator()(_Iterator __first, _Iterator __last, _OutputIterator __result, /*vec*/ std::false_type) const
+    template <typename _RandomAccessIterator1, typename _RandomAccessIterator2>
+    _RandomAccessIterator2
+    operator()(_RandomAccessIterator1 __first, _RandomAccessIterator1 __last, _RandomAccessIterator2 __result,
+               /*vec*/ std::false_type) const
     {
-        using _IteratorValueType = typename std::iterator_traits<_Iterator>::value_type;
+        using _IteratorValueType = typename std::iterator_traits<_RandomAccessIterator1>::value_type;
 
         for (; __first != __last; ++__first, ++__result)
         {
@@ -939,14 +981,14 @@ __brick_swap_ranges(_ForwardIterator __first, _ForwardIterator __last, _OutputIt
     return std::swap_ranges(__first, __last, __result);
 }
 
-template <class _ForwardIterator, class _OutputIterator>
-_OutputIterator
-__brick_swap_ranges(_ForwardIterator __first, _ForwardIterator __last, _OutputIterator __result,
+template <class _RandomAccessIterator1, class _RandomAccessIterator2>
+_RandomAccessIterator2
+__brick_swap_ranges(_RandomAccessIterator1 __first, _RandomAccessIterator1 __last, _RandomAccessIterator2 __result,
                     /*vector=*/std::true_type) noexcept
 {
     using std::iter_swap;
     return __unseq_backend::__simd_assign(__first, __last - __first, __result,
-                                          iter_swap<_ForwardIterator, _OutputIterator>);
+                                          iter_swap<_RandomAccessIterator1, _RandomAccessIterator2>);
 }
 
 //------------------------------------------------------------------------
@@ -960,12 +1002,13 @@ __brick_copy_if(_ForwardIterator __first, _ForwardIterator __last, _OutputIterat
     return std::copy_if(__first, __last, __result, __pred);
 }
 
-template <class _ForwardIterator, class _OutputIterator, class _UnaryPredicate>
-_OutputIterator
-__brick_copy_if(_ForwardIterator __first, _ForwardIterator __last, _OutputIterator __result, _UnaryPredicate __pred,
+template <class _RandomAccessIterator1, class _RandomAccessIterator2, class _UnaryPredicate>
+_RandomAccessIterator2
+__brick_copy_if(_RandomAccessIterator1 __first, _RandomAccessIterator1 __last, _RandomAccessIterator2 __result,
+                _UnaryPredicate __pred,
                 /*vector=*/std::true_type) noexcept
 {
-#if (_PSTL_MONOTONIC_PRESENT)
+#if defined(_PSTL_MONOTONIC_PRESENT)
     return __unseq_backend::__simd_copy_if(__first, __last - __first, __result, __pred);
 #else
     return std::copy_if(__first, __last, __result, __pred);
@@ -981,7 +1024,7 @@ __brick_calc_mask_1(_ForwardIterator __first, _ForwardIterator __last, bool* __r
     auto __count_true = _DifferenceType(0);
     auto __size = __last - __first;
 
-    static_assert(__is_random_access_iterator<_ForwardIterator>::value,
+    static_assert(__are_random_access_iterators<_ForwardIterator>::value,
                   "Pattern-brick error. Should be a random access iterator.");
 
     for (; __first != __last; ++__first, ++__mask)
@@ -1019,12 +1062,12 @@ __brick_copy_by_mask(_ForwardIterator __first, _ForwardIterator __last, _OutputI
     }
 }
 
-template <class _ForwardIterator, class _OutputIterator, class _Assigner>
+template <class _RandomAccessIterator1, class _RandomAccessIterator2, class _Assigner>
 void
-__brick_copy_by_mask(_ForwardIterator __first, _ForwardIterator __last, _OutputIterator __result,
+__brick_copy_by_mask(_RandomAccessIterator1 __first, _RandomAccessIterator1 __last, _RandomAccessIterator2 __result,
                      bool* __restrict __mask, _Assigner __assigner, /*vector=*/std::true_type) noexcept
 {
-#if (_PSTL_MONOTONIC_PRESENT)
+#if defined(_PSTL_MONOTONIC_PRESENT)
     __unseq_backend::__simd_copy_by_mask(__first, __last - __first, __result, __mask, __assigner);
 #else
     __internal::__brick_copy_by_mask(__first, __last, __result, __mask, __assigner, std::false_type());
@@ -1051,67 +1094,72 @@ __brick_partition_by_mask(_ForwardIterator __first, _ForwardIterator __last, _Ou
     }
 }
 
-template <class _RandomAccessIterator, class _OutputIterator1, class _OutputIterator2>
+template <class _RandomAccessIterator1, class _RandomAccessIterator2, class _RandomAccessIterator3>
 void
-__brick_partition_by_mask(_RandomAccessIterator __first, _RandomAccessIterator __last, _OutputIterator1 __out_true,
-                          _OutputIterator2 __out_false, bool* __mask, /*vector=*/std::true_type) noexcept
+__brick_partition_by_mask(_RandomAccessIterator1 __first, _RandomAccessIterator1 __last,
+                          _RandomAccessIterator2 __out_true, _RandomAccessIterator3 __out_false, bool* __mask,
+                          /*vector=*/std::true_type) noexcept
 {
-#if (_PSTL_MONOTONIC_PRESENT)
+#if defined(_PSTL_MONOTONIC_PRESENT)
     __unseq_backend::__simd_partition_by_mask(__first, __last - __first, __out_true, __out_false, __mask);
 #else
     __internal::__brick_partition_by_mask(__first, __last, __out_true, __out_false, __mask, std::false_type());
 #endif
 }
 
-template <class _ExecutionPolicy, class _ForwardIterator, class _OutputIterator, class _UnaryPredicate, class _IsVector>
+template <class _Tag, class _ExecutionPolicy, class _ForwardIterator, class _OutputIterator, class _UnaryPredicate>
 _OutputIterator
-__pattern_copy_if(_ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last, _OutputIterator __result,
-                  _UnaryPredicate __pred, _IsVector __is_vector, /*parallel=*/std::false_type) noexcept
+__pattern_copy_if(_Tag, _ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last, _OutputIterator __result,
+                  _UnaryPredicate __pred) noexcept
 {
-    return __internal::__brick_copy_if(__first, __last, __result, __pred, __is_vector);
+    return __internal::__brick_copy_if(__first, __last, __result, __pred, typename _Tag::__is_vector{});
 }
 
-template <class _ExecutionPolicy, class _RandomAccessIterator, class _OutputIterator, class _UnaryPredicate,
-          class _IsVector>
-_OutputIterator
-__pattern_copy_if(_ExecutionPolicy&& __exec, _RandomAccessIterator __first, _RandomAccessIterator __last,
-                  _OutputIterator __result, _UnaryPredicate __pred, _IsVector __is_vector, /*parallel=*/std::true_type)
+template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator1, class _RandomAccessIterator2,
+          class _UnaryPredicate>
+_RandomAccessIterator2
+__pattern_copy_if(__parallel_tag<_IsVector> __tag, _ExecutionPolicy&& __exec, _RandomAccessIterator1 __first,
+                  _RandomAccessIterator1 __last, _RandomAccessIterator2 __result, _UnaryPredicate __pred)
 {
-    typedef typename std::iterator_traits<_RandomAccessIterator>::difference_type _DifferenceType;
+    using __backend_tag = typename decltype(__tag)::__backend_tag;
+
+    typedef typename std::iterator_traits<_RandomAccessIterator1>::difference_type _DifferenceType;
     const _DifferenceType __n = __last - __first;
     if (_DifferenceType(1) < __n)
     {
         __par_backend::__buffer<bool> __mask_buf(__n);
-        return __internal::__except_handler([&__exec, __n, __first, __result, __is_vector, __pred, &__mask_buf]() {
-            bool* __mask = __mask_buf.get();
-            _DifferenceType __m{};
-            __par_backend::__parallel_strict_scan(
-                std::forward<_ExecutionPolicy>(__exec), __n, _DifferenceType(0),
-                [=](_DifferenceType __i, _DifferenceType __len) { // Reduce
-                    return __internal::__brick_calc_mask_1<_DifferenceType>(__first + __i, __first + (__i + __len),
-                                                                            __mask + __i, __pred, __is_vector)
-                        .first;
-                },
-                std::plus<_DifferenceType>(),                                                // Combine
-                [=](_DifferenceType __i, _DifferenceType __len, _DifferenceType __initial) { // Scan
-                    __internal::__brick_copy_by_mask(
-                        __first + __i, __first + (__i + __len), __result + __initial, __mask + __i,
-                        [](_RandomAccessIterator __x, _OutputIterator __z) { *__z = *__x; }, __is_vector);
-                },
-                [&__m](_DifferenceType __total) { __m = __total; });
-            return __result + __m;
-        });
+        return __internal::__except_handler(
+            [&__exec, __n, __first, __result, __pred, &__mask_buf]()
+            {
+                bool* __mask = __mask_buf.get();
+                _DifferenceType __m{};
+                __par_backend::__parallel_strict_scan(
+                    __backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __n, _DifferenceType(0),
+                    [=](_DifferenceType __i, _DifferenceType __len) { // Reduce
+                        return __internal::__brick_calc_mask_1<_DifferenceType>(__first + __i, __first + (__i + __len),
+                                                                                __mask + __i, __pred, _IsVector{})
+                            .first;
+                    },
+                    std::plus<_DifferenceType>(),                                                // Combine
+                    [=](_DifferenceType __i, _DifferenceType __len, _DifferenceType __initial) { // Scan
+                        __internal::__brick_copy_by_mask(
+                            __first + __i, __first + (__i + __len), __result + __initial, __mask + __i,
+                            [](_RandomAccessIterator1 __x, _RandomAccessIterator2 __z) { *__z = *__x; }, _IsVector{});
+                    },
+                    [&__m](_DifferenceType __total) { __m = __total; });
+                return __result + __m;
+            });
     }
     // trivial sequence - use serial algorithm
-    return __internal::__brick_copy_if(__first, __last, __result, __pred, __is_vector);
+    return __internal::__brick_copy_if(__first, __last, __result, __pred, _IsVector{});
 }
 
 //------------------------------------------------------------------------
 // count
 //------------------------------------------------------------------------
-template <class _ForwardIterator, class _Predicate>
-typename std::iterator_traits<_ForwardIterator>::difference_type
-__brick_count(_ForwardIterator __first, _ForwardIterator __last, _Predicate __pred,
+template <class _RandomAccessIterator, class _Predicate>
+typename std::iterator_traits<_RandomAccessIterator>::difference_type
+__brick_count(_RandomAccessIterator __first, _RandomAccessIterator __last, _Predicate __pred,
               /* is_vector = */ std::true_type) noexcept
 {
     return __unseq_backend::__simd_count(__first, __last - __first, __pred);
@@ -1125,66 +1173,70 @@ __brick_count(_ForwardIterator __first, _ForwardIterator __last, _Predicate __pr
     return std::count_if(__first, __last, __pred);
 }
 
-template <class _ExecutionPolicy, class _ForwardIterator, class _Predicate, class _IsVector>
+template <class _Tag, class _ExecutionPolicy, class _ForwardIterator, class _Predicate>
 typename std::iterator_traits<_ForwardIterator>::difference_type
-__pattern_count(_ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last, _Predicate __pred,
-                /* is_parallel */ std::false_type, _IsVector __is_vector) noexcept
+__pattern_count(_Tag, _ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last, _Predicate __pred) noexcept
 {
-    return __internal::__brick_count(__first, __last, __pred, __is_vector);
+    return __internal::__brick_count(__first, __last, __pred, typename _Tag::__is_vector{});
 }
 
-template <class _ExecutionPolicy, class _ForwardIterator, class _Predicate, class _IsVector>
-typename std::iterator_traits<_ForwardIterator>::difference_type
-__pattern_count(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _Predicate __pred,
-                /* is_parallel */ std::true_type, _IsVector __is_vector)
+template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _Predicate>
+typename std::iterator_traits<_RandomAccessIterator>::difference_type
+__pattern_count(__parallel_tag<_IsVector> __tag, _ExecutionPolicy&& __exec, _RandomAccessIterator __first,
+                _RandomAccessIterator __last, _Predicate __pred)
 {
-    typedef typename std::iterator_traits<_ForwardIterator>::difference_type _SizeType;
-    return __internal::__except_handler([&]() {
-        return __par_backend::__parallel_reduce(
-            std::forward<_ExecutionPolicy>(__exec), __first, __last, _SizeType(0),
-            [__pred, __is_vector](_ForwardIterator __begin, _ForwardIterator __end, _SizeType __value) -> _SizeType {
-                return __value + __internal::__brick_count(__begin, __end, __pred, __is_vector);
-            },
-            std::plus<_SizeType>());
-    });
+    using __backend_tag = typename decltype(__tag)::__backend_tag;
+
+    typedef typename std::iterator_traits<_RandomAccessIterator>::difference_type _SizeType;
+    return __internal::__except_handler(
+        [&]()
+        {
+            return __par_backend::__parallel_reduce(
+                __backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __first, __last, _SizeType(0),
+                [__pred](_RandomAccessIterator __begin, _RandomAccessIterator __end, _SizeType __value) -> _SizeType
+                { return __value + __internal::__brick_count(__begin, __end, __pred, _IsVector{}); },
+                std::plus<_SizeType>());
+        });
 }
 
 //------------------------------------------------------------------------
 // unique
 //------------------------------------------------------------------------
 
-template <class _ForwardIterator, class _BinaryPredicate>
-_ForwardIterator
-__brick_unique(_ForwardIterator __first, _ForwardIterator __last, _BinaryPredicate __pred,
+template <class _RandomAccessIterator, class _BinaryPredicate>
+_RandomAccessIterator
+__brick_unique(_RandomAccessIterator __first, _RandomAccessIterator __last, _BinaryPredicate __pred,
                /*is_vector=*/std::false_type) noexcept
 {
     return std::unique(__first, __last, __pred);
 }
 
-template <class _ForwardIterator, class _BinaryPredicate>
-_ForwardIterator
-__brick_unique(_ForwardIterator __first, _ForwardIterator __last, _BinaryPredicate __pred,
+template <class _RandomAccessIterator, class _BinaryPredicate>
+_RandomAccessIterator
+__brick_unique(_RandomAccessIterator __first, _RandomAccessIterator __last, _BinaryPredicate __pred,
                /*is_vector=*/std::true_type) noexcept
 {
     _PSTL_PRAGMA_MESSAGE("Vectorized algorithm unimplemented, redirected to serial");
     return std::unique(__first, __last, __pred);
 }
 
-template <class _ExecutionPolicy, class _ForwardIterator, class _BinaryPredicate, class _IsVector>
+template <class _Tag, class _ExecutionPolicy, class _ForwardIterator, class _BinaryPredicate>
 _ForwardIterator
-__pattern_unique(_ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last, _BinaryPredicate __pred,
-                 _IsVector __is_vector, /*is_parallel=*/std::false_type) noexcept
+__pattern_unique(_Tag, _ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last,
+                 _BinaryPredicate __pred) noexcept
 {
-    return __internal::__brick_unique(__first, __last, __pred, __is_vector);
+    return __internal::__brick_unique(__first, __last, __pred, typename _Tag::__is_vector{});
 }
 
 // That function is shared between two algorithms - remove_if (__pattern_remove_if) and unique (pattern unique). But a mask calculation is different.
 // So, a caller passes _CalcMask brick into remove_elements.
-template <class _ExecutionPolicy, class _ForwardIterator, class _CalcMask, class _IsVector>
+template <class _IsVector, class _ExecutionPolicy, class _ForwardIterator, class _CalcMask>
 _ForwardIterator
-__remove_elements(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _CalcMask __calc_mask,
-                  _IsVector __is_vector)
+__remove_elements(__parallel_tag<_IsVector> __tag, _ExecutionPolicy&& __exec, _ForwardIterator __first,
+                  _ForwardIterator __last, _CalcMask __calc_mask)
 {
+    using __backend_tag = typename decltype(__tag)::__backend_tag;
+
     typedef typename std::iterator_traits<_ForwardIterator>::difference_type _DifferenceType;
     typedef typename std::iterator_traits<_ForwardIterator>::value_type _Tp;
     _DifferenceType __n = __last - __first;
@@ -1193,9 +1245,10 @@ __remove_elements(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardI
     return __internal::__except_handler([&]() {
         bool* __mask = __mask_buf.get();
         _DifferenceType __min = __par_backend::__parallel_reduce(
-            std::forward<_ExecutionPolicy>(__exec), _DifferenceType(0), __n, __n,
-            [__first, __mask, &__calc_mask, __is_vector](_DifferenceType __i, _DifferenceType __j,
-                                                         _DifferenceType __local_min) -> _DifferenceType {
+            __backend_tag{}, std::forward<_ExecutionPolicy>(__exec), _DifferenceType(0), __n, __n,
+            [__first, __mask, &__calc_mask](_DifferenceType __i, _DifferenceType __j,
+                                            _DifferenceType __local_min) -> _DifferenceType
+            {
                 // Create mask
                 __calc_mask(__mask + __i, __mask + __j, __first + __i);
 
@@ -1205,17 +1258,16 @@ __remove_elements(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardI
                     return __local_min;
                 }
                 // find first iterator that should be removed
-                bool* __result = __internal::__brick_find_if(__mask + __i, __mask + __j,
-                                                             [](bool __val) { return !__val; }, __is_vector);
+                bool* __result = __internal::__brick_find_if(
+                    __mask + __i, __mask + __j, [](bool __val) { return !__val; }, _IsVector{});
                 if (__result - __mask == __j)
                 {
                     return __local_min;
                 }
                 return std::min(__local_min, _DifferenceType(__result - __mask));
             },
-            [](_DifferenceType __local_min1, _DifferenceType __local_min2) -> _DifferenceType {
-                return std::min(__local_min1, __local_min2);
-            });
+            [](_DifferenceType __local_min1, _DifferenceType __local_min2) -> _DifferenceType
+            { return std::min(__local_min1, __local_min2); });
 
         // No elements to remove - exit
         if (__min == __n)
@@ -1231,44 +1283,46 @@ __remove_elements(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardI
         _DifferenceType __m{};
         // 2. Elements that doesn't satisfy pred are moved to result
         __par_backend::__parallel_strict_scan(
-            std::forward<_ExecutionPolicy>(__exec), __n, _DifferenceType(0),
-            [__mask, __is_vector](_DifferenceType __i, _DifferenceType __len) {
-                return __internal::__brick_count(__mask + __i, __mask + __i + __len, [](bool __val) { return __val; },
-                                                 __is_vector);
+            __backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __n, _DifferenceType(0),
+            [__mask](_DifferenceType __i, _DifferenceType __len)
+            {
+                return __internal::__brick_count(
+                    __mask + __i, __mask + __i + __len, [](bool __val) { return __val; }, _IsVector{});
             },
             std::plus<_DifferenceType>(),
-            [=](_DifferenceType __i, _DifferenceType __len, _DifferenceType __initial) {
+            [=](_DifferenceType __i, _DifferenceType __len, _DifferenceType __initial)
+            {
                 __internal::__brick_copy_by_mask(
                     __first + __i, __first + __i + __len, __result + __initial, __mask + __i,
-                    [](_ForwardIterator __x, _Tp* __z) {
-                        __internal::__invoke_if_else(std::is_trivial<_Tp>(), [&]() { *__z = std::move(*__x); },
-                                                     [&]() { ::new (std::addressof(*__z)) _Tp(std::move(*__x)); });
+                    [](_ForwardIterator __x, _Tp* __z)
+                    {
+                        __internal::__invoke_if_else(
+                            std::is_trivial<_Tp>(), [&]() { *__z = std::move(*__x); },
+                            [&]() { ::new (std::addressof(*__z)) _Tp(std::move(*__x)); });
                     },
-                    __is_vector);
+                    _IsVector{});
             },
             [&__m](_DifferenceType __total) { __m = __total; });
 
         // 3. Elements from result are moved to [first, last)
         __par_backend::__parallel_for(
-            std::forward<_ExecutionPolicy>(__exec), __result, __result + __m,
-            [__result, __first, __is_vector](_Tp* __i, _Tp* __j) {
+            __backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __result, __result + __m,
+            [__result, __first](_Tp* __i, _Tp* __j)
+            {
                 __invoke_if_else(
-                    std::is_trivial<_Tp>(),
-                    [&]() { __brick_move(__i, __j, __first + (__i - __result), __is_vector); },
-                    [&]() {
-                        __brick_move_destroy()(__i, __j, __first + (__i - __result), __is_vector);
-                    });
+                    std::is_trivial<_Tp>(), [&]() { __brick_move(__i, __j, __first + (__i - __result), _IsVector{}); },
+                    [&]() { __brick_move_destroy()(__i, __j, __first + (__i - __result), _IsVector{}); });
             });
         return __first + __m;
     });
 }
 
-template <class _ExecutionPolicy, class _ForwardIterator, class _BinaryPredicate, class _IsVector>
-_ForwardIterator
-__pattern_unique(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _BinaryPredicate __pred,
-                 _IsVector __is_vector, /*is_parallel=*/std::true_type) noexcept
+template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _BinaryPredicate>
+_RandomAccessIterator
+__pattern_unique(__parallel_tag<_IsVector> __tag, _ExecutionPolicy&& __exec, _RandomAccessIterator __first,
+                 _RandomAccessIterator __last, _BinaryPredicate __pred) noexcept
 {
-    typedef typename std::iterator_traits<_ForwardIterator>::reference _ReferenceType;
+    typedef typename std::iterator_traits<_RandomAccessIterator>::reference _ReferenceType;
 
     if (__first == __last)
     {
@@ -1277,16 +1331,16 @@ __pattern_unique(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIt
     if (__first + 1 == __last || __first + 2 == __last)
     {
         // Trivial sequence - use serial algorithm
-        return __internal::__brick_unique(__first, __last, __pred, __is_vector);
+        return __internal::__brick_unique(__first, __last, __pred, _IsVector{});
     }
     return __internal::__remove_elements(
-        std::forward<_ExecutionPolicy>(__exec), ++__first, __last,
-        [&__pred, __is_vector](bool* __b, bool* __e, _ForwardIterator __it) {
+        __tag, std::forward<_ExecutionPolicy>(__exec), ++__first, __last,
+        [&__pred](bool* __b, bool* __e, _RandomAccessIterator __it)
+        {
             __internal::__brick_walk3(
                 __b, __e, __it - 1, __it,
-                [&__pred](bool& __x, _ReferenceType __y, _ReferenceType __z) { __x = !__pred(__y, __z); }, __is_vector);
-        },
-        __is_vector);
+                [&__pred](bool& __x, _ReferenceType __y, _ReferenceType __z) { __x = !__pred(__y, __z); }, _IsVector{});
+        });
 }
 
 //------------------------------------------------------------------------
@@ -1294,32 +1348,31 @@ __pattern_unique(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIt
 //------------------------------------------------------------------------
 
 template <class _ForwardIterator, class _OutputIterator, class _BinaryPredicate>
-  _OutputIterator
+_OutputIterator
 __brick_unique_copy(_ForwardIterator __first, _ForwardIterator __last, _OutputIterator __result, _BinaryPredicate __pred,
                     /*vector=*/std::false_type) noexcept
 {
     return std::unique_copy(__first, __last, __result, __pred);
 }
 
-template <class _RandomAccessIterator, class _OutputIterator, class _BinaryPredicate>
-  _OutputIterator
-__brick_unique_copy(_RandomAccessIterator __first, _RandomAccessIterator __last, _OutputIterator __result,
+template <class _RandomAccessIterator1, class _RandomAccessIterator2, class _BinaryPredicate>
+_RandomAccessIterator2
+__brick_unique_copy(_RandomAccessIterator1 __first, _RandomAccessIterator1 __last, _RandomAccessIterator2 __result,
                     _BinaryPredicate __pred, /*vector=*/std::true_type) noexcept
 {
-#if (_PSTL_MONOTONIC_PRESENT)
+#if defined(_PSTL_MONOTONIC_PRESENT)
     return __unseq_backend::__simd_unique_copy(__first, __last - __first, __result, __pred);
 #else
     return std::unique_copy(__first, __last, __result, __pred);
 #endif
 }
 
-template <class _ExecutionPolicy, class _ForwardIterator, class _OutputIterator, class _BinaryPredicate,
-          class _IsVector>
+template <class _Tag, class _ExecutionPolicy, class _ForwardIterator, class _OutputIterator, class _BinaryPredicate>
 _OutputIterator
-__pattern_unique_copy(_ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last, _OutputIterator __result,
-                      _BinaryPredicate __pred, _IsVector __is_vector, /*parallel=*/std::false_type) noexcept
+__pattern_unique_copy(_Tag, _ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last,
+                      _OutputIterator __result, _BinaryPredicate __pred) noexcept
 {
-    return __internal::__brick_unique_copy(__first, __last, __result, __pred, __is_vector);
+    return __internal::__brick_unique_copy(__first, __last, __result, __pred, typename _Tag::__is_vector{});
 }
 
 template <class _DifferenceType, class _RandomAccessIterator, class _BinaryPredicate>
@@ -1344,54 +1397,58 @@ __brick_calc_mask_2(_RandomAccessIterator __first, _RandomAccessIterator __last,
     return __unseq_backend::__simd_calc_mask_2(__first, __last - __first, __mask, __pred);
 }
 
-template <class _ExecutionPolicy, class _RandomAccessIterator, class _OutputIterator, class _BinaryPredicate,
-          class _IsVector>
-_OutputIterator
-__pattern_unique_copy(_ExecutionPolicy&& __exec, _RandomAccessIterator __first, _RandomAccessIterator __last,
-                      _OutputIterator __result, _BinaryPredicate __pred, _IsVector __is_vector,
-                      /*parallel=*/std::true_type)
+template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator1, class _RandomAccessIterator2,
+          class _BinaryPredicate>
+_RandomAccessIterator2
+__pattern_unique_copy(__parallel_tag<_IsVector> __tag, _ExecutionPolicy&& __exec, _RandomAccessIterator1 __first,
+                      _RandomAccessIterator1 __last, _RandomAccessIterator2 __result, _BinaryPredicate __pred)
 {
-    typedef typename std::iterator_traits<_RandomAccessIterator>::difference_type _DifferenceType;
+    using __backend_tag = typename decltype(__tag)::__backend_tag;
+
+    typedef typename std::iterator_traits<_RandomAccessIterator1>::difference_type _DifferenceType;
     const _DifferenceType __n = __last - __first;
     if (_DifferenceType(2) < __n)
     {
         __par_backend::__buffer<bool> __mask_buf(__n);
         if (_DifferenceType(2) < __n)
         {
-            return __internal::__except_handler([&__exec, __n, __first, __result, __pred, __is_vector, &__mask_buf]() {
-                bool* __mask = __mask_buf.get();
-                _DifferenceType __m{};
-                __par_backend::__parallel_strict_scan(
-                    std::forward<_ExecutionPolicy>(__exec), __n, _DifferenceType(0),
-                    [=](_DifferenceType __i, _DifferenceType __len) -> _DifferenceType { // Reduce
-                        _DifferenceType __extra = 0;
-                        if (__i == 0)
-                        {
-                            // Special boundary case
-                            __mask[__i] = true;
-                            if (--__len == 0)
-                                return 1;
-                            ++__i;
-                            ++__extra;
-                        }
-                        return __internal::__brick_calc_mask_2<_DifferenceType>(__first + __i, __first + (__i + __len),
-                                                                                __mask + __i, __pred, __is_vector) +
-                               __extra;
-                    },
-                    std::plus<_DifferenceType>(),                                                // Combine
-                    [=](_DifferenceType __i, _DifferenceType __len, _DifferenceType __initial) { // Scan
-                        // Phase 2 is same as for __pattern_copy_if
-                        __internal::__brick_copy_by_mask(
-                            __first + __i, __first + (__i + __len), __result + __initial, __mask + __i,
-                            [](_RandomAccessIterator __x, _OutputIterator __z) { *__z = *__x; }, __is_vector);
-                    },
-                    [&__m](_DifferenceType __total) { __m = __total; });
-                return __result + __m;
-            });
+            return __internal::__except_handler(
+                [&__exec, __n, __first, __result, __pred, &__mask_buf]()
+                {
+                    bool* __mask = __mask_buf.get();
+                    _DifferenceType __m{};
+                    __par_backend::__parallel_strict_scan(
+                        __backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __n, _DifferenceType(0),
+                        [=](_DifferenceType __i, _DifferenceType __len) -> _DifferenceType { // Reduce
+                            _DifferenceType __extra = 0;
+                            if (__i == 0)
+                            {
+                                // Special boundary case
+                                __mask[__i] = true;
+                                if (--__len == 0)
+                                    return 1;
+                                ++__i;
+                                ++__extra;
+                            }
+                            return __internal::__brick_calc_mask_2<_DifferenceType>(
+                                       __first + __i, __first + (__i + __len), __mask + __i, __pred, _IsVector{}) +
+                                   __extra;
+                        },
+                        std::plus<_DifferenceType>(),                                                // Combine
+                        [=](_DifferenceType __i, _DifferenceType __len, _DifferenceType __initial) { // Scan
+                            // Phase 2 is same as for __pattern_copy_if
+                            __internal::__brick_copy_by_mask(
+                                __first + __i, __first + (__i + __len), __result + __initial, __mask + __i,
+                                [](_RandomAccessIterator1 __x, _RandomAccessIterator2 __z) { *__z = *__x; },
+                                _IsVector{});
+                        },
+                        [&__m](_DifferenceType __total) { __m = __total; });
+                    return __result + __m;
+                });
         }
     }
     // trivial sequence - use serial algorithm
-    return __internal::__brick_unique_copy(__first, __last, __result, __pred, __is_vector);
+    return __internal::__brick_unique_copy(__first, __last, __result, __pred, _IsVector{});
 }
 
 //------------------------------------------------------------------------
@@ -1404,14 +1461,14 @@ __brick_reverse(_BidirectionalIterator __first, _BidirectionalIterator __last, /
     std::reverse(__first, __last);
 }
 
-template <class _BidirectionalIterator>
+template <class _RandomAccessIterator>
 void
-__brick_reverse(_BidirectionalIterator __first, _BidirectionalIterator __last, /*__is_vector=*/std::true_type) noexcept
+__brick_reverse(_RandomAccessIterator __first, _RandomAccessIterator __last, /*__is_vector=*/std::true_type) noexcept
 {
-    typedef typename std::iterator_traits<_BidirectionalIterator>::reference _ReferenceType;
+    typedef typename std::iterator_traits<_RandomAccessIterator>::reference _ReferenceType;
 
     const auto __n = (__last - __first) / 2;
-    __unseq_backend::__simd_walk_2(__first, __n, std::reverse_iterator<_BidirectionalIterator>(__last),
+    __unseq_backend::__simd_walk_2(__first, __n, std::reverse_iterator<_RandomAccessIterator>(__last),
                                    [](_ReferenceType __x, _ReferenceType __y) {
                                        using std::swap;
                                        swap(__x, __y);
@@ -1432,39 +1489,38 @@ __brick_reverse(_BidirectionalIterator __first, _BidirectionalIterator __last, _
 }
 
 // this brick is called in parallel version, so we can use iterator arithmetic
-template <class _BidirectionalIterator>
+template <class _RandomAccessIterator>
 void
-__brick_reverse(_BidirectionalIterator __first, _BidirectionalIterator __last, _BidirectionalIterator __d_last,
+__brick_reverse(_RandomAccessIterator __first, _RandomAccessIterator __last, _RandomAccessIterator __d_last,
                 /*is_vector=*/std::true_type) noexcept
 {
-    typedef typename std::iterator_traits<_BidirectionalIterator>::reference _ReferenceType;
+    typedef typename std::iterator_traits<_RandomAccessIterator>::reference _ReferenceType;
 
-    __unseq_backend::__simd_walk_2(__first, __last - __first, std::reverse_iterator<_BidirectionalIterator>(__d_last),
+    __unseq_backend::__simd_walk_2(__first, __last - __first, std::reverse_iterator<_RandomAccessIterator>(__d_last),
                                    [](_ReferenceType __x, _ReferenceType __y) {
                                        using std::swap;
                                        swap(__x, __y);
                                    });
 }
 
-template <class _ExecutionPolicy, class _BidirectionalIterator, class _IsVector>
+template <class _Tag, class _ExecutionPolicy, class _BidirectionalIterator>
 void
-__pattern_reverse(_ExecutionPolicy&&, _BidirectionalIterator __first, _BidirectionalIterator __last,
-                  _IsVector __is_vector,
-                  /*is_parallel=*/std::false_type) noexcept
+__pattern_reverse(_Tag, _ExecutionPolicy&&, _BidirectionalIterator __first, _BidirectionalIterator __last) noexcept
 {
-    __internal::__brick_reverse(__first, __last, __is_vector);
+    __internal::__brick_reverse(__first, __last, typename _Tag::__is_vector{});
 }
 
-template <class _ExecutionPolicy, class _BidirectionalIterator, class _IsVector>
+template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator>
 void
-__pattern_reverse(_ExecutionPolicy&& __exec, _BidirectionalIterator __first, _BidirectionalIterator __last,
-                  _IsVector __is_vector, /*is_parallel=*/std::true_type)
+__pattern_reverse(__parallel_tag<_IsVector> __tag, _ExecutionPolicy&& __exec, _RandomAccessIterator __first,
+                  _RandomAccessIterator __last)
 {
+    using __backend_tag = typename decltype(__tag)::__backend_tag;
+
     __par_backend::__parallel_for(
-        std::forward<_ExecutionPolicy>(__exec), __first, __first + (__last - __first) / 2,
-        [__is_vector, __first, __last](_BidirectionalIterator __inner_first, _BidirectionalIterator __inner_last) {
-            __internal::__brick_reverse(__inner_first, __inner_last, __last - (__inner_first - __first), __is_vector);
-        });
+        __backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __first, __first + (__last - __first) / 2,
+        [__first, __last](_RandomAccessIterator __inner_first, _RandomAccessIterator __inner_last)
+        { __internal::__brick_reverse(__inner_first, __inner_last, __last - (__inner_first - __first), _IsVector{}); });
 }
 
 //------------------------------------------------------------------------
@@ -1479,39 +1535,41 @@ __brick_reverse_copy(_BidirectionalIterator __first, _BidirectionalIterator __la
     return std::reverse_copy(__first, __last, __d_first);
 }
 
-template <class _BidirectionalIterator, class _OutputIterator>
-_OutputIterator
-__brick_reverse_copy(_BidirectionalIterator __first, _BidirectionalIterator __last, _OutputIterator __d_first,
+template <class _RandomAccessIterator1, class _RandomAccessIterator2>
+_RandomAccessIterator2
+__brick_reverse_copy(_RandomAccessIterator1 __first, _RandomAccessIterator1 __last, _RandomAccessIterator2 __d_first,
                      /*is_vector=*/std::true_type) noexcept
 {
-    typedef typename std::iterator_traits<_BidirectionalIterator>::reference _ReferenceType1;
-    typedef typename std::iterator_traits<_OutputIterator>::reference _ReferenceType2;
+    typedef typename std::iterator_traits<_RandomAccessIterator1>::reference _ReferenceType1;
+    typedef typename std::iterator_traits<_RandomAccessIterator2>::reference _ReferenceType2;
 
-    return __unseq_backend::__simd_walk_2(std::reverse_iterator<_BidirectionalIterator>(__last), __last - __first,
+    return __unseq_backend::__simd_walk_2(std::reverse_iterator<_RandomAccessIterator1>(__last), __last - __first,
                                           __d_first, [](_ReferenceType1 __x, _ReferenceType2 __y) { __y = __x; });
 }
 
-template <class _ExecutionPolicy, class _BidirectionalIterator, class _OutputIterator, class _IsVector>
+template <class _Tag, class _ExecutionPolicy, class _BidirectionalIterator, class _OutputIterator>
 _OutputIterator
-__pattern_reverse_copy(_ExecutionPolicy&&, _BidirectionalIterator __first, _BidirectionalIterator __last,
-                       _OutputIterator __d_first, _IsVector __is_vector, /*is_parallel=*/std::false_type) noexcept
+__pattern_reverse_copy(_Tag, _ExecutionPolicy&&, _BidirectionalIterator __first, _BidirectionalIterator __last,
+                       _OutputIterator __d_first) noexcept
 {
-    return __internal::__brick_reverse_copy(__first, __last, __d_first, __is_vector);
+    return __internal::__brick_reverse_copy(__first, __last, __d_first, typename _Tag::__is_vector{});
 }
 
-template <class _ExecutionPolicy, class _BidirectionalIterator, class _OutputIterator, class _IsVector>
-_OutputIterator
-__pattern_reverse_copy(_ExecutionPolicy&& __exec, _BidirectionalIterator __first, _BidirectionalIterator __last,
-                       _OutputIterator __d_first, _IsVector __is_vector, /*is_parallel=*/std::true_type)
+template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator1, class _RandomAccessIterator2>
+_RandomAccessIterator2
+__pattern_reverse_copy(__parallel_tag<_IsVector> __tag, _ExecutionPolicy&& __exec, _RandomAccessIterator1 __first,
+                       _RandomAccessIterator1 __last, _RandomAccessIterator2 __d_first)
 {
+    using __backend_tag = typename decltype(__tag)::__backend_tag;
+
     auto __len = __last - __first;
-    __par_backend::__parallel_for(std::forward<_ExecutionPolicy>(__exec), __first, __last,
-                                  [__is_vector, __first, __len, __d_first](_BidirectionalIterator __inner_first,
-                                                                           _BidirectionalIterator __inner_last) {
-                                      __internal::__brick_reverse_copy(__inner_first, __inner_last,
-                                                                       __d_first + (__len - (__inner_last - __first)),
-                                                                       __is_vector);
-                                  });
+    __par_backend::__parallel_for(
+        __backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __first, __last,
+        [__first, __len, __d_first](_RandomAccessIterator1 __inner_first, _RandomAccessIterator1 __inner_last)
+        {
+            __internal::__brick_reverse_copy(__inner_first, __inner_last,
+                                             __d_first + (__len - (__inner_last - __first)), _IsVector{});
+        });
     return __d_first + __len;
 }
 
@@ -1523,7 +1581,7 @@ _ForwardIterator
 __brick_rotate(_ForwardIterator __first, _ForwardIterator __middle, _ForwardIterator __last,
                /*is_vector=*/std::false_type) noexcept
 {
-#if _PSTL_CPP11_STD_ROTATE_BROKEN
+#if defined(_PSTL_CPP11_STD_ROTATE_BROKEN)
     std::rotate(__first, __middle, __last);
     return std::next(__first, std::distance(__middle, __last));
 #else
@@ -1531,14 +1589,14 @@ __brick_rotate(_ForwardIterator __first, _ForwardIterator __middle, _ForwardIter
 #endif
 }
 
-template <class _ForwardIterator>
-_ForwardIterator
-__brick_rotate(_ForwardIterator __first, _ForwardIterator __middle, _ForwardIterator __last,
+template <class _RandomAccessIterator>
+_RandomAccessIterator
+__brick_rotate(_RandomAccessIterator __first, _RandomAccessIterator __middle, _RandomAccessIterator __last,
                /*is_vector=*/std::true_type) noexcept
 {
     auto __n = __last - __first;
     auto __m = __middle - __first;
-    const _ForwardIterator __ret = __first + (__last - __middle);
+    const _RandomAccessIterator __ret = __first + (__last - __middle);
 
     bool __is_left = (__m <= __n / 2);
     if (!__is_left)
@@ -1553,7 +1611,7 @@ __brick_rotate(_ForwardIterator __first, _ForwardIterator __middle, _ForwardIter
             for (; __last - __first >= __m_2; __first += __m)
             {
                 __unseq_backend::__simd_assign(__first, __m, __first + __m,
-                                               iter_swap<_ForwardIterator, _ForwardIterator>);
+                                               iter_swap<_RandomAccessIterator, _RandomAccessIterator>);
             }
         }
         else
@@ -1561,7 +1619,7 @@ __brick_rotate(_ForwardIterator __first, _ForwardIterator __middle, _ForwardIter
             for (; __last - __first >= __m_2; __last -= __m)
             {
                 __unseq_backend::__simd_assign(__last - __m, __m, __last - __m_2,
-                                               iter_swap<_ForwardIterator, _ForwardIterator>);
+                                               iter_swap<_RandomAccessIterator, _RandomAccessIterator>);
             }
         }
         __is_left = !__is_left;
@@ -1572,73 +1630,73 @@ __brick_rotate(_ForwardIterator __first, _ForwardIterator __middle, _ForwardIter
     return __ret;
 }
 
-template <class _ExecutionPolicy, class _ForwardIterator, class _IsVector>
+template <class _Tag, class _ExecutionPolicy, class _ForwardIterator>
 _ForwardIterator
-__pattern_rotate(_ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __middle, _ForwardIterator __last,
-                 _IsVector __is_vector, /*is_parallel=*/std::false_type) noexcept
+__pattern_rotate(_Tag, _ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __middle,
+                 _ForwardIterator __last) noexcept
 {
-    return __internal::__brick_rotate(__first, __middle, __last, __is_vector);
+    return __internal::__brick_rotate(__first, __middle, __last, typename _Tag::__is_vector{});
 }
 
-template <class _ExecutionPolicy, class _ForwardIterator, class _IsVector>
-_ForwardIterator
-__pattern_rotate(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __middle,
-                 _ForwardIterator __last, _IsVector __is_vector, /*is_parallel=*/std::true_type)
+template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator>
+_RandomAccessIterator
+__pattern_rotate(__parallel_tag<_IsVector> __tag, _ExecutionPolicy&& __exec, _RandomAccessIterator __first,
+                 _RandomAccessIterator __middle, _RandomAccessIterator __last)
 {
-    typedef typename std::iterator_traits<_ForwardIterator>::value_type _Tp;
+    using __backend_tag = typename decltype(__tag)::__backend_tag;
+
+    typedef typename std::iterator_traits<_RandomAccessIterator>::value_type _Tp;
     auto __n = __last - __first;
     auto __m = __middle - __first;
     if (__m <= __n / 2)
     {
         __par_backend::__buffer<_Tp> __buf(__n - __m);
-        return __internal::__except_handler([&__exec, __n, __m, __first, __middle, __last, __is_vector, &__buf]() {
-            _Tp* __result = __buf.get();
-            __par_backend::__parallel_for(
-                std::forward<_ExecutionPolicy>(__exec), __middle, __last,
-                [__middle, __result, __is_vector](_ForwardIterator __b, _ForwardIterator __e) {
-                    __internal::__brick_uninitialized_move(__b, __e, __result + (__b - __middle), __is_vector);
-                });
+        return __internal::__except_handler(
+            [&__exec, __n, __m, __first, __middle, __last, &__buf]()
+            {
+                _Tp* __result = __buf.get();
+                __par_backend::__parallel_for(
+                    __backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __middle, __last,
+                    [__middle, __result](_RandomAccessIterator __b, _RandomAccessIterator __e)
+                    { __internal::__brick_uninitialized_move(__b, __e, __result + (__b - __middle), _IsVector{}); });
 
-            __par_backend::__parallel_for(std::forward<_ExecutionPolicy>(__exec), __first, __middle,
-                                          [__last, __middle, __is_vector](_ForwardIterator __b, _ForwardIterator __e) {
-                                              __internal::__brick_move(__b, __e, __b + (__last - __middle),
-                                                                       __is_vector);
-                                          });
+                __par_backend::__parallel_for(
+                    __backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __first, __middle,
+                    [__last, __middle](_RandomAccessIterator __b, _RandomAccessIterator __e)
+                    { __internal::__brick_move(__b, __e, __b + (__last - __middle), _IsVector{}); });
 
-            __par_backend::__parallel_for(std::forward<_ExecutionPolicy>(__exec), __result, __result + (__n - __m),
-                                          [__first, __result, __is_vector](_Tp* __b, _Tp* __e) {
-                                              __brick_move_destroy()(
-                                                  __b, __e, __first + (__b - __result), __is_vector);
-                                          });
+                __par_backend::__parallel_for(
+                    __backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __result, __result + (__n - __m),
+                    [__first, __result](_Tp* __b, _Tp* __e)
+                    { __brick_move_destroy()(__b, __e, __first + (__b - __result), _IsVector{}); });
 
-            return __first + (__last - __middle);
-        });
+                return __first + (__last - __middle);
+            });
     }
     else
     {
         __par_backend::__buffer<_Tp> __buf(__m);
-        return __internal::__except_handler([&__exec, __n, __m, __first, __middle, __last, __is_vector, &__buf]() {
-            _Tp* __result = __buf.get();
-            __par_backend::__parallel_for(std::forward<_ExecutionPolicy>(__exec), __first, __middle,
-                                          [__first, __result, __is_vector](_ForwardIterator __b, _ForwardIterator __e) {
-                                              __internal::__brick_uninitialized_move(
-                                                  __b, __e, __result + (__b - __first), __is_vector);
-                                          });
+        return __internal::__except_handler(
+            [&__exec, __n, __m, __first, __middle, __last, &__buf]()
+            {
+                _Tp* __result = __buf.get();
+                __par_backend::__parallel_for(
+                    __backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __first, __middle,
+                    [__first, __result](_RandomAccessIterator __b, _RandomAccessIterator __e)
+                    { __internal::__brick_uninitialized_move(__b, __e, __result + (__b - __first), _IsVector{}); });
 
-            __par_backend::__parallel_for(std::forward<_ExecutionPolicy>(__exec), __middle, __last,
-                                          [__first, __middle, __is_vector](_ForwardIterator __b, _ForwardIterator __e) {
-                                              __internal::__brick_move(__b, __e, __first + (__b - __middle),
-                                                                       __is_vector);
-                                          });
+                __par_backend::__parallel_for(
+                    __backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __middle, __last,
+                    [__first, __middle](_RandomAccessIterator __b, _RandomAccessIterator __e)
+                    { __internal::__brick_move(__b, __e, __first + (__b - __middle), _IsVector{}); });
 
-            __par_backend::__parallel_for(std::forward<_ExecutionPolicy>(__exec), __result, __result + __m,
-                                          [__n, __m, __first, __result, __is_vector](_Tp* __b, _Tp* __e) {
-                                              __brick_move_destroy()(
-                                                  __b, __e, __first + ((__n - __m) + (__b - __result)), __is_vector);
-                                          });
+                __par_backend::__parallel_for(
+                    __backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __result, __result + __m,
+                    [__n, __m, __first, __result](_Tp* __b, _Tp* __e)
+                    { __brick_move_destroy()(__b, __e, __first + ((__n - __m) + (__b - __result)), _IsVector{}); });
 
-            return __first + (__last - __middle);
-        });
+                return __first + (__last - __middle);
+            });
     }
 }
 
@@ -1654,47 +1712,49 @@ __brick_rotate_copy(_ForwardIterator __first, _ForwardIterator __middle, _Forwar
     return std::rotate_copy(__first, __middle, __last, __result);
 }
 
-template <class _ForwardIterator, class _OutputIterator>
-_OutputIterator
-__brick_rotate_copy(_ForwardIterator __first, _ForwardIterator __middle, _ForwardIterator __last,
-                    _OutputIterator __result, /*__is_vector=*/std::true_type) noexcept
+template <class _RandomAccessIterator1, class _RandomAccessIterator2>
+_RandomAccessIterator2
+__brick_rotate_copy(_RandomAccessIterator1 __first, _RandomAccessIterator1 __middle, _RandomAccessIterator1 __last,
+                    _RandomAccessIterator2 __result, /*__is_vector=*/std::true_type) noexcept
 {
-    _OutputIterator __res = __internal::__brick_copy(__middle, __last, __result, std::true_type());
+    _RandomAccessIterator2 __res = __internal::__brick_copy(__middle, __last, __result, std::true_type());
     return __internal::__brick_copy(__first, __middle, __res, std::true_type());
 }
 
-template <class _ExecutionPolicy, class _ForwardIterator, class _OutputIterator, class _IsVector>
+template <class _Tag, class _ExecutionPolicy, class _ForwardIterator, class _OutputIterator>
 _OutputIterator
-__pattern_rotate_copy(_ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __middle, _ForwardIterator __last,
-                      _OutputIterator __result, _IsVector __is_vector, /*is_parallel=*/std::false_type) noexcept
+__pattern_rotate_copy(_Tag, _ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __middle,
+                      _ForwardIterator __last, _OutputIterator __result) noexcept
 {
-    return __internal::__brick_rotate_copy(__first, __middle, __last, __result, __is_vector);
+    return __internal::__brick_rotate_copy(__first, __middle, __last, __result, typename _Tag::__is_vector{});
 }
 
-template <class _ExecutionPolicy, class _ForwardIterator, class _OutputIterator, class _IsVector>
-_OutputIterator
-__pattern_rotate_copy(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __middle,
-                      _ForwardIterator __last, _OutputIterator __result, _IsVector __is_vector,
-                      /*is_parallel=*/std::true_type)
+template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator1, class _RandomAccessIterator2>
+_RandomAccessIterator2
+__pattern_rotate_copy(__parallel_tag<_IsVector> __tag, _ExecutionPolicy&& __exec, _RandomAccessIterator1 __first,
+                      _RandomAccessIterator1 __middle, _RandomAccessIterator1 __last, _RandomAccessIterator2 __result)
 {
+    using __backend_tag = typename decltype(__tag)::__backend_tag;
+
     __par_backend::__parallel_for(
-        std::forward<_ExecutionPolicy>(__exec), __first, __last,
-        [__first, __last, __middle, __result, __is_vector](_ForwardIterator __b, _ForwardIterator __e) {
+        __backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __first, __last,
+        [__first, __last, __middle, __result](_RandomAccessIterator1 __b, _RandomAccessIterator1 __e)
+        {
             if (__b > __middle)
             {
-                __internal::__brick_copy(__b, __e, __result + (__b - __middle), __is_vector);
+                __internal::__brick_copy(__b, __e, __result + (__b - __middle), _IsVector{});
             }
             else
             {
-                _OutputIterator __new_result = __result + ((__last - __middle) + (__b - __first));
+                _RandomAccessIterator2 __new_result = __result + ((__last - __middle) + (__b - __first));
                 if (__e < __middle)
                 {
-                    __internal::__brick_copy(__b, __e, __new_result, __is_vector);
+                    __internal::__brick_copy(__b, __e, __new_result, _IsVector{});
                 }
                 else
                 {
-                    __internal::__brick_copy(__b, __middle, __new_result, __is_vector);
-                    __internal::__brick_copy(__middle, __e, __result, __is_vector);
+                    __internal::__brick_copy(__b, __middle, __new_result, _IsVector{});
+                    __internal::__brick_copy(__middle, __e, __result, _IsVector{});
                 }
             }
         });
@@ -1713,21 +1773,21 @@ __brick_is_partitioned(_ForwardIterator __first, _ForwardIterator __last, _Unary
     return std::is_partitioned(__first, __last, __pred);
 }
 
-template <class _ForwardIterator, class _UnaryPredicate>
+template <class _RandomAccessIterator, class _UnaryPredicate>
 bool
-__brick_is_partitioned(_ForwardIterator __first, _ForwardIterator __last, _UnaryPredicate __pred,
+__brick_is_partitioned(_RandomAccessIterator __first, _RandomAccessIterator __last, _UnaryPredicate __pred,
                        /*is_vector=*/std::true_type) noexcept
 {
-    typedef typename std::iterator_traits<_ForwardIterator>::difference_type _SizeType;
+    typedef typename std::iterator_traits<_RandomAccessIterator>::difference_type _SizeType;
     if (__first == __last)
     {
         return true;
     }
     else
     {
-        _ForwardIterator __result = __unseq_backend::__simd_first(
+        _RandomAccessIterator __result = __unseq_backend::__simd_first(
             __first, _SizeType(0), __last - __first,
-            [&__pred](_ForwardIterator __it, _SizeType __i) { return !__pred(__it[__i]); });
+            [&__pred](_RandomAccessIterator __it, _SizeType __i) { return !__pred(__it[__i]); });
         if (__result == __last)
         {
             return true;
@@ -1740,18 +1800,18 @@ __brick_is_partitioned(_ForwardIterator __first, _ForwardIterator __last, _Unary
     }
 }
 
-template <class _ExecutionPolicy, class _ForwardIterator, class _UnaryPredicate, class _IsVector>
+template <class _Tag, class _ExecutionPolicy, class _ForwardIterator, class _UnaryPredicate>
 bool
-__pattern_is_partitioned(_ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last, _UnaryPredicate __pred,
-                         _IsVector __is_vector, /*is_parallel=*/std::false_type) noexcept
+__pattern_is_partitioned(_Tag, _ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last,
+                         _UnaryPredicate __pred) noexcept
 {
-    return __internal::__brick_is_partitioned(__first, __last, __pred, __is_vector);
+    return __internal::__brick_is_partitioned(__first, __last, __pred, typename _Tag::__is_vector{});
 }
 
-template <class _ExecutionPolicy, class _ForwardIterator, class _UnaryPredicate, class _IsVector>
+template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _UnaryPredicate>
 bool
-__pattern_is_partitioned(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last,
-                         _UnaryPredicate __pred, _IsVector __is_vector, /*is_parallel=*/std::true_type)
+__pattern_is_partitioned(__parallel_tag<_IsVector> __tag, _ExecutionPolicy&& __exec, _RandomAccessIterator __first,
+                         _RandomAccessIterator __last, _UnaryPredicate __pred)
 {
     if (__first == __last)
     {
@@ -1759,6 +1819,8 @@ __pattern_is_partitioned(_ExecutionPolicy&& __exec, _ForwardIterator __first, _F
     }
     else
     {
+        using __backend_tag = typename decltype(__tag)::__backend_tag;
+
         return __internal::__except_handler([&]() {
             // State of current range:
             // broken     - current range is not partitioned by pred
@@ -1782,9 +1844,10 @@ __pattern_is_partitioned(_ExecutionPolicy&& __exec, _ForwardIterator __first, _F
                                      __broken,     __broken,     __true_false, __broken};
 
             __init = __par_backend::__parallel_reduce(
-                std::forward<_ExecutionPolicy>(__exec), __first, __last, __init,
-                [&__pred, &__table, __is_vector](_ForwardIterator __i, _ForwardIterator __j,
-                                                 _ReduceType __value) -> _ReduceType {
+                __backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __first, __last, __init,
+                [&__pred, &__table](_RandomAccessIterator __i, _RandomAccessIterator __j,
+                                    _ReduceType __value) -> _ReduceType
+                {
                     if (__value == __broken)
                     {
                         return __broken;
@@ -1794,12 +1857,12 @@ __pattern_is_partitioned(_ExecutionPolicy&& __exec, _ForwardIterator __first, _F
                     if (__pred(*__i))
                     {
                         // find first element that don't satisfy pred
-                        _ForwardIterator __x =
-                            __internal::__brick_find_if(__i + 1, __j, std::not_fn(__pred), __is_vector);
+                        _RandomAccessIterator __x =
+                            __internal::__brick_find_if(__i + 1, __j, std::not_fn(__pred), _IsVector{});
                         if (__x != __j)
                         {
                             // find first element after "x" that satisfy pred
-                            _ForwardIterator __y = __internal::__brick_find_if(__x + 1, __j, __pred, __is_vector);
+                            _RandomAccessIterator __y = __internal::__brick_find_if(__x + 1, __j, __pred, _IsVector{});
                             // if it was found then range isn't partitioned by pred
                             if (__y != __j)
                             {
@@ -1819,7 +1882,7 @@ __pattern_is_partitioned(_ExecutionPolicy&& __exec, _ForwardIterator __first, _F
                     { // if first element doesn't satisfy pred
                         // then we should find the first element that satisfy pred.
                         // If we found it then range isn't partitioned by pred
-                        if (__internal::__brick_find_if(__i + 1, __j, __pred, __is_vector) != __j)
+                        if (__internal::__brick_find_if(__i + 1, __j, __pred, _IsVector{}) != __j)
                         {
                             return __broken;
                         }
@@ -1832,7 +1895,8 @@ __pattern_is_partitioned(_ExecutionPolicy&& __exec, _ForwardIterator __first, _F
                     return (__value == -1) ? __res : __table[__value * 4 + __res];
                 },
 
-                [&__table](_ReduceType __val1, _ReduceType __val2) -> _ReduceType {
+                [&__table](_ReduceType __val1, _ReduceType __val2) -> _ReduceType
+                {
                     if (__val1 == __broken || __val2 == __broken)
                     {
                         return __broken;
@@ -1857,43 +1921,45 @@ __brick_partition(_ForwardIterator __first, _ForwardIterator __last, _UnaryPredi
     return std::partition(__first, __last, __pred);
 }
 
-template <class _ForwardIterator, class _UnaryPredicate>
-_ForwardIterator
-__brick_partition(_ForwardIterator __first, _ForwardIterator __last, _UnaryPredicate __pred,
+template <class _RandomAccessIterator, class _UnaryPredicate>
+_RandomAccessIterator
+__brick_partition(_RandomAccessIterator __first, _RandomAccessIterator __last, _UnaryPredicate __pred,
                   /*is_vector=*/std::true_type) noexcept
 {
     _PSTL_PRAGMA_MESSAGE("Vectorized algorithm unimplemented, redirected to serial");
     return std::partition(__first, __last, __pred);
 }
 
-template <class _ExecutionPolicy, class _ForwardIterator, class _UnaryPredicate, class _IsVector>
+template <class _Tag, class _ExecutionPolicy, class _ForwardIterator, class _UnaryPredicate>
 _ForwardIterator
-__pattern_partition(_ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last, _UnaryPredicate __pred,
-                    _IsVector __is_vector, /*is_parallel=*/std::false_type) noexcept
+__pattern_partition(_Tag, _ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last,
+                    _UnaryPredicate __pred) noexcept
 {
-    return __internal::__brick_partition(__first, __last, __pred, __is_vector);
+    return __internal::__brick_partition(__first, __last, __pred, typename _Tag::__is_vector{});
 }
 
-template <class _ExecutionPolicy, class _ForwardIterator, class _UnaryPredicate, class _IsVector>
-_ForwardIterator
-__pattern_partition(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last,
-                    _UnaryPredicate __pred, _IsVector __is_vector, /*is_parallel=*/std::true_type)
+template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _UnaryPredicate>
+_RandomAccessIterator
+__pattern_partition(__parallel_tag<_IsVector> __tag, _ExecutionPolicy&& __exec, _RandomAccessIterator __first,
+                    _RandomAccessIterator __last, _UnaryPredicate __pred)
 {
+    using __backend_tag = typename decltype(__tag)::__backend_tag;
 
     // partitioned range: elements before pivot satisfy pred (true part),
     //                    elements after pivot don't satisfy pred (false part)
     struct _PartitionRange
     {
-        _ForwardIterator __begin;
-        _ForwardIterator __pivot;
-        _ForwardIterator __end;
+        _RandomAccessIterator __begin;
+        _RandomAccessIterator __pivot;
+        _RandomAccessIterator __end;
     };
 
     return __internal::__except_handler([&]() {
         _PartitionRange __init{__last, __last, __last};
 
         // lambda for merging two partitioned ranges to one partitioned range
-        auto __reductor = [&__exec, __is_vector](_PartitionRange __val1, _PartitionRange __val2) -> _PartitionRange {
+        auto __reductor = [&__exec](_PartitionRange __val1, _PartitionRange __val2) -> _PartitionRange
+        {
             auto __size1 = __val1.__end - __val1.__pivot;
             auto __size2 = __val2.__pivot - __val2.__begin;
             auto __new_begin = __val2.__begin - (__val1.__end - __val1.__begin);
@@ -1908,10 +1974,10 @@ __pattern_partition(_ExecutionPolicy&& __exec, _ForwardIterator __first, _Forwar
             else if (__size2 > __size1)
             {
                 __par_backend::__parallel_for(
-                    std::forward<_ExecutionPolicy>(__exec), __val1.__pivot, __val1.__pivot + __size1,
-                    [__val1, __val2, __size1, __is_vector](_ForwardIterator __i, _ForwardIterator __j) {
+                    __backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __val1.__pivot, __val1.__pivot + __size1,
+                    [__val1, __val2, __size1](_RandomAccessIterator __i, _RandomAccessIterator __j) {
                         __internal::__brick_swap_ranges(__i, __j, (__val2.__pivot - __size1) + (__i - __val1.__pivot),
-                                                        __is_vector);
+                                                        _IsVector{});
                     });
                 return {__new_begin, __val2.__pivot - __size1, __val2.__end};
             }
@@ -1919,20 +1985,21 @@ __pattern_partition(_ExecutionPolicy&& __exec, _ForwardIterator __first, _Forwar
             else
             {
                 __par_backend::__parallel_for(
-                    std::forward<_ExecutionPolicy>(__exec), __val1.__pivot, __val1.__pivot + __size2,
-                    [__val1, __val2, __is_vector](_ForwardIterator __i, _ForwardIterator __j) {
-                        __internal::__brick_swap_ranges(__i, __j, __val2.__begin + (__i - __val1.__pivot), __is_vector);
+                    __backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __val1.__pivot, __val1.__pivot + __size2,
+                    [__val1, __val2](_RandomAccessIterator __i, _RandomAccessIterator __j) {
+                        __internal::__brick_swap_ranges(__i, __j, __val2.__begin + (__i - __val1.__pivot), _IsVector{});
                     });
                 return {__new_begin, __val1.__pivot + __size2, __val2.__end};
             }
         };
 
         _PartitionRange __result = __par_backend::__parallel_reduce(
-            std::forward<_ExecutionPolicy>(__exec), __first, __last, __init,
-            [__pred, __is_vector, __reductor](_ForwardIterator __i, _ForwardIterator __j,
-                                              _PartitionRange __value) -> _PartitionRange {
+            __backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __first, __last, __init,
+            [__pred, __reductor](_RandomAccessIterator __i, _RandomAccessIterator __j,
+                                 _PartitionRange __value) -> _PartitionRange
+            {
                 //1. serial partition
-                _ForwardIterator __pivot = __internal::__brick_partition(__i, __j, __pred, __is_vector);
+                _RandomAccessIterator __pivot = __internal::__brick_partition(__i, __j, __pred, _IsVector{});
 
                 // 2. merging of two ranges (left and right respectively)
                 return __reductor(__value, {__i, __pivot, __j});
@@ -1954,44 +2021,45 @@ __brick_stable_partition(_BidirectionalIterator __first, _BidirectionalIterator
     return std::stable_partition(__first, __last, __pred);
 }
 
-template <class _BidirectionalIterator, class _UnaryPredicate>
-_BidirectionalIterator
-__brick_stable_partition(_BidirectionalIterator __first, _BidirectionalIterator __last, _UnaryPredicate __pred,
+template <class _RandomAccessIterator, class _UnaryPredicate>
+_RandomAccessIterator
+__brick_stable_partition(_RandomAccessIterator __first, _RandomAccessIterator __last, _UnaryPredicate __pred,
                          /*__is_vector=*/std::true_type) noexcept
 {
     _PSTL_PRAGMA_MESSAGE("Vectorized algorithm unimplemented, redirected to serial");
     return std::stable_partition(__first, __last, __pred);
 }
 
-template <class _ExecutionPolicy, class _BidirectionalIterator, class _UnaryPredicate, class _IsVector>
+template <class _Tag, class _ExecutionPolicy, class _BidirectionalIterator, class _UnaryPredicate>
 _BidirectionalIterator
-__pattern_stable_partition(_ExecutionPolicy&&, _BidirectionalIterator __first, _BidirectionalIterator __last,
-                           _UnaryPredicate __pred, _IsVector __is_vector,
-                           /*is_parallelization=*/std::false_type) noexcept
+__pattern_stable_partition(_Tag, _ExecutionPolicy&&, _BidirectionalIterator __first, _BidirectionalIterator __last,
+                           _UnaryPredicate __pred) noexcept
 {
-    return __internal::__brick_stable_partition(__first, __last, __pred, __is_vector);
+    return __internal::__brick_stable_partition(__first, __last, __pred, typename _Tag::__is_vector{});
 }
 
-template <class _ExecutionPolicy, class _BidirectionalIterator, class _UnaryPredicate, class _IsVector>
-_BidirectionalIterator
-__pattern_stable_partition(_ExecutionPolicy&& __exec, _BidirectionalIterator __first, _BidirectionalIterator __last,
-                           _UnaryPredicate __pred, _IsVector __is_vector,
-                           /*is_parallelization=*/std::true_type) noexcept
+template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _UnaryPredicate>
+_RandomAccessIterator
+__pattern_stable_partition(__parallel_tag<_IsVector> __tag, _ExecutionPolicy&& __exec, _RandomAccessIterator __first,
+                           _RandomAccessIterator __last, _UnaryPredicate __pred) noexcept
 {
+    using __backend_tag = typename decltype(__tag)::__backend_tag;
+
     // partitioned range: elements before pivot satisfy pred (true part),
     //                    elements after pivot don't satisfy pred (false part)
     struct _PartitionRange
     {
-        _BidirectionalIterator __begin;
-        _BidirectionalIterator __pivot;
-        _BidirectionalIterator __end;
+        _RandomAccessIterator __begin;
+        _RandomAccessIterator __pivot;
+        _RandomAccessIterator __end;
     };
 
     return __internal::__except_handler([&]() {
         _PartitionRange __init{__last, __last, __last};
 
         // lambda for merging two partitioned ranges to one partitioned range
-        auto __reductor = [__is_vector](_PartitionRange __val1, _PartitionRange __val2) -> _PartitionRange {
+        auto __reductor = [](_PartitionRange __val1, _PartitionRange __val2) -> _PartitionRange
+        {
             auto __size1 = __val1.__end - __val1.__pivot;
             auto __new_begin = __val2.__begin - (__val1.__end - __val1.__begin);
 
@@ -2004,17 +2072,18 @@ __pattern_stable_partition(_ExecutionPolicy&& __exec, _BidirectionalIterator __f
             // then we should swap the false part of left range and last part of true part of right range
             else
             {
-                __internal::__brick_rotate(__val1.__pivot, __val2.__begin, __val2.__pivot, __is_vector);
+                __internal::__brick_rotate(__val1.__pivot, __val2.__begin, __val2.__pivot, _IsVector{});
                 return {__new_begin, __val2.__pivot - __size1, __val2.__end};
             }
         };
 
         _PartitionRange __result = __par_backend::__parallel_reduce(
-            std::forward<_ExecutionPolicy>(__exec), __first, __last, __init,
-            [&__pred, __is_vector, __reductor](_BidirectionalIterator __i, _BidirectionalIterator __j,
-                                               _PartitionRange __value) -> _PartitionRange {
+            __backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __first, __last, __init,
+            [&__pred, __reductor](_RandomAccessIterator __i, _RandomAccessIterator __j,
+                                  _PartitionRange __value) -> _PartitionRange
+            {
                 //1. serial stable_partition
-                _BidirectionalIterator __pivot = __internal::__brick_stable_partition(__i, __j, __pred, __is_vector);
+                _RandomAccessIterator __pivot = __internal::__brick_stable_partition(__i, __j, __pred, _IsVector{});
 
                 // 2. merging of two ranges (left and right respectively)
                 return __reductor(__value, {__i, __pivot, __j});
@@ -2036,170 +2105,190 @@ __brick_partition_copy(_ForwardIterator __first, _ForwardIterator __last, _Outpu
     return std::partition_copy(__first, __last, __out_true, __out_false, __pred);
 }
 
-template <class _ForwardIterator, class _OutputIterator1, class _OutputIterator2, class _UnaryPredicate>
-std::pair<_OutputIterator1, _OutputIterator2>
-__brick_partition_copy(_ForwardIterator __first, _ForwardIterator __last, _OutputIterator1 __out_true,
-                       _OutputIterator2 __out_false, _UnaryPredicate __pred, /*is_vector=*/std::true_type) noexcept
+template <class _RandomAccessIterator1, class _RandomAccessIterator2, class _RandomAccessIterator3,
+          class _UnaryPredicate>
+std::pair<_RandomAccessIterator2, _RandomAccessIterator3>
+__brick_partition_copy(_RandomAccessIterator1 __first, _RandomAccessIterator1 __last, _RandomAccessIterator2 __out_true,
+                       _RandomAccessIterator3 __out_false, _UnaryPredicate __pred,
+                       /*is_vector=*/std::true_type) noexcept
 {
-#if (_PSTL_MONOTONIC_PRESENT)
+#if defined(_PSTL_MONOTONIC_PRESENT)
     return __unseq_backend::__simd_partition_copy(__first, __last - __first, __out_true, __out_false, __pred);
 #else
     return std::partition_copy(__first, __last, __out_true, __out_false, __pred);
 #endif
 }
 
-template <class _ExecutionPolicy, class _ForwardIterator, class _OutputIterator1, class _OutputIterator2,
-          class _UnaryPredicate, class _IsVector>
+template <class _Tag, class _ExecutionPolicy, class _ForwardIterator, class _OutputIterator1, class _OutputIterator2,
+          class _UnaryPredicate>
 std::pair<_OutputIterator1, _OutputIterator2>
-__pattern_partition_copy(_ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last,
-                         _OutputIterator1 __out_true, _OutputIterator2 __out_false, _UnaryPredicate __pred,
-                         _IsVector __is_vector, /*is_parallelization=*/std::false_type) noexcept
+__pattern_partition_copy(_Tag, _ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last,
+                         _OutputIterator1 __out_true, _OutputIterator2 __out_false, _UnaryPredicate __pred) noexcept
 {
-    return __internal::__brick_partition_copy(__first, __last, __out_true, __out_false, __pred, __is_vector);
+    return __internal::__brick_partition_copy(__first, __last, __out_true, __out_false, __pred,
+                                              typename _Tag::__is_vector{});
 }
 
-template <class _ExecutionPolicy, class _RandomAccessIterator, class _OutputIterator1, class _OutputIterator2,
-          class _UnaryPredicate, class _IsVector>
-std::pair<_OutputIterator1, _OutputIterator2>
-__pattern_partition_copy(_ExecutionPolicy&& __exec, _RandomAccessIterator __first, _RandomAccessIterator __last,
-                         _OutputIterator1 __out_true, _OutputIterator2 __out_false, _UnaryPredicate __pred,
-                         _IsVector __is_vector, /*is_parallelization=*/std::true_type)
+template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator1, class _RandomAccessIterator2,
+          class _RandomAccessIterator3, class _UnaryPredicate>
+std::pair<_RandomAccessIterator2, _RandomAccessIterator3>
+__pattern_partition_copy(__parallel_tag<_IsVector> __tag, _ExecutionPolicy&& __exec, _RandomAccessIterator1 __first,
+                         _RandomAccessIterator1 __last, _RandomAccessIterator2 __out_true,
+                         _RandomAccessIterator3 __out_false, _UnaryPredicate __pred)
 {
-    typedef typename std::iterator_traits<_RandomAccessIterator>::difference_type _DifferenceType;
+    using __backend_tag = typename decltype(__tag)::__backend_tag;
+
+    typedef typename std::iterator_traits<_RandomAccessIterator1>::difference_type _DifferenceType;
     typedef std::pair<_DifferenceType, _DifferenceType> _ReturnType;
     const _DifferenceType __n = __last - __first;
     if (_DifferenceType(1) < __n)
     {
         __par_backend::__buffer<bool> __mask_buf(__n);
-        return __internal::__except_handler([&__exec, __n, __first, __out_true, __out_false, __is_vector, __pred,
-                                             &__mask_buf]() {
-            bool* __mask = __mask_buf.get();
-            _ReturnType __m{};
-            __par_backend::__parallel_strict_scan(
-                std::forward<_ExecutionPolicy>(__exec), __n, std::make_pair(_DifferenceType(0), _DifferenceType(0)),
-                [=](_DifferenceType __i, _DifferenceType __len) { // Reduce
-                    return __internal::__brick_calc_mask_1<_DifferenceType>(__first + __i, __first + (__i + __len),
-                                                                            __mask + __i, __pred, __is_vector);
-                },
-                [](const _ReturnType& __x, const _ReturnType& __y) -> _ReturnType {
-                    return std::make_pair(__x.first + __y.first, __x.second + __y.second);
-                },                                                                       // Combine
-                [=](_DifferenceType __i, _DifferenceType __len, _ReturnType __initial) { // Scan
-                    __internal::__brick_partition_by_mask(__first + __i, __first + (__i + __len),
-                                                          __out_true + __initial.first, __out_false + __initial.second,
-                                                          __mask + __i, __is_vector);
-                },
-                [&__m](_ReturnType __total) { __m = __total; });
-            return std::make_pair(__out_true + __m.first, __out_false + __m.second);
-        });
+        return __internal::__except_handler(
+            [&__exec, __n, __first, __out_true, __out_false, __pred, &__mask_buf]()
+            {
+                bool* __mask = __mask_buf.get();
+                _ReturnType __m{};
+                __par_backend::__parallel_strict_scan(
+                    __backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __n,
+                    std::make_pair(_DifferenceType(0), _DifferenceType(0)),
+                    [=](_DifferenceType __i, _DifferenceType __len) { // Reduce
+                        return __internal::__brick_calc_mask_1<_DifferenceType>(__first + __i, __first + (__i + __len),
+                                                                                __mask + __i, __pred, _IsVector{});
+                    },
+                    [](const _ReturnType& __x, const _ReturnType& __y) -> _ReturnType
+                    { return std::make_pair(__x.first + __y.first, __x.second + __y.second); }, // Combine
+                    [=](_DifferenceType __i, _DifferenceType __len, _ReturnType __initial) {    // Scan
+                        __internal::__brick_partition_by_mask(
+                            __first + __i, __first + (__i + __len), __out_true + __initial.first,
+                            __out_false + __initial.second, __mask + __i, _IsVector{});
+                    },
+                    [&__m](_ReturnType __total) { __m = __total; });
+                return std::make_pair(__out_true + __m.first, __out_false + __m.second);
+            });
     }
     // trivial sequence - use serial algorithm
-    return __internal::__brick_partition_copy(__first, __last, __out_true, __out_false, __pred, __is_vector);
+    return __internal::__brick_partition_copy(__first, __last, __out_true, __out_false, __pred, _IsVector{});
 }
 
 //------------------------------------------------------------------------
 // sort
 //------------------------------------------------------------------------
 
-template <class _ExecutionPolicy, class _RandomAccessIterator, class _Compare, class _IsVector,
-          class _IsMoveConstructible>
+template <class _Tag, class _ExecutionPolicy, class _RandomAccessIterator, class _Compare, class _IsMoveConstructible>
 void
-__pattern_sort(_ExecutionPolicy&&, _RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp,
-               _IsVector /*is_vector*/, /*is_parallel=*/std::false_type, _IsMoveConstructible) noexcept
+__pattern_sort(_Tag, _ExecutionPolicy&&, _RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp,
+               _IsMoveConstructible) noexcept
 {
     std::sort(__first, __last, __comp);
 }
 
-template <class _ExecutionPolicy, class _RandomAccessIterator, class _Compare, class _IsVector>
+template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _Compare>
 void
-__pattern_sort(_ExecutionPolicy&& __exec, _RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp,
-               _IsVector /*is_vector*/, /*is_parallel=*/std::true_type, /*is_move_constructible=*/std::true_type)
+__pattern_sort(__parallel_tag<_IsVector> __tag, _ExecutionPolicy&& __exec, _RandomAccessIterator __first,
+               _RandomAccessIterator __last, _Compare __comp, /*is_move_constructible=*/std::true_type)
 {
-    __internal::__except_handler([&]() {
-        __par_backend::__parallel_stable_sort(std::forward<_ExecutionPolicy>(__exec), __first, __last, __comp,
-                                              [](_RandomAccessIterator __first, _RandomAccessIterator __last,
-                                                 _Compare __comp) { std::sort(__first, __last, __comp); });
-    });
+    using __backend_tag = typename decltype(__tag)::__backend_tag;
+
+    __internal::__except_handler(
+        [&]()
+        {
+            __par_backend::__parallel_stable_sort(
+                __backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __first, __last, __comp,
+                [](_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp)
+                { std::sort(__first, __last, __comp); });
+        });
 }
 
 //------------------------------------------------------------------------
 // stable_sort
 //------------------------------------------------------------------------
 
-template <class _ExecutionPolicy, class _RandomAccessIterator, class _Compare, class _IsVector>
+template <class _Tag, class _ExecutionPolicy, class _RandomAccessIterator, class _Compare>
 void
-__pattern_stable_sort(_ExecutionPolicy&&, _RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp,
-                      _IsVector /*is_vector*/, /*is_parallel=*/std::false_type) noexcept
+__pattern_stable_sort(_Tag, _ExecutionPolicy&&, _RandomAccessIterator __first, _RandomAccessIterator __last,
+                      _Compare __comp) noexcept
 {
     std::stable_sort(__first, __last, __comp);
 }
 
-template <class _ExecutionPolicy, class _RandomAccessIterator, class _Compare, class _IsVector>
+template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _Compare>
 void
-__pattern_stable_sort(_ExecutionPolicy&& __exec, _RandomAccessIterator __first, _RandomAccessIterator __last,
-                      _Compare __comp, _IsVector /*is_vector*/, /*is_parallel=*/std::true_type)
+__pattern_stable_sort(__parallel_tag<_IsVector> __tag, _ExecutionPolicy&& __exec, _RandomAccessIterator __first,
+                      _RandomAccessIterator __last, _Compare __comp)
 {
-    __internal::__except_handler([&]() {
-        __par_backend::__parallel_stable_sort(std::forward<_ExecutionPolicy>(__exec), __first, __last, __comp,
-                                              [](_RandomAccessIterator __first, _RandomAccessIterator __last,
-                                                 _Compare __comp) { std::stable_sort(__first, __last, __comp); });
-    });
+    using __backend_tag = typename decltype(__tag)::__backend_tag;
+
+    __internal::__except_handler(
+        [&]()
+        {
+            __par_backend::__parallel_stable_sort(
+                __backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __first, __last, __comp,
+                [](_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp)
+                { std::stable_sort(__first, __last, __comp); });
+        });
 }
 
 //------------------------------------------------------------------------
 // partial_sort
 //------------------------------------------------------------------------
 
-template <class _ExecutionPolicy, class _RandomAccessIterator, class _Compare, class _IsVector>
+template <class _Tag, class _ExecutionPolicy, class _RandomAccessIterator, class _Compare>
 void
-__pattern_partial_sort(_ExecutionPolicy&&, _RandomAccessIterator __first, _RandomAccessIterator __middle,
-                       _RandomAccessIterator __last, _Compare __comp, _IsVector,
-                       /*is_parallel=*/std::false_type) noexcept
+__pattern_partial_sort(_Tag, _ExecutionPolicy&&, _RandomAccessIterator __first, _RandomAccessIterator __middle,
+                       _RandomAccessIterator __last, _Compare __comp) noexcept
 {
     std::partial_sort(__first, __middle, __last, __comp);
 }
 
-template <class _ExecutionPolicy, class _RandomAccessIterator, class _Compare, class _IsVector>
+template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _Compare>
 void
-__pattern_partial_sort(_ExecutionPolicy&& __exec, _RandomAccessIterator __first, _RandomAccessIterator __middle,
-                       _RandomAccessIterator __last, _Compare __comp, _IsVector, /*is_parallel=*/std::true_type)
+__pattern_partial_sort(__parallel_tag<_IsVector> __tag, _ExecutionPolicy&& __exec, _RandomAccessIterator __first,
+                       _RandomAccessIterator __middle, _RandomAccessIterator __last, _Compare __comp)
 {
+    using __backend_tag = typename decltype(__tag)::__backend_tag;
+
     const auto __n = __middle - __first;
     if (__n == 0)
         return;
 
-    __internal::__except_handler([&]() {
-        __par_backend::__parallel_stable_sort(
-            std::forward<_ExecutionPolicy>(__exec), __first, __last, __comp,
-            [__n](_RandomAccessIterator __begin, _RandomAccessIterator __end, _Compare __comp) {
-                if (__n < __end - __begin)
-                    std::partial_sort(__begin, __begin + __n, __end, __comp);
-                else
-                    std::sort(__begin, __end, __comp);
-            },
-            __n);
-    });
+    __internal::__except_handler(
+        [&]()
+        {
+            __par_backend::__parallel_stable_sort(
+                __backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __first, __last, __comp,
+                [__n](_RandomAccessIterator __begin, _RandomAccessIterator __end, _Compare __comp)
+                {
+                    if (__n < __end - __begin)
+                        std::partial_sort(__begin, __begin + __n, __end, __comp);
+                    else
+                        std::sort(__begin, __end, __comp);
+                },
+                __n);
+        });
 }
 
 //------------------------------------------------------------------------
 // partial_sort_copy
 //------------------------------------------------------------------------
 
-template <class _ExecutionPolicy, class _ForwardIterator, class _RandomAccessIterator, class _Compare, class _IsVector>
+template <class _Tag, class _ExecutionPolicy, class _ForwardIterator, class _RandomAccessIterator, class _Compare>
 _RandomAccessIterator
-__pattern_partial_sort_copy(_ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last,
-                            _RandomAccessIterator __d_first, _RandomAccessIterator __d_last, _Compare __comp, _IsVector,
-                            /*is_parallel=*/std::false_type) noexcept
+__pattern_partial_sort_copy(_Tag, _ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last,
+                            _RandomAccessIterator __d_first, _RandomAccessIterator __d_last, _Compare __comp) noexcept
 {
     return std::partial_sort_copy(__first, __last, __d_first, __d_last, __comp);
 }
 
-template <class _ExecutionPolicy, class _ForwardIterator, class _RandomAccessIterator, class _Compare, class _IsVector>
-_RandomAccessIterator
-__pattern_partial_sort_copy(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last,
-                            _RandomAccessIterator __d_first, _RandomAccessIterator __d_last, _Compare __comp,
-                            _IsVector __is_vector, /*is_parallel=*/std::true_type)
+template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator1, class _RandomAccessIterator2,
+          class _Compare>
+_RandomAccessIterator2
+__pattern_partial_sort_copy(__parallel_tag<_IsVector> __tag, _ExecutionPolicy&& __exec, _RandomAccessIterator1 __first,
+                            _RandomAccessIterator1 __last, _RandomAccessIterator2 __d_first,
+                            _RandomAccessIterator2 __d_last, _Compare __comp)
 {
+    using __backend_tag = typename decltype(__tag)::__backend_tag;
+
     if (__last == __first || __d_last == __d_first)
     {
         return __d_first;
@@ -2210,18 +2299,18 @@ __pattern_partial_sort_copy(_ExecutionPolicy&& __exec, _ForwardIterator __first,
         if (__n2 >= __n1)
         {
             __par_backend::__parallel_stable_sort(
-                std::forward<_ExecutionPolicy>(__exec), __d_first, __d_first + __n1, __comp,
-                [__first, __d_first, __is_vector](_RandomAccessIterator __i, _RandomAccessIterator __j,
-                                                  _Compare __comp) {
-                    _ForwardIterator __i1 = __first + (__i - __d_first);
-                    _ForwardIterator __j1 = __first + (__j - __d_first);
+                __backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __d_first, __d_first + __n1, __comp,
+                [__first, __d_first](_RandomAccessIterator2 __i, _RandomAccessIterator2 __j, _Compare __comp)
+                {
+                    _RandomAccessIterator1 __i1 = __first + (__i - __d_first);
+                    _RandomAccessIterator1 __j1 = __first + (__j - __d_first);
 
                 // 1. Copy elements from input to output
-#    if !_PSTL_ICC_18_OMP_SIMD_BROKEN
-                    __internal::__brick_copy(__i1, __j1, __i, __is_vector);
-#    else
+#if !defined(_PSTL_ICC_18_OMP_SIMD_BROKEN)
+                    __internal::__brick_copy(__i1, __j1, __i, _IsVector{});
+#else
                     std::copy(__i1, __j1, __i);
-#    endif
+#endif
                     // 2. Sort elements in output sequence
                     std::sort(__i, __j, __comp);
                 },
@@ -2230,38 +2319,38 @@ __pattern_partial_sort_copy(_ExecutionPolicy&& __exec, _ForwardIterator __first,
         }
         else
         {
-            typedef typename std::iterator_traits<_ForwardIterator>::value_type _T1;
-            typedef typename std::iterator_traits<_RandomAccessIterator>::value_type _T2;
+            typedef typename std::iterator_traits<_RandomAccessIterator1>::value_type _T1;
+            typedef typename std::iterator_traits<_RandomAccessIterator2>::value_type _T2;
             __par_backend::__buffer<_T1> __buf(__n1);
             _T1* __r = __buf.get();
 
-            __par_backend::__parallel_stable_sort(std::forward<_ExecutionPolicy>(__exec), __r, __r + __n1, __comp,
-                                                  [__n2, __first, __r](_T1* __i, _T1* __j, _Compare __comp) {
-                                                      _ForwardIterator __it = __first + (__i - __r);
+            __par_backend::__parallel_stable_sort(
+                __backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __r, __r + __n1, __comp,
+                [__n2, __first, __r](_T1* __i, _T1* __j, _Compare __comp)
+                {
+                    _RandomAccessIterator1 __it = __first + (__i - __r);
 
-                                                      // 1. Copy elements from input to raw memory
-                                                      for (_T1* __k = __i; __k != __j; ++__k, ++__it)
-                                                      {
-                                                          ::new (__k) _T2(*__it);
-                                                      }
+                    // 1. Copy elements from input to raw memory
+                    for (_T1* __k = __i; __k != __j; ++__k, ++__it)
+                    {
+                        ::new (__k) _T2(*__it);
+                    }
 
-                                                      // 2. Sort elements in temporary __buffer
-                                                      if (__n2 < __j - __i)
-                                                          std::partial_sort(__i, __i + __n2, __j, __comp);
-                                                      else
-                                                          std::sort(__i, __j, __comp);
-                                                  },
-                                                  __n2);
+                    // 2. Sort elements in temporary __buffer
+                    if (__n2 < __j - __i)
+                        std::partial_sort(__i, __i + __n2, __j, __comp);
+                    else
+                        std::sort(__i, __j, __comp);
+                },
+                __n2);
 
             // 3. Move elements from temporary __buffer to output
-            __par_backend::__parallel_for(std::forward<_ExecutionPolicy>(__exec), __r, __r + __n2,
-                                          [__r, __d_first, __is_vector](_T1* __i, _T1* __j) {
-                                              __brick_move_destroy()(
-                                                  __i, __j, __d_first + (__i - __r), __is_vector);
-                                          });
-            __par_backend::__parallel_for(
-                std::forward<_ExecutionPolicy>(__exec), __r + __n2, __r + __n1,
-                [__is_vector](_T1* __i, _T1* __j) { __brick_destroy(__i, __j, __is_vector); });
+            __par_backend::__parallel_for(__backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __r, __r + __n2,
+                                          [__r, __d_first](_T1* __i, _T1* __j)
+                                          { __brick_move_destroy()(__i, __j, __d_first + (__i - __r), _IsVector{}); });
+            __par_backend::__parallel_for(__backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __r + __n2,
+                                          __r + __n1,
+                                          [](_T1* __i, _T1* __j) { __brick_destroy(__i, __j, _IsVector{}); });
 
             return __d_first + __n2;
         }
@@ -2271,9 +2360,9 @@ __pattern_partial_sort_copy(_ExecutionPolicy&& __exec, _ForwardIterator __first,
 //------------------------------------------------------------------------
 // adjacent_find
 //------------------------------------------------------------------------
-template <class _ForwardIterator, class _BinaryPredicate>
-_ForwardIterator
-__brick_adjacent_find(_ForwardIterator __first, _ForwardIterator __last, _BinaryPredicate __pred,
+template <class _RandomAccessIterator, class _BinaryPredicate>
+_RandomAccessIterator
+__brick_adjacent_find(_RandomAccessIterator __first, _RandomAccessIterator __last, _BinaryPredicate __pred,
                       /* IsVector = */ std::true_type, bool __or_semantic) noexcept
 {
     return __unseq_backend::__simd_adjacent_find(__first, __last, __pred, __or_semantic);
@@ -2287,78 +2376,79 @@ __brick_adjacent_find(_ForwardIterator __first, _ForwardIterator __last, _Binary
     return std::adjacent_find(__first, __last, __pred);
 }
 
-template <class _ExecutionPolicy, class _ForwardIterator, class _BinaryPredicate, class _IsVector>
+template <class _Tag, class _ExecutionPolicy, class _ForwardIterator, class _BinaryPredicate>
 _ForwardIterator
-__pattern_adjacent_find(_ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last, _BinaryPredicate __pred,
-                        /* is_parallel */ std::false_type, _IsVector __is_vector, bool __or_semantic) noexcept
+__pattern_adjacent_find(_Tag, _ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last,
+                        _BinaryPredicate __pred, bool __or_semantic) noexcept
 {
-    return __internal::__brick_adjacent_find(__first, __last, __pred, __is_vector, __or_semantic);
+    return __internal::__brick_adjacent_find(__first, __last, __pred, typename _Tag::__is_vector{}, __or_semantic);
 }
 
-template <class _ExecutionPolicy, class _RandomAccessIterator, class _BinaryPredicate, class _IsVector>
+template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _BinaryPredicate>
 _RandomAccessIterator
-__pattern_adjacent_find(_ExecutionPolicy&& __exec, _RandomAccessIterator __first, _RandomAccessIterator __last,
-                        _BinaryPredicate __pred, /* is_parallel */ std::true_type, _IsVector __is_vector,
-                        bool __or_semantic)
+__pattern_adjacent_find(__parallel_tag<_IsVector> __tag, _ExecutionPolicy&& __exec, _RandomAccessIterator __first,
+                        _RandomAccessIterator __last, _BinaryPredicate __pred, bool __or_semantic)
 {
     if (__last - __first < 2)
         return __last;
 
-    return __internal::__except_handler([&]() {
-        return __par_backend::__parallel_reduce(
-            std::forward<_ExecutionPolicy>(__exec), __first, __last, __last,
-            [__last, __pred, __is_vector, __or_semantic](_RandomAccessIterator __begin, _RandomAccessIterator __end,
-                                                         _RandomAccessIterator __value) -> _RandomAccessIterator {
-                // TODO: investigate performance benefits from the use of shared variable for the result,
-                // checking (compare_and_swap idiom) its __value at __first.
-                if (__or_semantic && __value < __last)
-                { //found
-                    __par_backend::__cancel_execution();
-                    return __value;
-                }
+    using __backend_tag = typename decltype(__tag)::__backend_tag;
 
-                if (__value > __begin)
+    return __internal::__except_handler(
+        [&]()
+        {
+            return __par_backend::__parallel_reduce(
+                __backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __first, __last, __last,
+                [__last, __pred, __or_semantic](_RandomAccessIterator __begin, _RandomAccessIterator __end,
+                                                _RandomAccessIterator __value) -> _RandomAccessIterator
                 {
-                    // modify __end to check the predicate on the boundary __values;
-                    // TODO: to use a custom range with boundaries overlapping
-                    // TODO: investigate what if we remove "if" below and run algorithm on range [__first, __last-1)
-                    // then check the pair [__last-1, __last)
-                    if (__end != __last)
-                        ++__end;
+                    // TODO: investigate performance benefits from the use of shared variable for the result,
+                    // checking (compare_and_swap idiom) its __value at __first.
+                    if (__or_semantic && __value < __last)
+                    { //found
+                        __par_backend::__cancel_execution();
+                        return __value;
+                    }
 
-                    //correct the global result iterator if the "brick" returns a local "__last"
-                    const _RandomAccessIterator __res =
-                        __internal::__brick_adjacent_find(__begin, __end, __pred, __is_vector, __or_semantic);
-                    if (__res < __end)
-                        __value = __res;
-                }
-                return __value;
-            },
-            [](_RandomAccessIterator __x, _RandomAccessIterator __y) -> _RandomAccessIterator {
-                return __x < __y ? __x : __y;
-            } //reduce a __value
-        );
-    });
+                    if (__value > __begin)
+                    {
+                        // modify __end to check the predicate on the boundary __values;
+                        // TODO: to use a custom range with boundaries overlapping
+                        // TODO: investigate what if we remove "if" below and run algorithm on range [__first, __last-1)
+                        // then check the pair [__last-1, __last)
+                        if (__end != __last)
+                            ++__end;
+
+                        //correct the global result iterator if the "brick" returns a local "__last"
+                        const _RandomAccessIterator __res =
+                            __internal::__brick_adjacent_find(__begin, __end, __pred, _IsVector{}, __or_semantic);
+                        if (__res < __end)
+                            __value = __res;
+                    }
+                    return __value;
+                },
+                [](_RandomAccessIterator __x, _RandomAccessIterator __y) -> _RandomAccessIterator
+                { return __x < __y ? __x : __y; } //reduce a __value
+            );
+        });
 }
 
 //------------------------------------------------------------------------
 // nth_element
 //------------------------------------------------------------------------
 
-template <class _ExecutionPolicy, class _RandomAccessIterator, class _Compare, class _IsVector>
+template <class _Tag, class _ExecutionPolicy, class _RandomAccessIterator, class _Compare>
 void
-__pattern_nth_element(_ExecutionPolicy&&, _RandomAccessIterator __first, _RandomAccessIterator __nth,
-                      _RandomAccessIterator __last, _Compare __comp, _IsVector,
-                      /*is_parallel=*/std::false_type) noexcept
+__pattern_nth_element(_Tag, _ExecutionPolicy&&, _RandomAccessIterator __first, _RandomAccessIterator __nth,
+                      _RandomAccessIterator __last, _Compare __comp) noexcept
 {
     std::nth_element(__first, __nth, __last, __comp);
 }
 
-template <class _ExecutionPolicy, class _RandomAccessIterator, class _Compare, class _IsVector>
+template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _Compare>
 void
-__pattern_nth_element(_ExecutionPolicy&& __exec, _RandomAccessIterator __first, _RandomAccessIterator __nth,
-                      _RandomAccessIterator __last, _Compare __comp, _IsVector __is_vector,
-                      /*is_parallel=*/std::true_type) noexcept
+__pattern_nth_element(__parallel_tag<_IsVector> __tag, _ExecutionPolicy&& __exec, _RandomAccessIterator __first,
+                      _RandomAccessIterator __nth, _RandomAccessIterator __last, _Compare __comp) noexcept
 {
     if (__first == __last || __nth == __last)
     {
@@ -2370,10 +2460,8 @@ __pattern_nth_element(_ExecutionPolicy&& __exec, _RandomAccessIterator __first,
     _RandomAccessIterator __x;
     do
     {
-        __x = __internal::__pattern_partition(std::forward<_ExecutionPolicy>(__exec), __first + 1, __last,
-                                              [&__comp, __first](const _Tp& __x) { return __comp(__x, *__first); },
-                                              __is_vector,
-                                              /*is_parallel=*/std::true_type());
+        __x = __internal::__pattern_partition(__tag, std::forward<_ExecutionPolicy>(__exec), __first + 1, __last,
+                                              [&__comp, __first](const _Tp& __x) { return __comp(__x, *__first); });
         --__x;
         if (__x != __first)
         {
@@ -2404,9 +2492,9 @@ __pattern_nth_element(_ExecutionPolicy&& __exec, _RandomAccessIterator __first,
 //------------------------------------------------------------------------
 // fill, fill_n
 //------------------------------------------------------------------------
-template <class _ForwardIterator, class _Tp>
+template <class _RandomAccessIterator, class _Tp>
 void
-__brick_fill(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value,
+__brick_fill(_RandomAccessIterator __first, _RandomAccessIterator __last, const _Tp& __value,
              /* __is_vector = */ std::true_type) noexcept
 {
     __unseq_backend::__simd_fill_n(__first, __last - __first, __value);
@@ -2420,31 +2508,34 @@ __brick_fill(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __val
     std::fill(__first, __last, __value);
 }
 
-template <class _ExecutionPolicy, class _ForwardIterator, class _Tp, class _IsVector>
+template <class _Tag, class _ExecutionPolicy, class _ForwardIterator, class _Tp>
 void
-__pattern_fill(_ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last, const _Tp& __value,
-               /*is_parallel=*/std::false_type, _IsVector __is_vector) noexcept
+__pattern_fill(_Tag, _ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last, const _Tp& __value) noexcept
 {
-    __internal::__brick_fill(__first, __last, __value, __is_vector);
+    __internal::__brick_fill(__first, __last, __value, typename _Tag::__is_vector{});
 }
 
-template <class _ExecutionPolicy, class _ForwardIterator, class _Tp, class _IsVector>
-_ForwardIterator
-__pattern_fill(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, const _Tp& __value,
-               /*is_parallel=*/std::true_type, _IsVector __is_vector)
+template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _Tp>
+_RandomAccessIterator
+__pattern_fill(__parallel_tag<_IsVector> __tag, _ExecutionPolicy&& __exec, _RandomAccessIterator __first,
+               _RandomAccessIterator __last, const _Tp& __value)
 {
-    return __internal::__except_handler([&__exec, __first, __last, &__value, __is_vector]() {
-        __par_backend::__parallel_for(std::forward<_ExecutionPolicy>(__exec), __first, __last,
-                                      [&__value, __is_vector](_ForwardIterator __begin, _ForwardIterator __end) {
-                                          __internal::__brick_fill(__begin, __end, __value, __is_vector);
-                                      });
-        return __last;
-    });
+    using __backend_tag = typename decltype(__tag)::__backend_tag;
+
+    return __internal::__except_handler(
+        [&__exec, __first, __last, &__value]()
+        {
+            __par_backend::__parallel_for(__backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __first, __last,
+                                          [&__value](_RandomAccessIterator __begin, _RandomAccessIterator __end)
+                                          { __internal::__brick_fill(__begin, __end, __value, _IsVector{}); });
+            return __last;
+        });
 }
 
-template <class _OutputIterator, class _Size, class _Tp>
-_OutputIterator
-__brick_fill_n(_OutputIterator __first, _Size __count, const _Tp& __value, /* __is_vector = */ std::true_type) noexcept
+template <class _RandomAccessIterator, class _Size, class _Tp>
+_RandomAccessIterator
+__brick_fill_n(_RandomAccessIterator __first, _Size __count, const _Tp& __value,
+               /* __is_vector = */ std::true_type) noexcept
 {
     return __unseq_backend::__simd_fill_n(__first, __count, __value);
 }
@@ -2456,21 +2547,20 @@ __brick_fill_n(_OutputIterator __first, _Size __count, const _Tp& __value, /* __
     return std::fill_n(__first, __count, __value);
 }
 
-template <class _ExecutionPolicy, class _OutputIterator, class _Size, class _Tp, class _IsVector>
+template <class _Tag, class _ExecutionPolicy, class _OutputIterator, class _Size, class _Tp>
 _OutputIterator
-__pattern_fill_n(_ExecutionPolicy&&, _OutputIterator __first, _Size __count, const _Tp& __value,
-                 /*is_parallel=*/std::false_type, _IsVector __is_vector) noexcept
+__pattern_fill_n(_Tag, _ExecutionPolicy&&, _OutputIterator __first, _Size __count, const _Tp& __value) noexcept
 {
-    return __internal::__brick_fill_n(__first, __count, __value, __is_vector);
+    return __internal::__brick_fill_n(__first, __count, __value, typename _Tag::__is_vector{});
 }
 
-template <class _ExecutionPolicy, class _OutputIterator, class _Size, class _Tp, class _IsVector>
-_OutputIterator
-__pattern_fill_n(_ExecutionPolicy&& __exec, _OutputIterator __first, _Size __count, const _Tp& __value,
-                 /*is_parallel=*/std::true_type, _IsVector __is_vector)
+template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _Size, class _Tp>
+_RandomAccessIterator
+__pattern_fill_n(__parallel_tag<_IsVector> __tag, _ExecutionPolicy&& __exec, _RandomAccessIterator __first,
+                 _Size __count, const _Tp& __value)
 {
-    return __internal::__pattern_fill(std::forward<_ExecutionPolicy>(__exec), __first, __first + __count, __value,
-                                      std::true_type(), __is_vector);
+    return __internal::__pattern_fill(__tag, std::forward<_ExecutionPolicy>(__exec), __first, __first + __count,
+                                      __value);
 }
 
 //------------------------------------------------------------------------
@@ -2492,59 +2582,61 @@ __brick_generate(_ForwardIterator __first, _ForwardIterator __last, _Generator _
     std::generate(__first, __last, __g);
 }
 
-template <class _ExecutionPolicy, class _ForwardIterator, class _Generator, class _IsVector>
+template <class _Tag, class _ExecutionPolicy, class _ForwardIterator, class _Generator>
 void
-__pattern_generate(_ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last, _Generator __g,
-                   /*is_parallel=*/std::false_type, _IsVector __is_vector) noexcept
+__pattern_generate(_Tag, _ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last, _Generator __g) noexcept
 {
-    __internal::__brick_generate(__first, __last, __g, __is_vector);
+    __internal::__brick_generate(__first, __last, __g, typename _Tag::__is_vector{});
 }
 
-template <class _ExecutionPolicy, class _ForwardIterator, class _Generator, class _IsVector>
-_ForwardIterator
-__pattern_generate(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _Generator __g,
-                   /*is_parallel=*/std::true_type, _IsVector __is_vector)
+template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _Generator>
+_RandomAccessIterator
+__pattern_generate(__parallel_tag<_IsVector> __tag, _ExecutionPolicy&& __exec, _RandomAccessIterator __first,
+                   _RandomAccessIterator __last, _Generator __g)
 {
-    return __internal::__except_handler([&]() {
-        __par_backend::__parallel_for(std::forward<_ExecutionPolicy>(__exec), __first, __last,
-                                      [__g, __is_vector](_ForwardIterator __begin, _ForwardIterator __end) {
-                                          __internal::__brick_generate(__begin, __end, __g, __is_vector);
-                                      });
-        return __last;
-    });
+    using __backend_tag = typename decltype(__tag)::__backend_tag;
+
+    return __internal::__except_handler(
+        [&]()
+        {
+            __par_backend::__parallel_for(__backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __first, __last,
+                                          [__g](_RandomAccessIterator __begin, _RandomAccessIterator __end)
+                                          { __internal::__brick_generate(__begin, __end, __g, _IsVector{}); });
+            return __last;
+        });
 }
 
-template <class _OutputIterator, class _Size, class _Generator>
-  _OutputIterator
-__brick_generate_n(_OutputIterator __first, _Size __count, _Generator __g, /* is_vector = */ std::true_type) noexcept
+template <class _RandomAccessIterator, class Size, class _Generator>
+_RandomAccessIterator
+__brick_generate_n(_RandomAccessIterator __first, Size __count, _Generator __g,
+                   /* is_vector = */ std::true_type) noexcept
 {
     return __unseq_backend::__simd_generate_n(__first, __count, __g);
 }
 
-template <class _OutputIterator, class _Size, class _Generator>
-  _OutputIterator
-__brick_generate_n(_OutputIterator __first, _Size __count, _Generator __g, /* is_vector = */ std::false_type) noexcept
+template <class OutputIterator, class Size, class _Generator>
+OutputIterator
+__brick_generate_n(OutputIterator __first, Size __count, _Generator __g, /* is_vector = */ std::false_type) noexcept
 {
     return std::generate_n(__first, __count, __g);
 }
 
-template <class _ExecutionPolicy, class _OutputIterator, class _Size, class _Generator, class _IsVector>
+template <class _Tag, class _ExecutionPolicy, class _OutputIterator, class _Size, class _Generator>
 _OutputIterator
-__pattern_generate_n(_ExecutionPolicy&&, _OutputIterator __first, _Size __count, _Generator __g,
-                     /*is_parallel=*/std::false_type, _IsVector __is_vector) noexcept
+__pattern_generate_n(_Tag, _ExecutionPolicy&&, _OutputIterator __first, _Size __count, _Generator __g) noexcept
 {
-    return __internal::__brick_generate_n(__first, __count, __g, __is_vector);
+    return __internal::__brick_generate_n(__first, __count, __g, typename _Tag::__is_vector{});
 }
 
-template <class _ExecutionPolicy, class _OutputIterator, class _Size, class _Generator, class _IsVector>
-_OutputIterator
-__pattern_generate_n(_ExecutionPolicy&& __exec, _OutputIterator __first, _Size __count, _Generator __g,
-                     /*is_parallel=*/std::true_type, _IsVector __is_vector)
+template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _Size, class _Generator>
+_RandomAccessIterator
+__pattern_generate_n(__parallel_tag<_IsVector> __tag, _ExecutionPolicy&& __exec, _RandomAccessIterator __first,
+                     _Size __count, _Generator __g)
 {
-    static_assert(__is_random_access_iterator<_OutputIterator>::value,
+    static_assert(__are_random_access_iterators<_RandomAccessIterator>::value,
                   "Pattern-brick error. Should be a random access iterator.");
-    return __internal::__pattern_generate(std::forward<_ExecutionPolicy>(__exec), __first, __first + __count, __g,
-                                          std::true_type(), __is_vector);
+    return __internal::__pattern_generate(__tag, std::forward<_ExecutionPolicy>(__exec), __first, __first + __count,
+                                          __g);
 }
 
 //------------------------------------------------------------------------
@@ -2564,41 +2656,41 @@ _RandomAccessIterator
 __brick_remove_if(_RandomAccessIterator __first, _RandomAccessIterator __last, _UnaryPredicate __pred,
                   /* __is_vector = */ std::true_type) noexcept
 {
-#if _PSTL_MONOTONIC_PRESENT
+#if defined(_PSTL_MONOTONIC_PRESENT)
     return __unseq_backend::__simd_remove_if(__first, __last - __first, __pred);
 #else
     return std::remove_if(__first, __last, __pred);
 #endif
 }
 
-template <class _ExecutionPolicy, class _ForwardIterator, class _UnaryPredicate, class _IsVector>
+template <class _Tag, class _ExecutionPolicy, class _ForwardIterator, class _UnaryPredicate>
 _ForwardIterator
-__pattern_remove_if(_ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last, _UnaryPredicate __pred,
-                    _IsVector __is_vector, /*is_parallel*/ std::false_type) noexcept
+__pattern_remove_if(_Tag, _ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last,
+                    _UnaryPredicate __pred) noexcept
 {
-    return __internal::__brick_remove_if(__first, __last, __pred, __is_vector);
+    return __internal::__brick_remove_if(__first, __last, __pred, typename _Tag::__is_vector{});
 }
 
-template <class _ExecutionPolicy, class _ForwardIterator, class _UnaryPredicate, class _IsVector>
-_ForwardIterator
-__pattern_remove_if(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last,
-                    _UnaryPredicate __pred, _IsVector __is_vector, /*is_parallel*/ std::true_type) noexcept
+template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _UnaryPredicate>
+_RandomAccessIterator
+__pattern_remove_if(__parallel_tag<_IsVector> __tag, _ExecutionPolicy&& __exec, _RandomAccessIterator __first,
+                    _RandomAccessIterator __last, _UnaryPredicate __pred) noexcept
 {
-    typedef typename std::iterator_traits<_ForwardIterator>::reference _ReferenceType;
+    typedef typename std::iterator_traits<_RandomAccessIterator>::reference _ReferenceType;
 
     if (__first == __last || __first + 1 == __last)
     {
         // Trivial sequence - use serial algorithm
-        return __internal::__brick_remove_if(__first, __last, __pred, __is_vector);
+        return __internal::__brick_remove_if(__first, __last, __pred, _IsVector{});
     }
 
     return __internal::__remove_elements(
-        std::forward<_ExecutionPolicy>(__exec), __first, __last,
-        [&__pred, __is_vector](bool* __b, bool* __e, _ForwardIterator __it) {
-            __internal::__brick_walk2(__b, __e, __it, [&__pred](bool& __x, _ReferenceType __y) { __x = !__pred(__y); },
-                                      __is_vector);
-        },
-        __is_vector);
+        __tag, std::forward<_ExecutionPolicy>(__exec), __first, __last,
+        [&__pred](bool* __b, bool* __e, _RandomAccessIterator __it)
+        {
+            __internal::__brick_walk2(
+                __b, __e, __it, [&__pred](bool& __x, _ReferenceType __y) { __x = !__pred(__y); }, _IsVector{});
+        });
 }
 
 //------------------------------------------------------------------------
@@ -2614,39 +2706,42 @@ __brick_merge(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIte
     return std::merge(__first1, __last1, __first2, __last2, __d_first, __comp);
 }
 
-template <class _ForwardIterator1, class _ForwardIterator2, class _OutputIterator, class _Compare>
-_OutputIterator
-__brick_merge(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2,
-              _ForwardIterator2 __last2, _OutputIterator __d_first, _Compare __comp,
+template <class _RandomAccessIterator1, class _RandomAccessIterator2, class _RandomAccessIterator3, class _Compare>
+_RandomAccessIterator3
+__brick_merge(_RandomAccessIterator1 __first1, _RandomAccessIterator1 __last1, _RandomAccessIterator2 __first2,
+              _RandomAccessIterator2 __last2, _RandomAccessIterator3 __d_first, _Compare __comp,
               /* __is_vector = */ std::true_type) noexcept
 {
     _PSTL_PRAGMA_MESSAGE("Vectorized algorithm unimplemented, redirected to serial");
     return std::merge(__first1, __last1, __first2, __last2, __d_first, __comp);
 }
 
-template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _OutputIterator,
-          class _Compare, class _IsVector>
+template <class _Tag, class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _OutputIterator,
+          class _Compare>
 _OutputIterator
-__pattern_merge(_ExecutionPolicy&&, _ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2,
-                _ForwardIterator2 __last2, _OutputIterator __d_first, _Compare __comp, _IsVector __is_vector,
-                /* is_parallel = */ std::false_type) noexcept
+__pattern_merge(_Tag, _ExecutionPolicy&&, _ForwardIterator1 __first1, _ForwardIterator1 __last1,
+                _ForwardIterator2 __first2, _ForwardIterator2 __last2, _OutputIterator __d_first,
+                _Compare __comp) noexcept
 {
-    return __internal::__brick_merge(__first1, __last1, __first2, __last2, __d_first, __comp, __is_vector);
+    return __internal::__brick_merge(__first1, __last1, __first2, __last2, __d_first, __comp,
+                                     typename _Tag::__is_vector{});
 }
 
-template <class _ExecutionPolicy, class _RandomAccessIterator1, class _RandomAccessIterator2, class _OutputIterator,
-          class _Compare, class _IsVector>
-_OutputIterator
-__pattern_merge(_ExecutionPolicy&& __exec, _RandomAccessIterator1 __first1, _RandomAccessIterator1 __last1,
-                _RandomAccessIterator2 __first2, _RandomAccessIterator2 __last2, _OutputIterator __d_first,
-                _Compare __comp, _IsVector __is_vector, /* is_parallel = */ std::true_type)
+template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator1, class _RandomAccessIterator2,
+          class _RandomAccessIterator3, class _Compare>
+_RandomAccessIterator3
+__pattern_merge(__parallel_tag<_IsVector> __tag, _ExecutionPolicy&& __exec, _RandomAccessIterator1 __first1,
+                _RandomAccessIterator1 __last1, _RandomAccessIterator2 __first2, _RandomAccessIterator2 __last2,
+                _RandomAccessIterator3 __d_first, _Compare __comp)
 {
+    using __backend_tag = typename decltype(__tag)::__backend_tag;
+
     __par_backend::__parallel_merge(
-        std::forward<_ExecutionPolicy>(__exec), __first1, __last1, __first2, __last2, __d_first, __comp,
-        [__is_vector](_RandomAccessIterator1 __f1, _RandomAccessIterator1 __l1, _RandomAccessIterator2 __f2,
-                      _RandomAccessIterator2 __l2, _OutputIterator __f3, _Compare __comp) {
-            return __internal::__brick_merge(__f1, __l1, __f2, __l2, __f3, __comp, __is_vector);
-        });
+        __backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __first1, __last1, __first2, __last2, __d_first,
+        __comp,
+        [](_RandomAccessIterator1 __f1, _RandomAccessIterator1 __l1, _RandomAccessIterator2 __f2,
+           _RandomAccessIterator2 __l2, _RandomAccessIterator3 __f3, _Compare __comp)
+        { return __internal::__brick_merge(__f1, __l1, __f2, __l2, __f3, __comp, _IsVector{}); });
     return __d_first + (__last1 - __first1) + (__last2 - __first2);
 }
 
@@ -2661,83 +2756,89 @@ __brick_inplace_merge(_BidirectionalIterator __first, _BidirectionalIterator __m
     std::inplace_merge(__first, __middle, __last, __comp);
 }
 
-template <class _BidirectionalIterator, class _Compare>
+template <class _RandomAccessIterator, class _Compare>
 void
-__brick_inplace_merge(_BidirectionalIterator __first, _BidirectionalIterator __middle, _BidirectionalIterator __last,
+__brick_inplace_merge(_RandomAccessIterator __first, _RandomAccessIterator __middle, _RandomAccessIterator __last,
                       _Compare __comp, /* __is_vector = */ std::true_type) noexcept
 {
     _PSTL_PRAGMA_MESSAGE("Vectorized algorithm unimplemented, redirected to serial")
     std::inplace_merge(__first, __middle, __last, __comp);
 }
 
-template <class _ExecutionPolicy, class _BidirectionalIterator, class _Compare, class _IsVector>
+template <class _Tag, class _ExecutionPolicy, class _BidirectionalIterator, class _Compare>
 void
-__pattern_inplace_merge(_ExecutionPolicy&&, _BidirectionalIterator __first, _BidirectionalIterator __middle,
-                        _BidirectionalIterator __last, _Compare __comp, _IsVector __is_vector,
-                        /* is_parallel = */ std::false_type) noexcept
+__pattern_inplace_merge(_Tag, _ExecutionPolicy&&, _BidirectionalIterator __first, _BidirectionalIterator __middle,
+                        _BidirectionalIterator __last, _Compare __comp) noexcept
 {
-    __internal::__brick_inplace_merge(__first, __middle, __last, __comp, __is_vector);
+    __internal::__brick_inplace_merge(__first, __middle, __last, __comp, typename _Tag::__is_vector{});
 }
 
-template <class _ExecutionPolicy, class _BidirectionalIterator, class _Compare, class _IsVector>
+template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _Compare>
 void
-__pattern_inplace_merge(_ExecutionPolicy&& __exec, _BidirectionalIterator __first, _BidirectionalIterator __middle,
-                        _BidirectionalIterator __last, _Compare __comp, _IsVector __is_vector,
-                        /*is_parallel=*/std::true_type)
+__pattern_inplace_merge(__parallel_tag<_IsVector> __tag, _ExecutionPolicy&& __exec, _RandomAccessIterator __first,
+                        _RandomAccessIterator __middle, _RandomAccessIterator __last, _Compare __comp)
 {
+    using __backend_tag = typename decltype(__tag)::__backend_tag;
+
     if (__first == __last || __first == __middle || __middle == __last)
     {
         return;
     }
-    typedef typename std::iterator_traits<_BidirectionalIterator>::value_type _Tp;
+    typedef typename std::iterator_traits<_RandomAccessIterator>::value_type _Tp;
     auto __n = __last - __first;
     __par_backend::__buffer<_Tp> __buf(__n);
     _Tp* __r = __buf.get();
-    __internal::__except_handler([&]() {
-        auto __move_values = [](_BidirectionalIterator __x, _Tp* __z) {
-            __internal::__invoke_if_else(std::is_trivial<_Tp>(), [&]() { *__z = std::move(*__x); },
-                                         [&]() { ::new (std::addressof(*__z)) _Tp(std::move(*__x)); });
-        };
+    __internal::__except_handler(
+        [&]()
+        {
+            auto __move_values = [](_RandomAccessIterator __x, _Tp* __z)
+            {
+                __internal::__invoke_if_else(
+                    std::is_trivial<_Tp>(), [&]() { *__z = std::move(*__x); },
+                    [&]() { ::new (std::addressof(*__z)) _Tp(std::move(*__x)); });
+            };
 
-        auto __move_sequences = [](_BidirectionalIterator __first1, _BidirectionalIterator __last1, _Tp* __first2) {
-            return __internal::__brick_uninitialized_move(__first1, __last1, __first2, _IsVector());
-        };
+            auto __move_sequences = [](_RandomAccessIterator __first1, _RandomAccessIterator __last1, _Tp* __first2)
+            { return __internal::__brick_uninitialized_move(__first1, __last1, __first2, _IsVector()); };
 
-        __par_backend::__parallel_merge(
-            std::forward<_ExecutionPolicy>(__exec), __first, __middle, __middle, __last, __r, __comp,
-            [__n, __move_values, __move_sequences](_BidirectionalIterator __f1, _BidirectionalIterator __l1,
-                                                   _BidirectionalIterator __f2, _BidirectionalIterator __l2, _Tp* __f3,
-                                                   _Compare __comp) {
-                (__utils::__serial_move_merge(__n))(__f1, __l1, __f2, __l2, __f3, __comp, __move_values, __move_values,
-                                                    __move_sequences, __move_sequences);
-                return __f3 + (__l1 - __f1) + (__l2 - __f2);
-            });
-        __par_backend::__parallel_for(
-            std::forward<_ExecutionPolicy>(__exec), __r, __r + __n, [__r, __first, __is_vector](_Tp* __i, _Tp* __j) {
-                __brick_move_destroy()(__i, __j, __first + (__i - __r), __is_vector);
-            });
-    });
+            __par_backend::__parallel_merge(
+                __backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __first, __middle, __middle, __last, __r,
+                __comp,
+                [__n, __move_values, __move_sequences](_RandomAccessIterator __f1, _RandomAccessIterator __l1,
+                                                       _RandomAccessIterator __f2, _RandomAccessIterator __l2,
+                                                       _Tp* __f3, _Compare __comp)
+                {
+                    (__utils::__serial_move_merge(__n))(__f1, __l1, __f2, __l2, __f3, __comp, __move_values,
+                                                        __move_values, __move_sequences, __move_sequences);
+                    return __f3 + (__l1 - __f1) + (__l2 - __f2);
+                });
+            __par_backend::__parallel_for(__backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __r, __r + __n,
+                                          [__r, __first](_Tp* __i, _Tp* __j)
+                                          { __brick_move_destroy()(__i, __j, __first + (__i - __r), _IsVector{}); });
+        });
 }
 
 //------------------------------------------------------------------------
 // includes
 //------------------------------------------------------------------------
 
-template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _Compare, class _IsVector>
+template <class _Tag, class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _Compare>
 bool
-__pattern_includes(_ExecutionPolicy&&, _ForwardIterator1 __first1, _ForwardIterator1 __last1,
-                   _ForwardIterator2 __first2, _ForwardIterator2 __last2, _Compare __comp, _IsVector,
-                   /*is_parallel=*/std::false_type) noexcept
+__pattern_includes(_Tag, _ExecutionPolicy&&, _ForwardIterator1 __first1, _ForwardIterator1 __last1,
+                   _ForwardIterator2 __first2, _ForwardIterator2 __last2, _Compare __comp) noexcept
 {
     return std::includes(__first1, __last1, __first2, __last2, __comp);
 }
 
-template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _Compare, class _IsVector>
+template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator1, class _RandomAccessIterator2,
+          class _Compare>
 bool
-__pattern_includes(_ExecutionPolicy&& __exec, _ForwardIterator1 __first1, _ForwardIterator1 __last1,
-                   _ForwardIterator2 __first2, _ForwardIterator2 __last2, _Compare __comp, _IsVector,
-                   /*is_parallel=*/std::true_type)
+__pattern_includes(__parallel_tag<_IsVector> __tag, _ExecutionPolicy&& __exec, _RandomAccessIterator1 __first1,
+                   _RandomAccessIterator1 __last1, _RandomAccessIterator2 __first2, _RandomAccessIterator2 __last2,
+                   _Compare __comp)
 {
+    using __backend_tag = typename decltype(__tag)::__backend_tag;
+
     if (__first2 >= __last2)
         return true;
 
@@ -2751,51 +2852,55 @@ __pattern_includes(_ExecutionPolicy&& __exec, _ForwardIterator1 __first1, _Forwa
     if (__last2 - __first2 == 1)
         return !__comp(*__first1, *__first2) && !__comp(*__first2, *__first1);
 
-    return __internal::__except_handler([&]() {
-        return !__internal::__parallel_or(
-            std::forward<_ExecutionPolicy>(__exec), __first2, __last2,
-            [__first1, __last1, __first2, __last2, &__comp](_ForwardIterator2 __i, _ForwardIterator2 __j) {
-                _PSTL_ASSERT(__j > __i);
-                //assert(__j - __i > 1);
-
-                //1. moving boundaries to "consume" subsequence of equal elements
-                auto __is_equal = [&__comp](_ForwardIterator2 __a, _ForwardIterator2 __b) -> bool {
-                    return !__comp(*__a, *__b) && !__comp(*__b, *__a);
-                };
-
-                //1.1 left bound, case "aaa[aaaxyz...]" - searching "x"
-                if (__i > __first2 && __is_equal(__i, __i - 1))
+    return __internal::__except_handler(
+        [&]()
+        {
+            return !__internal::__parallel_or(
+                __backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __first2, __last2,
+                [__first1, __last1, __first2, __last2, &__comp](_RandomAccessIterator2 __i, _RandomAccessIterator2 __j)
                 {
-                    //whole subrange continues to content equal elements - return "no op"
-                    if (__is_equal(__i, __j - 1))
-                        return false;
+                    _PSTL_ASSERT(__j > __i);
+                    //_PSTL_ASSERT(__j - __i > 1);
 
-                    __i = std::upper_bound(__i, __last2, *__i, __comp);
-                }
+                    //1. moving boundaries to "consume" subsequence of equal elements
+                    auto __is_equal = [&__comp](_RandomAccessIterator2 __a, _RandomAccessIterator2 __b) -> bool
+                    { return !__comp(*__a, *__b) && !__comp(*__b, *__a); };
 
-                //1.2 right bound, case "[...aaa]aaaxyz" - searching "x"
-                if (__j < __last2 && __is_equal(__j - 1, __j))
-                    __j = std::upper_bound(__j, __last2, *__j, __comp);
+                    //1.1 left bound, case "aaa[aaaxyz...]" - searching "x"
+                    if (__i > __first2 && __is_equal(__i, __i - 1))
+                    {
+                        //whole subrange continues to content equal elements - return "no op"
+                        if (__is_equal(__i, __j - 1))
+                            return false;
 
-                //2. testing is __a subsequence of the second range included into the first range
-                auto __b = std::lower_bound(__first1, __last1, *__i, __comp);
+                        __i = std::upper_bound(__i, __last2, *__i, __comp);
+                    }
 
-                _PSTL_ASSERT(!__comp(*(__last1 - 1), *__b));
-                _PSTL_ASSERT(!__comp(*(__j - 1), *__i));
-                return !std::includes(__b, __last1, __i, __j, __comp);
-            });
-    });
+                    //1.2 right bound, case "[...aaa]aaaxyz" - searching "x"
+                    if (__j < __last2 && __is_equal(__j - 1, __j))
+                        __j = std::upper_bound(__j, __last2, *__j, __comp);
+
+                    //2. testing is __a subsequence of the second range included into the first range
+                    auto __b = std::lower_bound(__first1, __last1, *__i, __comp);
+
+                    _PSTL_ASSERT(!__comp(*(__last1 - 1), *__b));
+                    _PSTL_ASSERT(!__comp(*(__j - 1), *__i));
+                    return !std::includes(__b, __last1, __i, __j, __comp);
+                });
+        });
 }
 
 constexpr auto __set_algo_cut_off = 1000;
 
-template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _OutputIterator,
-          class _Compare, class _IsVector, class _SizeFunction, class _SetOP>
+template <class _IsVector, class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2,
+          class _OutputIterator, class _Compare, class _SizeFunction, class _SetOP>
 _OutputIterator
-__parallel_set_op(_ExecutionPolicy&& __exec, _ForwardIterator1 __first1, _ForwardIterator1 __last1,
-                  _ForwardIterator2 __first2, _ForwardIterator2 __last2, _OutputIterator __result, _Compare __comp,
-                  _SizeFunction __size_func, _SetOP __set_op, _IsVector __is_vector)
+__parallel_set_op(__parallel_tag<_IsVector> __tag, _ExecutionPolicy&& __exec, _ForwardIterator1 __first1,
+                  _ForwardIterator1 __last1, _ForwardIterator2 __first2, _ForwardIterator2 __last2,
+                  _OutputIterator __result, _Compare __comp, _SizeFunction __size_func, _SetOP __set_op)
 {
+    using __backend_tag = typename decltype(__tag)::__backend_tag;
+
     typedef typename std::iterator_traits<_ForwardIterator1>::difference_type _DifferenceType;
     typedef typename std::iterator_traits<_OutputIterator>::value_type _Tp;
 
@@ -2814,100 +2919,100 @@ __parallel_set_op(_ExecutionPolicy&& __exec, _ForwardIterator1 __first1, _Forwar
 
     __par_backend::__buffer<_Tp> __buf(__size_func(__n1, __n2));
 
-    return __internal::__except_handler([&__exec, __n1, __first1, __last1, __first2, __last2, __result, __is_vector,
-                                         __comp, __size_func, __set_op, &__buf]() {
-        auto __buffer = __buf.get();
-        _DifferenceType __m{};
-        auto __scan = [=](_DifferenceType, _DifferenceType, const _SetRange& __s) { // Scan
-            if (!__s.empty())
-                __brick_move_destroy()(__buffer + __s.__buf_pos,
-                                                         __buffer + (__s.__buf_pos + __s.__len), __result + __s.__pos,
-                                                         __is_vector);
-        };
-        __par_backend::__parallel_strict_scan(
-            std::forward<_ExecutionPolicy>(__exec), __n1, _SetRange{0, 0, 0}, //-1, 0},
-            [=](_DifferenceType __i, _DifferenceType __len) {                 // Reduce
-                //[__b; __e) - a subrange of the first sequence, to reduce
-                _ForwardIterator1 __b = __first1 + __i, __e = __first1 + (__i + __len);
+    return __internal::__except_handler(
+        [&__exec, __n1, __first1, __last1, __first2, __last2, __result, __comp, __size_func, __set_op, &__buf]()
+        {
+            auto __buffer = __buf.get();
+            _DifferenceType __m{};
+            auto __scan = [=](_DifferenceType, _DifferenceType, const _SetRange& __s) { // Scan
+                if (!__s.empty())
+                    __brick_move_destroy()(__buffer + __s.__buf_pos, __buffer + (__s.__buf_pos + __s.__len),
+                                           __result + __s.__pos, _IsVector{});
+            };
+            __par_backend::__parallel_strict_scan(
+                __backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __n1, _SetRange{0, 0, 0}, //-1, 0},
+                [=](_DifferenceType __i, _DifferenceType __len) {                                  // Reduce
+                    //[__b; __e) - a subrange of the first sequence, to reduce
+                    _ForwardIterator1 __b = __first1 + __i, __e = __first1 + (__i + __len);
 
-                //try searching for the first element which not equal to *__b
-                if (__b != __first1)
-                    __b = std::upper_bound(__b, __last1, *__b, __comp);
+                    //try searching for the first element which not equal to *__b
+                    if (__b != __first1)
+                        __b = std::upper_bound(__b, __last1, *__b, __comp);
 
-                //try searching for the first element which not equal to *__e
-                if (__e != __last1)
-                    __e = std::upper_bound(__e, __last1, *__e, __comp);
+                    //try searching for the first element which not equal to *__e
+                    if (__e != __last1)
+                        __e = std::upper_bound(__e, __last1, *__e, __comp);
 
-                //check is [__b; __e) empty
-                if (__e - __b < 1)
-                {
-                    _ForwardIterator2 __bb = __last2;
-                    if (__b != __last1)
+                    //check is [__b; __e) empty
+                    if (__e - __b < 1)
+                    {
+                        _ForwardIterator2 __bb = __last2;
+                        if (__b != __last1)
+                            __bb = std::lower_bound(__first2, __last2, *__b, __comp);
+
+                        const _DifferenceType __buf_pos = __size_func((__b - __first1), (__bb - __first2));
+                        return _SetRange{0, 0, __buf_pos};
+                    }
+
+                    //try searching for "corresponding" subrange [__bb; __ee) in the second sequence
+                    _ForwardIterator2 __bb = __first2;
+                    if (__b != __first1)
                         __bb = std::lower_bound(__first2, __last2, *__b, __comp);
 
+                    _ForwardIterator2 __ee = __last2;
+                    if (__e != __last1)
+                        __ee = std::lower_bound(__bb, __last2, *__e, __comp);
+
                     const _DifferenceType __buf_pos = __size_func((__b - __first1), (__bb - __first2));
-                    return _SetRange{0, 0, __buf_pos};
-                }
+                    auto __buffer_b = __buffer + __buf_pos;
+                    auto __res = __set_op(__b, __e, __bb, __ee, __buffer_b, __comp);
 
-                //try searching for "corresponding" subrange [__bb; __ee) in the second sequence
-                _ForwardIterator2 __bb = __first2;
-                if (__b != __first1)
-                    __bb = std::lower_bound(__first2, __last2, *__b, __comp);
-
-                _ForwardIterator2 __ee = __last2;
-                if (__e != __last1)
-                    __ee = std::lower_bound(__bb, __last2, *__e, __comp);
-
-                const _DifferenceType __buf_pos = __size_func((__b - __first1), (__bb - __first2));
-                auto __buffer_b = __buffer + __buf_pos;
-                auto __res = __set_op(__b, __e, __bb, __ee, __buffer_b, __comp);
-
-                return _SetRange{0, __res - __buffer_b, __buf_pos};
-            },
-            [](const _SetRange& __a, const _SetRange& __b) { // Combine
-                if (__b.__buf_pos > __a.__buf_pos || ((__b.__buf_pos == __a.__buf_pos) && !__b.empty()))
-                    return _SetRange{__a.__pos + __a.__len + __b.__pos, __b.__len, __b.__buf_pos};
-                return _SetRange{__b.__pos + __b.__len + __a.__pos, __a.__len, __a.__buf_pos};
-            },
-            __scan,                                     // Scan
-            [&__m, &__scan](const _SetRange& __total) { // Apex
-                //final scan
-                __scan(0, 0, __total);
-                __m = __total.__pos + __total.__len;
-            });
-        return __result + __m;
-    });
+                    return _SetRange{0, __res - __buffer_b, __buf_pos};
+                },
+                [](const _SetRange& __a, const _SetRange& __b) { // Combine
+                    if (__b.__buf_pos > __a.__buf_pos || ((__b.__buf_pos == __a.__buf_pos) && !__b.empty()))
+                        return _SetRange{__a.__pos + __a.__len + __b.__pos, __b.__len, __b.__buf_pos};
+                    return _SetRange{__b.__pos + __b.__len + __a.__pos, __a.__len, __a.__buf_pos};
+                },
+                __scan,                                     // Scan
+                [&__m, &__scan](const _SetRange& __total) { // Apex
+                    //final scan
+                    __scan(0, 0, __total);
+                    __m = __total.__pos + __total.__len;
+                });
+            return __result + __m;
+        });
 }
 
 //a shared parallel pattern for '__pattern_set_union' and '__pattern_set_symmetric_difference'
-template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _OutputIterator,
-          class _Compare, class _SetUnionOp, class _IsVector>
+template <class _Tag, class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _OutputIterator,
+          class _Compare, class _SetUnionOp>
 _OutputIterator
-__parallel_set_union_op(_ExecutionPolicy&& __exec, _ForwardIterator1 __first1, _ForwardIterator1 __last1,
+__parallel_set_union_op(_Tag __tag, _ExecutionPolicy&& __exec, _ForwardIterator1 __first1, _ForwardIterator1 __last1,
                         _ForwardIterator2 __first2, _ForwardIterator2 __last2, _OutputIterator __result,
-                        _Compare __comp, _SetUnionOp __set_union_op, _IsVector __is_vector)
+                        _Compare __comp, _SetUnionOp __set_union_op)
 {
+    using __backend_tag = typename decltype(__tag)::__backend_tag;
+
     typedef typename std::iterator_traits<_ForwardIterator1>::difference_type _DifferenceType;
 
     const auto __n1 = __last1 - __first1;
     const auto __n2 = __last2 - __first2;
 
-    auto __copy_range1 = [__is_vector](_ForwardIterator1 __begin, _ForwardIterator1 __end, _OutputIterator __res) {
-        return __internal::__brick_copy(__begin, __end, __res, __is_vector);
-    };
-    auto __copy_range2 = [__is_vector](_ForwardIterator2 __begin, _ForwardIterator2 __end, _OutputIterator __res) {
-        return __internal::__brick_copy(__begin, __end, __res, __is_vector);
-    };
+    auto copy_range1 = [](_ForwardIterator1 __begin, _ForwardIterator1 __end, _OutputIterator __res)
+    { return __internal::__brick_copy(__begin, __end, __res, typename _Tag::__is_vector{}); };
+    auto copy_range2 = [](_ForwardIterator2 __begin, _ForwardIterator2 __end, _OutputIterator __res)
+    { return __internal::__brick_copy(__begin, __end, __res, typename _Tag::__is_vector{}); };
 
     // {1} {}: parallel copying just first sequence
     if (__n2 == 0)
-        return __internal::__pattern_walk2_brick(std::forward<_ExecutionPolicy>(__exec), __first1, __last1, __result,
-                                                 __copy_range1, std::true_type());
+        return __internal::__pattern_walk2_brick(__tag, std::forward<_ExecutionPolicy>(__exec), __first1, __last1,
+                                                 __result, copy_range1);
 
     // {} {2}: parallel copying justmake  second sequence
     if (__n1 == 0)
-        return __internal::__pattern_walk2_brick(std::forward<_ExecutionPolicy>(__exec), __first2, __last2, __result,
-                                                 __copy_range2, std::true_type());
+        return __internal::__pattern_walk2_brick(__tag, std::forward<_ExecutionPolicy>(__exec), __first2, __last2,
+                                                 __result, copy_range2);
 
     // testing  whether the sequences are intersected
     _ForwardIterator1 __left_bound_seq_1 = std::lower_bound(__first1, __last1, *__first2, __comp);
@@ -2916,14 +3021,16 @@ __parallel_set_union_op(_ExecutionPolicy&& __exec, _ForwardIterator1 __first1, _
     {
         //{1} < {2}: seq2 is wholly greater than seq1, so, do parallel copying seq1 and seq2
         __par_backend::__parallel_invoke(
-            std::forward<_ExecutionPolicy>(__exec),
-            [=] {
-                __internal::__pattern_walk2_brick(std::forward<_ExecutionPolicy>(__exec), __first1, __last1, __result,
-                                                  __copy_range1, std::true_type());
+            __backend_tag{}, std::forward<_ExecutionPolicy>(__exec),
+            [=]
+            {
+                __internal::__pattern_walk2_brick(__tag, std::forward<_ExecutionPolicy>(__exec), __first1, __last1,
+                                                  __result, copy_range1);
             },
-            [=] {
-                __internal::__pattern_walk2_brick(std::forward<_ExecutionPolicy>(__exec), __first2, __last2,
-                                                  __result + __n1, __copy_range2, std::true_type());
+            [=]
+            {
+                __internal::__pattern_walk2_brick(__tag, std::forward<_ExecutionPolicy>(__exec), __first2, __last2,
+                                                  __result + __n1, copy_range2);
             });
         return __result + __n1 + __n2;
     }
@@ -2935,14 +3042,16 @@ __parallel_set_union_op(_ExecutionPolicy&& __exec, _ForwardIterator1 __first1, _
     {
         //{2} < {1}: seq2 is wholly greater than seq1, so, do parallel copying seq1 and seq2
         __par_backend::__parallel_invoke(
-            std::forward<_ExecutionPolicy>(__exec),
-            [=] {
-                __internal::__pattern_walk2_brick(std::forward<_ExecutionPolicy>(__exec), __first2, __last2, __result,
-                                                  __copy_range2, std::true_type());
+            __backend_tag{}, std::forward<_ExecutionPolicy>(__exec),
+            [=]
+            {
+                __internal::__pattern_walk2_brick(__tag, std::forward<_ExecutionPolicy>(__exec), __first2, __last2,
+                                                  __result, copy_range2);
             },
-            [=] {
-                __internal::__pattern_walk2_brick(std::forward<_ExecutionPolicy>(__exec), __first1, __last1,
-                                                  __result + __n2, __copy_range1, std::true_type());
+            [=]
+            {
+                __internal::__pattern_walk2_brick(__tag, std::forward<_ExecutionPolicy>(__exec), __first1, __last1,
+                                                  __result + __n2, copy_range1);
             });
         return __result + __n1 + __n2;
     }
@@ -2953,17 +3062,19 @@ __parallel_set_union_op(_ExecutionPolicy&& __exec, _ForwardIterator1 __first1, _
         auto __res_or = __result;
         __result += __m1; //we know proper offset due to [first1; left_bound_seq_1) < [first2; last2)
         __par_backend::__parallel_invoke(
-            std::forward<_ExecutionPolicy>(__exec),
+            __backend_tag{}, std::forward<_ExecutionPolicy>(__exec),
             //do parallel copying of [first1; left_bound_seq_1)
-            [=] {
-                __internal::__pattern_walk2_brick(std::forward<_ExecutionPolicy>(__exec), __first1, __left_bound_seq_1,
-                                                  __res_or, __copy_range1, std::true_type());
+            [=]
+            {
+                __internal::__pattern_walk2_brick(__tag, std::forward<_ExecutionPolicy>(__exec), __first1,
+                                                  __left_bound_seq_1, __res_or, copy_range1);
             },
-            [=, &__result] {
+            [=, &__result]
+            {
                 __result = __internal::__parallel_set_op(
-                    std::forward<_ExecutionPolicy>(__exec), __left_bound_seq_1, __last1, __first2, __last2, __result,
-                    __comp, [](_DifferenceType __n, _DifferenceType __m) { return __n + __m; }, __set_union_op,
-                    __is_vector);
+                    __tag, std::forward<_ExecutionPolicy>(__exec), __left_bound_seq_1, __last1, __first2, __last2,
+                    __result, __comp, [](_DifferenceType __n, _DifferenceType __m) { return __n + __m; },
+                    __set_union_op);
             });
         return __result;
     }
@@ -2975,24 +3086,26 @@ __parallel_set_union_op(_ExecutionPolicy&& __exec, _ForwardIterator1 __first1, _
         auto __res_or = __result;
         __result += __m2; //we know proper offset due to [first2; left_bound_seq_2) < [first1; last1)
         __par_backend::__parallel_invoke(
-            std::forward<_ExecutionPolicy>(__exec),
+            __backend_tag{}, std::forward<_ExecutionPolicy>(__exec),
             //do parallel copying of [first2; left_bound_seq_2)
-            [=] {
-                __internal::__pattern_walk2_brick(std::forward<_ExecutionPolicy>(__exec), __first2, __left_bound_seq_2,
-                                                  __res_or, __copy_range2, std::true_type());
+            [=]
+            {
+                __internal::__pattern_walk2_brick(__tag, std::forward<_ExecutionPolicy>(__exec), __first2,
+                                                  __left_bound_seq_2, __res_or, copy_range2);
             },
-            [=, &__result] {
+            [=, &__result]
+            {
                 __result = __internal::__parallel_set_op(
-                    std::forward<_ExecutionPolicy>(__exec), __first1, __last1, __left_bound_seq_2, __last2, __result,
-                    __comp, [](_DifferenceType __n, _DifferenceType __m) { return __n + __m; }, __set_union_op,
-                    __is_vector);
+                    __tag, std::forward<_ExecutionPolicy>(__exec), __first1, __last1, __left_bound_seq_2, __last2,
+                    __result, __comp, [](_DifferenceType __n, _DifferenceType __m) { return __n + __m; },
+                    __set_union_op);
             });
         return __result;
     }
 
     return __internal::__parallel_set_op(
-        std::forward<_ExecutionPolicy>(__exec), __first1, __last1, __first2, __last2, __result, __comp,
-        [](_DifferenceType __n, _DifferenceType __m) { return __n + __m; }, __set_union_op, __is_vector);
+        __tag, std::forward<_ExecutionPolicy>(__exec), __first1, __last1, __first2, __last2, __result, __comp,
+        [](_DifferenceType __n, _DifferenceType __m) { return __n + __m; }, __set_union_op);
 }
 
 //------------------------------------------------------------------------
@@ -3019,33 +3132,33 @@ struct __BrickCopyConstruct
     }
 };
 
-template <class _ForwardIterator1, class _ForwardIterator2, class _OutputIterator, class _Compare>
+template <class _RandomAccessIterator1, class _RandomAccessIterator2, class _OutputIterator, class _Compare>
 _OutputIterator
-__brick_set_union(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2,
-                  _ForwardIterator2 __last2, _OutputIterator __result, _Compare __comp,
+__brick_set_union(_RandomAccessIterator1 __first1, _RandomAccessIterator1 __last1, _RandomAccessIterator2 __first2,
+                  _RandomAccessIterator2 __last2, _OutputIterator __result, _Compare __comp,
                   /*__is_vector=*/std::true_type) noexcept
 {
     _PSTL_PRAGMA_MESSAGE("Vectorized algorithm unimplemented, redirected to serial");
     return std::set_union(__first1, __last1, __first2, __last2, __result, __comp);
 }
 
-template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _OutputIterator,
-          class _Compare, class _IsVector>
+template <class _Tag, class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _OutputIterator,
+          class _Compare>
 _OutputIterator
-__pattern_set_union(_ExecutionPolicy&&, _ForwardIterator1 __first1, _ForwardIterator1 __last1,
-                    _ForwardIterator2 __first2, _ForwardIterator2 __last2, _OutputIterator __result, _Compare __comp,
-                    _IsVector __is_vector,
-                    /*is_parallel=*/std::false_type) noexcept
+__pattern_set_union(_Tag, _ExecutionPolicy&&, _ForwardIterator1 __first1, _ForwardIterator1 __last1,
+                    _ForwardIterator2 __first2, _ForwardIterator2 __last2, _OutputIterator __result,
+                    _Compare __comp) noexcept
 {
-    return __internal::__brick_set_union(__first1, __last1, __first2, __last2, __result, __comp, __is_vector);
+    return __internal::__brick_set_union(__first1, __last1, __first2, __last2, __result, __comp,
+                                         typename _Tag::__is_vector{});
 }
 
-template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _OutputIterator,
-          class _Compare, class _IsVector>
+template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator1, class _RandomAccessIterator2,
+          class _OutputIterator, class _Compare>
 _OutputIterator
-__pattern_set_union(_ExecutionPolicy&& __exec, _ForwardIterator1 __first1, _ForwardIterator1 __last1,
-                    _ForwardIterator2 __first2, _ForwardIterator2 __last2, _OutputIterator __result, _Compare __comp,
-                    _IsVector __is_vector, /*__is_parallel=*/std::true_type)
+__pattern_set_union(__parallel_tag<_IsVector> __tag, _ExecutionPolicy&& __exec, _RandomAccessIterator1 __first1,
+                    _RandomAccessIterator1 __last1, _RandomAccessIterator2 __first2, _RandomAccessIterator2 __last2,
+                    _OutputIterator __result, _Compare __comp)
 {
 
     const auto __n1 = __last1 - __first1;
@@ -3057,13 +3170,13 @@ __pattern_set_union(_ExecutionPolicy&& __exec, _ForwardIterator1 __first1, _Forw
 
     typedef typename std::iterator_traits<_OutputIterator>::value_type _Tp;
     return __parallel_set_union_op(
-        std::forward<_ExecutionPolicy>(__exec), __first1, __last1, __first2, __last2, __result, __comp,
-        [](_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2, _ForwardIterator2 __last2,
-           _Tp* __result, _Compare __comp) {
+        __tag, std::forward<_ExecutionPolicy>(__exec), __first1, __last1, __first2, __last2, __result, __comp,
+        [](_RandomAccessIterator1 __first1, _RandomAccessIterator1 __last1, _RandomAccessIterator2 __first2,
+           _RandomAccessIterator2 __last2, _Tp* __result, _Compare __comp)
+        {
             return __pstl::__utils::__set_union_construct(__first1, __last1, __first2, __last2, __result, __comp,
                                                           __BrickCopyConstruct<_IsVector>());
-        },
-        __is_vector);
+        });
 }
 
 //------------------------------------------------------------------------
@@ -3079,35 +3192,37 @@ __brick_set_intersection(_ForwardIterator1 __first1, _ForwardIterator1 __last1,
     return std::set_intersection(__first1, __last1, __first2, __last2, __result, __comp);
 }
 
-template <class _ForwardIterator1, class _ForwardIterator2, class _OutputIterator, class _Compare>
-_OutputIterator
-__brick_set_intersection(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2,
-                         _ForwardIterator2 __last2, _OutputIterator __result, _Compare __comp,
+template <class _RandomAccessIterator1, class _RandomAccessIterator2, class _RandomAccessIterator3, class _Compare>
+_RandomAccessIterator3
+__brick_set_intersection(_RandomAccessIterator1 __first1, _RandomAccessIterator1 __last1,
+                         _RandomAccessIterator2 __first2, _RandomAccessIterator2 __last2,
+                         _RandomAccessIterator3 __result, _Compare __comp,
                          /*__is_vector=*/std::true_type) noexcept
 {
     _PSTL_PRAGMA_MESSAGE("Vectorized algorithm unimplemented, redirected to serial");
     return std::set_intersection(__first1, __last1, __first2, __last2, __result, __comp);
 }
 
-template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _OutputIterator,
-          class _Compare, class _IsVector>
+template <class _Tag, class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _OutputIterator,
+          class _Compare>
 _OutputIterator
-__pattern_set_intersection(_ExecutionPolicy&&, _ForwardIterator1 __first1, _ForwardIterator1 __last1,
+__pattern_set_intersection(_Tag, _ExecutionPolicy&&, _ForwardIterator1 __first1, _ForwardIterator1 __last1,
                            _ForwardIterator2 __first2, _ForwardIterator2 __last2, _OutputIterator __result,
-                           _Compare __comp, _IsVector __is_vector, /*is_parallel=*/std::false_type) noexcept
+                           _Compare __comp) noexcept
 {
-    return __internal::__brick_set_intersection(__first1, __last1, __first2, __last2, __result, __comp, __is_vector);
+    return __internal::__brick_set_intersection(__first1, __last1, __first2, __last2, __result, __comp,
+                                                typename _Tag::__is_vector{});
 }
 
-template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _OutputIterator,
-          class _Compare, class _IsVector>
-_OutputIterator
-__pattern_set_intersection(_ExecutionPolicy&& __exec, _ForwardIterator1 __first1, _ForwardIterator1 __last1,
-                           _ForwardIterator2 __first2, _ForwardIterator2 __last2, _OutputIterator __result,
-                           _Compare __comp, _IsVector __is_vector, /*is_parallel=*/std::true_type)
+template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator1, class _RandomAccessIterator2,
+          class _RandomAccessIterator3, class _Compare>
+_RandomAccessIterator3
+__pattern_set_intersection(__parallel_tag<_IsVector> __tag, _ExecutionPolicy&& __exec, _RandomAccessIterator1 __first1,
+                           _RandomAccessIterator1 __last1, _RandomAccessIterator2 __first2,
+                           _RandomAccessIterator2 __last2, _RandomAccessIterator3 __result, _Compare __comp)
 {
-    typedef typename std::iterator_traits<_OutputIterator>::value_type _Tp;
-    typedef typename std::iterator_traits<_ForwardIterator1>::difference_type _DifferenceType;
+    typedef typename std::iterator_traits<_RandomAccessIterator3>::value_type _Tp;
+    typedef typename std::iterator_traits<_RandomAccessIterator1>::difference_type _DifferenceType;
 
     const auto __n1 = __last1 - __first1;
     const auto __n2 = __last2 - __first2;
@@ -3117,13 +3232,13 @@ __pattern_set_intersection(_ExecutionPolicy&& __exec, _ForwardIterator1 __first1
         return __result;
 
     // testing  whether the sequences are intersected
-    _ForwardIterator1 __left_bound_seq_1 = std::lower_bound(__first1, __last1, *__first2, __comp);
+    _RandomAccessIterator1 __left_bound_seq_1 = std::lower_bound(__first1, __last1, *__first2, __comp);
     //{1} < {2}: seq 2 is wholly greater than seq 1, so, the intersection is empty
     if (__left_bound_seq_1 == __last1)
         return __result;
 
     // testing  whether the sequences are intersected
-    _ForwardIterator2 __left_bound_seq_2 = std::lower_bound(__first2, __last2, *__first1, __comp);
+    _RandomAccessIterator2 __left_bound_seq_2 = std::lower_bound(__first2, __last2, *__first1, __comp);
     //{2} < {1}: seq 1 is wholly greater than seq 2, so, the intersection is empty
     if (__left_bound_seq_2 == __last2)
         return __result;
@@ -3133,14 +3248,13 @@ __pattern_set_intersection(_ExecutionPolicy&& __exec, _ForwardIterator1 __first1
     {
         //we know proper offset due to [first1; left_bound_seq_1) < [first2; last2)
         return __internal::__parallel_set_op(
-            std::forward<_ExecutionPolicy>(__exec), __left_bound_seq_1, __last1, __first2, __last2, __result, __comp,
-            [](_DifferenceType __n, _DifferenceType __m) { return std::min(__n, __m); },
-            [](_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2,
-               _ForwardIterator2 __last2, _Tp* __result, _Compare __comp) {
+            __tag, std::forward<_ExecutionPolicy>(__exec), __left_bound_seq_1, __last1, __first2, __last2, __result,
+            __comp, [](_DifferenceType __n, _DifferenceType __m) { return std::min(__n, __m); },
+            [](_RandomAccessIterator1 __first1, _RandomAccessIterator1 __last1, _RandomAccessIterator2 __first2,
+               _RandomAccessIterator2 __last2, _Tp* __result, _Compare __comp) {
                 return __pstl::__utils::__set_intersection_construct(__first1, __last1, __first2, __last2, __result,
                                                                      __comp);
-            },
-            __is_vector);
+            });
     }
 
     const auto __m2 = __last2 - __left_bound_seq_2 + __n1;
@@ -3148,14 +3262,13 @@ __pattern_set_intersection(_ExecutionPolicy&& __exec, _ForwardIterator1 __first1
     {
         //we know proper offset due to [first2; left_bound_seq_2) < [first1; last1)
         __result = __internal::__parallel_set_op(
-            std::forward<_ExecutionPolicy>(__exec), __first1, __last1, __left_bound_seq_2, __last2, __result, __comp,
-            [](_DifferenceType __n, _DifferenceType __m) { return std::min(__n, __m); },
-            [](_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2,
-               _ForwardIterator2 __last2, _Tp* __result, _Compare __comp) {
+            __tag, std::forward<_ExecutionPolicy>(__exec), __first1, __last1, __left_bound_seq_2, __last2, __result,
+            __comp, [](_DifferenceType __n, _DifferenceType __m) { return std::min(__n, __m); },
+            [](_RandomAccessIterator1 __first1, _RandomAccessIterator1 __last1, _RandomAccessIterator2 __first2,
+               _RandomAccessIterator2 __last2, _Tp* __result, _Compare __comp) {
                 return __pstl::__utils::__set_intersection_construct(__first2, __last2, __first1, __last1, __result,
                                                                      __comp);
-            },
-            __is_vector);
+            });
         return __result;
     }
 
@@ -3176,35 +3289,36 @@ __brick_set_difference(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _F
     return std::set_difference(__first1, __last1, __first2, __last2, __result, __comp);
 }
 
-template <class _ForwardIterator1, class _ForwardIterator2, class _OutputIterator, class _Compare>
-_OutputIterator
-__brick_set_difference(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2,
-                       _ForwardIterator2 __last2, _OutputIterator __result, _Compare __comp,
+template <class _RandomAccessIterator1, class _RandomAccessIterator2, class _RandomAccessIterator3, class _Compare>
+_RandomAccessIterator3
+__brick_set_difference(_RandomAccessIterator1 __first1, _RandomAccessIterator1 __last1, _RandomAccessIterator2 __first2,
+                       _RandomAccessIterator2 __last2, _RandomAccessIterator3 __result, _Compare __comp,
                        /*__is_vector=*/std::true_type) noexcept
 {
     _PSTL_PRAGMA_MESSAGE("Vectorized algorithm unimplemented, redirected to serial");
     return std::set_difference(__first1, __last1, __first2, __last2, __result, __comp);
 }
 
-template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _OutputIterator,
-          class _Compare, class _IsVector>
+template <class _Tag, class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _OutputIterator,
+          class _Compare>
 _OutputIterator
-__pattern_set_difference(_ExecutionPolicy&&, _ForwardIterator1 __first1, _ForwardIterator1 __last1,
+__pattern_set_difference(_Tag, _ExecutionPolicy&&, _ForwardIterator1 __first1, _ForwardIterator1 __last1,
                          _ForwardIterator2 __first2, _ForwardIterator2 __last2, _OutputIterator __result,
-                         _Compare __comp, _IsVector __is_vector, /*is_parallel=*/std::false_type) noexcept
+                         _Compare __comp) noexcept
 {
-    return __internal::__brick_set_difference(__first1, __last1, __first2, __last2, __result, __comp, __is_vector);
+    return __internal::__brick_set_difference(__first1, __last1, __first2, __last2, __result, __comp,
+                                              typename _Tag::__is_vector{});
 }
 
-template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _OutputIterator,
-          class _Compare, class _IsVector>
-_OutputIterator
-__pattern_set_difference(_ExecutionPolicy&& __exec, _ForwardIterator1 __first1, _ForwardIterator1 __last1,
-                         _ForwardIterator2 __first2, _ForwardIterator2 __last2, _OutputIterator __result,
-                         _Compare __comp, _IsVector __is_vector, /*is_parallel=*/std::true_type)
+template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator1, class _RandomAccessIterator2,
+          class _RandomAccessIterator3, class _Compare>
+_RandomAccessIterator3
+__pattern_set_difference(__parallel_tag<_IsVector> __tag, _ExecutionPolicy&& __exec, _RandomAccessIterator1 __first1,
+                         _RandomAccessIterator1 __last1, _RandomAccessIterator2 __first2,
+                         _RandomAccessIterator2 __last2, _RandomAccessIterator3 __result, _Compare __comp)
 {
-    typedef typename std::iterator_traits<_OutputIterator>::value_type _Tp;
-    typedef typename std::iterator_traits<_ForwardIterator1>::difference_type _DifferenceType;
+    typedef typename std::iterator_traits<_RandomAccessIterator3>::value_type _Tp;
+    typedef typename std::iterator_traits<_RandomAccessIterator1>::difference_type _DifferenceType;
 
     const auto __n1 = __last1 - __first1;
     const auto __n2 = __last2 - __first2;
@@ -3216,44 +3330,38 @@ __pattern_set_difference(_ExecutionPolicy&& __exec, _ForwardIterator1 __first1,
     // {1} \ {}: parallel copying just first sequence
     if (__n2 == 0)
         return __internal::__pattern_walk2_brick(
-            std::forward<_ExecutionPolicy>(__exec), __first1, __last1, __result,
-            [__is_vector](_ForwardIterator1 __begin, _ForwardIterator1 __end, _OutputIterator __res) {
-                return __internal::__brick_copy(__begin, __end, __res, __is_vector);
-            },
-            std::true_type());
+            __tag, std::forward<_ExecutionPolicy>(__exec), __first1, __last1, __result,
+            [](_RandomAccessIterator1 __begin, _RandomAccessIterator1 __end, _RandomAccessIterator3 __res)
+            { return __internal::__brick_copy(__begin, __end, __res, _IsVector{}); });
 
     // testing  whether the sequences are intersected
-    _ForwardIterator1 __left_bound_seq_1 = std::lower_bound(__first1, __last1, *__first2, __comp);
+    _RandomAccessIterator1 __left_bound_seq_1 = std::lower_bound(__first1, __last1, *__first2, __comp);
     //{1} < {2}: seq 2 is wholly greater than seq 1, so, parallel copying just first sequence
     if (__left_bound_seq_1 == __last1)
         return __internal::__pattern_walk2_brick(
-            std::forward<_ExecutionPolicy>(__exec), __first1, __last1, __result,
-            [__is_vector](_ForwardIterator1 __begin, _ForwardIterator1 __end, _OutputIterator __res) {
-                return __internal::__brick_copy(__begin, __end, __res, __is_vector);
-            },
-            std::true_type());
+            __tag, std::forward<_ExecutionPolicy>(__exec), __first1, __last1, __result,
+            [](_RandomAccessIterator1 __begin, _RandomAccessIterator1 __end, _RandomAccessIterator3 __res)
+            { return __internal::__brick_copy(__begin, __end, __res, _IsVector{}); });
 
     // testing  whether the sequences are intersected
-    _ForwardIterator2 __left_bound_seq_2 = std::lower_bound(__first2, __last2, *__first1, __comp);
+    _RandomAccessIterator2 __left_bound_seq_2 = std::lower_bound(__first2, __last2, *__first1, __comp);
     //{2} < {1}: seq 1 is wholly greater than seq 2, so, parallel copying just first sequence
     if (__left_bound_seq_2 == __last2)
         return __internal::__pattern_walk2_brick(
-            std::forward<_ExecutionPolicy>(__exec), __first1, __last1, __result,
-            [__is_vector](_ForwardIterator1 __begin, _ForwardIterator1 __end, _OutputIterator __res) {
-                return __internal::__brick_copy(__begin, __end, __res, __is_vector);
-            },
-            std::true_type());
+            __tag, std::forward<_ExecutionPolicy>(__exec), __first1, __last1, __result,
+            [](_RandomAccessIterator1 __begin, _RandomAccessIterator1 __end, _RandomAccessIterator3 __res)
+            { return __internal::__brick_copy(__begin, __end, __res, _IsVector{}); });
 
     if (__n1 + __n2 > __set_algo_cut_off)
-        return __parallel_set_op(std::forward<_ExecutionPolicy>(__exec), __first1, __last1, __first2, __last2, __result,
-                                 __comp, [](_DifferenceType __n, _DifferenceType) { return __n; },
-                                 [](_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2,
-                                    _ForwardIterator2 __last2, _Tp* __result, _Compare __comp) {
-                                     return __pstl::__utils::__set_difference_construct(
-                                         __first1, __last1, __first2, __last2, __result, __comp,
-                                         __BrickCopyConstruct<_IsVector>());
-                                 },
-                                 __is_vector);
+        return __parallel_set_op(
+            __tag, std::forward<_ExecutionPolicy>(__exec), __first1, __last1, __first2, __last2, __result, __comp,
+            [](_DifferenceType __n, _DifferenceType) { return __n; },
+            [](_RandomAccessIterator1 __first1, _RandomAccessIterator1 __last1, _RandomAccessIterator2 __first2,
+               _RandomAccessIterator2 __last2, _Tp* __result, _Compare __comp)
+            {
+                return __pstl::__utils::__set_difference_construct(__first1, __last1, __first2, __last2, __result,
+                                                                   __comp, __BrickCopyConstruct<_IsVector>());
+            });
 
     // use serial algorithm
     return std::set_difference(__first1, __last1, __first2, __last2, __result, __comp);
@@ -3272,33 +3380,35 @@ __brick_set_symmetric_difference(_ForwardIterator1 __first1, _ForwardIterator1 _
     return std::set_symmetric_difference(__first1, __last1, __first2, __last2, __result, __comp);
 }
 
-template <class _ForwardIterator1, class _ForwardIterator2, class _OutputIterator, class _Compare>
-_OutputIterator
-__brick_set_symmetric_difference(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2,
-                                 _ForwardIterator2 __last2, _OutputIterator __result, _Compare __comp,
+template <class _RandomAccessIterator1, class _RandomAccessIterator2, class _RandomAccessIterator3, class _Compare>
+_RandomAccessIterator3
+__brick_set_symmetric_difference(_RandomAccessIterator1 __first1, _RandomAccessIterator1 __last1,
+                                 _RandomAccessIterator2 __first2, _RandomAccessIterator2 __last2,
+                                 _RandomAccessIterator3 __result, _Compare __comp,
                                  /*__is_vector=*/std::true_type) noexcept
 {
     _PSTL_PRAGMA_MESSAGE("Vectorized algorithm unimplemented, redirected to serial");
     return std::set_symmetric_difference(__first1, __last1, __first2, __last2, __result, __comp);
 }
 
-template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _OutputIterator,
-          class _Compare, class _IsVector>
+template <class _Tag, class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _OutputIterator,
+          class _Compare>
 _OutputIterator
-__pattern_set_symmetric_difference(_ExecutionPolicy&&, _ForwardIterator1 __first1, _ForwardIterator1 __last1,
+__pattern_set_symmetric_difference(_Tag, _ExecutionPolicy&&, _ForwardIterator1 __first1, _ForwardIterator1 __last1,
                                    _ForwardIterator2 __first2, _ForwardIterator2 __last2, _OutputIterator __result,
-                                   _Compare __comp, _IsVector __is_vector, /*is_parallel=*/std::false_type) noexcept
+                                   _Compare __comp) noexcept
 {
     return __internal::__brick_set_symmetric_difference(__first1, __last1, __first2, __last2, __result, __comp,
-                                                        __is_vector);
+                                                        typename _Tag::__is_vector{});
 }
 
-template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _OutputIterator,
-          class _Compare, class _IsVector>
-_OutputIterator
-__pattern_set_symmetric_difference(_ExecutionPolicy&& __exec, _ForwardIterator1 __first1, _ForwardIterator1 __last1,
-                                   _ForwardIterator2 __first2, _ForwardIterator2 __last2, _OutputIterator __result,
-                                   _Compare __comp, _IsVector __is_vector, /*is_parallel=*/std::true_type)
+template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator1, class _RandomAccessIterator2,
+          class _RandomAccessIterator3, class _Compare>
+_RandomAccessIterator3
+__pattern_set_symmetric_difference(__parallel_tag<_IsVector> __tag, _ExecutionPolicy&& __exec,
+                                   _RandomAccessIterator1 __first1, _RandomAccessIterator1 __last1,
+                                   _RandomAccessIterator2 __first2, _RandomAccessIterator2 __last2,
+                                   _RandomAccessIterator3 __result, _Compare __comp)
 {
 
     const auto __n1 = __last1 - __first1;
@@ -3308,15 +3418,15 @@ __pattern_set_symmetric_difference(_ExecutionPolicy&& __exec, _ForwardIterator1
     if (__n1 + __n2 <= __set_algo_cut_off)
         return std::set_symmetric_difference(__first1, __last1, __first2, __last2, __result, __comp);
 
-    typedef typename std::iterator_traits<_OutputIterator>::value_type _Tp;
+    typedef typename std::iterator_traits<_RandomAccessIterator3>::value_type _Tp;
     return __internal::__parallel_set_union_op(
-        std::forward<_ExecutionPolicy>(__exec), __first1, __last1, __first2, __last2, __result, __comp,
-        [](_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2, _ForwardIterator2 __last2,
-           _Tp* __result, _Compare __comp) {
+        __tag, std::forward<_ExecutionPolicy>(__exec), __first1, __last1, __first2, __last2, __result, __comp,
+        [](_RandomAccessIterator1 __first1, _RandomAccessIterator1 __last1, _RandomAccessIterator2 __first2,
+           _RandomAccessIterator2 __last2, _Tp* __result, _Compare __comp)
+        {
             return __pstl::__utils::__set_symmetric_difference_construct(__first1, __last1, __first2, __last2, __result,
                                                                          __comp, __BrickCopyConstruct<_IsVector>());
-        },
-        __is_vector);
+        });
 }
 
 //------------------------------------------------------------------------
@@ -3344,12 +3454,12 @@ __brick_is_heap_until(_RandomAccessIterator __first, _RandomAccessIterator __las
         [&__comp](_RandomAccessIterator __it, _SizeType __i) { return __comp(__it[(__i - 1) / 2], __it[__i]); });
 }
 
-template <class _ExecutionPolicy, class _RandomAccessIterator, class _Compare, class _IsVector>
+template <class _Tag, class _ExecutionPolicy, class _RandomAccessIterator, class _Compare>
 _RandomAccessIterator
-__pattern_is_heap_until(_ExecutionPolicy&&, _RandomAccessIterator __first, _RandomAccessIterator __last,
-                        _Compare __comp, _IsVector __is_vector, /* is_parallel = */ std::false_type) noexcept
+__pattern_is_heap_until(_Tag, _ExecutionPolicy&&, _RandomAccessIterator __first, _RandomAccessIterator __last,
+                        _Compare __comp) noexcept
 {
-    return __internal::__brick_is_heap_until(__first, __last, __comp, __is_vector);
+    return __internal::__brick_is_heap_until(__first, __last, __comp, typename _Tag::__is_vector{});
 }
 
 template <class _RandomAccessIterator, class _DifferenceType, class _Compare>
@@ -3378,22 +3488,27 @@ __is_heap_until_local(_RandomAccessIterator __first, _DifferenceType __begin, _D
         [&__comp](_RandomAccessIterator __it, _DifferenceType __i) { return __comp(__it[(__i - 1) / 2], __it[__i]); });
 }
 
-template <class _ExecutionPolicy, class _RandomAccessIterator, class _Compare, class _IsVector>
+template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _Compare>
 _RandomAccessIterator
-__pattern_is_heap_until(_ExecutionPolicy&& __exec, _RandomAccessIterator __first, _RandomAccessIterator __last,
-                        _Compare __comp, _IsVector __is_vector, /* is_parallel = */ std::true_type) noexcept
+__pattern_is_heap_until(__parallel_tag<_IsVector> __tag, _ExecutionPolicy&& __exec, _RandomAccessIterator __first,
+                        _RandomAccessIterator __last, _Compare __comp) noexcept
 {
+    using __backend_tag = typename decltype(__tag)::__backend_tag;
+
     if (__last - __first < 2)
         return __last;
 
-    return __internal::__except_handler([&]() {
-        return __parallel_find(
-            std::forward<_ExecutionPolicy>(__exec), __first, __last,
-            [__first, __comp, __is_vector](_RandomAccessIterator __i, _RandomAccessIterator __j) {
-                return __internal::__is_heap_until_local(__first, __i - __first, __j - __first, __comp, __is_vector);
-            },
-            std::less<typename std::iterator_traits<_RandomAccessIterator>::difference_type>(), /*is_first=*/true);
-    });
+    return __internal::__except_handler(
+        [&]()
+        {
+            return __parallel_find(
+                __backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __first, __last,
+                [__first, __comp](_RandomAccessIterator __i, _RandomAccessIterator __j) {
+                    return __internal::__is_heap_until_local(__first, __i - __first, __j - __first, __comp,
+                                                             _IsVector{});
+                },
+                std::less<typename std::iterator_traits<_RandomAccessIterator>::difference_type>(), /*is_first=*/true);
+        });
 }
 
 //------------------------------------------------------------------------
@@ -3408,47 +3523,51 @@ __brick_min_element(_ForwardIterator __first, _ForwardIterator __last, _Compare
     return std::min_element(__first, __last, __comp);
 }
 
-template <typename _ForwardIterator, typename _Compare>
-_ForwardIterator
-__brick_min_element(_ForwardIterator __first, _ForwardIterator __last, _Compare __comp,
+template <typename _RandomAccessIterator, typename _Compare>
+_RandomAccessIterator
+__brick_min_element(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp,
                     /* __is_vector = */ std::true_type) noexcept
 {
-#if _PSTL_UDR_PRESENT
+#if defined(_PSTL_UDR_PRESENT)
     return __unseq_backend::__simd_min_element(__first, __last - __first, __comp);
 #else
     return std::min_element(__first, __last, __comp);
 #endif
 }
 
-template <typename _ExecutionPolicy, typename _ForwardIterator, typename _Compare, typename _IsVector>
+template <typename _Tag, typename _ExecutionPolicy, typename _ForwardIterator, typename _Compare>
 _ForwardIterator
-__pattern_min_element(_ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last, _Compare __comp,
-                      _IsVector __is_vector, /* is_parallel = */ std::false_type) noexcept
+__pattern_min_element(_Tag, _ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last,
+                      _Compare __comp) noexcept
 {
-    return __internal::__brick_min_element(__first, __last, __comp, __is_vector);
+    return __internal::__brick_min_element(__first, __last, __comp, typename _Tag::__is_vector{});
 }
 
-template <typename _ExecutionPolicy, typename _RandomAccessIterator, typename _Compare, typename _IsVector>
+template <typename _IsVector, typename _ExecutionPolicy, typename _RandomAccessIterator, typename _Compare>
 _RandomAccessIterator
-__pattern_min_element(_ExecutionPolicy&& __exec, _RandomAccessIterator __first, _RandomAccessIterator __last,
-                      _Compare __comp, _IsVector __is_vector, /* is_parallel = */ std::true_type)
+__pattern_min_element(__parallel_tag<_IsVector> __tag, _ExecutionPolicy&& __exec, _RandomAccessIterator __first,
+                      _RandomAccessIterator __last, _Compare __comp)
 {
     if (__first == __last)
         return __last;
 
-    return __internal::__except_handler([&]() {
-        return __par_backend::__parallel_reduce(
-            std::forward<_ExecutionPolicy>(__exec), __first + 1, __last, __first,
-            [=](_RandomAccessIterator __begin, _RandomAccessIterator __end,
-                _RandomAccessIterator __init) -> _RandomAccessIterator {
-                const _RandomAccessIterator subresult =
-                    __internal::__brick_min_element(__begin, __end, __comp, __is_vector);
-                return __internal::__cmp_iterators_by_values(__init, subresult, __comp);
-            },
-            [=](_RandomAccessIterator __it1, _RandomAccessIterator __it2) -> _RandomAccessIterator {
-                return __internal::__cmp_iterators_by_values(__it1, __it2, __comp);
-            });
-    });
+    using __backend_tag = typename decltype(__tag)::__backend_tag;
+
+    return __internal::__except_handler(
+        [&]()
+        {
+            return __par_backend::__parallel_reduce(
+                __backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __first + 1, __last, __first,
+                [=](_RandomAccessIterator __begin, _RandomAccessIterator __end,
+                    _RandomAccessIterator __init) -> _RandomAccessIterator
+                {
+                    const _RandomAccessIterator subresult =
+                        __internal::__brick_min_element(__begin, __end, __comp, _IsVector{});
+                    return __internal::__cmp_iterators_by_values(__init, subresult, __comp);
+                },
+                [=](_RandomAccessIterator __it1, _RandomAccessIterator __it2) -> _RandomAccessIterator
+                { return __internal::__cmp_iterators_by_values(__it1, __it2, __comp); });
+        });
 }
 
 //------------------------------------------------------------------------
@@ -3463,46 +3582,51 @@ __brick_minmax_element(_ForwardIterator __first, _ForwardIterator __last, _Compa
     return std::minmax_element(__first, __last, __comp);
 }
 
-template <typename _ForwardIterator, typename _Compare>
-std::pair<_ForwardIterator, _ForwardIterator>
-__brick_minmax_element(_ForwardIterator __first, _ForwardIterator __last, _Compare __comp,
+template <typename _RandomAccessIterator, typename _Compare>
+std::pair<_RandomAccessIterator, _RandomAccessIterator>
+__brick_minmax_element(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp,
                        /* __is_vector = */ std::true_type) noexcept
 {
-#if _PSTL_UDR_PRESENT
+#if defined(_PSTL_UDR_PRESENT)
     return __unseq_backend::__simd_minmax_element(__first, __last - __first, __comp);
 #else
     return std::minmax_element(__first, __last, __comp);
 #endif
 }
 
-template <typename _ExecutionPolicy, typename _ForwardIterator, typename _Compare, typename _IsVector>
+template <typename _Tag, typename _ExecutionPolicy, typename _ForwardIterator, typename _Compare>
 std::pair<_ForwardIterator, _ForwardIterator>
-__pattern_minmax_element(_ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last, _Compare __comp,
-                         _IsVector __is_vector, /* is_parallel = */ std::false_type) noexcept
+__pattern_minmax_element(_Tag, _ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last,
+                         _Compare __comp) noexcept
 {
-    return __internal::__brick_minmax_element(__first, __last, __comp, __is_vector);
+    return __internal::__brick_minmax_element(__first, __last, __comp, typename _Tag::__is_vector{});
 }
 
-template <typename _ExecutionPolicy, typename _ForwardIterator, typename _Compare, typename _IsVector>
-std::pair<_ForwardIterator, _ForwardIterator>
-__pattern_minmax_element(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _Compare __comp,
-                         _IsVector __is_vector, /* is_parallel = */ std::true_type)
+template <typename _IsVector, typename _ExecutionPolicy, typename _RandomAccessIterator, typename _Compare>
+std::pair<_RandomAccessIterator, _RandomAccessIterator>
+__pattern_minmax_element(__parallel_tag<_IsVector> __tag, _ExecutionPolicy&& __exec, _RandomAccessIterator __first,
+                         _RandomAccessIterator __last, _Compare __comp)
 {
     if (__first == __last)
         return std::make_pair(__first, __first);
 
+    using __backend_tag = typename decltype(__tag)::__backend_tag;
+
     return __internal::__except_handler([&]() {
-        typedef std::pair<_ForwardIterator, _ForwardIterator> _Result;
+        typedef std::pair<_RandomAccessIterator, _RandomAccessIterator> _Result;
 
         return __par_backend::__parallel_reduce(
-            std::forward<_ExecutionPolicy>(__exec), __first + 1, __last, std::make_pair(__first, __first),
-            [=](_ForwardIterator __begin, _ForwardIterator __end, _Result __init) -> _Result {
-                const _Result __subresult = __internal::__brick_minmax_element(__begin, __end, __comp, __is_vector);
+            __backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __first + 1, __last,
+            std::make_pair(__first, __first),
+            [=](_RandomAccessIterator __begin, _RandomAccessIterator __end, _Result __init) -> _Result
+            {
+                const _Result __subresult = __internal::__brick_minmax_element(__begin, __end, __comp, _IsVector{});
                 return std::make_pair(
                     __internal::__cmp_iterators_by_values(__subresult.first, __init.first, __comp),
                     __internal::__cmp_iterators_by_values(__init.second, __subresult.second, std::not_fn(__comp)));
             },
-            [=](_Result __p1, _Result __p2) -> _Result {
+            [=](_Result __p1, _Result __p2) -> _Result
+            {
                 return std::make_pair(
                     __internal::__cmp_iterators_by_values(__p1.first, __p2.first, __comp),
                     __internal::__cmp_iterators_by_values(__p2.second, __p1.second, std::not_fn(__comp)));
@@ -3518,7 +3642,7 @@ std::pair<_ForwardIterator1, _ForwardIterator2>
 __mismatch_serial(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2,
                   _ForwardIterator2 __last2, _BinaryPredicate __pred)
 {
-#if _PSTL_CPP14_2RANGE_MISMATCH_EQUAL_PRESENT
+#if defined(_PSTL_CPP14_2RANGE_MISMATCH_EQUAL_PRESENT)
     return std::mismatch(__first1, __last1, __first2, __last2, __pred);
 #else
     for (; __first1 != __last1 && __first2 != __last2 && __pred(*__first1, *__first2); ++__first1, ++__first2)
@@ -3536,38 +3660,40 @@ __brick_mismatch(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _Forward
     return __mismatch_serial(__first1, __last1, __first2, __last2, __pred);
 }
 
-template <class _ForwardIterator1, class _ForwardIterator2, class _Predicate>
-std::pair<_ForwardIterator1, _ForwardIterator2>
-__brick_mismatch(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2,
-                 _ForwardIterator2 __last2, _Predicate __pred, /* __is_vector = */ std::true_type) noexcept
+template <class _RandomAccessIterator1, class _RandomAccessIterator2, class _Predicate>
+std::pair<_RandomAccessIterator1, _RandomAccessIterator2>
+__brick_mismatch(_RandomAccessIterator1 __first1, _RandomAccessIterator1 __last1, _RandomAccessIterator2 __first2,
+                 _RandomAccessIterator2 __last2, _Predicate __pred, /* __is_vector = */ std::true_type) noexcept
 {
     auto __n = std::min(__last1 - __first1, __last2 - __first2);
     return __unseq_backend::__simd_first(__first1, __n, __first2, std::not_fn(__pred));
 }
 
-template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _Predicate, class _IsVector>
+template <class _Tag, class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _Predicate>
 std::pair<_ForwardIterator1, _ForwardIterator2>
-__pattern_mismatch(_ExecutionPolicy&&, _ForwardIterator1 __first1, _ForwardIterator1 __last1,
-                   _ForwardIterator2 __first2, _ForwardIterator2 __last2, _Predicate __pred, _IsVector __is_vector,
-                   /* is_parallel = */ std::false_type) noexcept
+__pattern_mismatch(_Tag, _ExecutionPolicy&&, _ForwardIterator1 __first1, _ForwardIterator1 __last1,
+                   _ForwardIterator2 __first2, _ForwardIterator2 __last2, _Predicate __pred) noexcept
 {
-    return __internal::__brick_mismatch(__first1, __last1, __first2, __last2, __pred, __is_vector);
+    return __internal::__brick_mismatch(__first1, __last1, __first2, __last2, __pred, typename _Tag::__is_vector{});
 }
 
-template <class _ExecutionPolicy, class _RandomAccessIterator1, class _RandomAccessIterator2, class _Predicate,
-          class _IsVector>
+template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator1, class _RandomAccessIterator2,
+          class _Predicate>
 std::pair<_RandomAccessIterator1, _RandomAccessIterator2>
-__pattern_mismatch(_ExecutionPolicy&& __exec, _RandomAccessIterator1 __first1, _RandomAccessIterator1 __last1,
-                   _RandomAccessIterator2 __first2, _RandomAccessIterator2 __last2, _Predicate __pred,
-                   _IsVector __is_vector, /* is_parallel = */ std::true_type) noexcept
+__pattern_mismatch(__parallel_tag<_IsVector> __tag, _ExecutionPolicy&& __exec, _RandomAccessIterator1 __first1,
+                   _RandomAccessIterator1 __last1, _RandomAccessIterator2 __first2, _RandomAccessIterator2 __last2,
+                   _Predicate __pred) noexcept
 {
+    using __backend_tag = typename decltype(__tag)::__backend_tag;
+
     return __internal::__except_handler([&]() {
         auto __n = std::min(__last1 - __first1, __last2 - __first2);
         auto __result = __internal::__parallel_find(
-            std::forward<_ExecutionPolicy>(__exec), __first1, __first1 + __n,
-            [__first1, __first2, __pred, __is_vector](_RandomAccessIterator1 __i, _RandomAccessIterator1 __j) {
+            __backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __first1, __first1 + __n,
+            [__first1, __first2, __pred](_RandomAccessIterator1 __i, _RandomAccessIterator1 __j)
+            {
                 return __internal::__brick_mismatch(__i, __j, __first2 + (__i - __first1), __first2 + (__j - __first1),
-                                                    __pred, __is_vector)
+                                                    __pred, _IsVector{})
                     .first;
             },
             std::less<typename std::iterator_traits<_RandomAccessIterator1>::difference_type>(), /*is_first=*/true);
@@ -3588,10 +3714,11 @@ __brick_lexicographical_compare(_ForwardIterator1 __first1, _ForwardIterator1 __
     return std::lexicographical_compare(__first1, __last1, __first2, __last2, __comp);
 }
 
-template <class _ForwardIterator1, class _ForwardIterator2, class _Compare>
+template <class _RandomAccessIterator1, class _RandomAccessIterator2, class _Compare>
 bool
-__brick_lexicographical_compare(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2,
-                                _ForwardIterator2 __last2, _Compare __comp, /* __is_vector = */ std::true_type) noexcept
+__brick_lexicographical_compare(_RandomAccessIterator1 __first1, _RandomAccessIterator1 __last1,
+                                _RandomAccessIterator2 __first2, _RandomAccessIterator2 __last2, _Compare __comp,
+                                /* __is_vector = */ std::true_type) noexcept
 {
     if (__first2 == __last2)
     { // if second sequence is empty
@@ -3603,12 +3730,12 @@ __brick_lexicographical_compare(_ForwardIterator1 __first1, _ForwardIterator1 __
     }
     else
     {
-        typedef typename std::iterator_traits<_ForwardIterator1>::reference ref_type1;
-        typedef typename std::iterator_traits<_ForwardIterator2>::reference ref_type2;
+        typedef typename std::iterator_traits<_RandomAccessIterator1>::reference ref_type1;
+        typedef typename std::iterator_traits<_RandomAccessIterator2>::reference ref_type2;
         --__last1;
         --__last2;
         auto __n = std::min(__last1 - __first1, __last2 - __first2);
-        std::pair<_ForwardIterator1, _ForwardIterator2> __result = __unseq_backend::__simd_first(
+        std::pair<_RandomAccessIterator1, _RandomAccessIterator2> __result = __unseq_backend::__simd_first(
             __first1, __n, __first2, [__comp](const ref_type1 __x, const ref_type2 __y) mutable {
                 return __comp(__x, __y) || __comp(__y, __x);
             });
@@ -3624,21 +3751,25 @@ __brick_lexicographical_compare(_ForwardIterator1 __first1, _ForwardIterator1 __
     }
 }
 
-template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _Compare, class _IsVector>
+template <class _Tag, class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _Compare>
 bool
-__pattern_lexicographical_compare(_ExecutionPolicy&&, _ForwardIterator1 __first1, _ForwardIterator1 __last1,
-                                  _ForwardIterator2 __first2, _ForwardIterator2 __last2, _Compare __comp,
-                                  _IsVector __is_vector, /* is_parallel = */ std::false_type) noexcept
+__pattern_lexicographical_compare(_Tag, _ExecutionPolicy&&, _ForwardIterator1 __first1, _ForwardIterator1 __last1,
+                                  _ForwardIterator2 __first2, _ForwardIterator2 __last2, _Compare __comp) noexcept
 {
-    return __internal::__brick_lexicographical_compare(__first1, __last1, __first2, __last2, __comp, __is_vector);
+    return __internal::__brick_lexicographical_compare(__first1, __last1, __first2, __last2, __comp,
+                                                       typename _Tag::__is_vector{});
 }
 
-template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _Compare, class _IsVector>
+template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator1, class _RandomAccessIterator2,
+          class _Compare>
 bool
-__pattern_lexicographical_compare(_ExecutionPolicy&& __exec, _ForwardIterator1 __first1, _ForwardIterator1 __last1,
-                                  _ForwardIterator2 __first2, _ForwardIterator2 __last2, _Compare __comp,
-                                  _IsVector __is_vector, /* is_parallel = */ std::true_type) noexcept
+__pattern_lexicographical_compare(__parallel_tag<_IsVector> __tag, _ExecutionPolicy&& __exec,
+                                  _RandomAccessIterator1 __first1, _RandomAccessIterator1 __last1,
+                                  _RandomAccessIterator2 __first2, _RandomAccessIterator2 __last2,
+                                  _Compare __comp) noexcept
 {
+    using __backend_tag = typename decltype(__tag)::__backend_tag;
+
     if (__first2 == __last2)
     { // if second sequence is empty
         return false;
@@ -3649,22 +3780,23 @@ __pattern_lexicographical_compare(_ExecutionPolicy&& __exec, _ForwardIterator1 _
     }
     else
     {
-        typedef typename std::iterator_traits<_ForwardIterator1>::reference _RefType1;
-        typedef typename std::iterator_traits<_ForwardIterator2>::reference _RefType2;
+        typedef typename std::iterator_traits<_RandomAccessIterator1>::reference _RefType1;
+        typedef typename std::iterator_traits<_RandomAccessIterator2>::reference _RefType2;
         --__last1;
         --__last2;
         auto __n = std::min(__last1 - __first1, __last2 - __first2);
         auto __result = __internal::__parallel_find(
-            std::forward<_ExecutionPolicy>(__exec), __first1, __first1 + __n,
-            [__first1, __first2, &__comp, __is_vector](_ForwardIterator1 __i, _ForwardIterator1 __j) {
-                return __internal::__brick_mismatch(__i, __j, __first2 + (__i - __first1), __first2 + (__j - __first1),
-                                                    [&__comp](const _RefType1 __x, const _RefType2 __y) {
-                                                        return !__comp(__x, __y) && !__comp(__y, __x);
-                                                    },
-                                                    __is_vector)
+            __backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __first1, __first1 + __n,
+            [__first1, __first2, &__comp](_RandomAccessIterator1 __i, _RandomAccessIterator1 __j)
+            {
+                return __internal::__brick_mismatch(
+                           __i, __j, __first2 + (__i - __first1), __first2 + (__j - __first1),
+                           [&__comp](const _RefType1 __x, const _RefType2 __y)
+                           { return !__comp(__x, __y) && !__comp(__y, __x); },
+                           _IsVector{})
                     .first;
             },
-            std::less<typename std::iterator_traits<_ForwardIterator1>::difference_type>(), /*is_first=*/true);
+            std::less<typename std::iterator_traits<_RandomAccessIterator1>::difference_type>(), /*is_first=*/true);
 
         if (__result == __last1 && __first2 + (__result - __first1) != __last2)
         { // if first sequence shorter than second
diff --git a/libstdc++-v3/include/pstl/execution_defs.h b/libstdc++-v3/include/pstl/execution_defs.h
index 3eca558dac2..522518c4116 100644
--- a/libstdc++-v3/include/pstl/execution_defs.h
+++ b/libstdc++-v3/include/pstl/execution_defs.h
@@ -22,88 +22,20 @@ inline namespace v1
 // 2.4, Sequential execution policy
 class sequenced_policy
 {
-  public:
-    // For internal use only
-    static constexpr std::false_type
-    __allow_unsequenced()
-    {
-        return std::false_type{};
-    }
-    static constexpr std::false_type
-    __allow_vector()
-    {
-        return std::false_type{};
-    }
-    static constexpr std::false_type
-    __allow_parallel()
-    {
-        return std::false_type{};
-    }
 };
 
 // 2.5, Parallel execution policy
 class parallel_policy
 {
-  public:
-    // For internal use only
-    static constexpr std::false_type
-    __allow_unsequenced()
-    {
-        return std::false_type{};
-    }
-    static constexpr std::false_type
-    __allow_vector()
-    {
-        return std::false_type{};
-    }
-    static constexpr std::true_type
-    __allow_parallel()
-    {
-        return std::true_type{};
-    }
 };
 
 // 2.6, Parallel+Vector execution policy
 class parallel_unsequenced_policy
 {
-  public:
-    // For internal use only
-    static constexpr std::true_type
-    __allow_unsequenced()
-    {
-        return std::true_type{};
-    }
-    static constexpr std::true_type
-    __allow_vector()
-    {
-        return std::true_type{};
-    }
-    static constexpr std::true_type
-    __allow_parallel()
-    {
-        return std::true_type{};
-    }
 };
 
 class unsequenced_policy
 {
-  public:
-    // For internal use only
-    static constexpr std::true_type
-    __allow_unsequenced()
-    {
-        return std::true_type{};
-    }
-    static constexpr std::true_type
-    __allow_vector()
-    {
-        return std::true_type{};
-    }
-    static constexpr std::false_type
-    __allow_parallel()
-    {
-        return std::false_type{};
-    }
 };
 
 // 2.8, Execution policy objects
@@ -135,7 +67,7 @@ struct is_execution_policy<__pstl::execution::unsequenced_policy> : std::true_ty
 {
 };
 
-#if _PSTL_CPP14_VARIABLE_TEMPLATES_PRESENT
+#if defined (_PSTL_CPP14_VARIABLE_TEMPLATES_PRESENT)
 template <class _Tp>
 constexpr bool is_execution_policy_v = __pstl::execution::is_execution_policy<_Tp>::value;
 #endif
@@ -155,6 +87,12 @@ using __enable_if_execution_policy =
     typename std::enable_if<__pstl::execution::is_execution_policy<typename std::decay<_ExecPolicy>::type>::value,
                             _Tp>::type;
 #endif
+
+template <class _IsVector>
+struct __serial_tag;
+template <class _IsVector>
+struct __parallel_tag;
+
 } // namespace __internal
 
 } // namespace __pstl
diff --git a/libstdc++-v3/include/pstl/execution_impl.h b/libstdc++-v3/include/pstl/execution_impl.h
index e0969a1db9c..64f6cc4357a 100644
--- a/libstdc++-v3/include/pstl/execution_impl.h
+++ b/libstdc++-v3/include/pstl/execution_impl.h
@@ -20,141 +20,80 @@ namespace __pstl
 namespace __internal
 {
 
-using namespace __pstl::execution;
+template <typename _IteratorTag, typename... _IteratorTypes>
+using __are_iterators_of = std::conjunction<
+    std::is_base_of<_IteratorTag, typename std::iterator_traits<std::decay_t<_IteratorTypes>>::iterator_category>...>;
 
-/* predicate */
+template <typename... _IteratorTypes>
+using __are_random_access_iterators = __are_iterators_of<std::random_access_iterator_tag, _IteratorTypes...>;
 
-template <typename _Tp>
-std::false_type __lazy_and(_Tp, std::false_type)
+struct __serial_backend_tag
 {
-    return std::false_type{};
+};
+struct __tbb_backend_tag
+{
+};
+struct __openmp_backend_tag
+{
+};
+
+#if defined(_PSTL_PAR_BACKEND_TBB)
+using __par_backend_tag = __tbb_backend_tag;
+#elif defined(_PSTL_PAR_BACKEND_OPENMP)
+using __par_backend_tag = __openmp_backend_tag;
+#elif defined(_PSTL_PAR_BACKEND_SERIAL)
+using __par_backend_tag = __serial_backend_tag;
+#else
+#    error "A parallel backend must be specified";
+#endif
+
+template <class _IsVector>
+struct __serial_tag
+{
+    using __is_vector = _IsVector;
+};
+
+template <class _IsVector>
+struct __parallel_tag
+{
+    using __is_vector = _IsVector;
+    // backend tag can be change depending on
+    // TBB availability in the environment
+    using __backend_tag = __par_backend_tag;
+};
+
+template <class _IsVector, class... _IteratorTypes>
+using __tag_type = typename std::conditional<__internal::__are_random_access_iterators<_IteratorTypes...>::value,
+                                             __parallel_tag<_IsVector>, __serial_tag<_IsVector>>::type;
+
+template <class... _IteratorTypes>
+__serial_tag</*_IsVector = */ std::false_type>
+__select_backend(__pstl::execution::sequenced_policy, _IteratorTypes&&...)
+{
+    return {};
 }
 
-template <typename _Tp>
-inline _Tp
-__lazy_and(_Tp __a, std::true_type)
+template <class... _IteratorTypes>
+__serial_tag<__internal::__are_random_access_iterators<_IteratorTypes...>>
+__select_backend(__pstl::execution::unsequenced_policy, _IteratorTypes&&...)
 {
-    return __a;
+    return {};
 }
 
-template <typename _Tp>
-std::true_type __lazy_or(_Tp, std::true_type)
+template <class... _IteratorTypes>
+__tag_type</*_IsVector = */ std::false_type, _IteratorTypes...>
+__select_backend(__pstl::execution::parallel_policy, _IteratorTypes&&...)
 {
-    return std::true_type{};
+    return {};
 }
 
-template <typename _Tp>
-inline _Tp
-__lazy_or(_Tp __a, std::false_type)
+template <class... _IteratorTypes>
+__tag_type<__internal::__are_random_access_iterators<_IteratorTypes...>, _IteratorTypes...>
+__select_backend(__pstl::execution::parallel_unsequenced_policy, _IteratorTypes&&...)
 {
-    return __a;
+    return {};
 }
 
-/* iterator */
-template <typename _IteratorType, typename... _OtherIteratorTypes>
-struct __is_random_access_iterator
-{
-    static constexpr bool value = __internal::__is_random_access_iterator<_IteratorType>::value &&
-                                  __internal::__is_random_access_iterator<_OtherIteratorTypes...>::value;
-    typedef std::integral_constant<bool, value> type;
-};
-
-template <typename _IteratorType>
-struct __is_random_access_iterator<_IteratorType>
-    : std::is_same<typename std::iterator_traits<_IteratorType>::iterator_category, std::random_access_iterator_tag>
-{
-};
-
-/* policy */
-template <typename _Policy>
-struct __policy_traits
-{
-};
-
-template <>
-struct __policy_traits<sequenced_policy>
-{
-    typedef std::false_type allow_parallel;
-    typedef std::false_type allow_unsequenced;
-    typedef std::false_type allow_vector;
-};
-
-template <>
-struct __policy_traits<unsequenced_policy>
-{
-    typedef std::false_type allow_parallel;
-    typedef std::true_type allow_unsequenced;
-    typedef std::true_type allow_vector;
-};
-
-template <>
-struct __policy_traits<parallel_policy>
-{
-    typedef std::true_type allow_parallel;
-    typedef std::false_type allow_unsequenced;
-    typedef std::false_type allow_vector;
-};
-
-template <>
-struct __policy_traits<parallel_unsequenced_policy>
-{
-    typedef std::true_type allow_parallel;
-    typedef std::true_type allow_unsequenced;
-    typedef std::true_type allow_vector;
-};
-
-template <typename _ExecutionPolicy>
-using __collector_t =
-    typename __internal::__policy_traits<typename std::decay<_ExecutionPolicy>::type>::__collector_type;
-
-template <typename _ExecutionPolicy>
-using __allow_vector =
-    typename __internal::__policy_traits<typename std::decay<_ExecutionPolicy>::type>::__allow_vector;
-
-template <typename _ExecutionPolicy>
-using __allow_unsequenced =
-    typename __internal::__policy_traits<typename std::decay<_ExecutionPolicy>::type>::__allow_unsequenced;
-
-template <typename _ExecutionPolicy>
-using __allow_parallel =
-    typename __internal::__policy_traits<typename std::decay<_ExecutionPolicy>::type>::__allow_parallel;
-
-template <typename _ExecutionPolicy, typename... _IteratorTypes>
-auto
-__is_vectorization_preferred(_ExecutionPolicy&& __exec)
-    -> decltype(__internal::__lazy_and(__exec.__allow_vector(),
-                                       typename __internal::__is_random_access_iterator<_IteratorTypes...>::type()))
-{
-    return __internal::__lazy_and(__exec.__allow_vector(),
-                                  typename __internal::__is_random_access_iterator<_IteratorTypes...>::type());
-}
-
-template <typename _ExecutionPolicy, typename... _IteratorTypes>
-auto
-__is_parallelization_preferred(_ExecutionPolicy&& __exec)
-    -> decltype(__internal::__lazy_and(__exec.__allow_parallel(),
-                                       typename __internal::__is_random_access_iterator<_IteratorTypes...>::type()))
-{
-    return __internal::__lazy_and(__exec.__allow_parallel(),
-                                  typename __internal::__is_random_access_iterator<_IteratorTypes...>::type());
-}
-
-template <typename __policy, typename... _IteratorTypes>
-struct __prefer_unsequenced_tag
-{
-    static constexpr bool value = __internal::__allow_unsequenced<__policy>::value &&
-                                  __internal::__is_random_access_iterator<_IteratorTypes...>::value;
-    typedef std::integral_constant<bool, value> type;
-};
-
-template <typename __policy, typename... _IteratorTypes>
-struct __prefer_parallel_tag
-{
-    static constexpr bool value = __internal::__allow_parallel<__policy>::value &&
-                                  __internal::__is_random_access_iterator<_IteratorTypes...>::value;
-    typedef std::integral_constant<bool, value> type;
-};
-
 } // namespace __internal
 } // namespace __pstl
 
diff --git a/libstdc++-v3/include/pstl/glue_algorithm_impl.h b/libstdc++-v3/include/pstl/glue_algorithm_impl.h
index b16306f2e99..725df61c1d8 100644
--- a/libstdc++-v3/include/pstl/glue_algorithm_impl.h
+++ b/libstdc++-v3/include/pstl/glue_algorithm_impl.h
@@ -26,10 +26,10 @@ template <class _ExecutionPolicy, class _ForwardIterator, class _Predicate>
 __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, bool>
 any_of(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _Predicate __pred)
 {
-    return __pstl::__internal::__pattern_any_of(
-        std::forward<_ExecutionPolicy>(__exec), __first, __last, __pred,
-        __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec),
-        __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec));
+    auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first);
+
+    return __pstl::__internal::__pattern_any_of(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __last,
+                                                __pred);
 }
 
 // [alg.all_of]
@@ -56,20 +56,19 @@ template <class _ExecutionPolicy, class _ForwardIterator, class _Function>
 __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, void>
 for_each(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _Function __f)
 {
-    __pstl::__internal::__pattern_walk1(
-        std::forward<_ExecutionPolicy>(__exec), __first, __last, __f,
-        __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec),
-        __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec));
+    auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first);
+
+    __pstl::__internal::__pattern_walk1(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __last, __f);
 }
 
 template <class _ExecutionPolicy, class _ForwardIterator, class _Size, class _Function>
 __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator>
 for_each_n(_ExecutionPolicy&& __exec, _ForwardIterator __first, _Size __n, _Function __f)
 {
-    return __pstl::__internal::__pattern_walk1_n(
-        std::forward<_ExecutionPolicy>(__exec), __first, __n, __f,
-        __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec),
-        __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec));
+    auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first);
+
+    return __pstl::__internal::__pattern_walk1_n(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __n,
+                                                 __f);
 }
 
 // [alg.find]
@@ -78,10 +77,10 @@ template <class _ExecutionPolicy, class _ForwardIterator, class _Predicate>
 __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator>
 find_if(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _Predicate __pred)
 {
-    return __pstl::__internal::__pattern_find_if(
-        std::forward<_ExecutionPolicy>(__exec), __first, __last, __pred,
-        __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec),
-        __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec));
+    auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first);
+
+    return __pstl::__internal::__pattern_find_if(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first,
+                                                 __last, __pred);
 }
 
 template <class _ExecutionPolicy, class _ForwardIterator, class _Predicate>
@@ -105,12 +104,10 @@ __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardItera
 find_end(_ExecutionPolicy&& __exec, _ForwardIterator1 __first, _ForwardIterator1 __last, _ForwardIterator2 __s_first,
          _ForwardIterator2 __s_last, _BinaryPredicate __pred)
 {
-    return __pstl::__internal::__pattern_find_end(
-        std::forward<_ExecutionPolicy>(__exec), __first, __last, __s_first, __s_last, __pred,
-        __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator1, _ForwardIterator2>(
-            __exec),
-        __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator1, _ForwardIterator2>(
-            __exec));
+    auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first, __s_first);
+
+    return __pstl::__internal::__pattern_find_end(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first,
+                                                  __last, __s_first, __s_last, __pred);
 }
 
 template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2>
@@ -128,12 +125,10 @@ __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardItera
 find_first_of(_ExecutionPolicy&& __exec, _ForwardIterator1 __first, _ForwardIterator1 __last,
               _ForwardIterator2 __s_first, _ForwardIterator2 __s_last, _BinaryPredicate __pred)
 {
-    return __pstl::__internal::__pattern_find_first_of(
-        std::forward<_ExecutionPolicy>(__exec), __first, __last, __s_first, __s_last, __pred,
-        __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator1, _ForwardIterator2>(
-            __exec),
-        __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator1, _ForwardIterator2>(
-            __exec));
+    auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first, __s_first);
+
+    return __pstl::__internal::__pattern_find_first_of(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first,
+                                                       __last, __s_first, __s_last, __pred);
 }
 
 template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2>
@@ -150,23 +145,20 @@ template <class _ExecutionPolicy, class _ForwardIterator>
 __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator>
 adjacent_find(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last)
 {
+    auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first);
+
     typedef typename iterator_traits<_ForwardIterator>::value_type _ValueType;
-    return __pstl::__internal::__pattern_adjacent_find(
-        std::forward<_ExecutionPolicy>(__exec), __first, __last, std::equal_to<_ValueType>(),
-        __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec),
-        __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec),
-        /*first_semantic*/ false);
+    return __pstl::__internal::__pattern_adjacent_find(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first,
+                                                       __last, std::equal_to<_ValueType>(), /*first_semantic*/ false);
 }
 
 template <class _ExecutionPolicy, class _ForwardIterator, class _BinaryPredicate>
 __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator>
 adjacent_find(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _BinaryPredicate __pred)
 {
-    return __pstl::__internal::__pattern_adjacent_find(
-        std::forward<_ExecutionPolicy>(__exec), __first, __last, __pred,
-        __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec),
-        __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec),
-        /*first_semantic*/ false);
+    auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first);
+    return __pstl::__internal::__pattern_adjacent_find(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first,
+                                                       __last, __pred, /*first_semantic*/ false);
 }
 
 // [alg.count]
@@ -179,12 +171,11 @@ __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy,
                                                  typename iterator_traits<_ForwardIterator>::difference_type>
 count(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, const _Tp& __value)
 {
+    auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first);
+
     typedef typename iterator_traits<_ForwardIterator>::value_type _ValueType;
-    return __pstl::__internal::__pattern_count(
-        std::forward<_ExecutionPolicy>(__exec), __first, __last,
-        [&__value](const _ValueType& __x) { return __value == __x; },
-        __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec),
-        __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec));
+    return __pstl::__internal::__pattern_count(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __last,
+                                               [&__value](const _ValueType& __x) { return __value == __x; });
 }
 
 template <class _ExecutionPolicy, class _ForwardIterator, class _Predicate>
@@ -192,10 +183,9 @@ __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy,
                                                  typename iterator_traits<_ForwardIterator>::difference_type>
 count_if(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _Predicate __pred)
 {
-    return __pstl::__internal::__pattern_count(
-        std::forward<_ExecutionPolicy>(__exec), __first, __last, __pred,
-        __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec),
-        __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec));
+    auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first);
+    return __pstl::__internal::__pattern_count(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __last,
+                                               __pred);
 }
 
 // [alg.search]
@@ -205,12 +195,10 @@ __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardItera
 search(_ExecutionPolicy&& __exec, _ForwardIterator1 __first, _ForwardIterator1 __last, _ForwardIterator2 __s_first,
        _ForwardIterator2 __s_last, _BinaryPredicate __pred)
 {
-    return __pstl::__internal::__pattern_search(
-        std::forward<_ExecutionPolicy>(__exec), __first, __last, __s_first, __s_last, __pred,
-        __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator1, _ForwardIterator2>(
-            __exec),
-        __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator1, _ForwardIterator2>(
-            __exec));
+    auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first, __s_first);
+
+    return __pstl::__internal::__pattern_search(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __last,
+                                                __s_first, __s_last, __pred);
 }
 
 template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2>
@@ -226,10 +214,10 @@ __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardItera
 search_n(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _Size __count,
          const _Tp& __value, _BinaryPredicate __pred)
 {
-    return __pstl::__internal::__pattern_search_n(
-        std::forward<_ExecutionPolicy>(__exec), __first, __last, __count, __value, __pred,
-        __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec),
-        __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec));
+    auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first);
+
+    return __pstl::__internal::__pattern_search_n(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first,
+                                                  __last, __count, __value, __pred);
 }
 
 template <class _ExecutionPolicy, class _ForwardIterator, class _Size, class _Tp>
@@ -247,34 +235,28 @@ template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterato
 __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator2>
 copy(_ExecutionPolicy&& __exec, _ForwardIterator1 __first, _ForwardIterator1 __last, _ForwardIterator2 __result)
 {
-    const auto __is_vector =
-        __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator1, _ForwardIterator2>(
-            __exec);
+    auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first, __result);
+
+    using __is_vector = typename decltype(__dispatch_tag)::__is_vector;
 
     return __pstl::__internal::__pattern_walk2_brick(
-        std::forward<_ExecutionPolicy>(__exec), __first, __last, __result,
-        [__is_vector](_ForwardIterator1 __begin, _ForwardIterator1 __end, _ForwardIterator2 __res) {
-            return __pstl::__internal::__brick_copy(__begin, __end, __res, __is_vector);
-        },
-        __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator1, _ForwardIterator2>(
-            __exec));
+        __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __last, __result,
+        [](_ForwardIterator1 __begin, _ForwardIterator1 __end, _ForwardIterator2 __res)
+        { return __pstl::__internal::__brick_copy(__begin, __end, __res, __is_vector{}); });
 }
 
 template <class _ExecutionPolicy, class _ForwardIterator1, class _Size, class _ForwardIterator2>
 __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator2>
 copy_n(_ExecutionPolicy&& __exec, _ForwardIterator1 __first, _Size __n, _ForwardIterator2 __result)
 {
-    const auto __is_vector =
-        __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator1, _ForwardIterator2>(
-            __exec);
+    auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first, __result);
+
+    using __is_vector = typename decltype(__dispatch_tag)::__is_vector;
 
     return __pstl::__internal::__pattern_walk2_brick_n(
-        std::forward<_ExecutionPolicy>(__exec), __first, __n, __result,
-        [__is_vector](_ForwardIterator1 __begin, _Size __sz, _ForwardIterator2 __res) {
-            return __pstl::__internal::__brick_copy_n(__begin, __sz, __res, __is_vector);
-        },
-        __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator1, _ForwardIterator2>(
-            __exec));
+        __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __n, __result,
+        [](_ForwardIterator1 __begin, _Size __sz, _ForwardIterator2 __res)
+        { return __pstl::__internal::__brick_copy_n(__begin, __sz, __res, __is_vector{}); });
 }
 
 template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _Predicate>
@@ -282,12 +264,10 @@ __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardItera
 copy_if(_ExecutionPolicy&& __exec, _ForwardIterator1 __first, _ForwardIterator1 __last, _ForwardIterator2 __result,
         _Predicate __pred)
 {
-    return __pstl::__internal::__pattern_copy_if(
-        std::forward<_ExecutionPolicy>(__exec), __first, __last, __result, __pred,
-        __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator1, _ForwardIterator2>(
-            __exec),
-        __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator1, _ForwardIterator2>(
-            __exec));
+    auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first, __result);
+
+    return __pstl::__internal::__pattern_copy_if(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first,
+                                                 __last, __result, __pred);
 }
 
 // [alg.swap]
@@ -299,16 +279,16 @@ swap_ranges(_ExecutionPolicy&& __exec, _ForwardIterator1 __first1, _ForwardItera
 {
     typedef typename iterator_traits<_ForwardIterator1>::reference _ReferenceType1;
     typedef typename iterator_traits<_ForwardIterator2>::reference _ReferenceType2;
-    return __pstl::__internal::__pattern_walk2(
-        std::forward<_ExecutionPolicy>(__exec), __first1, __last1, __first2,
-        [](_ReferenceType1 __x, _ReferenceType2 __y) {
-            using std::swap;
-            swap(__x, __y);
-        },
-        __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator1, _ForwardIterator2>(
-            __exec),
-        __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator1, _ForwardIterator2>(
-            __exec));
+
+    auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first1, __first2);
+
+    return __pstl::__internal::__pattern_walk2(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first1,
+                                               __last1, __first2,
+                                               [](_ReferenceType1 __x, _ReferenceType2 __y)
+                                               {
+                                                   using std::swap;
+                                                   swap(__x, __y);
+                                               });
 }
 
 // [alg.transform]
@@ -320,13 +300,12 @@ transform(_ExecutionPolicy&& __exec, _ForwardIterator1 __first, _ForwardIterator
 {
     typedef typename iterator_traits<_ForwardIterator1>::reference _InputType;
     typedef typename iterator_traits<_ForwardIterator2>::reference _OutputType;
-    return __pstl::__internal::__pattern_walk2(
-        std::forward<_ExecutionPolicy>(__exec), __first, __last, __result,
-        [__op](_InputType __x, _OutputType __y) mutable { __y = __op(__x); },
-        __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator1, _ForwardIterator2>(
-            __exec),
-        __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator1, _ForwardIterator2>(
-            __exec));
+
+    auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first, __result);
+
+    return __pstl::__internal::__pattern_walk2(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __last,
+                                               __result,
+                                               [__op](_InputType __x, _OutputType __y) mutable { __y = __op(__x); });
 }
 
 template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _ForwardIterator,
@@ -338,13 +317,12 @@ transform(_ExecutionPolicy&& __exec, _ForwardIterator1 __first1, _ForwardIterato
     typedef typename iterator_traits<_ForwardIterator1>::reference _Input1Type;
     typedef typename iterator_traits<_ForwardIterator2>::reference _Input2Type;
     typedef typename iterator_traits<_ForwardIterator>::reference _OutputType;
+
+    auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first1, __first2, __result);
+
     return __pstl::__internal::__pattern_walk3(
-        std::forward<_ExecutionPolicy>(__exec), __first1, __last1, __first2, __result,
-        [__op](_Input1Type __x, _Input2Type __y, _OutputType __z) mutable { __z = __op(__x, __y); },
-        __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator1, _ForwardIterator2,
-                                                         _ForwardIterator>(__exec),
-        __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator1, _ForwardIterator2,
-                                                           _ForwardIterator>(__exec));
+        __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first1, __last1, __first2, __result,
+        [__op](_Input1Type x, _Input2Type y, _OutputType z) mutable { z = __op(x, y); });
 }
 
 // [alg.replace]
@@ -355,16 +333,17 @@ replace_if(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator
            const _Tp& __new_value)
 {
     typedef typename iterator_traits<_ForwardIterator>::reference _ElementType;
-    __pstl::__internal::__pattern_walk1(
-        std::forward<_ExecutionPolicy>(__exec), __first, __last,
-        [&__pred, &__new_value](_ElementType __elem) {
-            if (__pred(__elem))
-            {
-                __elem = __new_value;
-            }
-        },
-        __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec),
-        __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec));
+
+    auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first);
+
+    __pstl::__internal::__pattern_walk1(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __last,
+                                        [&__pred, &__new_value](_ElementType __elem)
+                                        {
+                                            if (__pred(__elem))
+                                            {
+                                                __elem = __new_value;
+                                            }
+                                        });
 }
 
 template <class _ExecutionPolicy, class _ForwardIterator, class _Tp>
@@ -383,13 +362,12 @@ replace_copy_if(_ExecutionPolicy&& __exec, _ForwardIterator1 __first, _ForwardIt
 {
     typedef typename iterator_traits<_ForwardIterator1>::reference _InputType;
     typedef typename iterator_traits<_ForwardIterator2>::reference _OutputType;
+
+    auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first, __result);
+
     return __pstl::__internal::__pattern_walk2(
-        std::forward<_ExecutionPolicy>(__exec), __first, __last, __result,
-        [__pred, &__new_value](_InputType __x, _OutputType __y) mutable { __y = __pred(__x) ? __new_value : __x; },
-        __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator1, _ForwardIterator2>(
-            __exec),
-        __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator1, _ForwardIterator2>(
-            __exec));
+        __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __last, __result,
+        [__pred, &__new_value](_InputType __x, _OutputType __y) mutable { __y = __pred(__x) ? __new_value : __x; });
 }
 
 template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _Tp>
@@ -407,10 +385,10 @@ template <class _ExecutionPolicy, class _ForwardIterator, class _Tp>
 __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, void>
 fill(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, const _Tp& __value)
 {
-    __pstl::__internal::__pattern_fill(
-        std::forward<_ExecutionPolicy>(__exec), __first, __last, __value,
-        __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec),
-        __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec));
+    auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first);
+
+    __pstl::__internal::__pattern_fill(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __last,
+                                       __value);
 }
 
 template <class _ExecutionPolicy, class _ForwardIterator, class _Size, class _Tp>
@@ -420,10 +398,10 @@ fill_n(_ExecutionPolicy&& __exec, _ForwardIterator __first, _Size __count, const
     if (__count <= 0)
         return __first;
 
-    return __pstl::__internal::__pattern_fill_n(
-        std::forward<_ExecutionPolicy>(__exec), __first, __count, __value,
-        __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec),
-        __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec));
+    auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first);
+
+    return __pstl::__internal::__pattern_fill_n(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first,
+                                                __count, __value);
 }
 
 // [alg.generate]
@@ -431,10 +409,10 @@ template <class _ExecutionPolicy, class _ForwardIterator, class _Generator>
 __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, void>
 generate(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _Generator __g)
 {
-    __pstl::__internal::__pattern_generate(
-        std::forward<_ExecutionPolicy>(__exec), __first, __last, __g,
-        __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec),
-        __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec));
+    auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first);
+
+    __pstl::__internal::__pattern_generate(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __last,
+                                           __g);
 }
 
 template <class _ExecutionPolicy, class _ForwardIterator, class _Size, class _Generator>
@@ -444,10 +422,10 @@ generate_n(_ExecutionPolicy&& __exec, _ForwardIterator __first, _Size __count, _
     if (__count <= 0)
         return __first;
 
-    return __pstl::__internal::__pattern_generate_n(
-        std::forward<_ExecutionPolicy>(__exec), __first, __count, __g,
-        __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec),
-        __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec));
+    auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first);
+
+    return __pstl::__internal::__pattern_generate_n(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first,
+                                                    __count, __g);
 }
 
 // [alg.remove]
@@ -473,10 +451,10 @@ template <class _ExecutionPolicy, class _ForwardIterator, class _UnaryPredicate>
 __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator>
 remove_if(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _UnaryPredicate __pred)
 {
-    return __pstl::__internal::__pattern_remove_if(
-        std::forward<_ExecutionPolicy>(__exec), __first, __last, __pred,
-        __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec),
-        __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec));
+    auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first);
+
+    return __pstl::__internal::__pattern_remove_if(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first,
+                                                   __last, __pred);
 }
 
 template <class _ExecutionPolicy, class _ForwardIterator, class _Tp>
@@ -493,10 +471,10 @@ template <class _ExecutionPolicy, class _ForwardIterator, class _BinaryPredicate
 __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator>
 unique(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _BinaryPredicate __pred)
 {
-    return __pstl::__internal::__pattern_unique(
-        std::forward<_ExecutionPolicy>(__exec), __first, __last, __pred,
-        __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec),
-        __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec));
+    auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first);
+
+    return __pstl::__internal::__pattern_unique(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __last,
+                                                __pred);
 }
 
 template <class _ExecutionPolicy, class _ForwardIterator>
@@ -511,12 +489,10 @@ __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardItera
 unique_copy(_ExecutionPolicy&& __exec, _ForwardIterator1 __first, _ForwardIterator1 __last, _ForwardIterator2 __result,
             _BinaryPredicate __pred)
 {
-    return __pstl::__internal::__pattern_unique_copy(
-        std::forward<_ExecutionPolicy>(__exec), __first, __last, __result, __pred,
-        __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator1, _ForwardIterator2>(
-            __exec),
-        __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator1, _ForwardIterator2>(
-            __exec));
+    auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first, __result);
+
+    return __pstl::__internal::__pattern_unique_copy(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first,
+                                                     __last, __result, __pred);
 }
 
 template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2>
@@ -532,10 +508,9 @@ template <class _ExecutionPolicy, class _BidirectionalIterator>
 __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, void>
 reverse(_ExecutionPolicy&& __exec, _BidirectionalIterator __first, _BidirectionalIterator __last)
 {
-    __pstl::__internal::__pattern_reverse(
-        std::forward<_ExecutionPolicy>(__exec), __first, __last,
-        __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _BidirectionalIterator>(__exec),
-        __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _BidirectionalIterator>(__exec));
+    auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first);
+
+    __pstl::__internal::__pattern_reverse(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __last);
 }
 
 template <class _ExecutionPolicy, class _BidirectionalIterator, class _ForwardIterator>
@@ -543,12 +518,10 @@ __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardItera
 reverse_copy(_ExecutionPolicy&& __exec, _BidirectionalIterator __first, _BidirectionalIterator __last,
              _ForwardIterator __d_first)
 {
-    return __pstl::__internal::__pattern_reverse_copy(
-        std::forward<_ExecutionPolicy>(__exec), __first, __last, __d_first,
-        __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _BidirectionalIterator, _ForwardIterator>(
-            __exec),
-        __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _BidirectionalIterator, _ForwardIterator>(
-            __exec));
+    auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first, __d_first);
+
+    return __pstl::__internal::__pattern_reverse_copy(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first,
+                                                      __last, __d_first);
 }
 
 // [alg.rotate]
@@ -557,10 +530,10 @@ template <class _ExecutionPolicy, class _ForwardIterator>
 __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator>
 rotate(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __middle, _ForwardIterator __last)
 {
-    return __pstl::__internal::__pattern_rotate(
-        std::forward<_ExecutionPolicy>(__exec), __first, __middle, __last,
-        __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec),
-        __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec));
+    auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first);
+
+    return __pstl::__internal::__pattern_rotate(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first,
+                                                __middle, __last);
 }
 
 template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2>
@@ -568,12 +541,10 @@ __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardItera
 rotate_copy(_ExecutionPolicy&& __exec, _ForwardIterator1 __first, _ForwardIterator1 __middle, _ForwardIterator1 __last,
             _ForwardIterator2 __result)
 {
-    return __pstl::__internal::__pattern_rotate_copy(
-        std::forward<_ExecutionPolicy>(__exec), __first, __middle, __last, __result,
-        __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator1, _ForwardIterator2>(
-            __exec),
-        __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator1, _ForwardIterator2>(
-            __exec));
+    auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first, __result);
+
+    return __pstl::__internal::__pattern_rotate_copy(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first,
+                                                     __middle, __last, __result);
 }
 
 // [alg.partitions]
@@ -582,20 +553,19 @@ template <class _ExecutionPolicy, class _ForwardIterator, class _UnaryPredicate>
 __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, bool>
 is_partitioned(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _UnaryPredicate __pred)
 {
-    return __pstl::__internal::__pattern_is_partitioned(
-        std::forward<_ExecutionPolicy>(__exec), __first, __last, __pred,
-        __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec),
-        __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec));
+    auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first);
+    return __pstl::__internal::__pattern_is_partitioned(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first,
+                                                        __last, __pred);
 }
 
 template <class _ExecutionPolicy, class _ForwardIterator, class _UnaryPredicate>
 __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator>
 partition(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _UnaryPredicate __pred)
 {
-    return __pstl::__internal::__pattern_partition(
-        std::forward<_ExecutionPolicy>(__exec), __first, __last, __pred,
-        __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec),
-        __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec));
+    auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first);
+
+    return __pstl::__internal::__pattern_partition(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first,
+                                                   __last, __pred);
 }
 
 template <class _ExecutionPolicy, class _BidirectionalIterator, class _UnaryPredicate>
@@ -603,10 +573,9 @@ __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _Bidirectiona
 stable_partition(_ExecutionPolicy&& __exec, _BidirectionalIterator __first, _BidirectionalIterator __last,
                  _UnaryPredicate __pred)
 {
-    return __pstl::__internal::__pattern_stable_partition(
-        std::forward<_ExecutionPolicy>(__exec), __first, __last, __pred,
-        __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _BidirectionalIterator>(__exec),
-        __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _BidirectionalIterator>(__exec));
+    auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first);
+    return __pstl::__internal::__pattern_stable_partition(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec),
+                                                          __first, __last, __pred);
 }
 
 template <class _ExecutionPolicy, class _ForwardIterator, class _ForwardIterator1, class _ForwardIterator2,
@@ -615,12 +584,10 @@ __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, std::pair<_Fo
 partition_copy(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last,
                _ForwardIterator1 __out_true, _ForwardIterator2 __out_false, _UnaryPredicate __pred)
 {
-    return __pstl::__internal::__pattern_partition_copy(
-        std::forward<_ExecutionPolicy>(__exec), __first, __last, __out_true, __out_false, __pred,
-        __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator, _ForwardIterator1,
-                                                         _ForwardIterator2>(__exec),
-        __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator, _ForwardIterator1,
-                                                           _ForwardIterator2>(__exec));
+    auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first, __out_true, __out_false);
+
+    return __pstl::__internal::__pattern_partition_copy(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first,
+                                                        __last, __out_true, __out_false, __pred);
 }
 
 // [alg.sort]
@@ -629,12 +596,11 @@ template <class _ExecutionPolicy, class _RandomAccessIterator, class _Compare>
 __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, void>
 sort(_ExecutionPolicy&& __exec, _RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp)
 {
+    auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first);
+
     typedef typename iterator_traits<_RandomAccessIterator>::value_type _InputType;
-    return __pstl::__internal::__pattern_sort(
-        std::forward<_ExecutionPolicy>(__exec), __first, __last, __comp,
-        __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _RandomAccessIterator>(__exec),
-        __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _RandomAccessIterator>(__exec),
-        typename std::is_move_constructible<_InputType>::type());
+    return __pstl::__internal::__pattern_sort(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __last,
+                                              __comp, typename std::is_move_constructible<_InputType>::type());
 }
 
 template <class _ExecutionPolicy, class _RandomAccessIterator>
@@ -651,10 +617,10 @@ template <class _ExecutionPolicy, class _RandomAccessIterator, class _Compare>
 __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, void>
 stable_sort(_ExecutionPolicy&& __exec, _RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp)
 {
-    return __pstl::__internal::__pattern_stable_sort(
-        std::forward<_ExecutionPolicy>(__exec), __first, __last, __comp,
-        __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _RandomAccessIterator>(__exec),
-        __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _RandomAccessIterator>(__exec));
+    auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first);
+
+    return __pstl::__internal::__pattern_stable_sort(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first,
+                                                     __last, __comp);
 }
 
 template <class _ExecutionPolicy, class _RandomAccessIterator>
@@ -672,12 +638,10 @@ __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, std::pair<_Fo
 mismatch(_ExecutionPolicy&& __exec, _ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2,
          _ForwardIterator2 __last2, _BinaryPredicate __pred)
 {
-    return __pstl::__internal::__pattern_mismatch(
-        std::forward<_ExecutionPolicy>(__exec), __first1, __last1, __first2, __last2, __pred,
-        __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator1, _ForwardIterator2>(
-            __exec),
-        __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator1, _ForwardIterator2>(
-            __exec));
+    auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first1, __first2);
+
+    return __pstl::__internal::__pattern_mismatch(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first1,
+                                                  __last1, __first2, __last2, __pred);
 }
 
 template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate>
@@ -714,10 +678,10 @@ __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, bool>
 equal(_ExecutionPolicy&& __exec, _ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2,
       _BinaryPredicate __p)
 {
-    return __pstl::__internal::__pattern_equal(
-        std::forward<_ExecutionPolicy>(__exec), __first1, __last1, __first2, __p,
-        __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator1>(__exec),
-        __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator1>(__exec));
+    auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first1, __first2);
+
+    return __pstl::__internal::__pattern_equal(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first1,
+                                               __last1, __first2, __p);
 }
 
 template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2>
@@ -732,10 +696,10 @@ __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, bool>
 equal(_ExecutionPolicy&& __exec, _ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2,
       _ForwardIterator2 __last2, _BinaryPredicate __p)
 {
-    return __pstl::__internal::__pattern_equal(
-        std::forward<_ExecutionPolicy>(__exec), __first1, __last1, __first2, __last2, __p,
-        __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator1>(__exec),
-        __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator1>(__exec));
+    auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first1, __first2);
+
+    return __pstl::__internal::__pattern_equal(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first1,
+                                               __last1, __first2, __last2, __p);
 }
 
 template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2>
@@ -751,17 +715,14 @@ template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterato
 __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator2>
 move(_ExecutionPolicy&& __exec, _ForwardIterator1 __first, _ForwardIterator1 __last, _ForwardIterator2 __d_first)
 {
-    const auto __is_vector =
-        __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator1, _ForwardIterator2>(
-            __exec);
+    auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first, __d_first);
+
+    using __is_vector = typename decltype(__dispatch_tag)::__is_vector;
 
     return __pstl::__internal::__pattern_walk2_brick(
-        std::forward<_ExecutionPolicy>(__exec), __first, __last, __d_first,
-        [__is_vector](_ForwardIterator1 __begin, _ForwardIterator1 __end, _ForwardIterator2 __res) {
-            return __pstl::__internal::__brick_move(__begin, __end, __res, __is_vector);
-        },
-        __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator1, _ForwardIterator2>(
-            __exec));
+        __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __last, __d_first,
+        [](_ForwardIterator1 __begin, _ForwardIterator1 __end, _ForwardIterator2 __res)
+        { return __pstl::__internal::__brick_move(__begin, __end, __res, __is_vector{}); });
 }
 
 // [partial.sort]
@@ -771,10 +732,10 @@ __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, void>
 partial_sort(_ExecutionPolicy&& __exec, _RandomAccessIterator __first, _RandomAccessIterator __middle,
              _RandomAccessIterator __last, _Compare __comp)
 {
-    __pstl::__internal::__pattern_partial_sort(
-        std::forward<_ExecutionPolicy>(__exec), __first, __middle, __last, __comp,
-        __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _RandomAccessIterator>(__exec),
-        __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _RandomAccessIterator>(__exec));
+    auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first);
+
+    __pstl::__internal::__pattern_partial_sort(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first,
+                                               __middle, __last, __comp);
 }
 
 template <class _ExecutionPolicy, class _RandomAccessIterator>
@@ -793,12 +754,10 @@ __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _RandomAccess
 partial_sort_copy(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last,
                   _RandomAccessIterator __d_first, _RandomAccessIterator __d_last, _Compare __comp)
 {
-    return __pstl::__internal::__pattern_partial_sort_copy(
-        std::forward<_ExecutionPolicy>(__exec), __first, __last, __d_first, __d_last, __comp,
-        __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator, _RandomAccessIterator>(
-            __exec),
-        __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator, _RandomAccessIterator>(
-            __exec));
+    auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first, __d_first);
+
+    return __pstl::__internal::__pattern_partial_sort_copy(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec),
+                                                           __first, __last, __d_first, __d_last, __comp);
 }
 
 template <class _ExecutionPolicy, class _ForwardIterator, class _RandomAccessIterator>
@@ -815,11 +774,11 @@ template <class _ExecutionPolicy, class _ForwardIterator, class _Compare>
 __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator>
 is_sorted_until(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _Compare __comp)
 {
-    const _ForwardIterator __res = __pstl::__internal::__pattern_adjacent_find(
-        std::forward<_ExecutionPolicy>(__exec), __first, __last, __pstl::__internal::__reorder_pred<_Compare>(__comp),
-        __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec),
-        __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec),
-        /*first_semantic*/ false);
+    auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first);
+    const _ForwardIterator __res =
+        __pstl::__internal::__pattern_adjacent_find(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first,
+                                                    __last, __pstl::__internal::__reorder_pred<_Compare>(__comp),
+                                                    /*first_semantic*/ false);
     return __res == __last ? __last : std::next(__res);
 }
 
@@ -835,12 +794,10 @@ template <class _ExecutionPolicy, class _ForwardIterator, class _Compare>
 __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, bool>
 is_sorted(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _Compare __comp)
 {
-    return __pstl::__internal::__pattern_adjacent_find(
-               std::forward<_ExecutionPolicy>(__exec), __first, __last,
-               __pstl::__internal::__reorder_pred<_Compare>(__comp),
-               __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec),
-               __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec),
-               /*or_semantic*/ true) == __last;
+    auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first);
+    return __pstl::__internal::__pattern_adjacent_find(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first,
+                                                       __last, __pstl::__internal::__reorder_pred<_Compare>(__comp),
+                                                       /*or_semantic*/ true) == __last;
 }
 
 template <class _ExecutionPolicy, class _ForwardIterator>
@@ -858,12 +815,10 @@ __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardItera
 merge(_ExecutionPolicy&& __exec, _ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2,
       _ForwardIterator2 __last2, _ForwardIterator __d_first, _Compare __comp)
 {
-    return __pstl::__internal::__pattern_merge(
-        std::forward<_ExecutionPolicy>(__exec), __first1, __last1, __first2, __last2, __d_first, __comp,
-        __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator1, _ForwardIterator2,
-                                                         _ForwardIterator>(__exec),
-        __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator1, _ForwardIterator2,
-                                                           _ForwardIterator>(__exec));
+    auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first1, __first2, __d_first);
+
+    return __pstl::__internal::__pattern_merge(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first1,
+                                               __last1, __first2, __last2, __d_first, __comp);
 }
 
 template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _ForwardIterator>
@@ -880,10 +835,10 @@ __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, void>
 inplace_merge(_ExecutionPolicy&& __exec, _BidirectionalIterator __first, _BidirectionalIterator __middle,
               _BidirectionalIterator __last, _Compare __comp)
 {
-    __pstl::__internal::__pattern_inplace_merge(
-        std::forward<_ExecutionPolicy>(__exec), __first, __middle, __last, __comp,
-        __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _BidirectionalIterator>(__exec),
-        __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _BidirectionalIterator>(__exec));
+    auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first);
+
+    __pstl::__internal::__pattern_inplace_merge(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first,
+                                                __middle, __last, __comp);
 }
 
 template <class _ExecutionPolicy, class _BidirectionalIterator>
@@ -902,12 +857,10 @@ __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, bool>
 includes(_ExecutionPolicy&& __exec, _ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2,
          _ForwardIterator2 __last2, _Compare __comp)
 {
-    return __pstl::__internal::__pattern_includes(
-        std::forward<_ExecutionPolicy>(__exec), __first1, __last1, __first2, __last2, __comp,
-        __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator1, _ForwardIterator2>(
-            __exec),
-        __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator1, _ForwardIterator2>(
-            __exec));
+    auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first1, __first2);
+
+    return __pstl::__internal::__pattern_includes(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first1,
+                                                  __last1, __first2, __last2, __comp);
 }
 
 template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2>
@@ -926,12 +879,10 @@ __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardItera
 set_union(_ExecutionPolicy&& __exec, _ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2,
           _ForwardIterator2 __last2, _ForwardIterator __result, _Compare __comp)
 {
-    return __pstl::__internal::__pattern_set_union(
-        std::forward<_ExecutionPolicy>(__exec), __first1, __last1, __first2, __last2, __result, __comp,
-        __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator1, _ForwardIterator2,
-                                                         _ForwardIterator>(__exec),
-        __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator1, _ForwardIterator2,
-                                                           _ForwardIterator>(__exec));
+    auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first1, __first2, __result);
+
+    return __pstl::__internal::__pattern_set_union(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first1,
+                                                   __last1, __first2, __last2, __result, __comp);
 }
 
 template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _ForwardIterator>
@@ -951,12 +902,10 @@ __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardItera
 set_intersection(_ExecutionPolicy&& __exec, _ForwardIterator1 __first1, _ForwardIterator1 __last1,
                  _ForwardIterator2 __first2, _ForwardIterator2 __last2, _ForwardIterator __result, _Compare __comp)
 {
-    return __pstl::__internal::__pattern_set_intersection(
-        std::forward<_ExecutionPolicy>(__exec), __first1, __last1, __first2, __last2, __result, __comp,
-        __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator1, _ForwardIterator2,
-                                                         _ForwardIterator>(__exec),
-        __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator1, _ForwardIterator2,
-                                                           _ForwardIterator>(__exec));
+    auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first1, __first2, __result);
+
+    return __pstl::__internal::__pattern_set_intersection(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec),
+                                                          __first1, __last1, __first2, __last2, __result, __comp);
 }
 
 template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _ForwardIterator>
@@ -976,12 +925,10 @@ __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardItera
 set_difference(_ExecutionPolicy&& __exec, _ForwardIterator1 __first1, _ForwardIterator1 __last1,
                _ForwardIterator2 __first2, _ForwardIterator2 __last2, _ForwardIterator __result, _Compare __comp)
 {
-    return __pstl::__internal::__pattern_set_difference(
-        std::forward<_ExecutionPolicy>(__exec), __first1, __last1, __first2, __last2, __result, __comp,
-        __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator1, _ForwardIterator2,
-                                                         _ForwardIterator>(__exec),
-        __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator1, _ForwardIterator2,
-                                                           _ForwardIterator>(__exec));
+    auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first1, __first2, __result);
+
+    return __pstl::__internal::__pattern_set_difference(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec),
+                                                        __first1, __last1, __first2, __last2, __result, __comp);
 }
 
 template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _ForwardIterator>
@@ -1002,12 +949,10 @@ set_symmetric_difference(_ExecutionPolicy&& __exec, _ForwardIterator1 __first1,
                          _ForwardIterator2 __first2, _ForwardIterator2 __last2, _ForwardIterator __result,
                          _Compare __comp)
 {
+    auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first1, __first2, __result);
+
     return __pstl::__internal::__pattern_set_symmetric_difference(
-        std::forward<_ExecutionPolicy>(__exec), __first1, __last1, __first2, __last2, __result, __comp,
-        __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator1, _ForwardIterator2,
-                                                         _ForwardIterator>(__exec),
-        __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator1, _ForwardIterator2,
-                                                           _ForwardIterator>(__exec));
+        __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first1, __last1, __first2, __last2, __result, __comp);
 }
 
 template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _ForwardIterator>
@@ -1024,10 +969,10 @@ template <class _ExecutionPolicy, class _RandomAccessIterator, class _Compare>
 __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _RandomAccessIterator>
 is_heap_until(_ExecutionPolicy&& __exec, _RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp)
 {
-    return __pstl::__internal::__pattern_is_heap_until(
-        std::forward<_ExecutionPolicy>(__exec), __first, __last, __comp,
-        __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _RandomAccessIterator>(__exec),
-        __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _RandomAccessIterator>(__exec));
+    auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first);
+
+    return __pstl::__internal::__pattern_is_heap_until(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first,
+                                                       __last, __comp);
 }
 
 template <class _ExecutionPolicy, class _RandomAccessIterator>
@@ -1059,10 +1004,9 @@ template <class _ExecutionPolicy, class _ForwardIterator, class _Compare>
 __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator>
 min_element(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _Compare __comp)
 {
-    return __pstl::__internal::__pattern_min_element(
-        std::forward<_ExecutionPolicy>(__exec), __first, __last, __comp,
-        __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec),
-        __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec));
+    auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first);
+    return __pstl::__internal::__pattern_min_element(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first,
+                                                     __last, __comp);
 }
 
 template <class _ExecutionPolicy, class _ForwardIterator>
@@ -1094,10 +1038,9 @@ template <class _ExecutionPolicy, class _ForwardIterator, class _Compare>
 __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, std::pair<_ForwardIterator, _ForwardIterator>>
 minmax_element(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _Compare __comp)
 {
-    return __pstl::__internal::__pattern_minmax_element(
-        std::forward<_ExecutionPolicy>(__exec), __first, __last, __comp,
-        __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec),
-        __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec));
+    auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first);
+    return __pstl::__internal::__pattern_minmax_element(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first,
+                                                        __last, __comp);
 }
 
 template <class _ExecutionPolicy, class _ForwardIterator>
@@ -1115,10 +1058,10 @@ __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, void>
 nth_element(_ExecutionPolicy&& __exec, _RandomAccessIterator __first, _RandomAccessIterator __nth,
             _RandomAccessIterator __last, _Compare __comp)
 {
-    __pstl::__internal::__pattern_nth_element(
-        std::forward<_ExecutionPolicy>(__exec), __first, __nth, __last, __comp,
-        __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _RandomAccessIterator>(__exec),
-        __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _RandomAccessIterator>(__exec));
+    auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first);
+
+    __pstl::__internal::__pattern_nth_element(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __nth,
+                                              __last, __comp);
 }
 
 template <class _ExecutionPolicy, class _RandomAccessIterator>
@@ -1137,12 +1080,10 @@ __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, bool>
 lexicographical_compare(_ExecutionPolicy&& __exec, _ForwardIterator1 __first1, _ForwardIterator1 __last1,
                         _ForwardIterator2 __first2, _ForwardIterator2 __last2, _Compare __comp)
 {
-    return __pstl::__internal::__pattern_lexicographical_compare(
-        std::forward<_ExecutionPolicy>(__exec), __first1, __last1, __first2, __last2, __comp,
-        __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator1, _ForwardIterator2>(
-            __exec),
-        __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator1, _ForwardIterator2>(
-            __exec));
+    auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first1, __first2);
+
+    return __pstl::__internal::__pattern_lexicographical_compare(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec),
+                                                                 __first1, __last1, __first2, __last2, __comp);
 }
 
 template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2>
diff --git a/libstdc++-v3/include/pstl/glue_execution_defs.h b/libstdc++-v3/include/pstl/glue_execution_defs.h
index 24ede331ac1..57413cb6f27 100644
--- a/libstdc++-v3/include/pstl/glue_execution_defs.h
+++ b/libstdc++-v3/include/pstl/glue_execution_defs.h
@@ -18,8 +18,8 @@ namespace std
 {
 // Type trait
 using __pstl::execution::is_execution_policy;
-#if _PSTL_CPP14_VARIABLE_TEMPLATES_PRESENT
-#    if __INTEL_COMPILER
+#if defined(_PSTL_CPP14_VARIABLE_TEMPLATES_PRESENT)
+#    if defined(__INTEL_COMPILER)
 template <class T>
 constexpr bool is_execution_policy_v = is_execution_policy<T>::value;
 #    else
diff --git a/libstdc++-v3/include/pstl/glue_memory_impl.h b/libstdc++-v3/include/pstl/glue_memory_impl.h
index ea462e9ccdd..7850605f94a 100644
--- a/libstdc++-v3/include/pstl/glue_memory_impl.h
+++ b/libstdc++-v3/include/pstl/glue_memory_impl.h
@@ -13,6 +13,8 @@
 #include "utils.h"
 #include "algorithm_fwd.h"
 
+#include "execution_impl.h"
+
 namespace std
 {
 
@@ -27,28 +29,25 @@ uninitialized_copy(_ExecutionPolicy&& __exec, _InputIterator __first, _InputIter
     typedef typename iterator_traits<_InputIterator>::reference _ReferenceType1;
     typedef typename iterator_traits<_ForwardIterator>::reference _ReferenceType2;
 
-    const auto __is_parallel =
-        __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _InputIterator, _ForwardIterator>(__exec);
-    const auto __is_vector =
-        __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _InputIterator, _ForwardIterator>(__exec);
+    auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first, __result);
+
+    using __is_vector = typename decltype(__dispatch_tag)::__is_vector;
 
     return __pstl::__internal::__invoke_if_else(
         std::integral_constant < bool, std::is_trivial<_ValueType1>::value&& std::is_trivial<_ValueType2>::value > (),
-        [&]() {
+        [&]()
+        {
             return __pstl::__internal::__pattern_walk2_brick(
-                std::forward<_ExecutionPolicy>(__exec), __first, __last, __result,
-                [__is_vector](_InputIterator __begin, _InputIterator __end, _ForwardIterator __res) {
-                    return __pstl::__internal::__brick_copy(__begin, __end, __res, __is_vector);
-                },
-                __is_parallel);
+                __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __last, __result,
+                [](_InputIterator __begin, _InputIterator __end, _ForwardIterator __res)
+                { return __pstl::__internal::__brick_copy(__begin, __end, __res, __is_vector{}); });
         },
-        [&]() {
-            return __pstl::__internal::__pattern_walk2(std::forward<_ExecutionPolicy>(__exec), __first, __last,
-                                                       __result,
-                                                       [](_ReferenceType1 __val1, _ReferenceType2 __val2) {
-                                                           ::new (std::addressof(__val2)) _ValueType2(__val1);
-                                                       },
-                                                       __is_vector, __is_parallel);
+        [&]()
+        {
+            return __pstl::__internal::__pattern_walk2(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first,
+                                                       __last, __result,
+                                                       [](_ReferenceType1 __val1, _ReferenceType2 __val2)
+                                                       { ::new (std::addressof(__val2)) _ValueType2(__val1); });
         });
 }
 
@@ -61,27 +60,25 @@ uninitialized_copy_n(_ExecutionPolicy&& __exec, _InputIterator __first, _Size __
     typedef typename iterator_traits<_InputIterator>::reference _ReferenceType1;
     typedef typename iterator_traits<_ForwardIterator>::reference _ReferenceType2;
 
-    const auto __is_parallel =
-        __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _InputIterator, _ForwardIterator>(__exec);
-    const auto __is_vector =
-        __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _InputIterator, _ForwardIterator>(__exec);
+    auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first, __result);
+
+    using __is_vector = typename decltype(__dispatch_tag)::__is_vector;
 
     return __pstl::__internal::__invoke_if_else(
         std::integral_constant < bool, std::is_trivial<_ValueType1>::value&& std::is_trivial<_ValueType2>::value > (),
-        [&]() {
+        [&]()
+        {
             return __pstl::__internal::__pattern_walk2_brick_n(
-                std::forward<_ExecutionPolicy>(__exec), __first, __n, __result,
-                [__is_vector](_InputIterator __begin, _Size __sz, _ForwardIterator __res) {
-                    return __pstl::__internal::__brick_copy_n(__begin, __sz, __res, __is_vector);
-                },
-                __is_parallel);
+                __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __n, __result,
+                [](_InputIterator __begin, _Size __sz, _ForwardIterator __res)
+                { return __pstl::__internal::__brick_copy_n(__begin, __sz, __res, __is_vector{}); });
         },
-        [&]() {
-            return __pstl::__internal::__pattern_walk2_n(std::forward<_ExecutionPolicy>(__exec), __first, __n, __result,
-                                                         [](_ReferenceType1 __val1, _ReferenceType2 __val2) {
-                                                             ::new (std::addressof(__val2)) _ValueType2(__val1);
-                                                         },
-                                                         __is_vector, __is_parallel);
+        [&]()
+        {
+            return __pstl::__internal::__pattern_walk2_n(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec),
+                                                         __first, __n, __result,
+                                                         [](_ReferenceType1 __val1, _ReferenceType2 __val2)
+                                                         { ::new (std::addressof(__val2)) _ValueType2(__val1); });
         });
 }
 
@@ -96,28 +93,25 @@ uninitialized_move(_ExecutionPolicy&& __exec, _InputIterator __first, _InputIter
     typedef typename iterator_traits<_InputIterator>::reference _ReferenceType1;
     typedef typename iterator_traits<_ForwardIterator>::reference _ReferenceType2;
 
-    const auto __is_parallel =
-        __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _InputIterator, _ForwardIterator>(__exec);
-    const auto __is_vector =
-        __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _InputIterator, _ForwardIterator>(__exec);
+    auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first, __result);
+
+    using __is_vector = typename decltype(__dispatch_tag)::__is_vector;
 
     return __pstl::__internal::__invoke_if_else(
         std::integral_constant < bool, std::is_trivial<_ValueType1>::value&& std::is_trivial<_ValueType2>::value > (),
-        [&]() {
+        [&]()
+        {
             return __pstl::__internal::__pattern_walk2_brick(
-                std::forward<_ExecutionPolicy>(__exec), __first, __last, __result,
-                [__is_vector](_InputIterator __begin, _InputIterator __end, _ForwardIterator __res) {
-                    return __pstl::__internal::__brick_copy(__begin, __end, __res, __is_vector);
-                },
-                __is_parallel);
+                __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __last, __result,
+                [](_InputIterator __begin, _InputIterator __end, _ForwardIterator __res)
+                { return __pstl::__internal::__brick_copy(__begin, __end, __res, __is_vector{}); });
         },
-        [&]() {
+        [&]()
+        {
             return __pstl::__internal::__pattern_walk2(
-                std::forward<_ExecutionPolicy>(__exec), __first, __last, __result,
-                [](_ReferenceType1 __val1, _ReferenceType2 __val2) {
-                    ::new (std::addressof(__val2)) _ValueType2(std::move(__val1));
-                },
-                __is_vector, __is_parallel);
+                __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __last, __result,
+                [](_ReferenceType1 __val1, _ReferenceType2 __val2)
+                { ::new (std::addressof(__val2)) _ValueType2(std::move(__val1)); });
         });
 }
 
@@ -130,28 +124,25 @@ uninitialized_move_n(_ExecutionPolicy&& __exec, _InputIterator __first, _Size __
     typedef typename iterator_traits<_InputIterator>::reference _ReferenceType1;
     typedef typename iterator_traits<_ForwardIterator>::reference _ReferenceType2;
 
-    const auto __is_parallel =
-        __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _InputIterator, _ForwardIterator>(__exec);
-    const auto __is_vector =
-        __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _InputIterator, _ForwardIterator>(__exec);
+    auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first, __result);
+
+    using __is_vector = typename decltype(__dispatch_tag)::__is_vector;
 
     return __pstl::__internal::__invoke_if_else(
         std::integral_constant < bool, std::is_trivial<_ValueType1>::value&& std::is_trivial<_ValueType2>::value > (),
-        [&]() {
+        [&]()
+        {
             return __pstl::__internal::__pattern_walk2_brick_n(
-                std::forward<_ExecutionPolicy>(__exec), __first, __n, __result,
-                [__is_vector](_InputIterator __begin, _Size __sz, _ForwardIterator __res) {
-                    return __pstl::__internal::__brick_copy_n(__begin, __sz, __res, __is_vector);
-                },
-                __is_parallel);
+                __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __n, __result,
+                [](_InputIterator __begin, _Size __sz, _ForwardIterator __res)
+                { return __pstl::__internal::__brick_copy_n(__begin, __sz, __res, __is_vector{}); });
         },
-        [&]() {
-            return __pstl::__internal::__pattern_walk2_n(std::forward<_ExecutionPolicy>(__exec), __first, __n, __result,
-                                                         [](_ReferenceType1 __val1, _ReferenceType2 __val2) {
-                                                             ::new (std::addressof(__val2))
-                                                                 _ValueType2(std::move(__val1));
-                                                         },
-                                                         __is_vector, __is_parallel);
+        [&]()
+        {
+            return __pstl::__internal::__pattern_walk2_n(
+                __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __n, __result,
+                [](_ReferenceType1 __val1, _ReferenceType2 __val2)
+                { ::new (std::addressof(__val2)) _ValueType2(std::move(__val1)); });
         });
 }
 
@@ -164,26 +155,24 @@ uninitialized_fill(_ExecutionPolicy&& __exec, _ForwardIterator __first, _Forward
     typedef typename iterator_traits<_ForwardIterator>::value_type _ValueType;
     typedef typename iterator_traits<_ForwardIterator>::reference _ReferenceType;
 
-    const auto __is_parallel =
-        __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec);
-    const auto __is_vector =
-        __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec);
+    auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first);
+
+    using __is_vector = typename decltype(__dispatch_tag)::__is_vector;
 
     __pstl::__internal::__invoke_if_else(
         std::is_arithmetic<_ValueType>(),
-        [&]() {
+        [&]()
+        {
             __pstl::__internal::__pattern_walk_brick(
-                std::forward<_ExecutionPolicy>(__exec), __first, __last,
-                [&__value, &__is_vector](_ForwardIterator __begin, _ForwardIterator __end) {
-                    __pstl::__internal::__brick_fill(__begin, __end, _ValueType(__value), __is_vector);
-                },
-                __is_parallel);
+                __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __last,
+                [&__value](_ForwardIterator __begin, _ForwardIterator __end)
+                { __pstl::__internal::__brick_fill(__begin, __end, _ValueType(__value), __is_vector{}); });
         },
-        [&]() {
-            __pstl::__internal::__pattern_walk1(
-                std::forward<_ExecutionPolicy>(__exec), __first, __last,
-                [&__value](_ReferenceType __val) { ::new (std::addressof(__val)) _ValueType(__value); }, __is_vector,
-                __is_parallel);
+        [&]()
+        {
+            __pstl::__internal::__pattern_walk1(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __last,
+                                                [&__value](_ReferenceType __val)
+                                                { ::new (std::addressof(__val)) _ValueType(__value); });
         });
 }
 
@@ -194,26 +183,24 @@ uninitialized_fill_n(_ExecutionPolicy&& __exec, _ForwardIterator __first, _Size
     typedef typename iterator_traits<_ForwardIterator>::value_type _ValueType;
     typedef typename iterator_traits<_ForwardIterator>::reference _ReferenceType;
 
-    const auto __is_parallel =
-        __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec);
-    const auto __is_vector =
-        __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec);
+    auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first);
+
+    using __is_vector = typename decltype(__dispatch_tag)::__is_vector;
 
     return __pstl::__internal::__invoke_if_else(
         std::is_arithmetic<_ValueType>(),
-        [&]() {
+        [&]()
+        {
             return __pstl::__internal::__pattern_walk_brick_n(
-                std::forward<_ExecutionPolicy>(__exec), __first, __n,
-                [&__value, &__is_vector](_ForwardIterator __begin, _Size __count) {
-                    return __pstl::__internal::__brick_fill_n(__begin, __count, _ValueType(__value), __is_vector);
-                },
-                __is_parallel);
+                __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __n,
+                [&__value](_ForwardIterator __begin, _Size __count)
+                { return __pstl::__internal::__brick_fill_n(__begin, __count, _ValueType(__value), __is_vector{}); });
         },
-        [&]() {
+        [&]()
+        {
             return __pstl::__internal::__pattern_walk1_n(
-                std::forward<_ExecutionPolicy>(__exec), __first, __n,
-                [&__value](_ReferenceType __val) { ::new (std::addressof(__val)) _ValueType(__value); }, __is_vector,
-                __is_parallel);
+                __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __n,
+                [&__value](_ReferenceType __val) { ::new (std::addressof(__val)) _ValueType(__value); });
         });
 }
 
@@ -226,16 +213,15 @@ destroy(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __
     typedef typename iterator_traits<_ForwardIterator>::value_type _ValueType;
     typedef typename iterator_traits<_ForwardIterator>::reference _ReferenceType;
 
-    const auto __is_parallel =
-        __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec);
-    const auto __is_vector =
-        __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec);
+    auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first);
 
-    __pstl::__internal::__invoke_if_not(std::is_trivially_destructible<_ValueType>(), [&]() {
-        __pstl::__internal::__pattern_walk1(std::forward<_ExecutionPolicy>(__exec), __first, __last,
-                                            [](_ReferenceType __val) { __val.~_ValueType(); }, __is_vector,
-                                            __is_parallel);
-    });
+    __pstl::__internal::__invoke_if_not(std::is_trivially_destructible<_ValueType>(),
+                                        [&]()
+                                        {
+                                            __pstl::__internal::__pattern_walk1(
+                                                __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __last,
+                                                [](_ReferenceType __val) { __val.~_ValueType(); });
+                                        });
 }
 
 template <class _ExecutionPolicy, class _ForwardIterator, class _Size>
@@ -245,17 +231,15 @@ destroy_n(_ExecutionPolicy&& __exec, _ForwardIterator __first, _Size __n)
     typedef typename iterator_traits<_ForwardIterator>::value_type _ValueType;
     typedef typename iterator_traits<_ForwardIterator>::reference _ReferenceType;
 
-    const auto __is_parallel =
-        __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec);
-    const auto __is_vector =
-        __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec);
+    auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first);
 
     return __pstl::__internal::__invoke_if_else(
         std::is_trivially_destructible<_ValueType>(), [&]() { return std::next(__first, __n); },
-        [&]() {
-            return __pstl::__internal::__pattern_walk1_n(std::forward<_ExecutionPolicy>(__exec), __first, __n,
-                                                         [](_ReferenceType __val) { __val.~_ValueType(); }, __is_vector,
-                                                         __is_parallel);
+        [&]()
+        {
+            return __pstl::__internal::__pattern_walk1_n(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec),
+                                                         __first, __n,
+                                                         [](_ReferenceType __val) { __val.~_ValueType(); });
         });
 }
 
@@ -268,16 +252,15 @@ uninitialized_default_construct(_ExecutionPolicy&& __exec, _ForwardIterator __fi
     typedef typename iterator_traits<_ForwardIterator>::value_type _ValueType;
     typedef typename iterator_traits<_ForwardIterator>::reference _ReferenceType;
 
-    const auto __is_parallel =
-        __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec);
-    const auto __is_vector =
-        __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec);
+    auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first);
 
-    __pstl::__internal::__invoke_if_not(std::is_trivial<_ValueType>(), [&]() {
-        __pstl::__internal::__pattern_walk1(std::forward<_ExecutionPolicy>(__exec), __first, __last,
-                                            [](_ReferenceType __val) { ::new (std::addressof(__val)) _ValueType; },
-                                            __is_vector, __is_parallel);
-    });
+    __pstl::__internal::__invoke_if_not(std::is_trivial<_ValueType>(),
+                                        [&]()
+                                        {
+                                            __pstl::__internal::__pattern_walk1(
+                                                __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __last,
+                                                [](_ReferenceType __val) { ::new (std::addressof(__val)) _ValueType; });
+                                        });
 }
 
 template <class _ExecutionPolicy, class _ForwardIterator, class _Size>
@@ -287,17 +270,15 @@ uninitialized_default_construct_n(_ExecutionPolicy&& __exec, _ForwardIterator __
     typedef typename iterator_traits<_ForwardIterator>::value_type _ValueType;
     typedef typename iterator_traits<_ForwardIterator>::reference _ReferenceType;
 
-    const auto __is_parallel =
-        __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec);
-    const auto __is_vector =
-        __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec);
+    auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first);
 
     return __pstl::__internal::__invoke_if_else(
         std::is_trivial<_ValueType>(), [&]() { return std::next(__first, __n); },
-        [&]() {
+        [&]()
+        {
             return __pstl::__internal::__pattern_walk1_n(
-                std::forward<_ExecutionPolicy>(__exec), __first, __n,
-                [](_ReferenceType __val) { ::new (std::addressof(__val)) _ValueType; }, __is_vector, __is_parallel);
+                __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __n,
+                [](_ReferenceType __val) { ::new (std::addressof(__val)) _ValueType; });
         });
 }
 
@@ -310,25 +291,24 @@ uninitialized_value_construct(_ExecutionPolicy&& __exec, _ForwardIterator __firs
     typedef typename iterator_traits<_ForwardIterator>::value_type _ValueType;
     typedef typename iterator_traits<_ForwardIterator>::reference _ReferenceType;
 
-    const auto __is_parallel =
-        __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec);
-    const auto __is_vector =
-        __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec);
+    auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first);
+
+    using __is_vector = typename decltype(__dispatch_tag)::__is_vector;
 
     __pstl::__internal::__invoke_if_else(
         std::is_trivial<_ValueType>(),
-        [&]() {
-            __pstl::__internal::__pattern_walk_brick(std::forward<_ExecutionPolicy>(__exec), __first, __last,
-                                                     [__is_vector](_ForwardIterator __begin, _ForwardIterator __end) {
-                                                         __pstl::__internal::__brick_fill(__begin, __end, _ValueType(),
-                                                                                          __is_vector);
-                                                     },
-                                                     __is_parallel);
+        [&]()
+        {
+            __pstl::__internal::__pattern_walk_brick(
+                __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __last,
+                [](_ForwardIterator __begin, _ForwardIterator __end)
+                { __pstl::__internal::__brick_fill(__begin, __end, _ValueType(), __is_vector{}); });
         },
-        [&]() {
-            __pstl::__internal::__pattern_walk1(
-                std::forward<_ExecutionPolicy>(__exec), __first, __last,
-                [](_ReferenceType __val) { ::new (std::addressof(__val)) _ValueType(); }, __is_vector, __is_parallel);
+        [&]()
+        {
+            __pstl::__internal::__pattern_walk1(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __last,
+                                                [](_ReferenceType __val)
+                                                { ::new (std::addressof(__val)) _ValueType(); });
         });
 }
 
@@ -339,25 +319,24 @@ uninitialized_value_construct_n(_ExecutionPolicy&& __exec, _ForwardIterator __fi
     typedef typename iterator_traits<_ForwardIterator>::value_type _ValueType;
     typedef typename iterator_traits<_ForwardIterator>::reference _ReferenceType;
 
-    const auto __is_parallel =
-        __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec);
-    const auto __is_vector =
-        __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec);
+    auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first);
+
+    using __is_vector = typename decltype(__dispatch_tag)::__is_vector;
 
     return __pstl::__internal::__invoke_if_else(
         std::is_trivial<_ValueType>(),
-        [&]() {
-            return __pstl::__internal::__pattern_walk_brick_n(std::forward<_ExecutionPolicy>(__exec), __first, __n,
-                                                              [__is_vector](_ForwardIterator __begin, _Size __count) {
-                                                                  return __pstl::__internal::__brick_fill_n(
-                                                                      __begin, __count, _ValueType(), __is_vector);
-                                                              },
-                                                              __is_parallel);
+        [&]()
+        {
+            return __pstl::__internal::__pattern_walk_brick_n(
+                __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __n,
+                [](_ForwardIterator __begin, _Size __count)
+                { return __pstl::__internal::__brick_fill_n(__begin, __count, _ValueType(), __is_vector{}); });
         },
-        [&]() {
+        [&]()
+        {
             return __pstl::__internal::__pattern_walk1_n(
-                std::forward<_ExecutionPolicy>(__exec), __first, __n,
-                [](_ReferenceType __val) { ::new (std::addressof(__val)) _ValueType(); }, __is_vector, __is_parallel);
+                __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __n,
+                [](_ReferenceType __val) { ::new (std::addressof(__val)) _ValueType(); });
         });
 }
 
diff --git a/libstdc++-v3/include/pstl/glue_numeric_impl.h b/libstdc++-v3/include/pstl/glue_numeric_impl.h
index 9db64b513a4..490175c8b83 100644
--- a/libstdc++-v3/include/pstl/glue_numeric_impl.h
+++ b/libstdc++-v3/include/pstl/glue_numeric_impl.h
@@ -54,14 +54,12 @@ __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _Tp>
 transform_reduce(_ExecutionPolicy&& __exec, _ForwardIterator1 __first1, _ForwardIterator1 __last1,
                  _ForwardIterator2 __first2, _Tp __init)
 {
+    auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first1, __first2);
+
     typedef typename iterator_traits<_ForwardIterator1>::value_type _InputType;
-    return __pstl::__internal::__pattern_transform_reduce(
-        std::forward<_ExecutionPolicy>(__exec), __first1, __last1, __first2, __init, std::plus<_InputType>(),
-        std::multiplies<_InputType>(),
-        __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator1, _ForwardIterator2>(
-            __exec),
-        __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator1, _ForwardIterator2>(
-            __exec));
+    return __pstl::__internal::__pattern_transform_reduce(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec),
+                                                          __first1, __last1, __first2, __init, std::plus<_InputType>(),
+                                                          std::multiplies<_InputType>());
 }
 
 template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _Tp, class _BinaryOperation1,
@@ -70,12 +68,10 @@ __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _Tp>
 transform_reduce(_ExecutionPolicy&& __exec, _ForwardIterator1 __first1, _ForwardIterator1 __last1,
                  _ForwardIterator2 __first2, _Tp __init, _BinaryOperation1 __binary_op1, _BinaryOperation2 __binary_op2)
 {
-    return __pstl::__internal::__pattern_transform_reduce(
-        std::forward<_ExecutionPolicy>(__exec), __first1, __last1, __first2, __init, __binary_op1, __binary_op2,
-        __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator1, _ForwardIterator2>(
-            __exec),
-        __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator1, _ForwardIterator2>(
-            __exec));
+    auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first1, __first2);
+    return __pstl::__internal::__pattern_transform_reduce(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec),
+                                                          __first1, __last1, __first2, __init, __binary_op1,
+                                                          __binary_op2);
 }
 
 template <class _ExecutionPolicy, class _ForwardIterator, class _Tp, class _BinaryOperation, class _UnaryOperation>
@@ -83,10 +79,9 @@ __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _Tp>
 transform_reduce(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _Tp __init,
                  _BinaryOperation __binary_op, _UnaryOperation __unary_op)
 {
-    return __pstl::__internal::__pattern_transform_reduce(
-        std::forward<_ExecutionPolicy>(__exec), __first, __last, __init, __binary_op, __unary_op,
-        __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec),
-        __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator>(__exec));
+    auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first);
+    return __pstl::__internal::__pattern_transform_reduce(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec),
+                                                          __first, __last, __init, __binary_op, __unary_op);
 }
 
 // [exclusive.scan]
@@ -96,12 +91,12 @@ __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardItera
 exclusive_scan(_ExecutionPolicy&& __exec, _ForwardIterator1 __first, _ForwardIterator1 __last,
                _ForwardIterator2 __result, _Tp __init)
 {
+    auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first, __result);
+
     using namespace __pstl;
-    return __internal::__pattern_transform_scan(
-        std::forward<_ExecutionPolicy>(__exec), __first, __last, __result, __pstl::__internal::__no_op(), __init,
-        std::plus<_Tp>(), /*inclusive=*/std::false_type(),
-        __internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator1, _ForwardIterator2>(__exec),
-        __internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator1, _ForwardIterator2>(__exec));
+    return __internal::__pattern_transform_scan(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __last,
+                                                __result, __pstl::__internal::__no_op(), __init, std::plus<_Tp>(),
+                                                /*inclusive=*/std::false_type());
 }
 
 template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _Tp, class _BinaryOperation>
@@ -109,12 +104,12 @@ __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardItera
 exclusive_scan(_ExecutionPolicy&& __exec, _ForwardIterator1 __first, _ForwardIterator1 __last,
                _ForwardIterator2 __result, _Tp __init, _BinaryOperation __binary_op)
 {
+    auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first, __result);
+
     using namespace __pstl;
-    return __internal::__pattern_transform_scan(
-        std::forward<_ExecutionPolicy>(__exec), __first, __last, __result, __pstl::__internal::__no_op(), __init,
-        __binary_op, /*inclusive=*/std::false_type(),
-        __internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator1, _ForwardIterator2>(__exec),
-        __internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator1, _ForwardIterator2>(__exec));
+    return __internal::__pattern_transform_scan(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __last,
+                                                __result, __pstl::__internal::__no_op(), __init, __binary_op,
+                                                /*inclusive=*/std::false_type());
 }
 
 // [inclusive.scan]
@@ -156,13 +151,11 @@ transform_exclusive_scan(_ExecutionPolicy&& __exec, _ForwardIterator1 __first, _
                          _ForwardIterator2 __result, _Tp __init, _BinaryOperation __binary_op,
                          _UnaryOperation __unary_op)
 {
-    return __pstl::__internal::__pattern_transform_scan(
-        std::forward<_ExecutionPolicy>(__exec), __first, __last, __result, __unary_op, __init, __binary_op,
-        /*inclusive=*/std::false_type(),
-        __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator1, _ForwardIterator2>(
-            __exec),
-        __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator1, _ForwardIterator2>(
-            __exec));
+    auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first, __result);
+
+    return __pstl::__internal::__pattern_transform_scan(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first,
+                                                        __last, __result, __unary_op, __init, __binary_op,
+                                                        /*inclusive=*/std::false_type());
 }
 
 // [transform.inclusive.scan]
@@ -174,13 +167,11 @@ transform_inclusive_scan(_ExecutionPolicy&& __exec, _ForwardIterator1 __first, _
                          _ForwardIterator2 __result, _BinaryOperation __binary_op, _UnaryOperation __unary_op,
                          _Tp __init)
 {
-    return __pstl::__internal::__pattern_transform_scan(
-        std::forward<_ExecutionPolicy>(__exec), __first, __last, __result, __unary_op, __init, __binary_op,
-        /*inclusive=*/std::true_type(),
-        __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator1, _ForwardIterator2>(
-            __exec),
-        __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator1, _ForwardIterator2>(
-            __exec));
+    auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first, __result);
+
+    return __pstl::__internal::__pattern_transform_scan(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first,
+                                                        __last, __result, __unary_op, __init, __binary_op,
+                                                        /*inclusive=*/std::true_type());
 }
 
 template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _UnaryOperation,
@@ -213,12 +204,10 @@ adjacent_difference(_ExecutionPolicy&& __exec, _ForwardIterator1 __first, _Forwa
     if (__first == __last)
         return __d_first;
 
-    return __pstl::__internal::__pattern_adjacent_difference(
-        std::forward<_ExecutionPolicy>(__exec), __first, __last, __d_first, __op,
-        __pstl::__internal::__is_vectorization_preferred<_ExecutionPolicy, _ForwardIterator1, _ForwardIterator2>(
-            __exec),
-        __pstl::__internal::__is_parallelization_preferred<_ExecutionPolicy, _ForwardIterator1, _ForwardIterator2>(
-            __exec));
+    auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first, __d_first);
+
+    return __pstl::__internal::__pattern_adjacent_difference(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec),
+                                                             __first, __last, __d_first, __op);
 }
 
 template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2>
diff --git a/libstdc++-v3/include/pstl/memory_impl.h b/libstdc++-v3/include/pstl/memory_impl.h
index be5a103f93b..8cb32d043e5 100644
--- a/libstdc++-v3/include/pstl/memory_impl.h
+++ b/libstdc++-v3/include/pstl/memory_impl.h
@@ -36,13 +36,13 @@ __brick_uninitialized_move(_ForwardIterator __first, _ForwardIterator __last, _O
     return __result;
 }
 
-template <typename _ForwardIterator, typename _OutputIterator>
+template <typename _RandomAccessIterator, typename _OutputIterator>
 _OutputIterator
-__brick_uninitialized_move(_ForwardIterator __first, _ForwardIterator __last, _OutputIterator __result,
+__brick_uninitialized_move(_RandomAccessIterator __first, _RandomAccessIterator __last, _OutputIterator __result,
                            /*vector=*/std::true_type) noexcept
 {
     using __ValueType = typename std::iterator_traits<_OutputIterator>::value_type;
-    using _ReferenceType1 = typename std::iterator_traits<_ForwardIterator>::reference;
+    using _ReferenceType1 = typename std::iterator_traits<_RandomAccessIterator>::reference;
     using _ReferenceType2 = typename std::iterator_traits<_OutputIterator>::reference;
 
     return __unseq_backend::__simd_walk_2(
@@ -60,12 +60,12 @@ __brick_destroy(_Iterator __first, _Iterator __last, /*vector*/ std::false_type)
         __first->~_ValueType();
 }
 
-template <typename _Iterator>
+template <typename _RandomAccessIterator>
 void
-__brick_destroy(_Iterator __first, _Iterator __last, /*vector*/ std::true_type) noexcept
+__brick_destroy(_RandomAccessIterator __first, _RandomAccessIterator __last, /*vector*/ std::true_type) noexcept
 {
-    using _ValueType = typename std::iterator_traits<_Iterator>::value_type;
-    using _ReferenceType = typename std::iterator_traits<_Iterator>::reference;
+    using _ValueType = typename std::iterator_traits<_RandomAccessIterator>::value_type;
+    using _ReferenceType = typename std::iterator_traits<_RandomAccessIterator>::reference;
 
     __unseq_backend::__simd_walk_1(__first, __last - __first, [](_ReferenceType __x) { __x.~_ValueType(); });
 }
@@ -87,13 +87,13 @@ __brick_uninitialized_copy(_ForwardIterator __first, _ForwardIterator __last, _O
     return __result;
 }
 
-template <typename _ForwardIterator, typename _OutputIterator>
+template <typename _RandomAccessIterator, typename _OutputIterator>
 _OutputIterator
-__brick_uninitialized_copy(_ForwardIterator __first, _ForwardIterator __last, _OutputIterator __result,
+__brick_uninitialized_copy(_RandomAccessIterator __first, _RandomAccessIterator __last, _OutputIterator __result,
                            /*vector=*/std::true_type) noexcept
 {
     using __ValueType = typename std::iterator_traits<_OutputIterator>::value_type;
-    using _ReferenceType1 = typename std::iterator_traits<_ForwardIterator>::reference;
+    using _ReferenceType1 = typename std::iterator_traits<_RandomAccessIterator>::reference;
     using _ReferenceType2 = typename std::iterator_traits<_OutputIterator>::reference;
 
     return __unseq_backend::__simd_walk_2(
diff --git a/libstdc++-v3/include/pstl/numeric_fwd.h b/libstdc++-v3/include/pstl/numeric_fwd.h
index d92cacb7644..e98e3b1e12b 100644
--- a/libstdc++-v3/include/pstl/numeric_fwd.h
+++ b/libstdc++-v3/include/pstl/numeric_fwd.h
@@ -22,9 +22,10 @@ namespace __internal
 // transform_reduce (version with two binary functions, according to draft N4659)
 //------------------------------------------------------------------------
 
-template <class _ForwardIterator1, class _ForwardIterator2, class _Tp, class _BinaryOperation1, class _BinaryOperation2>
-_Tp __brick_transform_reduce(_ForwardIterator1, _ForwardIterator1, _ForwardIterator2, _Tp, _BinaryOperation1,
-                             _BinaryOperation2,
+template <class _RandomAccessIterator1, class _RandomAccessIterator2, class _Tp, class _BinaryOperation1,
+          class _BinaryOperation2>
+_Tp __brick_transform_reduce(_RandomAccessIterator1, _RandomAccessIterator1, _RandomAccessIterator2, _Tp,
+                             _BinaryOperation1, _BinaryOperation2,
                              /*__is_vector=*/std::true_type) noexcept;
 
 template <class _ForwardIterator1, class _ForwardIterator2, class _Tp, class _BinaryOperation1, class _BinaryOperation2>
@@ -32,45 +33,41 @@ _Tp __brick_transform_reduce(_ForwardIterator1, _ForwardIterator1, _ForwardItera
                              _BinaryOperation2,
                              /*__is_vector=*/std::false_type) noexcept;
 
-template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _Tp, class _BinaryOperation1,
-          class _BinaryOperation2, class _IsVector>
+template <class _Tag, class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _Tp,
+          class _BinaryOperation1, class _BinaryOperation2>
 _Tp
-__pattern_transform_reduce(_ExecutionPolicy&&, _ForwardIterator1, _ForwardIterator1, _ForwardIterator2, _Tp,
-                           _BinaryOperation1, _BinaryOperation2, _IsVector,
-                           /*is_parallel=*/std::false_type) noexcept;
+__pattern_transform_reduce(_Tag, _ExecutionPolicy&&, _ForwardIterator1, _ForwardIterator1, _ForwardIterator2, _Tp,
+                           _BinaryOperation1, _BinaryOperation2) noexcept;
 
-template <class _ExecutionPolicy, class _RandomAccessIterator1, class _RandomAccessIterator2, class _Tp,
-          class _BinaryOperation1, class _BinaryOperation2, class _IsVector>
+template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator1, class _RandomAccessIterator2,
+          class _Tp, class _BinaryOperation1, class _BinaryOperation2>
 _Tp
-__pattern_transform_reduce(_ExecutionPolicy&&, _RandomAccessIterator1, _RandomAccessIterator1, _RandomAccessIterator2,
-                           _Tp, _BinaryOperation1, _BinaryOperation2, _IsVector __is_vector,
-                           /*is_parallel=*/std::true_type);
+__pattern_transform_reduce(__parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator1,
+                           _RandomAccessIterator1, _RandomAccessIterator2, _Tp, _BinaryOperation1, _BinaryOperation2);
 
 //------------------------------------------------------------------------
 // transform_reduce (version with unary and binary functions)
 //------------------------------------------------------------------------
 
-template <class _ForwardIterator, class _Tp, class _UnaryOperation, class _BinaryOperation>
-_Tp __brick_transform_reduce(_ForwardIterator, _ForwardIterator, _Tp, _BinaryOperation, _UnaryOperation,
+template <class _RandomAccessIterator, class _Tp, class _UnaryOperation, class _BinaryOperation>
+_Tp __brick_transform_reduce(_RandomAccessIterator, _RandomAccessIterator, _Tp, _BinaryOperation, _UnaryOperation,
                              /*is_vector=*/std::true_type) noexcept;
 
 template <class _ForwardIterator, class _Tp, class _BinaryOperation, class _UnaryOperation>
 _Tp __brick_transform_reduce(_ForwardIterator, _ForwardIterator, _Tp, _BinaryOperation, _UnaryOperation,
                              /*is_vector=*/std::false_type) noexcept;
 
-template <class _ExecutionPolicy, class _ForwardIterator, class _Tp, class _BinaryOperation, class _UnaryOperation,
-          class _IsVector>
+template <class _Tag, class _ExecutionPolicy, class _ForwardIterator, class _Tp, class _BinaryOperation,
+          class _UnaryOperation>
 _Tp
-__pattern_transform_reduce(_ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _Tp, _BinaryOperation,
-                           _UnaryOperation, _IsVector,
-                           /*is_parallel=*/std::false_type) noexcept;
+__pattern_transform_reduce(_Tag, _ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _Tp, _BinaryOperation,
+                           _UnaryOperation) noexcept;
 
-template <class _ExecutionPolicy, class _ForwardIterator, class _Tp, class _BinaryOperation, class _UnaryOperation,
-          class _IsVector>
+template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _Tp, class _BinaryOperation,
+          class _UnaryOperation>
 _Tp
-__pattern_transform_reduce(_ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _Tp, _BinaryOperation,
-                           _UnaryOperation, _IsVector,
-                           /*is_parallel=*/std::true_type);
+__pattern_transform_reduce(__parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator,
+                           _Tp, _BinaryOperation, _UnaryOperation);
 
 //------------------------------------------------------------------------
 // transform_exclusive_scan
@@ -83,29 +80,28 @@ std::pair<_OutputIterator, _Tp> __brick_transform_scan(_ForwardIterator, _Forwar
                                                        _UnaryOperation, _Tp, _BinaryOperation,
                                                        /*Inclusive*/ std::false_type) noexcept;
 
-template <class _ForwardIterator, class _OutputIterator, class _UnaryOperation, class _Tp, class _BinaryOperation>
-std::pair<_OutputIterator, _Tp> __brick_transform_scan(_ForwardIterator, _ForwardIterator, _OutputIterator,
+template <class _RandomAccessIterator, class _OutputIterator, class _UnaryOperation, class _Tp, class _BinaryOperation>
+std::pair<_OutputIterator, _Tp> __brick_transform_scan(_RandomAccessIterator, _RandomAccessIterator, _OutputIterator,
                                                        _UnaryOperation, _Tp, _BinaryOperation,
                                                        /*Inclusive*/ std::true_type) noexcept;
 
-template <class _ExecutionPolicy, class _ForwardIterator, class _OutputIterator, class _UnaryOperation, class _Tp,
-          class _BinaryOperation, class _Inclusive, class _IsVector>
+template <class _Tag, class _ExecutionPolicy, class _ForwardIterator, class _OutputIterator, class _UnaryOperation,
+          class _Tp, class _BinaryOperation, class _Inclusive>
 _OutputIterator
-__pattern_transform_scan(_ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _OutputIterator, _UnaryOperation, _Tp,
-                         _BinaryOperation, _Inclusive, _IsVector,
-                         /*is_parallel=*/std::false_type) noexcept;
+__pattern_transform_scan(_Tag, _ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _OutputIterator, _UnaryOperation,
+                         _Tp, _BinaryOperation, _Inclusive) noexcept;
 
-template <class _ExecutionPolicy, class _RandomAccessIterator, class _OutputIterator, class _UnaryOperation, class _Tp,
-          class _BinaryOperation, class _Inclusive, class _IsVector>
+template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _OutputIterator,
+          class _UnaryOperation, class _Tp, class _BinaryOperation, class _Inclusive>
 typename std::enable_if<!std::is_floating_point<_Tp>::value, _OutputIterator>::type
-__pattern_transform_scan(_ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator, _OutputIterator,
-                         _UnaryOperation, _Tp, _BinaryOperation, _Inclusive, _IsVector, /*is_parallel=*/std::true_type);
+__pattern_transform_scan(__parallel_tag<_IsVector> __tag, _ExecutionPolicy&&, _RandomAccessIterator,
+                         _RandomAccessIterator, _OutputIterator, _UnaryOperation, _Tp, _BinaryOperation, _Inclusive);
 
-template <class _ExecutionPolicy, class _RandomAccessIterator, class _OutputIterator, class _UnaryOperation, class _Tp,
-          class _BinaryOperation, class _Inclusive, class _IsVector>
+template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _OutputIterator,
+          class _UnaryOperation, class _Tp, class _BinaryOperation, class _Inclusive>
 typename std::enable_if<std::is_floating_point<_Tp>::value, _OutputIterator>::type
-__pattern_transform_scan(_ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator, _OutputIterator,
-                         _UnaryOperation, _Tp, _BinaryOperation, _Inclusive, _IsVector, /*is_parallel=*/std::true_type);
+__pattern_transform_scan(__parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator,
+                         _OutputIterator, _UnaryOperation, _Tp, _BinaryOperation, _Inclusive);
 
 //------------------------------------------------------------------------
 // adjacent_difference
@@ -115,20 +111,20 @@ template <class _ForwardIterator, class _OutputIterator, class _BinaryOperation>
 _OutputIterator __brick_adjacent_difference(_ForwardIterator, _ForwardIterator, _OutputIterator, _BinaryOperation,
                                             /*is_vector*/ std::false_type) noexcept;
 
-template <class _ForwardIterator, class _OutputIterator, class _BinaryOperation>
-_OutputIterator __brick_adjacent_difference(_ForwardIterator, _ForwardIterator, _OutputIterator, _BinaryOperation,
+template <class _RandomAccessIterator, class _OutputIterator, class _BinaryOperation>
+_OutputIterator __brick_adjacent_difference(_RandomAccessIterator, _RandomAccessIterator, _OutputIterator,
+                                            _BinaryOperation,
                                             /*is_vector*/ std::true_type) noexcept;
 
-template <class _ExecutionPolicy, class _ForwardIterator, class _OutputIterator, class _BinaryOperation,
-          class _IsVector>
+template <class _Tag, class _ExecutionPolicy, class _ForwardIterator, class _OutputIterator, class _BinaryOperation>
 _OutputIterator
-__pattern_adjacent_difference(_ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _OutputIterator, _BinaryOperation,
-                              _IsVector, /*is_parallel*/ std::false_type) noexcept;
+__pattern_adjacent_difference(_Tag, _ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _OutputIterator,
+                              _BinaryOperation) noexcept;
 
-template <class _ExecutionPolicy, class _ForwardIterator, class _OutputIterator, class _BinaryOperation,
-          class _IsVector>
+template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _OutputIterator,
+          class _BinaryOperation>
 _OutputIterator
-__pattern_adjacent_difference(_ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _OutputIterator, _BinaryOperation,
+__pattern_adjacent_difference(_ExecutionPolicy&&, _OutputIterator, _OutputIterator, _OutputIterator, _BinaryOperation,
                               _IsVector, /*is_parallel*/ std::true_type);
 
 } // namespace __internal
diff --git a/libstdc++-v3/include/pstl/numeric_impl.h b/libstdc++-v3/include/pstl/numeric_impl.h
index 0b02bcf0789..f9118d045e1 100644
--- a/libstdc++-v3/include/pstl/numeric_impl.h
+++ b/libstdc++-v3/include/pstl/numeric_impl.h
@@ -38,50 +38,56 @@ __brick_transform_reduce(_ForwardIterator1 __first1, _ForwardIterator1 __last1,
     return std::inner_product(__first1, __last1, __first2, __init, __binary_op1, __binary_op2);
 }
 
-template <class _ForwardIterator1, class _ForwardIterator2, class _Tp, class _BinaryOperation1, class _BinaryOperation2>
+template <class _RandomAccessIterator1, class _RandomAccessIterator2, class _Tp, class _BinaryOperation1,
+          class _BinaryOperation2>
 _Tp
-__brick_transform_reduce(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2, _Tp __init,
-                         _BinaryOperation1 __binary_op1, _BinaryOperation2 __binary_op2,
+__brick_transform_reduce(_RandomAccessIterator1 __first1, _RandomAccessIterator1 __last1,
+                         _RandomAccessIterator2 __first2, _Tp __init, _BinaryOperation1 __binary_op1,
+                         _BinaryOperation2 __binary_op2,
                          /*is_vector=*/std::true_type) noexcept
 {
-    typedef typename std::iterator_traits<_ForwardIterator1>::difference_type _DifferenceType;
+    typedef typename std::iterator_traits<_RandomAccessIterator1>::difference_type _DifferenceType;
     return __unseq_backend::__simd_transform_reduce(
         __last1 - __first1, __init, __binary_op1,
         [=, &__binary_op2](_DifferenceType __i) { return __binary_op2(__first1[__i], __first2[__i]); });
 }
 
-template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _Tp, class _BinaryOperation1,
-          class _BinaryOperation2, class _IsVector>
+template <class _Tag, class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _Tp,
+          class _BinaryOperation1, class _BinaryOperation2>
 _Tp
-__pattern_transform_reduce(_ExecutionPolicy&&, _ForwardIterator1 __first1, _ForwardIterator1 __last1,
+__pattern_transform_reduce(_Tag, _ExecutionPolicy&&, _ForwardIterator1 __first1, _ForwardIterator1 __last1,
                            _ForwardIterator2 __first2, _Tp __init, _BinaryOperation1 __binary_op1,
-                           _BinaryOperation2 __binary_op2, _IsVector __is_vector,
-                           /*is_parallel=*/std::false_type) noexcept
+                           _BinaryOperation2 __binary_op2) noexcept
 {
-    return __brick_transform_reduce(__first1, __last1, __first2, __init, __binary_op1, __binary_op2, __is_vector);
+    return __brick_transform_reduce(__first1, __last1, __first2, __init, __binary_op1, __binary_op2,
+                                    typename _Tag::__is_vector{});
 }
 
-template <class _ExecutionPolicy, class _RandomAccessIterator1, class _RandomAccessIterator2, class _Tp,
-          class _BinaryOperation1, class _BinaryOperation2, class _IsVector>
+template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator1, class _RandomAccessIterator2,
+          class _Tp, class _BinaryOperation1, class _BinaryOperation2>
 _Tp
-__pattern_transform_reduce(_ExecutionPolicy&& __exec, _RandomAccessIterator1 __first1, _RandomAccessIterator1 __last1,
-                           _RandomAccessIterator2 __first2, _Tp __init, _BinaryOperation1 __binary_op1,
-                           _BinaryOperation2 __binary_op2, _IsVector __is_vector, /*is_parallel=*/std::true_type)
+__pattern_transform_reduce(__parallel_tag<_IsVector> __tag, _ExecutionPolicy&& __exec, _RandomAccessIterator1 __first1,
+                           _RandomAccessIterator1 __last1, _RandomAccessIterator2 __first2, _Tp __init,
+                           _BinaryOperation1 __binary_op1, _BinaryOperation2 __binary_op2)
 {
-    return __internal::__except_handler([&]() {
-        return __par_backend::__parallel_transform_reduce(
-            std::forward<_ExecutionPolicy>(__exec), __first1, __last1,
-            [__first1, __first2, __binary_op2](_RandomAccessIterator1 __i) mutable {
-                return __binary_op2(*__i, *(__first2 + (__i - __first1)));
-            },
-            __init,
-            __binary_op1, // Combine
-            [__first1, __first2, __binary_op1, __binary_op2,
-             __is_vector](_RandomAccessIterator1 __i, _RandomAccessIterator1 __j, _Tp __init) -> _Tp {
-                return __internal::__brick_transform_reduce(__i, __j, __first2 + (__i - __first1), __init, __binary_op1,
-                                                            __binary_op2, __is_vector);
-            });
-    });
+    using __backend_tag = typename decltype(__tag)::__backend_tag;
+
+    return __internal::__except_handler(
+        [&]()
+        {
+            return __par_backend::__parallel_transform_reduce(
+                __backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __first1, __last1,
+                [__first1, __first2, __binary_op2](_RandomAccessIterator1 __i) mutable
+                { return __binary_op2(*__i, *(__first2 + (__i - __first1))); },
+                __init,
+                __binary_op1, // Combine
+                [__first1, __first2, __binary_op1, __binary_op2](_RandomAccessIterator1 __i, _RandomAccessIterator1 __j,
+                                                                 _Tp __init) -> _Tp
+                {
+                    return __internal::__brick_transform_reduce(__i, __j, __first2 + (__i - __first1), __init,
+                                                                __binary_op1, __binary_op2, _IsVector{});
+                });
+        });
 }
 
 //------------------------------------------------------------------------
@@ -96,42 +102,47 @@ __brick_transform_reduce(_ForwardIterator __first, _ForwardIterator __last, _Tp
     return std::transform_reduce(__first, __last, __init, __binary_op, __unary_op);
 }
 
-template <class _ForwardIterator, class _Tp, class _UnaryOperation, class _BinaryOperation>
+template <class _RandomAccessIterator, class _Tp, class _UnaryOperation, class _BinaryOperation>
 _Tp
-__brick_transform_reduce(_ForwardIterator __first, _ForwardIterator __last, _Tp __init, _BinaryOperation __binary_op,
-                         _UnaryOperation __unary_op, /*is_vector=*/std::true_type) noexcept
+__brick_transform_reduce(_RandomAccessIterator __first, _RandomAccessIterator __last, _Tp __init,
+                         _BinaryOperation __binary_op, _UnaryOperation __unary_op,
+                         /*is_vector=*/std::true_type) noexcept
 {
-    typedef typename std::iterator_traits<_ForwardIterator>::difference_type _DifferenceType;
+    typedef typename std::iterator_traits<_RandomAccessIterator>::difference_type _DifferenceType;
     return __unseq_backend::__simd_transform_reduce(
         __last - __first, __init, __binary_op,
         [=, &__unary_op](_DifferenceType __i) { return __unary_op(__first[__i]); });
 }
 
-template <class _ExecutionPolicy, class _ForwardIterator, class _Tp, class _BinaryOperation, class _UnaryOperation,
-          class _IsVector>
+template <class _Tag, class _ExecutionPolicy, class _ForwardIterator, class _Tp, class _BinaryOperation,
+          class _UnaryOperation>
 _Tp
-__pattern_transform_reduce(_ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last, _Tp __init,
-                           _BinaryOperation __binary_op, _UnaryOperation __unary_op, _IsVector __is_vector,
-                           /*is_parallel=*/std::false_type) noexcept
+__pattern_transform_reduce(_Tag, _ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last, _Tp __init,
+                           _BinaryOperation __binary_op, _UnaryOperation __unary_op) noexcept
 {
-    return __internal::__brick_transform_reduce(__first, __last, __init, __binary_op, __unary_op, __is_vector);
+    return __internal::__brick_transform_reduce(__first, __last, __init, __binary_op, __unary_op,
+                                                typename _Tag::__is_vector{});
 }
 
-template <class _ExecutionPolicy, class _ForwardIterator, class _Tp, class _BinaryOperation, class _UnaryOperation,
-          class _IsVector>
+template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _Tp, class _BinaryOperation,
+          class _UnaryOperation>
 _Tp
-__pattern_transform_reduce(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _Tp __init,
-                           _BinaryOperation __binary_op, _UnaryOperation __unary_op, _IsVector __is_vector,
-                           /*is_parallel=*/std::true_type)
+__pattern_transform_reduce(__parallel_tag<_IsVector> __tag, _ExecutionPolicy&& __exec, _RandomAccessIterator __first,
+                           _RandomAccessIterator __last, _Tp __init, _BinaryOperation __binary_op,
+                           _UnaryOperation __unary_op)
 {
-    return __internal::__except_handler([&]() {
-        return __par_backend::__parallel_transform_reduce(
-            std::forward<_ExecutionPolicy>(__exec), __first, __last,
-            [__unary_op](_ForwardIterator __i) mutable { return __unary_op(*__i); }, __init, __binary_op,
-            [__unary_op, __binary_op, __is_vector](_ForwardIterator __i, _ForwardIterator __j, _Tp __init) {
-                return __internal::__brick_transform_reduce(__i, __j, __init, __binary_op, __unary_op, __is_vector);
-            });
-    });
+    using __backend_tag = typename decltype(__tag)::__backend_tag;
+
+    return __internal::__except_handler(
+        [&]()
+        {
+            return __par_backend::__parallel_transform_reduce(
+                __backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __first, __last,
+                [__unary_op](_RandomAccessIterator __i) mutable { return __unary_op(*__i); }, __init, __binary_op,
+                [__unary_op, __binary_op](_RandomAccessIterator __i, _RandomAccessIterator __j, _Tp __init) {
+                    return __internal::__brick_transform_reduce(__i, __j, __init, __binary_op, __unary_op, _IsVector{});
+                });
+        });
 }
 
 //------------------------------------------------------------------------
@@ -157,9 +168,9 @@ __brick_transform_scan(_ForwardIterator __first, _ForwardIterator __last, _Outpu
 }
 
 // Inclusive form
-template <class _ForwardIterator, class _OutputIterator, class _UnaryOperation, class _Tp, class _BinaryOperation>
+template <class _RandomAccessIterator, class _OutputIterator, class _UnaryOperation, class _Tp, class _BinaryOperation>
 std::pair<_OutputIterator, _Tp>
-__brick_transform_scan(_ForwardIterator __first, _ForwardIterator __last, _OutputIterator __result,
+__brick_transform_scan(_RandomAccessIterator __first, _RandomAccessIterator __last, _OutputIterator __result,
                        _UnaryOperation __unary_op, _Tp __init, _BinaryOperation __binary_op,
                        /*Inclusive*/ std::true_type, /*is_vector=*/std::false_type) noexcept
 {
@@ -179,14 +190,14 @@ using is_arithmetic_udop = std::integral_constant<bool, std::is_arithmetic<_Tp>:
 
 // [restriction] - T shall be DefaultConstructible.
 // [violation] - default ctor of T shall set the identity value for binary_op.
-template <class _ForwardIterator, class _OutputIterator, class _UnaryOperation, class _Tp, class _BinaryOperation,
+template <class _RandomAccessIterator, class _OutputIterator, class _UnaryOperation, class _Tp, class _BinaryOperation,
           class _Inclusive>
 typename std::enable_if<!is_arithmetic_udop<_Tp, _BinaryOperation>::value, std::pair<_OutputIterator, _Tp>>::type
-__brick_transform_scan(_ForwardIterator __first, _ForwardIterator __last, _OutputIterator __result,
+__brick_transform_scan(_RandomAccessIterator __first, _RandomAccessIterator __last, _OutputIterator __result,
                        _UnaryOperation __unary_op, _Tp __init, _BinaryOperation __binary_op, _Inclusive,
                        /*is_vector=*/std::true_type) noexcept
 {
-#if (_PSTL_UDS_PRESENT)
+#if defined(_PSTL_UDS_PRESENT)
     return __unseq_backend::__simd_scan(__first, __last - __first, __result, __unary_op, __init, __binary_op,
                                         _Inclusive());
 #else
@@ -196,10 +207,10 @@ __brick_transform_scan(_ForwardIterator __first, _ForwardIterator __last, _Outpu
 #endif
 }
 
-template <class _ForwardIterator, class _OutputIterator, class _UnaryOperation, class _Tp, class _BinaryOperation,
+template <class _RandomAccessIterator, class _OutputIterator, class _UnaryOperation, class _Tp, class _BinaryOperation,
           class _Inclusive>
 typename std::enable_if<is_arithmetic_udop<_Tp, _BinaryOperation>::value, std::pair<_OutputIterator, _Tp>>::type
-__brick_transform_scan(_ForwardIterator __first, _ForwardIterator __last, _OutputIterator __result,
+__brick_transform_scan(_RandomAccessIterator __first, _RandomAccessIterator __last, _OutputIterator __result,
                        _UnaryOperation __unary_op, _Tp __init, _BinaryOperation __binary_op, _Inclusive,
                        /*is_vector=*/std::true_type) noexcept
 {
@@ -207,55 +218,62 @@ __brick_transform_scan(_ForwardIterator __first, _ForwardIterator __last, _Outpu
                                               /*is_vector=*/std::false_type());
 }
 
-template <class _ExecutionPolicy, class _ForwardIterator, class _OutputIterator, class _UnaryOperation, class _Tp,
-          class _BinaryOperation, class _Inclusive, class _IsVector>
+template <class _Tag, class _ExecutionPolicy, class _ForwardIterator, class _OutputIterator, class _UnaryOperation,
+          class _Tp, class _BinaryOperation, class _Inclusive>
 _OutputIterator
-__pattern_transform_scan(_ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last,
+__pattern_transform_scan(_Tag, _ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last,
                          _OutputIterator __result, _UnaryOperation __unary_op, _Tp __init, _BinaryOperation __binary_op,
-                         _Inclusive, _IsVector __is_vector, /*is_parallel=*/std::false_type) noexcept
+                         _Inclusive) noexcept
 {
     return __internal::__brick_transform_scan(__first, __last, __result, __unary_op, __init, __binary_op, _Inclusive(),
-                                              __is_vector)
+                                              typename _Tag::__is_vector{})
         .first;
 }
 
-template <class _ExecutionPolicy, class _RandomAccessIterator, class _OutputIterator, class _UnaryOperation, class _Tp,
-          class _BinaryOperation, class _Inclusive, class _IsVector>
+template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _OutputIterator,
+          class _UnaryOperation, class _Tp, class _BinaryOperation, class _Inclusive>
 typename std::enable_if<!std::is_floating_point<_Tp>::value, _OutputIterator>::type
-__pattern_transform_scan(_ExecutionPolicy&& __exec, _RandomAccessIterator __first, _RandomAccessIterator __last,
-                         _OutputIterator __result, _UnaryOperation __unary_op, _Tp __init, _BinaryOperation __binary_op,
-                         _Inclusive, _IsVector __is_vector, /*is_parallel=*/std::true_type)
+__pattern_transform_scan(__parallel_tag<_IsVector> __tag, _ExecutionPolicy&& __exec, _RandomAccessIterator __first,
+                         _RandomAccessIterator __last, _OutputIterator __result, _UnaryOperation __unary_op, _Tp __init,
+                         _BinaryOperation __binary_op, _Inclusive)
 {
+    using __backend_tag = typename decltype(__tag)::__backend_tag;
+
     typedef typename std::iterator_traits<_RandomAccessIterator>::difference_type _DifferenceType;
 
-    return __internal::__except_handler([&]() {
-        __par_backend::__parallel_transform_scan(
-            std::forward<_ExecutionPolicy>(__exec), __last - __first,
-            [__first, __unary_op](_DifferenceType __i) mutable { return __unary_op(__first[__i]); }, __init,
-            __binary_op,
-            [__first, __unary_op, __binary_op](_DifferenceType __i, _DifferenceType __j, _Tp __init) {
-                // Execute serial __brick_transform_reduce, due to the explicit SIMD vectorization (reduction) requires a commutative operation for the guarantee of correct scan.
-                return __internal::__brick_transform_reduce(__first + __i, __first + __j, __init, __binary_op,
-                                                            __unary_op,
-                                                            /*__is_vector*/ std::false_type());
-            },
-            [__first, __unary_op, __binary_op, __result, __is_vector](_DifferenceType __i, _DifferenceType __j,
-                                                                      _Tp __init) {
-                return __internal::__brick_transform_scan(__first + __i, __first + __j, __result + __i, __unary_op,
-                                                          __init, __binary_op, _Inclusive(), __is_vector)
-                    .second;
-            });
-        return __result + (__last - __first);
-    });
+    return __internal::__except_handler(
+        [&]()
+        {
+            __par_backend::__parallel_transform_scan(
+                __backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __last - __first,
+                [__first, __unary_op](_DifferenceType __i) mutable { return __unary_op(__first[__i]); }, __init,
+                __binary_op,
+                [__first, __unary_op, __binary_op](_DifferenceType __i, _DifferenceType __j, _Tp __init)
+                {
+                    // Execute serial __brick_transform_reduce, due to the explicit SIMD vectorization (reduction) requires a commutative operation for the guarantee of correct scan.
+                    return __internal::__brick_transform_reduce(__first + __i, __first + __j, __init, __binary_op,
+                                                                __unary_op,
+                                                                /*__is_vector*/ std::false_type());
+                },
+                [__first, __unary_op, __binary_op, __result](_DifferenceType __i, _DifferenceType __j, _Tp __init)
+                {
+                    return __internal::__brick_transform_scan(__first + __i, __first + __j, __result + __i, __unary_op,
+                                                              __init, __binary_op, _Inclusive(), _IsVector{})
+                        .second;
+                });
+            return __result + (__last - __first);
+        });
 }
 
-template <class _ExecutionPolicy, class _RandomAccessIterator, class _OutputIterator, class _UnaryOperation, class _Tp,
-          class _BinaryOperation, class _Inclusive, class _IsVector>
+template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _OutputIterator,
+          class _UnaryOperation, class _Tp, class _BinaryOperation, class _Inclusive>
 typename std::enable_if<std::is_floating_point<_Tp>::value, _OutputIterator>::type
-__pattern_transform_scan(_ExecutionPolicy&& __exec, _RandomAccessIterator __first, _RandomAccessIterator __last,
-                         _OutputIterator __result, _UnaryOperation __unary_op, _Tp __init, _BinaryOperation __binary_op,
-                         _Inclusive, _IsVector __is_vector, /*is_parallel=*/std::true_type)
+__pattern_transform_scan(__parallel_tag<_IsVector> __tag, _ExecutionPolicy&& __exec, _RandomAccessIterator __first,
+                         _RandomAccessIterator __last, _OutputIterator __result, _UnaryOperation __unary_op, _Tp __init,
+                         _BinaryOperation __binary_op, _Inclusive)
 {
+    using __backend_tag = typename decltype(__tag)::__backend_tag;
+
     typedef typename std::iterator_traits<_RandomAccessIterator>::difference_type _DifferenceType;
     _DifferenceType __n = __last - __first;
 
@@ -263,26 +281,31 @@ __pattern_transform_scan(_ExecutionPolicy&& __exec, _RandomAccessIterator __firs
     {
         return __result;
     }
-    return __internal::__except_handler([&]() {
-        __par_backend::__parallel_strict_scan(
-            std::forward<_ExecutionPolicy>(__exec), __n, __init,
-            [__first, __unary_op, __binary_op, __result, __is_vector](_DifferenceType __i, _DifferenceType __len) {
-                return __internal::__brick_transform_scan(__first + __i, __first + (__i + __len), __result + __i,
-                                                          __unary_op, _Tp{}, __binary_op, _Inclusive(), __is_vector)
-                    .second;
-            },
-            __binary_op,
-            [__result, &__binary_op](_DifferenceType __i, _DifferenceType __len, _Tp __initial) {
-                return *(std::transform(__result + __i, __result + __i + __len, __result + __i,
-                                        [&__initial, &__binary_op](const _Tp& __x) {
-                                            _PSTL_PRAGMA_FORCEINLINE
-                                            return __binary_op(__initial, __x);
-                                        }) -
-                         1);
-            },
-            [](_Tp) {});
-        return __result + (__last - __first);
-    });
+    return __internal::__except_handler(
+        [&]()
+        {
+            __par_backend::__parallel_strict_scan(
+                __backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __n, __init,
+                [__first, __unary_op, __binary_op, __result](_DifferenceType __i, _DifferenceType __len)
+                {
+                    return __internal::__brick_transform_scan(__first + __i, __first + (__i + __len), __result + __i,
+                                                              __unary_op, _Tp{}, __binary_op, _Inclusive(), _IsVector{})
+                        .second;
+                },
+                __binary_op,
+                [__result, &__binary_op](_DifferenceType __i, _DifferenceType __len, _Tp __initial)
+                {
+                    return *(std::transform(__result + __i, __result + __i + __len, __result + __i,
+                                            [&__initial, &__binary_op](const _Tp& __x)
+                                            {
+                                                _PSTL_PRAGMA_FORCEINLINE
+                                                return __binary_op(__initial, __x);
+                                            }) -
+                             1);
+                },
+                [](_Tp) {});
+            return __result + (__last - __first);
+        });
 }
 
 //------------------------------------------------------------------------
@@ -297,15 +320,16 @@ __brick_adjacent_difference(_ForwardIterator __first, _ForwardIterator __last, _
     return std::adjacent_difference(__first, __last, __d_first, __op);
 }
 
-template <class _ForwardIterator1, class _ForwardIterator2, class _BinaryOperation>
-_ForwardIterator2
-__brick_adjacent_difference(_ForwardIterator1 __first, _ForwardIterator1 __last, _ForwardIterator2 __d_first,
-			    _BinaryOperation __op, /*is_vector=*/std::true_type) noexcept
+template <class _RandomAccessIterator1, class _RandomAccessIterator2, class BinaryOperation>
+_RandomAccessIterator2
+__brick_adjacent_difference(_RandomAccessIterator1 __first, _RandomAccessIterator1 __last,
+                            _RandomAccessIterator2 __d_first, BinaryOperation __op,
+                            /*is_vector=*/std::true_type) noexcept
 {
     _PSTL_ASSERT(__first != __last);
 
-    typedef typename std::iterator_traits<_ForwardIterator1>::reference _ReferenceType1;
-    typedef typename std::iterator_traits<_ForwardIterator2>::reference _ReferenceType2;
+    typedef typename std::iterator_traits<_RandomAccessIterator1>::reference _ReferenceType1;
+    typedef typename std::iterator_traits<_RandomAccessIterator2>::reference _ReferenceType2;
 
     auto __n = __last - __first;
     *__d_first = *__first;
@@ -314,37 +338,38 @@ __brick_adjacent_difference(_ForwardIterator1 __first, _ForwardIterator1 __last,
         [&__op](_ReferenceType1 __x, _ReferenceType1 __y, _ReferenceType2 __z) { __z = __op(__x, __y); });
 }
 
-template <class _ExecutionPolicy, class _ForwardIterator, class _OutputIterator, class _BinaryOperation,
-          class _IsVector>
+template <class _Tag, class _ExecutionPolicy, class _ForwardIterator, class _OutputIterator, class _BinaryOperation>
 _OutputIterator
-__pattern_adjacent_difference(_ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last,
-                              _OutputIterator __d_first, _BinaryOperation __op, _IsVector __is_vector,
-                              /*is_parallel*/ std::false_type) noexcept
+__pattern_adjacent_difference(_Tag, _ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last,
+                              _OutputIterator __d_first, _BinaryOperation __op) noexcept
 {
-    return __internal::__brick_adjacent_difference(__first, __last, __d_first, __op, __is_vector);
+    return __internal::__brick_adjacent_difference(__first, __last, __d_first, __op, typename _Tag::__is_vector{});
 }
 
-template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _BinaryOperation,
-          class _IsVector>
-_ForwardIterator2
-__pattern_adjacent_difference(_ExecutionPolicy&& __exec, _ForwardIterator1 __first, _ForwardIterator1 __last,
-                              _ForwardIterator2 __d_first, _BinaryOperation __op, _IsVector __is_vector,
-                              /*is_parallel=*/std::true_type)
+template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator1, class _RandomAccessIterator2,
+          class _BinaryOperation>
+_RandomAccessIterator2
+__pattern_adjacent_difference(__parallel_tag<_IsVector> __tag, _ExecutionPolicy&& __exec,
+                              _RandomAccessIterator1 __first, _RandomAccessIterator1 __last,
+                              _RandomAccessIterator2 __d_first, _BinaryOperation __op)
 {
     _PSTL_ASSERT(__first != __last);
-    typedef typename std::iterator_traits<_ForwardIterator1>::reference _ReferenceType1;
-    typedef typename std::iterator_traits<_ForwardIterator2>::reference _ReferenceType2;
+    typedef typename std::iterator_traits<_RandomAccessIterator1>::reference _ReferenceType1;
+    typedef typename std::iterator_traits<_RandomAccessIterator2>::reference _ReferenceType2;
+
+    using __backend_tag = typename decltype(__tag)::__backend_tag;
 
     *__d_first = *__first;
-    __par_backend::__parallel_for(
-        std::forward<_ExecutionPolicy>(__exec), __first, __last - 1,
-        [&__op, __is_vector, __d_first, __first](_ForwardIterator1 __b, _ForwardIterator1 __e) {
-            _ForwardIterator2 __d_b = __d_first + (__b - __first);
-            __internal::__brick_walk3(
-                __b, __e, __b + 1, __d_b + 1,
-                [&__op](_ReferenceType1 __x, _ReferenceType1 __y, _ReferenceType2 __z) { __z = __op(__y, __x); },
-                __is_vector);
-        });
+    __par_backend::__parallel_for(__backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __first, __last - 1,
+                                  [&__op, __d_first, __first](_RandomAccessIterator1 __b, _RandomAccessIterator1 __e)
+                                  {
+                                      _RandomAccessIterator2 __d_b = __d_first + (__b - __first);
+                                      __internal::__brick_walk3(
+                                          __b, __e, __b + 1, __d_b + 1,
+                                          [&__op](_ReferenceType1 __x, _ReferenceType1 __y, _ReferenceType2 __z)
+                                          { __z = __op(__y, __x); },
+                                          _IsVector{});
+                                  });
     return __d_first + (__last - __first);
 }
 
diff --git a/libstdc++-v3/include/pstl/parallel_backend.h b/libstdc++-v3/include/pstl/parallel_backend.h
index 4caa4a8e412..e9a90e11dba 100644
--- a/libstdc++-v3/include/pstl/parallel_backend.h
+++ b/libstdc++-v3/include/pstl/parallel_backend.h
@@ -22,6 +22,12 @@ namespace __pstl
 {
 namespace __par_backend = __tbb_backend;
 }
+#elif defined(_PSTL_PAR_BACKEND_OPENMP)
+#    include "parallel_backend_omp.h"
+namespace __pstl
+{
+namespace __par_backend = __omp_backend;
+}
 #else
 _PSTL_PRAGMA_MESSAGE("Parallel backend was not specified");
 #endif
diff --git a/libstdc++-v3/include/pstl/parallel_backend_serial.h b/libstdc++-v3/include/pstl/parallel_backend_serial.h
index 16e773d411a..db2da43eb06 100644
--- a/libstdc++-v3/include/pstl/parallel_backend_serial.h
+++ b/libstdc++-v3/include/pstl/parallel_backend_serial.h
@@ -50,15 +50,15 @@ __cancel_execution()
 
 template <class _ExecutionPolicy, class _Index, class _Fp>
 void
-__parallel_for(_ExecutionPolicy&&, _Index __first, _Index __last, _Fp __f)
+__parallel_for(__pstl::__internal::__serial_backend_tag, _ExecutionPolicy&&, _Index __first, _Index __last, _Fp __f)
 {
     __f(__first, __last);
 }
 
 template <class _ExecutionPolicy, class _Value, class _Index, typename _RealBody, typename _Reduction>
 _Value
-__parallel_reduce(_ExecutionPolicy&&, _Index __first, _Index __last, const _Value& __identity,
-                  const _RealBody& __real_body, const _Reduction&)
+__parallel_reduce(__pstl::__internal::__serial_backend_tag, _ExecutionPolicy&&, _Index __first, _Index __last,
+                  const _Value& __identity, const _RealBody& __real_body, const _Reduction&)
 {
     if (__first == __last)
     {
@@ -72,16 +72,16 @@ __parallel_reduce(_ExecutionPolicy&&, _Index __first, _Index __last, const _Valu
 
 template <class _ExecutionPolicy, class _Index, class _UnaryOp, class _Tp, class _BinaryOp, class _Reduce>
 _Tp
-__parallel_transform_reduce(_ExecutionPolicy&&, _Index __first, _Index __last, _UnaryOp, _Tp __init, _BinaryOp,
-                            _Reduce __reduce)
+__parallel_transform_reduce(__pstl::__internal::__serial_backend_tag, _ExecutionPolicy&&, _Index __first, _Index __last,
+                            _UnaryOp, _Tp __init, _BinaryOp, _Reduce __reduce)
 {
     return __reduce(__first, __last, __init);
 }
 
 template <class _ExecutionPolicy, typename _Index, typename _Tp, typename _Rp, typename _Cp, typename _Sp, typename _Ap>
 void
-__parallel_strict_scan(_ExecutionPolicy&&, _Index __n, _Tp __initial, _Rp __reduce, _Cp __combine, _Sp __scan,
-                       _Ap __apex)
+__parallel_strict_scan(__pstl::__internal::__serial_backend_tag, _ExecutionPolicy&&, _Index __n, _Tp __initial,
+                       _Rp __reduce, _Cp __combine, _Sp __scan, _Ap __apex)
 {
     _Tp __sum = __initial;
     if (__n)
@@ -93,15 +93,16 @@ __parallel_strict_scan(_ExecutionPolicy&&, _Index __n, _Tp __initial, _Rp __redu
 
 template <class _ExecutionPolicy, class _Index, class _UnaryOp, class _Tp, class _BinaryOp, class _Reduce, class _Scan>
 _Tp
-__parallel_transform_scan(_ExecutionPolicy&&, _Index __n, _UnaryOp, _Tp __init, _BinaryOp, _Reduce, _Scan __scan)
+__parallel_transform_scan(__pstl::__internal::__serial_backend_tag, _ExecutionPolicy&&, _Index __n, _UnaryOp,
+                          _Tp __init, _BinaryOp, _Reduce, _Scan __scan)
 {
     return __scan(_Index(0), __n, __init);
 }
 
 template <class _ExecutionPolicy, typename _RandomAccessIterator, typename _Compare, typename _LeafSort>
 void
-__parallel_stable_sort(_ExecutionPolicy&&, _RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp,
-                       _LeafSort __leaf_sort, std::size_t = 0)
+__parallel_stable_sort(__pstl::__internal::__serial_backend_tag, _ExecutionPolicy&&, _RandomAccessIterator __first,
+                       _RandomAccessIterator __last, _Compare __comp, _LeafSort __leaf_sort, std::size_t = 0)
 {
     __leaf_sort(__first, __last, __comp);
 }
@@ -109,16 +110,16 @@ __parallel_stable_sort(_ExecutionPolicy&&, _RandomAccessIterator __first, _Rando
 template <class _ExecutionPolicy, typename _RandomAccessIterator1, typename _RandomAccessIterator2,
           typename _RandomAccessIterator3, typename _Compare, typename _LeafMerge>
 void
-__parallel_merge(_ExecutionPolicy&&, _RandomAccessIterator1 __first1, _RandomAccessIterator1 __last1,
-                 _RandomAccessIterator2 __first2, _RandomAccessIterator2 __last2, _RandomAccessIterator3 __outit,
-                 _Compare __comp, _LeafMerge __leaf_merge)
+__parallel_merge(__pstl::__internal::__serial_backend_tag, _ExecutionPolicy&&, _RandomAccessIterator1 __first1,
+                 _RandomAccessIterator1 __last1, _RandomAccessIterator2 __first2, _RandomAccessIterator2 __last2,
+                 _RandomAccessIterator3 __outit, _Compare __comp, _LeafMerge __leaf_merge)
 {
     __leaf_merge(__first1, __last1, __first2, __last2, __outit, __comp);
 }
 
 template <class _ExecutionPolicy, typename _F1, typename _F2>
 void
-__parallel_invoke(_ExecutionPolicy&&, _F1&& __f1, _F2&& __f2)
+__parallel_invoke(__pstl::__internal::__serial_backend_tag, _ExecutionPolicy&&, _F1&& __f1, _F2&& __f2)
 {
     std::forward<_F1>(__f1)();
     std::forward<_F2>(__f2)();
diff --git a/libstdc++-v3/include/pstl/parallel_backend_tbb.h b/libstdc++-v3/include/pstl/parallel_backend_tbb.h
index 3fd1a06ebd8..3ff55237bff 100644
--- a/libstdc++-v3/include/pstl/parallel_backend_tbb.h
+++ b/libstdc++-v3/include/pstl/parallel_backend_tbb.h
@@ -99,7 +99,7 @@ class __parallel_for_body
 // wrapper over tbb::parallel_for
 template <class _ExecutionPolicy, class _Index, class _Fp>
 void
-__parallel_for(_ExecutionPolicy&&, _Index __first, _Index __last, _Fp __f)
+__parallel_for(__pstl::__internal::__tbb_backend_tag, _ExecutionPolicy&&, _Index __first, _Index __last, _Fp __f)
 {
     tbb::this_task_arena::isolate([=]() {
         tbb::parallel_for(tbb::blocked_range<_Index>(__first, __last), __parallel_for_body<_Index, _Fp>(__f));
@@ -110,8 +110,8 @@ __parallel_for(_ExecutionPolicy&&, _Index __first, _Index __last, _Fp __f)
 // wrapper over tbb::parallel_reduce
 template <class _ExecutionPolicy, class _Value, class _Index, typename _RealBody, typename _Reduction>
 _Value
-__parallel_reduce(_ExecutionPolicy&&, _Index __first, _Index __last, const _Value& __identity,
-                  const _RealBody& __real_body, const _Reduction& __reduction)
+__parallel_reduce(__pstl::__internal::__tbb_backend_tag, _ExecutionPolicy&&, _Index __first, _Index __last,
+                  const _Value& __identity, const _RealBody& __real_body, const _Reduction& __reduction)
 {
     return tbb::this_task_arena::isolate([__first, __last, &__identity, &__real_body, &__reduction]() -> _Value {
         return tbb::parallel_reduce(
@@ -191,8 +191,8 @@ struct __par_trans_red_body
 
 template <class _ExecutionPolicy, class _Index, class _Up, class _Tp, class _Cp, class _Rp>
 _Tp
-__parallel_transform_reduce(_ExecutionPolicy&&, _Index __first, _Index __last, _Up __u, _Tp __init, _Cp __combine,
-                            _Rp __brick_reduce)
+__parallel_transform_reduce(__pstl::__internal::__tbb_backend_tag, _ExecutionPolicy&&, _Index __first, _Index __last,
+                            _Up __u, _Tp __init, _Cp __combine, _Rp __brick_reduce)
 {
     __tbb_backend::__par_trans_red_body<_Index, _Up, _Tp, _Cp, _Rp> __body(__u, __init, __combine, __brick_reduce);
     // The grain size of 3 is used in order to provide mininum 2 elements for each body
@@ -354,8 +354,8 @@ __downsweep(_Index __i, _Index __m, _Index __tilesize, _Tp* __r, _Index __lastsi
 // T must have a trivial constructor and destructor.
 template <class _ExecutionPolicy, typename _Index, typename _Tp, typename _Rp, typename _Cp, typename _Sp, typename _Ap>
 void
-__parallel_strict_scan(_ExecutionPolicy&&, _Index __n, _Tp __initial, _Rp __reduce, _Cp __combine, _Sp __scan,
-                       _Ap __apex)
+__parallel_strict_scan(__pstl::__internal::__tbb_backend_tag, _ExecutionPolicy&&, _Index __n, _Tp __initial,
+                       _Rp __reduce, _Cp __combine, _Sp __scan, _Ap __apex)
 {
     tbb::this_task_arena::isolate([=, &__combine]() {
         if (__n > 1)
@@ -394,8 +394,8 @@ __parallel_strict_scan(_ExecutionPolicy&&, _Index __n, _Tp __initial, _Rp __redu
 
 template <class _ExecutionPolicy, class _Index, class _Up, class _Tp, class _Cp, class _Rp, class _Sp>
 _Tp
-__parallel_transform_scan(_ExecutionPolicy&&, _Index __n, _Up __u, _Tp __init, _Cp __combine, _Rp __brick_reduce,
-                          _Sp __scan)
+__parallel_transform_scan(__pstl::__internal::__tbb_backend_tag, _ExecutionPolicy&&, _Index __n, _Up __u, _Tp __init,
+                          _Cp __combine, _Rp __brick_reduce, _Sp __scan)
 {
     __trans_scan_body<_Index, _Up, _Tp, _Cp, _Rp, _Sp> __body(__u, __init, __combine, __brick_reduce, __scan);
     auto __range = tbb::blocked_range<_Index>(0, __n);
@@ -1154,8 +1154,8 @@ __stable_sort_func<_RandomAccessIterator1, _RandomAccessIterator2, _Compare, _Le
 
 template <class _ExecutionPolicy, typename _RandomAccessIterator, typename _Compare, typename _LeafSort>
 void
-__parallel_stable_sort(_ExecutionPolicy&&, _RandomAccessIterator __xs, _RandomAccessIterator __xe, _Compare __comp,
-                       _LeafSort __leaf_sort, std::size_t __nsort = 0)
+__parallel_stable_sort(__pstl::__internal::__tbb_backend_tag, _ExecutionPolicy&&, _RandomAccessIterator __xs,
+                       _RandomAccessIterator __xe, _Compare __comp, _LeafSort __leaf_sort, std::size_t __nsort = 0)
 {
     tbb::this_task_arena::isolate([=, &__nsort]() {
         //sorting based on task tree and parallel merge
@@ -1248,9 +1248,9 @@ operator()(__task* __self)
 template <class _ExecutionPolicy, typename _RandomAccessIterator1, typename _RandomAccessIterator2,
           typename _RandomAccessIterator3, typename _Compare, typename _LeafMerge>
 void
-__parallel_merge(_ExecutionPolicy&&, _RandomAccessIterator1 __xs, _RandomAccessIterator1 __xe,
-                 _RandomAccessIterator2 __ys, _RandomAccessIterator2 __ye, _RandomAccessIterator3 __zs, _Compare __comp,
-                 _LeafMerge __leaf_merge)
+__parallel_merge(__pstl::__internal::__tbb_backend_tag, _ExecutionPolicy&&, _RandomAccessIterator1 __xs,
+                 _RandomAccessIterator1 __xe, _RandomAccessIterator2 __ys, _RandomAccessIterator2 __ye,
+                 _RandomAccessIterator3 __zs, _Compare __comp, _LeafMerge __leaf_merge)
 {
     typedef typename std::iterator_traits<_RandomAccessIterator1>::difference_type _DifferenceType1;
     typedef typename std::iterator_traits<_RandomAccessIterator2>::difference_type _DifferenceType2;
@@ -1279,7 +1279,7 @@ __parallel_merge(_ExecutionPolicy&&, _RandomAccessIterator1 __xs, _RandomAccessI
 //------------------------------------------------------------------------
 template <class _ExecutionPolicy, typename _F1, typename _F2>
 void
-__parallel_invoke(_ExecutionPolicy&&, _F1&& __f1, _F2&& __f2)
+__parallel_invoke(__pstl::__internal::__tbb_backend_tag, _ExecutionPolicy&&, _F1&& __f1, _F2&& __f2)
 {
     //TODO: a version of tbb::this_task_arena::isolate with variadic arguments pack should be added in the future
     tbb::this_task_arena::isolate([&]() { tbb::parallel_invoke(std::forward<_F1>(__f1), std::forward<_F2>(__f2)); });
diff --git a/libstdc++-v3/include/pstl/parallel_impl.h b/libstdc++-v3/include/pstl/parallel_impl.h
index 46560c642ea..4cf2abde650 100644
--- a/libstdc++-v3/include/pstl/parallel_impl.h
+++ b/libstdc++-v3/include/pstl/parallel_impl.h
@@ -24,17 +24,19 @@ namespace __internal
 //-----------------------------------------------------------------------
 /** Return extremum value returned by brick f[i,j) for subranges [i,j) of [first,last)
 Each f[i,j) must return a value in [i,j). */
-template <class _ExecutionPolicy, class _Index, class _Brick, class _Compare>
+template <class _BackendTag, class _ExecutionPolicy, class _Index, class _Brick, class _Compare>
 _Index
-__parallel_find(_ExecutionPolicy&& __exec, _Index __first, _Index __last, _Brick __f, _Compare __comp, bool __b_first)
+__parallel_find(_BackendTag __tag, _ExecutionPolicy&& __exec, _Index __first, _Index __last, _Brick __f,
+                _Compare __comp, bool __b_first)
 {
     typedef typename std::iterator_traits<_Index>::difference_type _DifferenceType;
     const _DifferenceType __n = __last - __first;
     _DifferenceType __initial_dist = __b_first ? __n : -1;
     std::atomic<_DifferenceType> __extremum(__initial_dist);
     // TODO: find out what is better here: parallel_for or parallel_reduce
-    __par_backend::__parallel_for(std::forward<_ExecutionPolicy>(__exec), __first, __last,
-                                  [__comp, __f, __first, &__extremum](_Index __i, _Index __j) {
+    __par_backend::__parallel_for(__tag, std::forward<_ExecutionPolicy>(__exec), __first, __last,
+                                  [__comp, __f, __first, &__extremum](_Index __i, _Index __j)
+                                  {
                                       // See "Reducing Contention Through Priority Updates", PPoPP '13, for discussion of
                                       // why using a shared variable scales fairly well in this situation.
                                       if (__comp(__i - __first, __extremum))
@@ -59,13 +61,14 @@ __parallel_find(_ExecutionPolicy&& __exec, _Index __first, _Index __last, _Brick
 // parallel_or
 //------------------------------------------------------------------------
 //! Return true if brick f[i,j) returns true for some subrange [i,j) of [first,last)
-template <class _ExecutionPolicy, class _Index, class _Brick>
+template <class _BackendTag, class _ExecutionPolicy, class _Index, class _Brick>
 bool
-__parallel_or(_ExecutionPolicy&& __exec, _Index __first, _Index __last, _Brick __f)
+__parallel_or(_BackendTag __tag, _ExecutionPolicy&& __exec, _Index __first, _Index __last, _Brick __f)
 {
     std::atomic<bool> __found(false);
-    __par_backend::__parallel_for(std::forward<_ExecutionPolicy>(__exec), __first, __last,
-                                  [__f, &__found](_Index __i, _Index __j) {
+    __par_backend::__parallel_for(__tag, std::forward<_ExecutionPolicy>(__exec), __first, __last,
+                                  [__f, &__found](_Index __i, _Index __j)
+                                  {
                                       if (!__found.load(std::memory_order_relaxed) && __f(__i, __j))
                                       {
                                           __found.store(true, std::memory_order_relaxed);
diff --git a/libstdc++-v3/include/pstl/pstl_config.h b/libstdc++-v3/include/pstl/pstl_config.h
index d1bf08e5f3b..74d2139c736 100644
--- a/libstdc++-v3/include/pstl/pstl_config.h
+++ b/libstdc++-v3/include/pstl/pstl_config.h
@@ -11,12 +11,12 @@
 #define _PSTL_CONFIG_H
 
 // The version is XYYZ, where X is major, YY is minor, and Z is patch (i.e. X.YY.Z)
-#define _PSTL_VERSION 12000
+#define _PSTL_VERSION 17000
 #define _PSTL_VERSION_MAJOR (_PSTL_VERSION / 1000)
 #define _PSTL_VERSION_MINOR ((_PSTL_VERSION % 1000) / 10)
 #define _PSTL_VERSION_PATCH (_PSTL_VERSION % 10)
 
-#if !defined(_PSTL_PAR_BACKEND_SERIAL) && !defined(_PSTL_PAR_BACKEND_TBB)
+#if !defined(_PSTL_PAR_BACKEND_SERIAL) && !defined(_PSTL_PAR_BACKEND_TBB) && !defined(_PSTL_PAR_BACKEND_OPENMP)
 #    error "A parallel backend must be specified"
 #endif
 
@@ -53,13 +53,15 @@
 // the actual GCC version on the system.
 #define _PSTL_GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
 
-#if __clang__
+#if defined(__clang__)
 // according to clang documentation, version can be vendor specific
 #    define _PSTL_CLANG_VERSION (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__)
 #endif
 
 // Enable SIMD for compilers that support OpenMP 4.0
-#if (_OPENMP >= 201307) || (__INTEL_COMPILER >= 1600) || (!defined(__INTEL_COMPILER) && _PSTL_GCC_VERSION >= 40900) || \
+#if (defined(_OPENMP) && _OPENMP >= 201307) || \
+    (defined(__INTEL_COMPILER) && __INTEL_COMPILER >= 1600) || \
+    (!defined(__INTEL_COMPILER) && _PSTL_GCC_VERSION >= 40900) || \
     defined(__clang__)
 #    define _PSTL_PRAGMA_SIMD _PSTL_PRAGMA(omp simd)
 #    define _PSTL_PRAGMA_DECLARE_SIMD _PSTL_PRAGMA(omp declare simd)
@@ -74,13 +76,13 @@
 #    define _PSTL_PRAGMA_SIMD_REDUCTION(PRM)
 #endif //Enable SIMD
 
-#if (__INTEL_COMPILER)
+#if defined(__INTEL_COMPILER)
 #    define _PSTL_PRAGMA_FORCEINLINE _PSTL_PRAGMA(forceinline)
 #else
 #    define _PSTL_PRAGMA_FORCEINLINE
 #endif
 
-#if (__INTEL_COMPILER >= 1900)
+#if defined(__INTEL_COMPILER) && __INTEL_COMPILER >= 1900
 #    define _PSTL_PRAGMA_SIMD_SCAN(PRM) _PSTL_PRAGMA(omp simd reduction(inscan, PRM))
 #    define _PSTL_PRAGMA_SIMD_INCLUSIVE_SCAN(PRM) _PSTL_PRAGMA(omp scan inclusive(PRM))
 #    define _PSTL_PRAGMA_SIMD_EXCLUSIVE_SCAN(PRM) _PSTL_PRAGMA(omp scan exclusive(PRM))
@@ -91,34 +93,50 @@
 #endif
 
 // Should be defined to 1 for environments with a vendor implementation of C++17 execution policies
-#define _PSTL_CPP17_EXECUTION_POLICIES_PRESENT (_MSC_VER >= 1912)
+#define _PSTL_CPP17_EXECUTION_POLICIES_PRESENT (_MSC_VER >= 1912 && _MSVC_LANG >= 201703L) ||                          \
+    (_GLIBCXX_RELEASE >= 9 && __GLIBCXX__ >= 20190503 && __cplusplus >= 201703L)
 
-#define _PSTL_CPP14_2RANGE_MISMATCH_EQUAL_PRESENT                                                                      \
-    (_MSC_VER >= 1900 || __cplusplus >= 201300L || __cpp_lib_robust_nonmodifying_seq_ops == 201304)
-#define _PSTL_CPP14_MAKE_REVERSE_ITERATOR_PRESENT                                                                      \
-    (_MSC_VER >= 1900 || __cplusplus >= 201402L || __cpp_lib_make_reverse_iterator == 201402)
-#define _PSTL_CPP14_INTEGER_SEQUENCE_PRESENT (_MSC_VER >= 1900 || __cplusplus >= 201402L)
-#define _PSTL_CPP14_VARIABLE_TEMPLATES_PRESENT                                                                         \
-    (!__INTEL_COMPILER || __INTEL_COMPILER >= 1700) && (_MSC_FULL_VER >= 190023918 || __cplusplus >= 201402L)
-
-#define _PSTL_EARLYEXIT_PRESENT (__INTEL_COMPILER >= 1800)
-#define _PSTL_MONOTONIC_PRESENT (__INTEL_COMPILER >= 1800)
-
-#if (__INTEL_COMPILER >= 1900 || !defined(__INTEL_COMPILER) && _PSTL_GCC_VERSION >= 40900 || _OPENMP >= 201307)
-#    define _PSTL_UDR_PRESENT 1
-#else
-#    define _PSTL_UDR_PRESENT 0
+#if (defined(_MSC_VER) && _MSC_VER >= 1900) || \
+    __cplusplus >= 201300L || \
+    __cpp_lib_robust_nonmodifying_seq_ops == 201304
+#   define _PSTL_CPP14_2RANGE_MISMATCH_EQUAL_PRESENT
+#endif
+#if (defined(_MSC_VER) && _MSC_VER >= 1900) || \
+    __cplusplus >= 201402L || \
+    __cpp_lib_make_reverse_iterator == 201402
+#   define _PSTL_CPP14_MAKE_REVERSE_ITERATOR_PRESENT
+#endif
+#if (defined(_MSC_VER) && _MSC_VER >= 1900) || __cplusplus >= 201402L
+#   define _PSTL_CPP14_INTEGER_SEQUENCE_PRESENT
+#endif
+#if (defined(__INTEL_COMPILER) && __INTEL_COMPILER >= 1700) || \
+    (defined(_MSC_FULL_VER) && _MSC_FULL_VER >= 190023918) || \
+    __cplusplus >= 201402L
+#   define _PSTL_CPP14_VARIABLE_TEMPLATES_PRESENT
 #endif
 
-#define _PSTL_UDS_PRESENT (__INTEL_COMPILER >= 1900 && __INTEL_COMPILER_BUILD_DATE >= 20180626)
+#if defined(__INTEL_COMPILER) && __INTEL_COMPILER >= 1800
+#   define _PSTL_EARLYEXIT_PRESENT
+#   define _PSTL_MONOTONIC_PRESENT
+#endif
 
-#if _PSTL_EARLYEXIT_PRESENT
+#if (defined(__INTEL_COMPILER) && __INTEL_COMPILER >= 1900) || \
+    (!defined(__INTEL_COMPILER) && _PSTL_GCC_VERSION >= 40900) || \
+    (defined(_OPENMP) && _OPENMP >= 201307)
+#    define _PSTL_UDR_PRESENT
+#endif
+
+#if defined(__INTEL_COMPILER) && __INTEL_COMPILER >= 1900 && __INTEL_COMPILER_BUILD_DATE >= 20180626
+#   define _PSTL_UDS_PRESENT
+#endif
+
+#if defined(_PSTL_EARLYEXIT_PRESENT)
 #    define _PSTL_PRAGMA_SIMD_EARLYEXIT _PSTL_PRAGMA(omp simd early_exit)
 #else
 #    define _PSTL_PRAGMA_SIMD_EARLYEXIT
 #endif
 
-#if _PSTL_MONOTONIC_PRESENT
+#if defined(_PSTL_MONOTONIC_PRESENT)
 #    define _PSTL_PRAGMA_SIMD_ORDERED_MONOTONIC(PRM) _PSTL_PRAGMA(omp ordered simd monotonic(PRM))
 #    define _PSTL_PRAGMA_SIMD_ORDERED_MONOTONIC_2ARGS(PRM1, PRM2) _PSTL_PRAGMA(omp ordered simd monotonic(PRM1, PRM2))
 #else
@@ -136,7 +154,7 @@
 #define _PSTL_PRAGMA_DECLARE_REDUCTION(NAME, OP)                                                                       \
     _PSTL_PRAGMA(omp declare reduction(NAME:OP : omp_out(omp_in)) initializer(omp_priv = omp_orig))
 
-#if (__INTEL_COMPILER >= 1600)
+#if defined(__INTEL_COMPILER) && __INTEL_COMPILER >= 1600
 #    define _PSTL_PRAGMA_VECTOR_UNALIGNED _PSTL_PRAGMA(vector unaligned)
 #else
 #    define _PSTL_PRAGMA_VECTOR_UNALIGNED
@@ -149,7 +167,7 @@
 #    define _PSTL_USE_NONTEMPORAL_STORES_IF_ALLOWED
 #endif
 
-#if _MSC_VER || __INTEL_COMPILER //the preprocessors don't type a message location
+#if defined(_MSC_VER) || defined(__INTEL_COMPILER) // the preprocessors don't type a message location
 #    define _PSTL_PRAGMA_LOCATION __FILE__ ":" _PSTL_STRING(__LINE__) ": [Parallel STL message]: "
 #else
 #    define _PSTL_PRAGMA_LOCATION " [Parallel STL message]: "
@@ -157,7 +175,7 @@
 
 #define _PSTL_PRAGMA_MESSAGE_IMPL(x) _PSTL_PRAGMA(message(_PSTL_STRING_CONCAT(_PSTL_PRAGMA_LOCATION, x)))
 
-#if _PSTL_USAGE_WARNINGS
+#if defined(_PSTL_USAGE_WARNINGS)
 #    define _PSTL_PRAGMA_MESSAGE(x) _PSTL_PRAGMA_MESSAGE_IMPL(x)
 #    define _PSTL_PRAGMA_MESSAGE_POLICIES(x) _PSTL_PRAGMA_MESSAGE_IMPL(x)
 #else
@@ -166,8 +184,13 @@
 #endif
 
 // broken macros
-#define _PSTL_CPP11_STD_ROTATE_BROKEN ((__GLIBCXX__ && __GLIBCXX__ < 20150716) || (_MSC_VER && _MSC_VER < 1800))
+#if (defined(__GLIBCXX__) && __GLIBCXX__ < 20150716) || \
+    (defined(_MSC_VER) && _MSC_VER < 1800)
+#   define _PSTL_CPP11_STD_ROTATE_BROKEN
+#endif
 
-#define _PSTL_ICC_18_OMP_SIMD_BROKEN (__INTEL_COMPILER == 1800)
+#if defined(__INTEL_COMPILER) && __INTEL_COMPILER == 1800
+#   define _PSTL_ICC_18_OMP_SIMD_BROKEN
+#endif
 
 #endif /* _PSTL_CONFIG_H */
diff --git a/libstdc++-v3/include/pstl/unseq_backend_simd.h b/libstdc++-v3/include/pstl/unseq_backend_simd.h
index 7cda7ffeddc..af7e6c2d478 100644
--- a/libstdc++-v3/include/pstl/unseq_backend_simd.h
+++ b/libstdc++-v3/include/pstl/unseq_backend_simd.h
@@ -61,7 +61,7 @@ template <class _Index, class _DifferenceType, class _Pred>
 bool
 __simd_or(_Index __first, _DifferenceType __n, _Pred __pred) noexcept
 {
-#if _PSTL_EARLYEXIT_PRESENT
+#if defined(_PSTL_EARLYEXIT_PRESENT)
     _DifferenceType __i;
     _PSTL_PRAGMA_VECTOR_UNALIGNED
     _PSTL_PRAGMA_SIMD_EARLYEXIT
@@ -74,7 +74,7 @@ __simd_or(_Index __first, _DifferenceType __n, _Pred __pred) noexcept
     const _Index __last = __first + __n;
     while (__last != __first)
     {
-        __INT32_TYPE__ __flag = 1;
+        int32_t __flag = 1;
         _PSTL_PRAGMA_SIMD_REDUCTION(& : __flag)
         for (_DifferenceType __i = 0; __i < __block_size; ++__i)
             if (__pred(*(__first + __i)))
@@ -101,7 +101,7 @@ template <class _Index, class _DifferenceType, class _Compare>
 _Index
 __simd_first(_Index __first, _DifferenceType __begin, _DifferenceType __end, _Compare __comp) noexcept
 {
-#if _PSTL_EARLYEXIT_PRESENT
+#if defined(_PSTL_EARLYEXIT_PRESENT)
     _DifferenceType __i = __begin;
     _PSTL_PRAGMA_VECTOR_UNALIGNED // Do not generate peel loop part
         _PSTL_PRAGMA_SIMD_EARLYEXIT for (; __i < __end; ++__i)
@@ -161,7 +161,7 @@ template <class _Index1, class _DifferenceType, class _Index2, class _Pred>
 std::pair<_Index1, _Index2>
 __simd_first(_Index1 __first1, _DifferenceType __n, _Index2 __first2, _Pred __pred) noexcept
 {
-#if _PSTL_EARLYEXIT_PRESENT
+#if defined(_PSTL_EARLYEXIT_PRESENT)
     _DifferenceType __i = 0;
     _PSTL_PRAGMA_VECTOR_UNALIGNED
     _PSTL_PRAGMA_SIMD_EARLYEXIT
@@ -383,7 +383,7 @@ __simd_adjacent_find(_Index __first, _Index __last, _BinaryPredicate __pred, boo
     typedef typename std::iterator_traits<_Index>::difference_type _DifferenceType;
     _DifferenceType __i = 0;
 
-#if _PSTL_EARLYEXIT_PRESENT
+#if defined(_PSTL_EARLYEXIT_PRESENT)
     //Some compiler versions fail to compile the following loop when iterators are used. Indices are used instead
     const _DifferenceType __n = __last - __first - 1;
     _PSTL_PRAGMA_VECTOR_UNALIGNED
@@ -532,7 +532,7 @@ struct _Combiner
     _BinaryOp* __bin_op; // Here is a pointer to function because of default ctor
 
     _Combiner() : __value{}, __bin_op(nullptr) {}
-    _Combiner(const _Tp& value, const _BinaryOp* __bin_op) : __value(value), __bin_op(const_cast<_BinaryOp*>(__bin_op)) {}
+    _Combiner(const _Tp& value, const _BinaryOp* bin_op) : __value(value), __bin_op(const_cast<_BinaryOp*>(bin_op)) {}
     _Combiner(const _Combiner& __obj) : __value{}, __bin_op(__obj.__bin_op) {}
 
     void
@@ -624,8 +624,8 @@ __simd_min_element(_ForwardIterator __first, _Size __n, _Compare __comp) noexcep
         _Compare* __min_comp;
 
         _ComplexType() : __min_val{}, __min_ind{}, __min_comp(nullptr) {}
-        _ComplexType(const _ValueType& __val, const _Compare* comp)
-            : __min_val(__val), __min_ind(0), __min_comp(const_cast<_Compare*>(comp))
+        _ComplexType(const _ValueType& val, const _Compare* comp)
+            : __min_val(val), __min_ind(0), __min_comp(const_cast<_Compare*>(comp))
         {
         }
         _ComplexType(const _ComplexType& __obj)
@@ -685,8 +685,8 @@ __simd_minmax_element(_ForwardIterator __first, _Size __n, _Compare __comp) noex
         _Compare* __minmax_comp;
 
         _ComplexType() : __min_val{}, __max_val{}, __min_ind{}, __max_ind{}, __minmax_comp(nullptr) {}
-        _ComplexType(const _ValueType& __min_val, const _ValueType& __max_val, const _Compare* comp)
-            : __min_val(__min_val), __max_val(__max_val), __min_ind(0), __max_ind(0),
+        _ComplexType(const _ValueType& min_val, const _ValueType& max_val, const _Compare* comp)
+            : __min_val(min_val), __max_val(max_val), __min_ind(0), __max_ind(0),
               __minmax_comp(const_cast<_Compare*>(comp))
         {
         }
diff --git a/libstdc++-v3/include/pstl/utils.h b/libstdc++-v3/include/pstl/utils.h
index 0e908f1c539..e2611053f53 100644
--- a/libstdc++-v3/include/pstl/utils.h
+++ b/libstdc++-v3/include/pstl/utils.h
@@ -19,8 +19,8 @@ namespace __internal
 {
 
 template <typename _Fp>
-typename std::result_of<_Fp()>::type
-__except_handler(_Fp __f)
+auto
+__except_handler(_Fp __f) -> decltype(__f())
 {
     try
     {
@@ -44,8 +44,7 @@ __invoke_if(std::true_type, _Fp __f)
 }
 
 template <typename _Fp>
-void
-__invoke_if(std::false_type, _Fp __f)
+void __invoke_if(std::false_type, _Fp)
 {
 }
 
@@ -57,21 +56,20 @@ __invoke_if_not(std::false_type, _Fp __f)
 }
 
 template <typename _Fp>
-void
-__invoke_if_not(std::true_type, _Fp __f)
+void __invoke_if_not(std::true_type, _Fp)
 {
 }
 
 template <typename _F1, typename _F2>
-typename std::result_of<_F1()>::type
-__invoke_if_else(std::true_type, _F1 __f1, _F2 __f2)
+auto
+__invoke_if_else(std::true_type, _F1 __f1, _F2) -> decltype(__f1())
 {
     return __f1();
 }
 
 template <typename _F1, typename _F2>
-typename std::result_of<_F2()>::type
-__invoke_if_else(std::false_type, _F1 __f1, _F2 __f2)
+auto
+__invoke_if_else(std::false_type, _F1, _F2 __f2) -> decltype(__f2())
 {
     return __f2();
 }
@@ -87,23 +85,6 @@ struct __no_op
     }
 };
 
-//! Logical negation of a predicate
-template <typename _Pred>
-class __not_pred
-{
-    _Pred _M_pred;
-
-  public:
-    explicit __not_pred(_Pred __pred) : _M_pred(__pred) {}
-
-    template <typename... _Args>
-    bool
-    operator()(_Args&&... __args)
-    {
-        return !_M_pred(std::forward<_Args>(__args)...);
-    }
-};
-
 template <typename _Pred>
 class __reorder_pred
 {
@@ -120,36 +101,6 @@ class __reorder_pred
     }
 };
 
-//! "==" comparison.
-/** Not called "equal" to avoid (possibly unfounded) concerns about accidental invocation via
-    argument-dependent name lookup by code expecting to find the usual std::equal. */
-class __pstl_equal
-{
-  public:
-    explicit __pstl_equal() {}
-
-    template <typename _Xp, typename _Yp>
-    bool
-    operator()(_Xp&& __x, _Yp&& __y) const
-    {
-        return std::forward<_Xp>(__x) == std::forward<_Yp>(__y);
-    }
-};
-
-//! "<" comparison.
-class __pstl_less
-{
-  public:
-    explicit __pstl_less() {}
-
-    template <typename _Xp, typename _Yp>
-    bool
-    operator()(_Xp&& __x, _Yp&& __y) const
-    {
-        return std::forward<_Xp>(__x) < std::forward<_Yp>(__y);
-    }
-};
-
 //! Like a polymorphic lambda for pred(...,value)
 template <typename _Tp, typename _Predicate>
 class __equal_value_by_pred
diff --git a/libstdc++-v3/testsuite/20_util/specialized_algorithms/pstl/uninitialized_construct.cc b/libstdc++-v3/testsuite/20_util/specialized_algorithms/pstl/uninitialized_construct.cc
index dc099410242..407e4885327 100644
--- a/libstdc++-v3/testsuite/20_util/specialized_algorithms/pstl/uninitialized_construct.cc
+++ b/libstdc++-v3/testsuite/20_util/specialized_algorithms/pstl/uninitialized_construct.cc
@@ -112,12 +112,12 @@ test_uninit_construct_by_type()
     }
 }
 
-int32_t
+int
 main()
 {
 
     // for user-defined types
-#if !_PSTL_ICC_16_VC14_TEST_PAR_TBB_RT_RELEASE_64_BROKEN
+#if !defined(_PSTL_ICC_16_VC14_TEST_PAR_TBB_RT_RELEASE_64_BROKEN)
     test_uninit_construct_by_type<Wrapper<int32_t>>();
     test_uninit_construct_by_type<Wrapper<std::vector<std::string>>>();
 #endif
diff --git a/libstdc++-v3/testsuite/20_util/specialized_algorithms/pstl/uninitialized_copy_move.cc b/libstdc++-v3/testsuite/20_util/specialized_algorithms/pstl/uninitialized_copy_move.cc
index 73b09829574..2558147a7f1 100644
--- a/libstdc++-v3/testsuite/20_util/specialized_algorithms/pstl/uninitialized_copy_move.cc
+++ b/libstdc++-v3/testsuite/20_util/specialized_algorithms/pstl/uninitialized_copy_move.cc
@@ -81,16 +81,16 @@ struct test_uninitialized_copy_move
         std::destroy_n(exec, out_first, n);
     }
 
-#if _PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN || _PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN
+#if defined(_PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN) || defined(_PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN)
     template <typename InputIterator, typename OutputIterator>
     void
-    operator()(pstl::execution::unsequenced_policy, InputIterator first, InputIterator last, OutputIterator out_first,
+    operator()(__pstl::execution::unsequenced_policy, InputIterator first, InputIterator last, OutputIterator out_first,
                size_t n, /*is_trivial<T>=*/std::true_type)
     {
     }
     template <typename InputIterator, typename OutputIterator>
     void
-    operator()(pstl::execution::parallel_unsequenced_policy, InputIterator first, InputIterator last,
+    operator()(__pstl::execution::parallel_unsequenced_policy, InputIterator first, InputIterator last,
                OutputIterator out_first, size_t n, /*is_trivial<T>=*/std::true_type)
     {
     }
@@ -101,8 +101,6 @@ struct test_uninitialized_copy_move
     operator()(Policy&& exec, InputIterator first, InputIterator last, OutputIterator out_first, size_t n,
                /*is_trivial<T>=*/std::true_type)
     {
-        typedef typename std::iterator_traits<InputIterator>::value_type T;
-
         std::uninitialized_copy(exec, first, last, out_first);
         EXPECT_TRUE(IsCheckValueCorrectness(first, out_first, n), "wrong uninitialized_copy");
         std::destroy_n(exec, out_first, n);
@@ -134,7 +132,7 @@ test_uninitialized_copy_move_by_type()
     }
 }
 
-int32_t
+int
 main()
 {
 
@@ -143,8 +141,8 @@ main()
     test_uninitialized_copy_move_by_type<float64_t>();
 
     // for user-defined types
-#if !_PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN && !_PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN &&   \
-    !_PSTL_ICC_16_VC14_TEST_PAR_TBB_RT_RELEASE_64_BROKEN
+#if !defined(_PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN) && !defined(_PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN) &&     \
+    !defined(_PSTL_ICC_16_VC14_TEST_PAR_TBB_RT_RELEASE_64_BROKEN)
     test_uninitialized_copy_move_by_type<Wrapper<int8_t>>();
 #endif
 
diff --git a/libstdc++-v3/testsuite/20_util/specialized_algorithms/pstl/uninitialized_fill_destroy.cc b/libstdc++-v3/testsuite/20_util/specialized_algorithms/pstl/uninitialized_fill_destroy.cc
index 1683e64ad2d..fed9bdb8886 100644
--- a/libstdc++-v3/testsuite/20_util/specialized_algorithms/pstl/uninitialized_fill_destroy.cc
+++ b/libstdc++-v3/testsuite/20_util/specialized_algorithms/pstl/uninitialized_fill_destroy.cc
@@ -87,7 +87,7 @@ test_uninitialized_fill_destroy_by_type()
     }
 }
 
-int32_t
+int
 main()
 {
     // for trivial types
diff --git a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_merge/inplace_merge.cc b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_merge/inplace_merge.cc
index 14993446f6b..576f22423b8 100644
--- a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_merge/inplace_merge.cc
+++ b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_merge/inplace_merge.cc
@@ -30,18 +30,18 @@ using namespace TestUtils;
 
 struct test_one_policy
 {
-#if _PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN ||                                                            \
-    _PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN // dummy specialization by policy type, in case of broken configuration
+#if defined(_PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN) ||                                                             \
+    defined(_PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN) // dummy specialization by policy type, in case of broken configuration
     template <typename BiDirIt1, typename Size, typename Generator1, typename Generator2, typename Compare>
     void
-    operator()(pstl::execution::unsequenced_policy, BiDirIt1 first1, BiDirIt1 last1, BiDirIt1 first2, BiDirIt1 last2,
+    operator()(__pstl::execution::unsequenced_policy, BiDirIt1 first1, BiDirIt1 last1, BiDirIt1 first2, BiDirIt1 last2,
                Size n, Size m, Generator1 generator1, Generator2 generator2, Compare comp)
     {
     }
 
     template <typename BiDirIt1, typename Size, typename Generator1, typename Generator2, typename Compare>
     void
-    operator()(pstl::execution::parallel_unsequenced_policy, BiDirIt1 first1, BiDirIt1 last1, BiDirIt1 first2,
+    operator()(__pstl::execution::parallel_unsequenced_policy, BiDirIt1 first1, BiDirIt1 last1, BiDirIt1 first2,
                BiDirIt1 last2, Size n, Size m, Generator1 generator1, Generator2 generator2, Compare comp)
     {
     }
@@ -54,8 +54,6 @@ struct test_one_policy
     operator()(Policy&& exec, BiDirIt1 first1, BiDirIt1 last1, BiDirIt1 first2, BiDirIt1 last2, Size n, Size m,
                Generator1 generator1, Generator2 generator2, Compare comp)
     {
-
-        using T = typename std::iterator_traits<BiDirIt1>::value_type;
         const BiDirIt1 mid1 = std::next(first1, m);
         fill_data(first1, mid1, generator1);
         fill_data(mid1, last1, generator2);
@@ -72,8 +70,7 @@ struct test_one_policy
     template <typename Policy, typename BiDirIt1, typename Size, typename Generator1, typename Generator2,
               typename Compare>
     typename std::enable_if<is_same_iterator_category<BiDirIt1, std::forward_iterator_tag>::value, void>::type
-    operator()(Policy&& exec, BiDirIt1 first1, BiDirIt1 last1, BiDirIt1 first2, BiDirIt1 last2, Size n, Size m,
-               Generator1 generator1, Generator2 generator2, Compare comp)
+    operator()(Policy&&, BiDirIt1, BiDirIt1, BiDirIt1, BiDirIt1, Size, Size, Generator1, Generator2, Compare)
     {
     }
 };
@@ -146,7 +143,7 @@ struct test_non_const
     }
 };
 
-int32_t
+int
 main()
 {
     test_by_type<float64_t>([](int32_t i) { return -2 * i; }, [](int32_t i) { return -(2 * i + 1); },
@@ -160,6 +157,13 @@ main()
 
     test_algo_basic_single<int32_t>(run_for_rnd_bi<test_non_const<int32_t>>());
 
+    test_by_type<MemoryChecker>(
+        [](std::size_t idx){ return MemoryChecker{std::int32_t(idx * 2)}; },
+        [](std::size_t idx){ return MemoryChecker{std::int32_t(idx * 2 + 1)}; },
+        [](const MemoryChecker& val1, const MemoryChecker& val2){ return val1.value() == val2.value(); });
+    EXPECT_FALSE(MemoryChecker::alive_objects() < 0, "wrong effect from inplace_merge: number of ctors calls < num of dtors calls");
+    EXPECT_FALSE(MemoryChecker::alive_objects() > 0, "wrong effect from inplace_merge: number of ctors calls > num of dtors calls");
+
     std::cout << done() << std::endl;
     return 0;
 }
diff --git a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_merge/merge.cc b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_merge/merge.cc
index e6eeb1dde66..eab12608515 100644
--- a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_merge/merge.cc
+++ b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_merge/merge.cc
@@ -23,6 +23,7 @@
 #else
 #include <execution>
 #include <algorithm>
+#include <functional>
 #endif // PSTL_STANDALONE_TESTS
 
 #include "pstl/test_utils.h"
@@ -58,8 +59,7 @@ struct test_merge
     void
     operator()(Policy&& exec, std::reverse_iterator<InputIterator1> first1, std::reverse_iterator<InputIterator1> last1,
                std::reverse_iterator<InputIterator2> first2, std::reverse_iterator<InputIterator2> last2,
-               std::reverse_iterator<OutputIterator> out_first, std::reverse_iterator<OutputIterator> out_last,
-               Compare comp)
+               std::reverse_iterator<OutputIterator> out_first, std::reverse_iterator<OutputIterator> out_last, Compare)
     {
         using namespace std;
         typedef typename std::iterator_traits<std::reverse_iterator<InputIterator1>>::value_type T;
@@ -106,13 +106,13 @@ struct test_non_const
     }
 };
 
-int32_t
+int
 main()
 {
     test_merge_by_type<int32_t>([](size_t v) { return (v % 2 == 0 ? v : -v) * 3; }, [](size_t v) { return v * 2; });
     test_merge_by_type<float64_t>([](size_t v) { return float64_t(v); }, [](size_t v) { return float64_t(v - 100); });
 
-#if !_PSTL_ICC_16_17_TEST_64_TIMEOUT
+#if !defined(_PSTL_ICC_16_17_TEST_64_TIMEOUT)
     test_merge_by_type<Wrapper<int16_t>>([](size_t v) { return Wrapper<int16_t>(v % 100); },
                                          [](size_t v) { return Wrapper<int16_t>(v % 10); });
 #endif
diff --git a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/copy_if.cc b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/copy_if.cc
index 5b90e83f983..9c1f1725ac2 100644
--- a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/copy_if.cc
+++ b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/copy_if.cc
@@ -29,7 +29,7 @@ using namespace TestUtils;
 
 struct run_copy_if
 {
-#if _PSTL_ICC_16_VC14_TEST_PAR_TBB_RT_RELEASE_64_BROKEN // dummy specializations to skip testing in case of broken configuration
+#if defined(_PSTL_ICC_16_VC14_TEST_PAR_TBB_RT_RELEASE_64_BROKEN) // dummy specializations to skip testing in case of broken configuration
     template <typename InputIterator, typename OutputIterator, typename OutputIterator2, typename Size,
               typename Predicate, typename T>
     void
@@ -131,7 +131,7 @@ struct test_non_const
     }
 };
 
-int32_t
+int
 main()
 {
     test<float64_t>(-666.0, [](const float64_t& x) { return x * x <= 1024; },
@@ -140,12 +140,12 @@ main()
     test<int32_t>(-666, [](const int32_t& x) { return x != 42; },
                   [](size_t j) { return ((j + 1) % 5 & 2) != 0 ? int32_t(j + 1) : 42; });
 
-#if !_PSTL_ICC_17_TEST_MAC_RELEASE_32_BROKEN
+#if !defined(_PSTL_ICC_17_TEST_MAC_RELEASE_32_BROKEN)
     test<Number>(Number(42, OddTag()), IsMultiple(3, OddTag()), [](int32_t j) { return Number(j, OddTag()); });
 #endif
 
-#if !_PSTL_ICC_16_17_TEST_REDUCTION_RELEASE_BROKEN
-    test<int32_t>(-666, [](const int32_t& x) { return true; }, [](size_t j) { return j; }, false);
+#if !defined(_PSTL_ICC_16_17_TEST_REDUCTION_RELEASE_BROKEN)
+    test<int32_t>(-666, [](const int32_t&) { return true; }, [](size_t j) { return j; }, false);
 #endif
 
     test_algo_basic_double<int32_t>(run_for_rnd_fw<test_non_const>());
diff --git a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/copy_move.cc b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/copy_move.cc
index 73c368b6937..5f4f984ae06 100644
--- a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/copy_move.cc
+++ b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/copy_move.cc
@@ -31,11 +31,11 @@ using namespace TestUtils;
 struct run_copy
 {
 
-#if _PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN ||                                                            \
-    _PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN //dummy specialization by policy type, in case of broken configuration
+#if defined(_PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN) ||                                                             \
+    defined(_PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN) //dummy specialization by policy type, in case of broken configuration
     template <typename InputIterator, typename OutputIterator, typename OutputIterator2, typename Size, typename T>
     void
-    operator()(pstl::execution::unsequenced_policy, InputIterator first, InputIterator last, OutputIterator out_first,
+    operator()(__pstl::execution::unsequenced_policy, InputIterator first, InputIterator last, OutputIterator out_first,
                OutputIterator out_last, OutputIterator2 expected_first, OutputIterator2 expected_last, Size size,
                Size n, T trash)
     {
@@ -43,7 +43,7 @@ struct run_copy
 
     template <typename InputIterator, typename OutputIterator, typename OutputIterator2, typename Size, typename T>
     void
-    operator()(pstl::execution::parallel_unsequenced_policy, InputIterator first, InputIterator last,
+    operator()(__pstl::execution::parallel_unsequenced_policy, InputIterator first, InputIterator last,
                OutputIterator out_first, OutputIterator out_last, OutputIterator2 expected_first,
                OutputIterator2 expected_last, Size size, Size n, T trash)
     {
@@ -54,8 +54,7 @@ struct run_copy
               typename T>
     void
     operator()(Policy&& exec, InputIterator first, InputIterator last, OutputIterator out_first,
-               OutputIterator out_last, OutputIterator2 expected_first, OutputIterator2 expected_last, Size size,
-               Size n, T trash)
+               OutputIterator out_last, OutputIterator2 expected_first, OutputIterator2, Size size, Size n, T trash)
     {
         // Cleaning
         std::fill_n(expected_first, size, trash);
@@ -84,11 +83,11 @@ template <typename T>
 struct run_move
 {
 
-#if _PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN ||                                                            \
-    _PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN //dummy specialization by policy type, in case of broken configuration
+#if defined(_PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN) ||                                                             \
+    defined(_PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN) //dummy specialization by policy type, in case of broken configuration
     template <typename InputIterator, typename OutputIterator, typename OutputIterator2, typename Size>
     void
-    operator()(pstl::execution::unsequenced_policy, InputIterator first, InputIterator last, OutputIterator out_first,
+    operator()(__pstl::execution::unsequenced_policy, InputIterator first, InputIterator last, OutputIterator out_first,
                OutputIterator out_last, OutputIterator2 expected_first, OutputIterator2 expected_last, Size size,
                Size n, T trash)
     {
@@ -96,7 +95,7 @@ struct run_move
 
     template <typename InputIterator, typename OutputIterator, typename OutputIterator2, typename Size>
     void
-    operator()(pstl::execution::parallel_unsequenced_policy, InputIterator first, InputIterator last,
+    operator()(__pstl::execution::parallel_unsequenced_policy, InputIterator first, InputIterator last,
                OutputIterator out_first, OutputIterator out_last, OutputIterator2 expected_first,
                OutputIterator2 expected_last, Size size, Size n, T trash)
     {
@@ -106,8 +105,7 @@ struct run_move
     template <typename Policy, typename InputIterator, typename OutputIterator, typename OutputIterator2, typename Size>
     void
     operator()(Policy&& exec, InputIterator first, InputIterator last, OutputIterator out_first,
-               OutputIterator out_last, OutputIterator2 expected_first, OutputIterator2 expected_last, Size size,
-               Size n, T trash)
+               OutputIterator out_last, OutputIterator2 expected_first, OutputIterator2, Size size, Size, T trash)
     {
         // Cleaning
         std::fill_n(expected_first, size, trash);
@@ -127,11 +125,11 @@ template <typename T>
 struct run_move<Wrapper<T>>
 {
 
-#if _PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN ||                                                            \
-    _PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN //dummy specialization by policy type, in case of broken configuration
+#if defined(_PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN) ||                                                             \
+    defined(_PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN) //dummy specialization by policy type, in case of broken configuration
     template <typename InputIterator, typename OutputIterator, typename OutputIterator2, typename Size>
     void
-    operator()(pstl::execution::unsequenced_policy, InputIterator first, InputIterator last, OutputIterator out_first,
+    operator()(__pstl::execution::unsequenced_policy, InputIterator first, InputIterator last, OutputIterator out_first,
                OutputIterator out_last, OutputIterator2 expected_first, OutputIterator2 expected_last, Size size,
                Size n, Wrapper<T> trash)
     {
@@ -139,7 +137,7 @@ struct run_move<Wrapper<T>>
 
     template <typename InputIterator, typename OutputIterator, typename OutputIterator2, typename Size>
     void
-    operator()(pstl::execution::parallel_unsequenced_policy, InputIterator first, InputIterator last,
+    operator()(__pstl::execution::parallel_unsequenced_policy, InputIterator first, InputIterator last,
                OutputIterator out_first, OutputIterator out_last, OutputIterator2 expected_first,
                OutputIterator2 expected_last, Size size, Size n, Wrapper<T> trash)
     {
@@ -149,8 +147,7 @@ struct run_move<Wrapper<T>>
     template <typename Policy, typename InputIterator, typename OutputIterator, typename OutputIterator2, typename Size>
     void
     operator()(Policy&& exec, InputIterator first, InputIterator last, OutputIterator out_first,
-               OutputIterator out_last, OutputIterator2 expected_first, OutputIterator2 expected_last, Size size,
-               Size n, Wrapper<T> trash)
+               OutputIterator out_last, OutputIterator2, OutputIterator2, Size size, Size, Wrapper<T> trash)
     {
         // Cleaning
         std::fill_n(out_first, size, trash);
@@ -194,13 +191,13 @@ test(T trash, Convert convert)
     }
 }
 
-int32_t
+int
 main()
 {
     test<int32_t>(-666, [](size_t j) { return int32_t(j); });
     test<Wrapper<float64_t>>(Wrapper<float64_t>(-666.0), [](int32_t j) { return Wrapper<float64_t>(j); });
 
-#if !_PSTL_ICC_16_17_TEST_64_TIMEOUT
+#if !defined(_PSTL_ICC_16_17_TEST_64_TIMEOUT)
     test<float64_t>(-666.0, [](size_t j) { return float64_t(j); });
     test<Number>(Number(42, OddTag()), [](int32_t j) { return Number(j, OddTag()); });
 #endif
diff --git a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/fill.cc b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/fill.cc
index 733657bf48f..d5b40658d57 100644
--- a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/fill.cc
+++ b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/fill.cc
@@ -84,14 +84,14 @@ template <typename T>
 void
 test_fill_by_type(std::size_t n)
 {
-    Sequence<T> in(n, [](std::size_t v) -> T { return T(0); }); //fill with zeros
+    Sequence<T> in(n, [](std::size_t) -> T { return T(0); }); //fill with zeros
     T value = -1;
 
     invoke_on_all_policies(test_fill(), in.begin(), in.end(), value);
     invoke_on_all_policies(test_fill_n(), in.begin(), n, value);
 }
 
-int32_t
+int
 main()
 {
 
diff --git a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/generate.cc b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/generate.cc
index 1bd26216098..c04e51207c2 100644
--- a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/generate.cc
+++ b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/generate.cc
@@ -57,17 +57,18 @@ struct test_generate
         {
             Generator_count<T> g;
             generate(exec, first, last, g);
-            EXPECT_TRUE(std::count(first, last, g.default_value()) == n, "generate wrong result for generate");
+            Size count = std::count(first, last, g.default_value());
+            EXPECT_TRUE(count == n, "generate wrong result for generate");
             std::fill(first, last, T(0));
         }
 
         {
             Generator_count<T> g;
             const auto m = n / 2;
-            auto last = generate_n(exec, first, m, g);
-            EXPECT_TRUE(std::count(first, last, g.default_value()) == m && last == std::next(first, m),
-                        "generate_n wrong result for generate_n");
-            std::fill(first, last, T(0));
+            auto actual_last = generate_n(exec, first, m, g);
+            Size count = std::count(first, actual_last, g.default_value());
+            EXPECT_TRUE(count == m && actual_last == std::next(first, m), "generate_n wrong result for generate_n");
+            std::fill(first, actual_last, T(0));
         }
     }
 };
@@ -78,7 +79,7 @@ test_generate_by_type()
 {
     for (size_t n = 0; n <= 100000; n = n < 16 ? n + 1 : size_t(3.1415 * n))
     {
-        Sequence<T> in(n, [](size_t v) -> T { return T(0); }); //fill by zero
+        Sequence<T> in(n, [](size_t) -> T { return T(0); }); //fill by zero
 
         invoke_on_all_policies(test_generate(), in.begin(), in.end(), in.size());
     }
@@ -98,7 +99,7 @@ struct test_non_const
     }
 };
 
-int32_t
+int
 main()
 {
 
diff --git a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/is_partitioned.cc b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/is_partitioned.cc
index 3c70b14b019..20ee7d296f7 100644
--- a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/is_partitioned.cc
+++ b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/is_partitioned.cc
@@ -29,16 +29,16 @@ using namespace TestUtils;
 struct test_one_policy
 {
     //dummy specialization by policy type, in case of broken configuration
-#if _PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN || _PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN
+#if defined(_PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN) || defined(_PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN)
 
     template <typename Iterator1, typename Predicate>
     void
-    operator()(pstl::execution::unsequenced_policy, Iterator1 begin1, Iterator1 end1, Predicate pred)
+    operator()(__pstl::execution::unsequenced_policy, Iterator1 begin1, Iterator1 end1, Predicate pred)
     {
     }
     template <typename Iterator1, typename Predicate>
     void
-    operator()(pstl::execution::parallel_unsequenced_policy, Iterator1 begin1, Iterator1 end1, Predicate pred)
+    operator()(__pstl::execution::parallel_unsequenced_policy, Iterator1 begin1, Iterator1 end1, Predicate pred)
     {
     }
 #endif
@@ -92,14 +92,14 @@ struct test_non_const
     }
 };
 
-int32_t
+int
 main()
 {
     test<float64_t>([](const float64_t x) { return x < 0; });
     test<int32_t>([](const int32_t x) { return x > 1000; });
     test<uint16_t>([](const uint16_t x) { return x % 5 < 3; });
-#if !_PSTL_ICC_18_TEST_EARLY_EXIT_MONOTONIC_RELEASE_BROKEN && !_PSTL_ICC_19_TEST_IS_PARTITIONED_RELEASE_BROKEN
-    test<LocalWrapper<float64_t>>([](const LocalWrapper<float64_t>& x) { return true; });
+#if !defined(_PSTL_ICC_18_TEST_EARLY_EXIT_MONOTONIC_RELEASE_BROKEN) && !defined(_PSTL_ICC_19_TEST_IS_PARTITIONED_RELEASE_BROKEN)
+    test<LocalWrapper<float64_t>>([](const LocalWrapper<float64_t>&) { return true; });
 #endif
 
     test_algo_basic_single<int32_t>(run_for_rnd_fw<test_non_const>());
diff --git a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/partition.cc b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/partition.cc
index d084995574a..e13fe938d1f 100644
--- a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/partition.cc
+++ b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/partition.cc
@@ -66,15 +66,15 @@ is_equal(Iterator first, Iterator last, Iterator d_first)
 
 template <typename Iterator>
 typename std::enable_if<!std::is_trivial<typename std::iterator_traits<Iterator>::value_type>::value, bool>::type
-is_equal(Iterator first, Iterator last, Iterator d_first)
+    is_equal(Iterator, Iterator, Iterator)
 {
     return true;
 }
 
 struct test_one_policy
 {
-#if _PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN ||                                                            \
-    _PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN //dummy specializations to skip testing in case of broken configuration
+#if defined(_PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN) ||                                                             \
+    defined(_PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN) //dummy specializations to skip testing in case of broken configuration
     template <typename BiDirIt, typename Size, typename UnaryOp, typename Generator>
     void
     operator()(__pstl::execution::unsequenced_policy, BiDirIt first, BiDirIt last, BiDirIt exp_first, BiDirIt exp_last,
@@ -88,7 +88,7 @@ struct test_one_policy
                BiDirIt exp_last, Size n, UnaryOp unary_op, Generator generator)
     {
     }
-#elif _PSTL_ICC_16_VC14_TEST_PAR_TBB_RT_RELEASE_64_BROKEN //dummy specializations to skip testing in case of broken configuration
+#elif defined(_PSTL_ICC_16_VC14_TEST_PAR_TBB_RT_RELEASE_64_BROKEN) //dummy specializations to skip testing in case of broken configuration
     template <typename BiDirIt, typename Size, typename UnaryOp, typename Generator>
     void
     operator()(__pstl::execution::parallel_policy, BiDirIt first, BiDirIt last, BiDirIt exp_first, BiDirIt exp_last,
@@ -106,8 +106,8 @@ struct test_one_policy
 
     template <typename Policy, typename BiDirIt, typename Size, typename UnaryOp, typename Generator>
     typename std::enable_if<!is_same_iterator_category<BiDirIt, std::forward_iterator_tag>::value, void>::type
-    operator()(Policy&& exec, BiDirIt first, BiDirIt last, BiDirIt exp_first, BiDirIt exp_last, Size n,
-               UnaryOp unary_op, Generator generator)
+    operator()(Policy&& exec, BiDirIt first, BiDirIt last, BiDirIt exp_first, BiDirIt exp_last, Size, UnaryOp unary_op,
+               Generator generator)
     {
         // partition
         {
@@ -130,8 +130,7 @@ struct test_one_policy
     }
     template <typename Policy, typename BiDirIt, typename Size, typename UnaryOp, typename Generator>
     typename std::enable_if<is_same_iterator_category<BiDirIt, std::forward_iterator_tag>::value, void>::type
-    operator()(Policy&& exec, BiDirIt first, BiDirIt last, BiDirIt exp_first, BiDirIt exp_last, Size n,
-               UnaryOp unary_op, Generator generator)
+    operator()(Policy&&, BiDirIt, BiDirIt, BiDirIt, BiDirIt, Size, UnaryOp, Generator)
     {
     }
 };
@@ -170,10 +169,10 @@ struct test_non_const
     }
 };
 
-int32_t
+int
 main()
 {
-#if !_PSTL_ICC_16_17_TEST_REDUCTION_RELEASE_BROKEN
+#if !defined(_PSTL_ICC_16_17_TEST_REDUCTION_RELEASE_BROKEN)
     test_by_type<int32_t>([](int32_t i) { return i; }, [](int32_t) { return true; });
 #endif
     test_by_type<float64_t>([](int32_t i) { return -i; }, [](const float64_t x) { return x < 0; });
diff --git a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/partition_copy.cc b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/partition_copy.cc
index 63e1f21da37..804fcba2bf2 100644
--- a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/partition_copy.cc
+++ b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/partition_copy.cc
@@ -35,24 +35,23 @@ struct test_partition_copy
     template <typename Policy, typename InputIterator, typename OutputIterator, typename OutputIterator2,
               typename UnaryOp>
     void
-    operator()(Policy&& exec, InputIterator first, InputIterator last, OutputIterator true_first,
-               OutputIterator true_last, OutputIterator2 false_first, OutputIterator2 false_last, UnaryOp unary_op)
+    operator()(Policy&& exec, InputIterator first, InputIterator last, OutputIterator true_first, OutputIterator,
+               OutputIterator2 false_first, OutputIterator2, UnaryOp unary_op)
     {
 
         auto actual_ret = std::partition_copy(exec, first, last, true_first, false_first, unary_op);
 
         EXPECT_TRUE(std::distance(true_first, actual_ret.first) == std::count_if(first, last, unary_op),
                     "partition_copy has wrong effect from true sequence");
-        EXPECT_TRUE(std::distance(false_first, actual_ret.second) ==
-                        std::count_if(first, last, __pstl::__internal::__not_pred<UnaryOp>(unary_op)),
+        EXPECT_TRUE(std::distance(false_first, actual_ret.second) == std::count_if(first, last, std::not_fn(unary_op)),
                     "partition_copy has wrong effect from false sequence");
     }
 
     //dummy specialization by iterator type and policy type, in case of broken configuration
-#if _PSTL_ICC_1800_TEST_MONOTONIC_RELEASE_64_BROKEN
+#if defined(_PSTL_ICC_1800_TEST_MONOTONIC_RELEASE_64_BROKEN)
     template <typename InputIterator, typename OutputIterator, typename OutputIterator2, typename UnaryOp>
     void
-    operator()(pstl::execution::unsequenced_policy, std::reverse_iterator<InputIterator> first,
+    operator()(__pstl::execution::unsequenced_policy, std::reverse_iterator<InputIterator> first,
                std::reverse_iterator<InputIterator> last, std::reverse_iterator<OutputIterator> true_first,
                std::reverse_iterator<OutputIterator> true_last, std::reverse_iterator<OutputIterator2> false_first,
                OutputIterator2 false_last, UnaryOp unary_op)
@@ -60,7 +59,7 @@ struct test_partition_copy
     }
     template <typename InputIterator, typename OutputIterator, typename OutputIterator2, typename UnaryOp>
     void
-    operator()(pstl::execution::parallel_unsequenced_policy, std::reverse_iterator<InputIterator> first,
+    operator()(__pstl::execution::parallel_unsequenced_policy, std::reverse_iterator<InputIterator> first,
                std::reverse_iterator<InputIterator> last, std::reverse_iterator<OutputIterator> true_first,
                std::reverse_iterator<OutputIterator> true_last, std::reverse_iterator<OutputIterator2> false_first,
                OutputIterator2 false_last, UnaryOp unary_op)
@@ -106,13 +105,13 @@ struct test_non_const
     }
 };
 
-int32_t
+int
 main()
 {
     test<int32_t>([](const int32_t value) { return value % 2; });
 
-#if !_PSTL_ICC_16_17_TEST_REDUCTION_RELEASE_BROKEN
-    test<int32_t>([](const int32_t value) { return true; });
+#if !defined(_PSTL_ICC_16_17_TEST_REDUCTION_RELEASE_BROKEN)
+    test<int32_t>([](const int32_t) { return true; });
 #endif
 
     test<float64_t>([](const float64_t value) { return value > 2 << 6; });
diff --git a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/remove.cc b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/remove.cc
index f2e7520b82d..9d8e5b9b305 100644
--- a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/remove.cc
+++ b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/remove.cc
@@ -29,18 +29,18 @@ using namespace TestUtils;
 
 struct run_remove
 {
-#if _PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN ||                                                            \
-    _PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN //dummy specialization by policy type, in case of broken configuration
+#if defined(_PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN) ||                                                             \
+    defined(_PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN) //dummy specialization by policy type, in case of broken configuration
     template <typename InputIterator, typename OutputIterator, typename Size, typename T>
     void
-    operator()(pstl::execution::unsequenced_policy, InputIterator first, InputIterator last, OutputIterator out_first,
+    operator()(__pstl::execution::unsequenced_policy, InputIterator first, InputIterator last, OutputIterator out_first,
                OutputIterator out_last, OutputIterator expected_first, OutputIterator expected_last, Size n,
                const T& value)
     {
     }
     template <typename InputIterator, typename OutputIterator, typename Size, typename T>
     void
-    operator()(pstl::execution::parallel_unsequenced_policy, InputIterator first, InputIterator last,
+    operator()(__pstl::execution::parallel_unsequenced_policy, InputIterator first, InputIterator last,
                OutputIterator out_first, OutputIterator out_last, OutputIterator expected_first,
                OutputIterator expected_last, Size n, const T& value)
     {
@@ -67,18 +67,18 @@ struct run_remove
 
 struct run_remove_if
 {
-#if _PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN ||                                                            \
-    _PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN //dummy specialization by policy type, in case of broken configuration
+#if defined(_PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN) ||                                                             \
+    defined(_PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN) //dummy specialization by policy type, in case of broken configuration
     template <typename InputIterator, typename OutputIterator, typename Size, typename Predicate>
     void
-    operator()(pstl::execution::unsequenced_policy, InputIterator first, InputIterator last, OutputIterator out_first,
+    operator()(__pstl::execution::unsequenced_policy, InputIterator first, InputIterator last, OutputIterator out_first,
                OutputIterator out_last, OutputIterator expected_first, OutputIterator expected_last, Size n,
                Predicate pred)
     {
     }
     template <typename InputIterator, typename OutputIterator, typename Size, typename Predicate>
     void
-    operator()(pstl::execution::parallel_unsequenced_policy, InputIterator first, InputIterator last,
+    operator()(__pstl::execution::parallel_unsequenced_policy, InputIterator first, InputIterator last,
                OutputIterator out_first, OutputIterator out_last, OutputIterator expected_first,
                OutputIterator expected_last, Size n, Predicate pred)
     {
@@ -138,11 +138,11 @@ struct test_non_const
     }
 };
 
-int32_t
+int
 main()
 {
-#if !_PSTL_ICC_18_TEST_EARLY_EXIT_MONOTONIC_RELEASE_BROKEN
-    test<int32_t>(666, 42, [](int32_t val) { return true; }, [](size_t j) { return j; });
+#if !defined(_PSTL_ICC_18_TEST_EARLY_EXIT_MONOTONIC_RELEASE_BROKEN)
+    test<int32_t>(666, 42, [](int32_t) { return true; }, [](size_t j) { return j; });
 #endif
 
     test<int32_t>(666, 2001, [](const int32_t& val) { return val != 2001; },
@@ -150,13 +150,20 @@ main()
     test<float64_t>(-666.0, 8.5, [](const float64_t& val) { return val != 8.5; },
                     [](size_t j) { return ((j + 1) % 7 & 2) != 0 ? 8.5 : float64_t(j % 32 + j); });
 
-#if !_PSTL_ICC_17_TEST_MAC_RELEASE_32_BROKEN
+#if !defined(_PSTL_ICC_17_TEST_MAC_RELEASE_32_BROKEN)
     test<Number>(Number(-666, OddTag()), Number(42, OddTag()), IsMultiple(3, OddTag()),
                  [](int32_t j) { return Number(j, OddTag()); });
 #endif
 
     test_algo_basic_single<int32_t>(run_for_rnd_fw<test_non_const>());
 
+    test<MemoryChecker>(MemoryChecker{0}, MemoryChecker{1},
+        [](const MemoryChecker& val){ return val.value() == 1; },
+        [](std::size_t idx){ return MemoryChecker{std::int32_t(idx % 3 == 0)}; }
+    );
+    EXPECT_FALSE(MemoryChecker::alive_objects() < 0, "wrong effect from remove,remove_if: number of ctors calls < num of dtors calls");
+    EXPECT_FALSE(MemoryChecker::alive_objects() > 0, "wrong effect from remove,remove_if: number of ctors calls > num of dtors calls");
+
     std::cout << done() << std::endl;
     return 0;
 }
diff --git a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/remove_copy.cc b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/remove_copy.cc
index 9cc8c820a70..37d7b6679dd 100644
--- a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/remove_copy.cc
+++ b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/remove_copy.cc
@@ -33,16 +33,17 @@ struct run_remove_copy
               typename T>
     void
     operator()(Policy&& exec, InputIterator first, InputIterator last, OutputIterator out_first,
-               OutputIterator out_last, OutputIterator2 expected_first, OutputIterator2 expected_last, Size n,
-               const T& value, T trash)
+               OutputIterator out_last, OutputIterator2 expected_first, OutputIterator2, Size n, const T& value,
+               T trash)
     {
         // Cleaning
         std::fill_n(expected_first, n, trash);
         std::fill_n(out_first, n, trash);
 
         // Run copy_if
-        auto i = remove_copy(first, last, expected_first, value);
-        auto k = remove_copy(exec, first, last, out_first, value);
+        auto i = std::remove_copy(first, last, expected_first, value);
+        (void)i;
+        auto k = std::remove_copy(exec, first, last, out_first, value);
         EXPECT_EQ_N(expected_first, out_first, n, "wrong remove_copy effect");
         for (size_t j = 0; j < GuardSize; ++j)
         {
@@ -84,7 +85,7 @@ test(T trash, const T& value, Convert convert, bool check_weakness = true)
     }
 }
 
-int32_t
+int
 main()
 {
 
diff --git a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/replace.cc b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/replace.cc
index db82b87bf17..c6a515e4c88 100644
--- a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/replace.cc
+++ b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/replace.cc
@@ -31,9 +31,10 @@ struct copy_int
 {
     int32_t value;
     int32_t copied_times = 0;
-    explicit copy_int(int32_t val = 0) { value = val; }
+    constexpr explicit copy_int(int32_t val = 0) : value(val) {}
+    constexpr copy_int(copy_int const& other) : value(other.value), copied_times(other.copied_times) { }
 
-    copy_int&
+    constexpr copy_int&
     operator=(const copy_int& other)
     {
         if (&other == this)
@@ -46,7 +47,7 @@ struct copy_int
         return *this;
     }
 
-    bool
+    constexpr bool
     operator==(const copy_int& other) const
     {
         return (value == other.value);
@@ -112,13 +113,13 @@ test(Pred pred)
 
     const std::size_t max_len = 100000;
 
-    const T1 value = T1(0);
-    const T1 new_value = T1(666);
+    static constexpr T1 value = T1(0);
+    static constexpr T1 new_value = T1(666);
 
     Sequence<T2> expected(max_len);
     Sequence<T2> actual(max_len);
 
-    Sequence<T2> data(max_len, [&value](std::size_t i) {
+    Sequence<T2> data(max_len, [](std::size_t i) {
         if (i % 3 == 2)
         {
             return T1(i);
@@ -153,7 +154,7 @@ struct test_non_const
     }
 };
 
-int32_t
+int
 main()
 {
     test<int32_t, float32_t>(__pstl::__internal::__equal_value<int32_t>(666));
diff --git a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/replace_copy.cc b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/replace_copy.cc
index 6931162af29..18f6b549168 100644
--- a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/replace_copy.cc
+++ b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/replace_copy.cc
@@ -34,8 +34,8 @@ struct test_replace_copy
               typename Predicate, typename T>
     void
     operator()(Policy&& exec, InputIterator first, InputIterator last, OutputIterator out_first,
-               OutputIterator out_last, OutputIterator2 expected_first, OutputIterator2 expected_last, Size n,
-               Predicate pred, const T& old_value, const T& new_value, T trash)
+               OutputIterator out_last, OutputIterator2 expected_first, OutputIterator2, Size n, Predicate pred,
+               const T& old_value, const T& new_value, T trash)
     {
         // Cleaning
         std::fill_n(expected_first, n, trash);
@@ -91,7 +91,7 @@ struct test_non_const
     }
 };
 
-int32_t
+int
 main()
 {
 
@@ -101,7 +101,7 @@ main()
     test<int32_t>(-666, 42, 99, [](const int32_t& x) { return x != 42; },
                   [](size_t j) { return ((j + 1) % 5 & 2) != 0 ? 42 : -1 - int32_t(j); });
 
-#if !_PSTL_ICC_17_TEST_MAC_RELEASE_32_BROKEN
+#if !defined(_PSTL_ICC_17_TEST_MAC_RELEASE_32_BROKEN)
     test<Number>(Number(42, OddTag()), Number(2001, OddTag()), Number(2017, OddTag()), IsMultiple(3, OddTag()),
                  [](int32_t j) { return ((j + 1) % 3 & 2) != 0 ? Number(2001, OddTag()) : Number(j, OddTag()); });
 #endif
diff --git a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/rotate.cc b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/rotate.cc
index c7e00fb8570..9ec9b3bcc9b 100644
--- a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/rotate.cc
+++ b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/rotate.cc
@@ -83,8 +83,8 @@ struct compare<wrapper<T>>
 struct test_one_policy
 {
 
-#if _PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN ||                                                            \
-    _PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN // dummy specializations to skip testing in case of broken configuration
+#if defined(_PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN) ||                                                             \
+    defined(_PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN) // dummy specializations to skip testing in case of broken configuration
     template <typename Iterator, typename Size>
     void
     operator()(__pstl::execution::unsequenced_policy, Iterator data_b, Iterator data_e, Iterator actual_b,
@@ -123,10 +123,10 @@ struct test_one_policy
     template <typename ExecutionPolicy, typename Iterator, typename Size>
     typename std::enable_if<
         is_same_iterator_category<Iterator, std::random_access_iterator_tag>::value &&
-            !std::is_same<ExecutionPolicy, __pstl::execution::sequenced_policy>::value &&
+            !std::is_same<ExecutionPolicy, std::execution::sequenced_policy>::value &&
             std::is_same<typename std::iterator_traits<Iterator>::value_type, wrapper<float32_t>>::value,
         bool>::type
-    check_move(ExecutionPolicy&& exec, Iterator b, Iterator e, Size shift)
+    check_move(ExecutionPolicy&&, Iterator b, Iterator e, Size shift)
     {
         bool result = all_of(b, e, [](wrapper<float32_t>& a) {
             bool temp = a.move_count > 0;
@@ -139,10 +139,10 @@ struct test_one_policy
     template <typename ExecutionPolicy, typename Iterator, typename Size>
     typename std::enable_if<
         !(is_same_iterator_category<Iterator, std::random_access_iterator_tag>::value &&
-          !std::is_same<ExecutionPolicy, __pstl::execution::sequenced_policy>::value &&
+          !std::is_same<ExecutionPolicy, std::execution::sequenced_policy>::value &&
           std::is_same<typename std::iterator_traits<Iterator>::value_type, wrapper<float32_t>>::value),
         bool>::type
-    check_move(ExecutionPolicy&& exec, Iterator b, Iterator e, Size shift)
+    check_move(ExecutionPolicy&&, Iterator, Iterator, Size)
     {
         return true;
     }
@@ -171,7 +171,7 @@ test()
     }
 }
 
-int32_t
+int
 main()
 {
     test<int32_t>();
diff --git a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/rotate_copy.cc b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/rotate_copy.cc
index f80ec5a54a2..ea647c6c23a 100644
--- a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/rotate_copy.cc
+++ b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/rotate_copy.cc
@@ -78,17 +78,17 @@ struct comparator
 struct test_one_policy
 {
 
-#if _PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN ||                                                            \
-    _PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN // dummy specialization by policy type, in case of broken configuration
+#if defined(_PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN) ||                                                             \
+    defined(_PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN) // dummy specialization by policy type, in case of broken configuration
     template <typename Iterator1, typename Iterator2>
     typename std::enable_if<is_same_iterator_category<Iterator1, std::random_access_iterator_tag>::value, void>::type
-    operator()(pstl::execution::unsequenced_policy, Iterator1 data_b, Iterator1 data_e, Iterator2 actual_b,
+    operator()(__pstl::execution::unsequenced_policy, Iterator1 data_b, Iterator1 data_e, Iterator2 actual_b,
                Iterator2 actual_e, std::size_t shift)
     {
     }
     template <typename Iterator1, typename Iterator2>
     typename std::enable_if<is_same_iterator_category<Iterator1, std::random_access_iterator_tag>::value, void>::type
-    operator()(pstl::execution::parallel_unsequenced_policy, Iterator1 data_b, Iterator1 data_e, Iterator2 actual_b,
+    operator()(__pstl::execution::parallel_unsequenced_policy, Iterator1 data_b, Iterator1 data_e, Iterator2 actual_b,
                Iterator2 actual_e, std::size_t shift)
     {
     }
@@ -142,7 +142,7 @@ test()
     }
 }
 
-int32_t
+int
 main()
 {
     test<int32_t, int8_t>();
diff --git a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/swap_ranges.cc b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/swap_ranges.cc
index d17c11d78db..e371c3b2b04 100644
--- a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/swap_ranges.cc
+++ b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/swap_ranges.cc
@@ -61,7 +61,7 @@ template <typename T>
 struct check_swap
 {
     bool
-    operator()(T& a)
+    operator()(T&)
     {
         return true;
     }
@@ -129,7 +129,7 @@ test()
     }
 }
 
-int32_t
+int
 main()
 {
     test<wrapper<uint16_t>>();
diff --git a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/transform_binary.cc b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/transform_binary.cc
index 226a81a0405..1f5f239a94b 100644
--- a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/transform_binary.cc
+++ b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/transform_binary.cc
@@ -70,10 +70,11 @@ struct test_one_policy
     template <typename Policy, typename InputIterator1, typename InputIterator2, typename OutputIterator,
               typename BinaryOp>
     void
-    operator()(Policy&& exec, InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2,
-               OutputIterator out_first, OutputIterator out_last, BinaryOp op)
+    operator()(Policy&& exec, InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2,
+               OutputIterator out_first, OutputIterator, BinaryOp op)
     {
-        auto orrr = std::transform(exec, first1, last1, first2, out_first, op);
+        auto result = std::transform(exec, first1, last1, first2, out_first, op);
+        (void)result;
         check_and_reset(first1, last1, first2, out_first);
     }
 };
@@ -87,7 +88,7 @@ test(Predicate pred)
         Sequence<In1> in1(n, [](size_t k) { return k % 5 != 1 ? 3 * k - 7 : 0; });
         Sequence<In2> in2(n, [](size_t k) { return k % 7 != 2 ? 5 * k - 5 : 0; });
 
-        Sequence<Out> out(n, [](size_t k) { return -1; });
+        Sequence<Out> out(n, [](size_t) { return -1; });
 
         invoke_on_all_policies(test_one_policy(), in1.begin(), in1.end(), in2.begin(), in2.end(), out.begin(),
                                out.end(), pred);
@@ -110,7 +111,7 @@ struct test_non_const
     }
 };
 
-int32_t
+int
 main()
 {
     //const operator()
diff --git a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/transform_unary.cc b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/transform_unary.cc
index cece4751891..ddd8249b678 100644
--- a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/transform_unary.cc
+++ b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/transform_unary.cc
@@ -83,7 +83,7 @@ struct test_non_const
     }
 };
 
-int32_t
+int
 main()
 {
     test<int32_t, int32_t>();
diff --git a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/unique.cc b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/unique.cc
index 54c99530c4e..0f21e045089 100644
--- a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/unique.cc
+++ b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/unique.cc
@@ -29,32 +29,32 @@ using namespace TestUtils;
 
 struct run_unique
 {
-#if _PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN ||                                                            \
-    _PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN //dummy specialization by policy type, in case of broken configuration
+#if defined(_PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN) ||                                                             \
+    defined(_PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN) //dummy specialization by policy type, in case of broken configuration
     template <typename ForwardIt, typename Generator>
     void
-    operator()(pstl::execution::unsequenced_policy, ForwardIt first1, ForwardIt last1, ForwardIt first2,
+    operator()(__pstl::execution::unsequenced_policy, ForwardIt first1, ForwardIt last1, ForwardIt first2,
                ForwardIt last2, Generator generator)
     {
     }
 
     template <typename ForwardIt, typename Generator>
     void
-    operator()(pstl::execution::parallel_unsequenced_policy, ForwardIt first1, ForwardIt last1, ForwardIt first2,
+    operator()(__pstl::execution::parallel_unsequenced_policy, ForwardIt first1, ForwardIt last1, ForwardIt first2,
                ForwardIt last2, Generator generator)
     {
     }
 
     template <typename ForwardIt, typename BinaryPred, typename Generator>
     void
-    operator()(pstl::execution::unsequenced_policy, ForwardIt first1, ForwardIt last1, ForwardIt first2,
+    operator()(__pstl::execution::unsequenced_policy, ForwardIt first1, ForwardIt last1, ForwardIt first2,
                ForwardIt last2, BinaryPred pred, Generator generator)
     {
     }
 
     template <typename ForwardIt, typename BinaryPred, typename Generator>
     void
-    operator()(pstl::execution::parallel_unsequenced_policy, ForwardIt first1, ForwardIt last1, ForwardIt first2,
+    operator()(__pstl::execution::parallel_unsequenced_policy, ForwardIt first1, ForwardIt last1, ForwardIt first2,
                ForwardIt last2, BinaryPred pred, Generator generator)
     {
     }
@@ -144,10 +144,10 @@ struct test_non_const
     }
 };
 
-int32_t
+int
 main()
 {
-#if !_PSTL_ICC_16_17_18_TEST_UNIQUE_MASK_RELEASE_BROKEN
+#if !defined(_PSTL_ICC_16_17_18_TEST_UNIQUE_MASK_RELEASE_BROKEN)
     test<int32_t>([](size_t j) { return j / 3; },
                   [](const int32_t& val1, const int32_t& val2) { return val1 * val1 == val2 * val2; });
     test<float64_t>([](size_t) { return float64_t(1); },
@@ -160,6 +160,12 @@ main()
 
     test_algo_basic_single<int32_t>(run_for_rnd_fw<test_non_const<int32_t>>());
 
+    test<MemoryChecker>(
+        [](std::size_t idx){ return MemoryChecker{std::int32_t(idx / 3)}; },
+        [](const MemoryChecker& val1, const MemoryChecker& val2){ return val1.value() == val2.value(); });
+    EXPECT_FALSE(MemoryChecker::alive_objects() < 0, "wrong effect from unique: number of ctors calls < num of dtors calls");
+    EXPECT_FALSE(MemoryChecker::alive_objects() > 0, "wrong effect from unique: number of ctors calls > num of dtors calls");
+
     std::cout << done() << std::endl;
     return 0;
 }
diff --git a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/unique_copy_equal.cc b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/unique_copy_equal.cc
index 0351db7498a..c5bc25c9140 100644
--- a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/unique_copy_equal.cc
+++ b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_modifying_operations/unique_copy_equal.cc
@@ -29,7 +29,7 @@ using namespace TestUtils;
 
 struct run_unique_copy
 {
-#if _PSTL_ICC_16_VC14_TEST_PAR_TBB_RT_RELEASE_64_BROKEN // dummy specializations to skip testing in case of broken configuration
+#if defined(_PSTL_ICC_16_VC14_TEST_PAR_TBB_RT_RELEASE_64_BROKEN) // dummy specializations to skip testing in case of broken configuration
     template <typename InputIterator, typename OutputIterator, typename OutputIterator2, typename Size,
               typename Predicate, typename T>
     void
@@ -53,8 +53,8 @@ struct run_unique_copy
               typename Predicate, typename T>
     void
     operator()(Policy&& exec, InputIterator first, InputIterator last, OutputIterator out_first,
-               OutputIterator out_last, OutputIterator2 expected_first, OutputIterator2 expected_last, Size n,
-               Predicate pred, T trash)
+               OutputIterator out_last, OutputIterator2 expected_first, OutputIterator2, Size n, Predicate pred,
+               T trash)
     {
         // Cleaning
         std::fill_n(expected_first, n, trash);
@@ -123,17 +123,17 @@ struct test_non_const
     }
 };
 
-int32_t
-main(int32_t argc, char* argv[])
+int
+main()
 {
     test<Number>(Number(42, OddTag()), std::equal_to<Number>(),
                  [](int32_t j) { return Number(3 * j / 13 ^ (j & 8), OddTag()); });
 
     test<float32_t>(float32_t(42), std::equal_to<float32_t>(),
                     [](int32_t j) { return float32_t(5 * j / 23 ^ (j / 7)); });
-#if !_PSTL_ICC_16_17_TEST_REDUCTION_RELEASE_BROKEN
-    test<float32_t>(float32_t(42), [](float32_t x, float32_t y) { return false; },
-                    [](int32_t j) { return float32_t(j); }, false);
+#if !defined(_PSTL_ICC_16_17_TEST_REDUCTION_RELEASE_BROKEN)
+    test<float32_t>(float32_t(42), [](float32_t, float32_t) { return false; }, [](int32_t j) { return float32_t(j); },
+                    false);
 #endif
 
     test_algo_basic_double<int32_t>(run_for_rnd_fw<test_non_const<int32_t>>());
diff --git a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_nonmodifying/adjacent_find.cc b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_nonmodifying/adjacent_find.cc
index 81bca8229d8..a79f11bb1ed 100644
--- a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_nonmodifying/adjacent_find.cc
+++ b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_nonmodifying/adjacent_find.cc
@@ -50,13 +50,13 @@ test_adjacent_find_by_type()
 {
 
     size_t counts[] = {2, 3, 500};
-    for (int32_t c = 0; c < const_size(counts); ++c)
+    for (size_t c = 0; c < const_size(counts); ++c)
     {
 
-        for (int32_t e = 0; e < (counts[c] >= 64 ? 64 : (counts[c] == 2 ? 1 : 2)); ++e)
+        for (size_t e = 0; e < (counts[c] >= 64 ? 64 : (counts[c] == 2 ? 1 : 2)); ++e)
         {
-            Sequence<T> in(counts[c], [](int32_t v) -> T { return T(v); }); //fill 0...n
-            in[e] = in[e + 1] = -1;                                         //make an adjacent pair
+            Sequence<T> in(counts[c], [](size_t v) -> T { return T(v); }); //fill 0...n
+            in[e] = in[e + 1] = -1;                                        //make an adjacent pair
 
             auto i = std::adjacent_find(in.cbegin(), in.cend(), std::equal_to<T>());
             EXPECT_TRUE(i == in.cbegin() + e, "std::adjacent_find returned wrong result");
@@ -67,9 +67,9 @@ test_adjacent_find_by_type()
     }
 
     //special cases: size=0, size=1;
-    for (int32_t expect = 0; expect < 1; ++expect)
+    for (size_t expect = 0; expect < 1; ++expect)
     {
-        Sequence<T> in(expect, [](int32_t v) -> T { return T(v); }); //fill 0...n
+        Sequence<T> in(expect, [](size_t v) -> T { return T(v); }); //fill 0...n
         auto i = std::adjacent_find(in.cbegin(), in.cend(), std::equal_to<T>());
         EXPECT_TRUE(i == in.cbegin() + expect, "std::adjacent_find returned wrong result");
 
@@ -109,7 +109,7 @@ struct test_non_const
     }
 };
 
-int32_t
+int
 main()
 {
 
diff --git a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_nonmodifying/all_of.cc b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_nonmodifying/all_of.cc
index d1c3b98da37..0f03d00cdbc 100644
--- a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_nonmodifying/all_of.cc
+++ b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_nonmodifying/all_of.cc
@@ -69,7 +69,7 @@ test(size_t bits)
     {
 
         // Sequence of odd values
-        Sequence<T> in(n, [n, bits](size_t k) { return T(2 * HashBits(n, bits - 1) ^ 1); });
+        Sequence<T> in(n, [n, bits](size_t) { return T(2 * HashBits(n, bits - 1) ^ 1); });
 
         // Even value, or false when T is bool.
         T spike(2 * HashBits(n, bits - 1));
@@ -108,13 +108,13 @@ struct test_non_const
     }
 };
 
-int32_t
+int
 main()
 {
     test<int32_t>(8 * sizeof(int32_t));
     test<uint16_t>(8 * sizeof(uint16_t));
     test<float64_t>(53);
-#if !_PSTL_ICC_16_17_TEST_REDUCTION_BOOL_TYPE_RELEASE_64_BROKEN
+#if !defined(_PSTL_ICC_16_17_TEST_REDUCTION_BOOL_TYPE_RELEASE_64_BROKEN)
     test<bool>(1);
 #endif
 
diff --git a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_nonmodifying/any_of.cc b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_nonmodifying/any_of.cc
index 7b2f3c73a30..a4bbb7d176e 100644
--- a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_nonmodifying/any_of.cc
+++ b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_nonmodifying/any_of.cc
@@ -55,7 +55,7 @@ test(size_t bits)
     {
 
         // Sequence of odd values
-        Sequence<T> in(n, [n, bits](size_t k) { return T(2 * HashBits(n, bits - 1) ^ 1); });
+        Sequence<T> in(n, [n, bits](size_t) { return T(2 * HashBits(n, bits - 1) ^ 1); });
 
         // Even value, or false when T is bool.
         T spike(2 * HashBits(n, bits - 1));
@@ -94,13 +94,13 @@ struct test_non_const
     }
 };
 
-int32_t
+int
 main()
 {
     test<int32_t>(8 * sizeof(int32_t));
     test<uint16_t>(8 * sizeof(uint16_t));
     test<float64_t>(53);
-#if !_PSTL_ICC_16_17_TEST_REDUCTION_BOOL_TYPE_RELEASE_64_BROKEN
+#if !defined(_PSTL_ICC_16_17_TEST_REDUCTION_BOOL_TYPE_RELEASE_64_BROKEN)
     test<bool>(1);
 #endif
 
diff --git a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_nonmodifying/count.cc b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_nonmodifying/count.cc
index 25a1350edf8..b99754c51f1 100644
--- a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_nonmodifying/count.cc
+++ b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_nonmodifying/count.cc
@@ -98,12 +98,12 @@ struct test_non_const
     }
 };
 
-int32_t
+int
 main()
 {
     test<int32_t>(42, IsEqual<int32_t>(50, OddTag()), [](int32_t j) { return j; });
-#if !_PSTL_ICC_16_17_TEST_REDUCTION_RELEASE_BROKEN
-    test<int32_t>(42, [](const int32_t& x) { return true; }, [](int32_t j) { return j; });
+#if !defined(_PSTL_ICC_16_17_TEST_REDUCTION_RELEASE_BROKEN)
+    test<int32_t>(42, [](const int32_t&) { return true; }, [](int32_t j) { return j; });
 #endif
     test<float64_t>(42, IsEqual<float64_t>(50, OddTag()), [](int32_t j) { return float64_t(j); });
     test<Number>(Number(42, OddTag()), IsEqual<Number>(Number(50, OddTag()), OddTag()),
diff --git a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_nonmodifying/equal.cc b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_nonmodifying/equal.cc
index cec6b20bd6c..0e5ad030ee7 100644
--- a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_nonmodifying/equal.cc
+++ b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_nonmodifying/equal.cc
@@ -30,10 +30,10 @@ using namespace TestUtils;
 
 struct UserType
 {
+    size_t key;
     float32_t f;
     float64_t d;
     int32_t i;
-    size_t key;
 
     bool
     operator()(UserType a, UserType b)
@@ -157,14 +157,14 @@ struct test_non_const
     }
 };
 
-int32_t
+int
 main()
 {
 
     test<int32_t>(8 * sizeof(int32_t));
     test<uint16_t>(8 * sizeof(uint16_t));
     test<float64_t>(53);
-#if !_PSTL_ICC_16_17_TEST_REDUCTION_BOOL_TYPE_RELEASE_64_BROKEN
+#if !defined(_PSTL_ICC_16_17_TEST_REDUCTION_BOOL_TYPE_RELEASE_64_BROKEN)
     test<bool>(1);
 #endif
     test<UserType>(256);
diff --git a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_nonmodifying/find.cc b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_nonmodifying/find.cc
index 1eb9db3e7eb..c303ba689d7 100644
--- a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_nonmodifying/find.cc
+++ b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_nonmodifying/find.cc
@@ -29,16 +29,16 @@ using namespace TestUtils;
 
 struct test_find
 {
-#if _PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN ||                                                            \
-    _PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN //dummy specialization by policy type, in case of broken configuration
+#if defined(_PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN) ||                                                             \
+    defined(_PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN) //dummy specialization by policy type, in case of broken configuration
     template <typename Iterator, typename Value>
     void
-    operator()(pstl::execution::unsequenced_policy, Iterator first, Iterator last, Value value)
+    operator()(__pstl::execution::unsequenced_policy, Iterator first, Iterator last, Value value)
     {
     }
     template <typename Iterator, typename Value>
     void
-    operator()(pstl::execution::parallel_unsequenced_policy, Iterator first, Iterator last, Value value)
+    operator()(__pstl::execution::parallel_unsequenced_policy, Iterator first, Iterator last, Value value)
     {
     }
 #endif
@@ -88,12 +88,12 @@ class Weird
     Weird(int32_t val, OddTag) : value(val, OddTag()) {}
 };
 
-int32_t
+int
 main()
 {
     // Note that the "hit" and "miss" functions here avoid overflow issues.
-    test<Number>(Weird(42, OddTag()), [](int32_t j) { return Number(42, OddTag()); }, // hit
-                 [](int32_t j) { return Number(j == 42 ? 0 : j, OddTag()); });        // miss
+    test<Number>(Weird(42, OddTag()), [](int32_t) { return Number(42, OddTag()); }, // hit
+                 [](int32_t j) { return Number(j == 42 ? 0 : j, OddTag()); });      // miss
 
     // Test with value that is equal to two different bit patterns (-0.0 and 0.0)
     test<float32_t>(-0.0, [](int32_t j) { return j & 1 ? 0.0 : -0.0; }, // hit
diff --git a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_nonmodifying/find_end.cc b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_nonmodifying/find_end.cc
index e106b5c750e..e6a65a9848b 100644
--- a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_nonmodifying/find_end.cc
+++ b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_nonmodifying/find_end.cc
@@ -26,105 +26,77 @@
 
 using namespace TestUtils;
 
-struct test_one_policy
+struct test_find
 {
-#if _PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN ||                                                            \
-    _PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN //dummy specialization by policy type, in case of broken configuration
-    template <typename Iterator1, typename Iterator2, typename Predicate>
+#if defined(_PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN) ||                                                             \
+    defined(_PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN) //dummy specialization by policy type, in case of broken configuration
+    template <typename Iterator, typename Value>
     void
-    operator()(pstl::execution::unsequenced_policy, Iterator1 b, Iterator1 e, Iterator2 bsub, Iterator2 esub,
-               Predicate pred)
+    operator()(__pstl::execution::unsequenced_policy, Iterator first, Iterator last, Value value)
     {
     }
-    template <typename Iterator1, typename Iterator2, typename Predicate>
+    template <typename Iterator, typename Value>
     void
-    operator()(pstl::execution::parallel_unsequenced_policy, Iterator1 b, Iterator1 e, Iterator2 bsub, Iterator2 esub,
-               Predicate pred)
+    operator()(__pstl::execution::parallel_unsequenced_policy, Iterator first, Iterator last, Value value)
     {
     }
 #endif
 
-    template <typename ExecutionPolicy, typename Iterator1, typename Iterator2, typename Predicate>
+    template <typename Policy, typename Iterator, typename Value>
     void
-    operator()(ExecutionPolicy&& exec, Iterator1 b, Iterator1 e, Iterator2 bsub, Iterator2 esub, Predicate pred)
+    operator()(Policy&& exec, Iterator first, Iterator last, Value value)
     {
-        using namespace std;
-        // For find_end
-        {
-            auto expected = find_end(b, e, bsub, esub, pred);
-            auto actual = find_end(exec, b, e, bsub, esub);
-            EXPECT_TRUE(actual == expected, "wrong return result from find_end");
-
-            actual = find_end(exec, b, e, bsub, esub, pred);
-            EXPECT_TRUE(actual == expected, "wrong return result from find_end with a predicate");
-        }
-
-        // For search
-        {
-            auto expected = search(b, e, bsub, esub, pred);
-            auto actual = search(exec, b, e, bsub, esub);
-            EXPECT_TRUE(actual == expected, "wrong return result from search");
-
-            actual = search(exec, b, e, bsub, esub, pred);
-            EXPECT_TRUE(actual == expected, "wrong return result from search with a predicate");
-        }
+        auto i = std::find(first, last, value);
+        auto j = find(exec, first, last, value);
+        EXPECT_TRUE(i == j, "wrong return value from find");
     }
 };
 
-template <typename T>
+template <typename T, typename Value, typename Hit, typename Miss>
 void
-test(const std::size_t bits)
+test(Value value, Hit hit, Miss miss)
 {
-
-    const std::size_t max_n1 = 1000;
-    const std::size_t max_n2 = (max_n1 * 10) / 8;
-    Sequence<T> in(max_n1, [max_n1, bits](std::size_t) { return T(2 * HashBits(max_n1, bits - 1) ^ 1); });
-    Sequence<T> sub(max_n2, [max_n1, bits](std::size_t) { return T(2 * HashBits(max_n1, bits - 1)); });
-    for (std::size_t n1 = 0; n1 <= max_n1; n1 = n1 <= 16 ? n1 + 1 : size_t(3.1415 * n1))
+    // Try sequences of various lengths.
+    for (size_t n = 0; n <= 100000; n = n <= 16 ? n + 1 : size_t(3.1415 * n))
     {
-        std::size_t sub_n[] = {0, 1, 3, n1, (n1 * 10) / 8};
-        std::size_t res[] = {0, 1, n1 / 2, n1};
-        for (auto n2 : sub_n)
+        Sequence<T> in(n, [&](size_t k) -> T { return miss(n ^ k); });
+        // Try different find positions, including not found.
+        // By going backwards, we can add extra matches that are *not* supposed to be found.
+        // The decreasing exponential gives us O(n) total work for the loop since each find takes O(m) time.
+        for (size_t m = n; m > 0; m *= 0.6)
         {
-            for (auto r : res)
-            {
-                std::size_t i = r, isub = 0;
-                for (; i < n1 && isub < n2; ++i, ++isub)
-                    in[i] = sub[isub];
-                invoke_on_all_policies(test_one_policy(), in.begin(), in.begin() + n1, sub.begin(), sub.begin() + n2,
-                                       std::equal_to<T>());
-                invoke_on_all_policies(test_one_policy(), in.cbegin(), in.cbegin() + n1, sub.cbegin(),
-                                       sub.cbegin() + n2, std::equal_to<T>());
-            }
+            if (m < n)
+                in[m] = hit(n ^ m);
+            invoke_on_all_policies(test_find(), in.begin(), in.end(), value);
+            invoke_on_all_policies(test_find(), in.cbegin(), in.cend(), value);
         }
     }
 }
 
-template <typename T>
-struct test_non_const
+// Type defined for sake of checking that std::find works with asymmetric ==.
+class Weird
 {
-    template <typename Policy, typename FirstIterator, typename SecondInterator>
-    void
-    operator()(Policy&& exec, FirstIterator first_iter, SecondInterator second_iter)
+    Number value;
+
+  public:
+    friend bool
+    operator==(Number x, Weird y)
     {
-        invoke_if(exec, [&]() {
-            find_end(exec, first_iter, first_iter, second_iter, second_iter, non_const(std::equal_to<T>()));
-            search(exec, first_iter, first_iter, second_iter, second_iter, non_const(std::equal_to<T>()));
-        });
+        return x == y.value;
     }
+    Weird(int32_t val, OddTag) : value(val, OddTag()) {}
 };
 
-int32_t
+int
 main()
 {
-    test<int32_t>(8 * sizeof(int32_t));
-    test<uint16_t>(8 * sizeof(uint16_t));
-    test<float64_t>(53);
-#if !_PSTL_ICC_16_17_TEST_REDUCTION_BOOL_TYPE_RELEASE_64_BROKEN
-    test<bool>(1);
-#endif
+    // Note that the "hit" and "miss" functions here avoid overflow issues.
+    test<Number>(Weird(42, OddTag()), [](int32_t) { return Number(42, OddTag()); }, // hit
+                 [](int32_t j) { return Number(j == 42 ? 0 : j, OddTag()); });      // miss
 
-    test_algo_basic_double<int32_t>(run_for_rnd_fw<test_non_const<int32_t>>());
+    // Test with value that is equal to two different bit patterns (-0.0 and 0.0)
+    test<float32_t>(-0.0, [](int32_t j) { return j & 1 ? 0.0 : -0.0; }, // hit
+                    [](int32_t j) { return j == 0 ? ~j : j; });         // miss
 
     std::cout << done() << std::endl;
     return 0;
diff --git a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_nonmodifying/find_first_of.cc b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_nonmodifying/find_first_of.cc
index 365771d8af7..5a4a81a8db7 100644
--- a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_nonmodifying/find_first_of.cc
+++ b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_nonmodifying/find_first_of.cc
@@ -28,17 +28,17 @@ using namespace TestUtils;
 
 struct test_one_policy
 {
-#if _PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN ||                                                            \
-    _PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN //dummy specialization by policy type, in case of broken configuration
+#if defined(_PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN) ||                                                             \
+    defined(_PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN) //dummy specialization by policy type, in case of broken configuration
     template <typename Iterator1, typename Iterator2, typename Predicate>
     void
-    operator()(pstl::execution::unsequenced_policy, Iterator1 b, Iterator1 e, Iterator2 bsub, Iterator2 esub,
+    operator()(__pstl::execution::unsequenced_policy, Iterator1 b, Iterator1 e, Iterator2 bsub, Iterator2 esub,
                Predicate pred)
     {
     }
     template <typename Iterator1, typename Iterator2, typename Predicate>
     void
-    operator()(pstl::execution::parallel_unsequenced_policy, Iterator1 b, Iterator1 e, Iterator2 bsub, Iterator2 esub,
+    operator()(__pstl::execution::parallel_unsequenced_policy, Iterator1 b, Iterator1 e, Iterator2 bsub, Iterator2 esub,
                Predicate pred)
     {
     }
@@ -66,8 +66,8 @@ test(Predicate pred)
 
     const std::size_t max_n1 = 1000;
     const std::size_t max_n2 = (max_n1 * 10) / 8;
-    Sequence<T> in1(max_n1, [](std::size_t k) { return T(1); });
-    Sequence<T> in2(max_n2, [](std::size_t k) { return T(0); });
+    Sequence<T> in1(max_n1, [](std::size_t) { return T(1); });
+    Sequence<T> in2(max_n2, [](std::size_t) { return T(0); });
     for (std::size_t n1 = 0; n1 <= max_n1; n1 = n1 <= 16 ? n1 + 1 : size_t(3.1415 * n1))
     {
         std::size_t sub_n[] = {0, 1, n1 / 3, n1, (n1 * 10) / 8};
@@ -106,7 +106,7 @@ struct test_non_const
     }
 };
 
-int32_t
+int
 main()
 {
     test<int32_t>(std::equal_to<int32_t>());
diff --git a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_nonmodifying/find_if.cc b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_nonmodifying/find_if.cc
index 0449cedbf74..04ef148b5f3 100644
--- a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_nonmodifying/find_if.cc
+++ b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_nonmodifying/find_if.cc
@@ -29,17 +29,17 @@ using namespace TestUtils;
 
 struct test_find_if
 {
-#if _PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN ||                                                            \
-    _PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN //dummy specialization by policy type, in case of broken configuration
+#if defined(_PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN) ||                                                             \
+    defined(_PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN) //dummy specialization by policy type, in case of broken configuration
     template <typename Iterator, typename Predicate, typename NotPredicate>
     void
-    operator()(pstl::execution::unsequenced_policy, Iterator first, Iterator last, Predicate pred,
+    operator()(__pstl::execution::unsequenced_policy, Iterator first, Iterator last, Predicate pred,
                NotPredicate not_pred)
     {
     }
     template <typename Iterator, typename Predicate, typename NotPredicate>
     void
-    operator()(pstl::execution::parallel_unsequenced_policy, Iterator first, Iterator last, Predicate pred,
+    operator()(__pstl::execution::parallel_unsequenced_policy, Iterator first, Iterator last, Predicate pred,
                NotPredicate not_pred)
     {
     }
@@ -97,10 +97,10 @@ struct test_non_const
     }
 };
 
-int32_t
+int
 main()
 {
-#if !_PSTL_ICC_17_TEST_MAC_RELEASE_32_BROKEN
+#if !defined(_PSTL_ICC_17_TEST_MAC_RELEASE_32_BROKEN)
     // Note that the "hit" and "miss" functions here avoid overflow issues.
     test<Number>(IsMultiple(5, OddTag()), [](int32_t j) { return Number(j - j % 5, OddTag()); }, // hit
                  [](int32_t j) { return Number(j % 5 == 0 ? j ^ 1 : j, OddTag()); });            // miss
diff --git a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_nonmodifying/for_each.cc b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_nonmodifying/for_each.cc
index 412367c4583..51c51221b3c 100644
--- a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_nonmodifying/for_each.cc
+++ b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_nonmodifying/for_each.cc
@@ -62,7 +62,7 @@ struct test_one_policy
         EXPECT_EQ_N(expected_first, first, n, "wrong effect from for_each");
 
         // Try for_each_n
-        std::for_each_n(__pstl::execution::seq, expected_first, n, Flip<T>(1));
+        std::for_each_n(std::execution::seq, expected_first, n, Flip<T>(1));
         for_each_n(exec, first, n, Flip<T>(1));
         EXPECT_EQ_N(expected_first, first, n, "wrong effect from for_each_n");
     }
@@ -96,7 +96,7 @@ struct test_non_const
     }
 };
 
-int32_t
+int
 main()
 {
     test<int32_t>();
diff --git a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_nonmodifying/mismatch.cc b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_nonmodifying/mismatch.cc
index 36096b1f1aa..1173186f65c 100644
--- a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_nonmodifying/mismatch.cc
+++ b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_nonmodifying/mismatch.cc
@@ -53,7 +53,7 @@ struct test_mismatch
         using namespace std;
         typedef typename iterator_traits<Iterator1>::value_type T;
         {
-            const auto expected = mismatch(__pstl::execution::seq, first1, last1, first2, last2, std::equal_to<T>());
+            const auto expected = mismatch(std::execution::seq, first1, last1, first2, last2, std::equal_to<T>());
             const auto res1 = mismatch(exec, first1, last1, first2, last2, std::equal_to<T>());
             EXPECT_TRUE(expected == res1, "wrong return result from mismatch");
             const auto res2 = mismatch(exec, first1, last1, first2, last2);
@@ -129,7 +129,7 @@ struct test_non_const
     }
 };
 
-int32_t
+int
 main()
 {
 
diff --git a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_nonmodifying/none_of.cc b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_nonmodifying/none_of.cc
index b563e48409d..a49b6b2d45f 100644
--- a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_nonmodifying/none_of.cc
+++ b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_nonmodifying/none_of.cc
@@ -55,7 +55,7 @@ test(size_t bits)
     {
 
         // Sequence of odd values
-        Sequence<T> in(n, [n, bits](size_t k) { return T(2 * HashBits(n, bits - 1) ^ 1); });
+        Sequence<T> in(n, [n, bits](size_t) { return T(2 * HashBits(n, bits - 1) ^ 1); });
 
         // Even value, or false when T is bool.
         T spike(2 * HashBits(n, bits - 1));
@@ -92,13 +92,13 @@ struct test_non_const
     }
 };
 
-int32_t
+int
 main()
 {
     test<int32_t>(8 * sizeof(int32_t));
     test<uint16_t>(8 * sizeof(uint16_t));
     test<float64_t>(53);
-#if !_PSTL_ICC_16_17_TEST_REDUCTION_BOOL_TYPE_RELEASE_64_BROKEN
+#if !defined(_PSTL_ICC_16_17_TEST_REDUCTION_BOOL_TYPE_RELEASE_64_BROKEN)
     test<bool>(1);
 #endif
 
diff --git a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_nonmodifying/nth_element.cc b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_nonmodifying/nth_element.cc
index 9aca6d2a403..61bbca758b4 100644
--- a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_nonmodifying/nth_element.cc
+++ b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_nonmodifying/nth_element.cc
@@ -78,17 +78,17 @@ is_equal(const T& x, const T& y)
 
 struct test_one_policy
 {
-#if _PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN ||                                                            \
-    _PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN // dummy specialization by policy type, in case of broken configuration
+#if defined(_PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN) ||                                                             \
+    defined(_PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN) // dummy specialization by policy type, in case of broken configuration
     template <typename Iterator1, typename Size, typename Generator1, typename Generator2, typename Compare>
     typename std::enable_if<is_same_iterator_category<Iterator1, std::random_access_iterator_tag>::value, void>::type
-    operator()(pstl::execution::unsequenced_policy, Iterator1 first1, Iterator1 last1, Iterator1 first2,
+    operator()(__pstl::execution::unsequenced_policy, Iterator1 first1, Iterator1 last1, Iterator1 first2,
                Iterator1 last2, Size n, Size m, Generator1 generator1, Generator2 generator2, Compare comp)
     {
     }
     template <typename Iterator1, typename Size, typename Generator1, typename Generator2, typename Compare>
     typename std::enable_if<is_same_iterator_category<Iterator1, std::random_access_iterator_tag>::value, void>::type
-    operator()(pstl::execution::parallel_unsequenced_policy, Iterator1 first1, Iterator1 last1, Iterator1 first2,
+    operator()(__pstl::execution::parallel_unsequenced_policy, Iterator1 first1, Iterator1 last1, Iterator1 first2,
                Iterator1 last2, Size n, Size m, Generator1 generator1, Generator2 generator2, Compare comp)
     {
     }
@@ -123,8 +123,7 @@ struct test_one_policy
     template <typename Policy, typename Iterator1, typename Size, typename Generator1, typename Generator2,
               typename Compare>
     typename std::enable_if<!is_same_iterator_category<Iterator1, std::random_access_iterator_tag>::value, void>::type
-    operator()(Policy&& exec, Iterator1 first1, Iterator1 last1, Iterator1 first2, Iterator1 last2, Size n, Size m,
-               Generator1 generator1, Generator2 generator2, Compare comp)
+    operator()(Policy&&, Iterator1, Iterator1, Iterator1, Iterator1, Size, Size, Generator1, Generator2, Compare)
     {
     }
 };
@@ -166,7 +165,7 @@ struct test_non_const
     }
 };
 
-int32_t
+int
 main()
 {
     test_by_type<int32_t>([](int32_t i) { return 10 * i; }, [](int32_t i) { return i + 1; }, std::less<int32_t>());
diff --git a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_nonmodifying/reverse.cc b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_nonmodifying/reverse.cc
index 7db9049ea18..f3cc5d3bc0f 100644
--- a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_nonmodifying/reverse.cc
+++ b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_nonmodifying/reverse.cc
@@ -30,17 +30,17 @@ using namespace TestUtils;
 
 struct test_one_policy
 {
-#if _PSTL_ICC_18_VC141_TEST_SIMD_LAMBDA_RELEASE_BROKEN || _PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN ||     \
-    _PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN // dummy specialization by policy type, in case of broken configuration
+#if defined(_PSTL_ICC_18_VC141_TEST_SIMD_LAMBDA_RELEASE_BROKEN) || defined(_PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN) ||       \
+    defined(_PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN) // dummy specialization by policy type, in case of broken configuration
     template <typename Iterator1, typename Iterator2>
     typename std::enable_if<is_same_iterator_category<Iterator1, std::random_access_iterator_tag>::value, void>::type
-    operator()(pstl::execution::unsequenced_policy, Iterator1 data_b, Iterator1 data_e, Iterator2 actual_b,
+    operator()(__pstl::execution::unsequenced_policy, Iterator1 data_b, Iterator1 data_e, Iterator2 actual_b,
                Iterator2 actual_e)
     {
     }
     template <typename Iterator1, typename Iterator2>
     typename std::enable_if<is_same_iterator_category<Iterator1, std::random_access_iterator_tag>::value, void>::type
-    operator()(pstl::execution::parallel_unsequenced_policy, Iterator1 data_b, Iterator1 data_e, Iterator2 actual_b,
+    operator()(__pstl::execution::parallel_unsequenced_policy, Iterator1 data_b, Iterator1 data_e, Iterator2 actual_b,
                Iterator2 actual_e)
     {
     }
@@ -63,7 +63,7 @@ struct test_one_policy
 
     template <typename ExecutionPolicy, typename Iterator1, typename Iterator2>
     typename std::enable_if<is_same_iterator_category<Iterator1, std::forward_iterator_tag>::value>::type
-    operator()(ExecutionPolicy&& exec, Iterator1 data_b, Iterator1 data_e, Iterator2 actual_b, Iterator2 actual_e)
+    operator()(ExecutionPolicy&&, Iterator1, Iterator1, Iterator2, Iterator2)
     {
     }
 };
@@ -98,13 +98,13 @@ struct wrapper
     }
 };
 
-int32_t
+int
 main()
 {
     test<int32_t>();
     test<uint16_t>();
     test<float64_t>();
-#if !_PSTL_ICC_17_TEST_MAC_RELEASE_32_BROKEN
+#if !defined(_PSTL_ICC_17_TEST_MAC_RELEASE_32_BROKEN)
     test<wrapper<float64_t>>();
 #endif
 
diff --git a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_nonmodifying/reverse_copy.cc b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_nonmodifying/reverse_copy.cc
index 3ec0408c98e..a6c39a2268b 100644
--- a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_nonmodifying/reverse_copy.cc
+++ b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_nonmodifying/reverse_copy.cc
@@ -70,16 +70,16 @@ struct test_one_policy
     Iterator data_e;
     test_one_policy(Iterator b, Iterator e) : data_b(b), data_e(e) {}
 
-#if _PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN ||                                                            \
-    _PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN // dummy specialization by policy type, in case of broken configuration
+#if defined(_PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN) ||                                                             \
+    defined(_PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN) // dummy specialization by policy type, in case of broken configuration
     template <typename Iterator1>
     typename std::enable_if<is_same_iterator_category<Iterator1, std::random_access_iterator_tag>::value, void>::type
-    operator()(pstl::execution::unsequenced_policy, Iterator1 actual_b, Iterator1 actual_e)
+    operator()(__pstl::execution::unsequenced_policy, Iterator1 actual_b, Iterator1 actual_e)
     {
     }
     template <typename Iterator1>
     typename std::enable_if<is_same_iterator_category<Iterator1, std::random_access_iterator_tag>::value, void>::type
-    operator()(pstl::execution::parallel_unsequenced_policy, Iterator1 actual_b, Iterator1 actual_e)
+    operator()(__pstl::execution::parallel_unsequenced_policy, Iterator1 actual_b, Iterator1 actual_e)
     {
     }
 #endif
@@ -90,7 +90,6 @@ struct test_one_policy
     {
         using namespace std;
         using T = typename iterator_traits<Iterator1>::value_type;
-        using DifferenceType = typename iterator_traits<Iterator1>::difference_type;
 
         fill(actual_b, actual_e, T(-123));
         Iterator1 actual_return = reverse_copy(exec, data_b, data_e, actual_b);
@@ -127,11 +126,9 @@ test()
     }
 }
 
-int32_t
+int
 main()
 {
-    // clang-3.8 fails to correctly auto vectorize the loop in some cases of different types of container's elements,
-    // for example: int32_t and int8_t. This issue isn't detected for clang-3.9 and newer versions.
     test<int16_t, int8_t>();
     test<uint16_t, float32_t>();
     test<float64_t, int64_t>();
diff --git a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_nonmodifying/search_n.cc b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_nonmodifying/search_n.cc
index c0b73868d25..fab146fc74c 100644
--- a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_nonmodifying/search_n.cc
+++ b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_nonmodifying/search_n.cc
@@ -28,16 +28,16 @@ using namespace TestUtils;
 
 struct test_one_policy
 {
-#if _PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN ||                                                            \
-    _PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN //dummy specialization by policy type, in case of broken configuration
+#if defined(_PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN) ||                                                             \
+    defined(_PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN) //dummy specialization by policy type, in case of broken configuration
     template <typename Iterator, typename Size, typename T, typename Predicate>
     void
-    operator()(pstl::execution::unsequenced_policy, Iterator b, Iterator e, Size count, const T& value, Predicate pred)
+    operator()(__pstl::execution::unsequenced_policy, Iterator b, Iterator e, Size count, const T& value, Predicate pred)
     {
     }
     template <typename Iterator, typename Size, typename T, typename Predicate>
     void
-    operator()(pstl::execution::parallel_unsequenced_policy, Iterator b, Iterator e, Size count, const T& value,
+    operator()(__pstl::execution::parallel_unsequenced_policy, Iterator b, Iterator e, Size count, const T& value,
                Predicate pred)
     {
     }
@@ -77,7 +77,7 @@ test()
             }
             for (auto r : res)
             {
-                Sequence<T> in(n1, [n1](std::size_t k) { return T(0); });
+                Sequence<T> in(n1, [](std::size_t) { return T(0); });
                 std::size_t i = r, isub = 0;
                 for (; i < n1 && isub < n2; ++i, ++isub)
                     in[i] = value;
@@ -100,13 +100,13 @@ struct test_non_const
     }
 };
 
-int32_t
+int
 main()
 {
     test<int32_t>();
     test<uint16_t>();
     test<float64_t>();
-#if !_PSTL_ICC_16_17_TEST_REDUCTION_BOOL_TYPE_RELEASE_64_BROKEN
+#if !defined(_PSTL_ICC_16_17_TEST_REDUCTION_BOOL_TYPE_RELEASE_64_BROKEN)
     test<bool>();
 #endif
 
diff --git a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_sorting/includes.cc b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_sorting/includes.cc
index 3cf06aacbf3..ed07810618d 100644
--- a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_sorting/includes.cc
+++ b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_sorting/includes.cc
@@ -67,8 +67,7 @@ struct test_one_policy
 
     template <typename Policy, typename InputIterator1, typename InputIterator2, typename Compare>
     typename std::enable_if<TestUtils::isReverse<InputIterator1>::value, void>::type
-    operator()(Policy&& exec, InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2,
-               Compare comp)
+    operator()(Policy&&, InputIterator1, InputIterator1, InputIterator2, InputIterator2, Compare)
     {
     }
 };
@@ -104,11 +103,11 @@ test_includes(Compare compare)
     }
 }
 
-int32_t
+int
 main()
 {
 
-    test_includes<float64_t, float64_t>(__pstl::__internal::__pstl_less());
+    test_includes<float64_t, float64_t>(std::less<>());
     test_includes<Num<int64_t>, Num<int32_t>>([](const Num<int64_t>& x, const Num<int32_t>& y) { return x < y; });
     std::cout << done() << std::endl;
 
diff --git a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_sorting/is_heap.cc b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_sorting/is_heap.cc
index a4589937de7..bb3c3a57eca 100644
--- a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_sorting/is_heap.cc
+++ b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_sorting/is_heap.cc
@@ -43,16 +43,16 @@ struct WithCmpOp
 
 struct test_is_heap
 {
-#if _PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN ||                                                            \
-    _PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN //dummy specialization by policy type, in case of broken configuration
+#if defined(_PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN) ||                                                             \
+    defined(_PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN) //dummy specialization by policy type, in case of broken configuration
     template <typename Iterator, typename Predicate>
     typename std::enable_if<is_same_iterator_category<Iterator, std::random_access_iterator_tag>::value, void>::type
-    operator()(pstl::execution::unsequenced_policy, Iterator first, Iterator last, Predicate pred)
+    operator()(__pstl::execution::unsequenced_policy, Iterator first, Iterator last, Predicate pred)
     {
     }
     template <typename Iterator, typename Predicate>
     typename std::enable_if<is_same_iterator_category<Iterator, std::random_access_iterator_tag>::value, void>::type
-    operator()(pstl::execution::parallel_unsequenced_policy, Iterator first, Iterator last, Predicate pred)
+    operator()(__pstl::execution::parallel_unsequenced_policy, Iterator first, Iterator last, Predicate pred)
     {
     }
 #endif
@@ -87,13 +87,14 @@ struct test_is_heap
             const Iterator actual = is_heap_until(exec, first, last, pred);
             const auto x = std::distance(first, actual);
             EXPECT_TRUE(expected == actual, "wrong return value from is_heap_until with predicate");
+            EXPECT_EQ(x, y, "both iterators should be the same distance away from 'first'");
         }
     }
 
     // is_heap, is_heap_until works only with random access iterators
     template <typename Policy, typename Iterator, typename Predicate>
     typename std::enable_if<!is_same_iterator_category<Iterator, std::random_access_iterator_tag>::value, void>::type
-    operator()(Policy&& exec, Iterator first, Iterator last, Predicate pred)
+    operator()(Policy&&, Iterator, Iterator, Predicate)
     {
     }
 };
@@ -121,7 +122,7 @@ test_is_heap_by_type(Comp comp)
         invoke_on_all_policies(test_is_heap(), in.cbegin(), in.cend(), comp);
     }
 
-    Sequence<T> in(max_size / 10, [](size_t v) -> T { return T(1); });
+    Sequence<T> in(max_size / 10, [](size_t) -> T { return T(1); });
     invoke_on_all_policies(test_is_heap(), in.begin(), in.end(), comp);
 }
 
@@ -139,7 +140,7 @@ struct test_non_const
     }
 };
 
-int32_t
+int
 main()
 {
     test_is_heap_by_type<float32_t>(std::greater<float32_t>());
diff --git a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_sorting/is_sorted.cc b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_sorting/is_sorted.cc
index 3c0230d981b..d88144ebc27 100644
--- a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_sorting/is_sorted.cc
+++ b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_sorting/is_sorted.cc
@@ -76,7 +76,7 @@ test_is_sorted_by_type()
     invoke_on_all_policies(test_is_sorted(), in0.cbegin(), in0.cend(), std::is_sorted(in0.begin(), in0.end()));
 
     //non-descending order
-    Sequence<T> in1(9, [](size_t v) -> T { return T(0); });
+    Sequence<T> in1(9, [](size_t) -> T { return T(0); });
     invoke_on_all_policies(test_is_sorted(), in1.begin(), in1.end(), std::is_sorted(in1.begin(), in1.end()));
     invoke_on_all_policies(test_is_sorted(), in1.cbegin(), in1.cend(), std::is_sorted(in1.begin(), in1.end()));
 }
@@ -93,7 +93,7 @@ struct test_non_const
     }
 };
 
-int32_t
+int
 main()
 {
 
diff --git a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_sorting/lexicographical_compare.cc b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_sorting/lexicographical_compare.cc
index 1cc480cc66f..924aa78652e 100644
--- a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_sorting/lexicographical_compare.cc
+++ b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_sorting/lexicographical_compare.cc
@@ -165,12 +165,12 @@ struct test_non_const
     }
 };
 
-int32_t
+int
 main()
 {
     test<uint16_t, float64_t>(std::less<float64_t>());
     test<float32_t, int32_t>(std::greater<float32_t>());
-#if !_PSTL_ICC_18_TEST_EARLY_EXIT_AVX_RELEASE_BROKEN
+#if !defined(_PSTL_ICC_18_TEST_EARLY_EXIT_AVX_RELEASE_BROKEN)
     test<float64_t, int32_t>([](const float64_t x, const int32_t y) { return x * x < y * y; });
 #endif
     test<LocalWrapper<int32_t>, LocalWrapper<int32_t>>(
diff --git a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_sorting/minmax_element.cc b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_sorting/minmax_element.cc
index 60522a4dae5..0a9f41ca179 100644
--- a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_sorting/minmax_element.cc
+++ b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_sorting/minmax_element.cc
@@ -184,7 +184,7 @@ struct test_non_const
     }
 };
 
-int32_t
+int
 main()
 {
     using TestUtils::float64_t;
diff --git a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_sorting/partial_sort.cc b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_sorting/partial_sort.cc
index cf12bfc27b9..6d441cc3ae9 100644
--- a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_sorting/partial_sort.cc
+++ b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_sorting/partial_sort.cc
@@ -90,19 +90,18 @@ struct test_brick_partial_sort
             //checking upper bound number of comparisons; O(p*(last-first)log(middle-first)); where p - number of threads;
             if (m1 - first > 1)
             {
-                auto complex = std::ceil(n * std::log(float32_t(m1 - first)));
-#if _PSTL_USE_PAR_POLICIES
-                auto p = tbb::this_task_arena::max_concurrency();
-#else
-                auto p = 1;
-#endif
-
 #ifdef _DEBUG
+#    if defined(_PSTL_PAR_BACKEND_TBB)
+                auto p = tbb::this_task_arena::max_concurrency();
+#    else
+                auto p = 1;
+#    endif
+                auto complex = std::ceil(n * std::log(float32_t(m1 - first)));
                 if (count_comp > complex * p)
                 {
                     std::cout << "complexity exceeded" << std::endl;
                 }
-#endif
+#endif // _DEBUG
             }
         }
     }
@@ -110,8 +109,7 @@ struct test_brick_partial_sort
     template <typename Policy, typename InputIterator, typename Compare>
     typename std::enable_if<!is_same_iterator_category<InputIterator, std::random_access_iterator_tag>::value,
                             void>::type
-    operator()(Policy&& exec, InputIterator first, InputIterator last, InputIterator exp_first, InputIterator exp_last,
-               Compare compare)
+    operator()(Policy&&, InputIterator, InputIterator, InputIterator, InputIterator, Compare)
     {
     }
 };
@@ -142,7 +140,7 @@ struct test_non_const
     }
 };
 
-int32_t
+int
 main()
 {
     count_val = 0;
diff --git a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_sorting/partial_sort_copy.cc b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_sorting/partial_sort_copy.cc
index 7c5608ac248..72336d62885 100644
--- a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_sorting/partial_sort_copy.cc
+++ b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_sorting/partial_sort_copy.cc
@@ -64,32 +64,32 @@ struct test_one_policy
         : d_first(b1), d_last(e1), exp_first(b2), exp_last(e2)
     {
     }
-#if _PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN ||                                                            \
-    _PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN // dummy specialization by policy type, in case of broken configuration
+#if defined(_PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN) ||                                                             \
+    defined(_PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN) // dummy specialization by policy type, in case of broken configuration
     template <typename InputIterator, typename Size, typename T, typename Compare>
     void
-    operator()(pstl::execution::unsequenced_policy, InputIterator first, InputIterator last, Size n1, Size n2,
+    operator()(__pstl::execution::unsequenced_policy, InputIterator first, InputIterator last, Size n1, Size n2,
                const T& trash, Compare compare)
     {
     }
 
     template <typename InputIterator, typename Size, typename T, typename Compare>
     void
-    operator()(pstl::execution::parallel_unsequenced_policy, InputIterator first, InputIterator last, Size n1, Size n2,
+    operator()(__pstl::execution::parallel_unsequenced_policy, InputIterator first, InputIterator last, Size n1, Size n2,
                const T& trash, Compare compare)
     {
     }
 
     template <typename InputIterator, typename Size, typename T>
     void
-    operator()(pstl::execution::unsequenced_policy, InputIterator first, InputIterator last, Size n1, Size n2,
+    operator()(__pstl::execution::unsequenced_policy, InputIterator first, InputIterator last, Size n1, Size n2,
                const T& trash)
     {
     }
 
     template <typename InputIterator, typename Size, typename T>
     void
-    operator()(pstl::execution::parallel_unsequenced_policy, InputIterator first, InputIterator last, Size n1, Size n2,
+    operator()(__pstl::execution::parallel_unsequenced_policy, InputIterator first, InputIterator last, Size n1, Size n2,
                const T& trash)
     {
     }
@@ -187,7 +187,7 @@ struct test_non_const
     }
 };
 
-int32_t
+int
 main()
 {
     test_partial_sort_copy<Num<float32_t>>([](Num<float32_t> x, Num<float32_t> y) { return x < y; });
@@ -195,6 +195,11 @@ main()
 
     test_algo_basic_double<int32_t>(run_for_rnd<test_non_const<int32_t>>());
 
+    test_partial_sort_copy<MemoryChecker>(
+        [](const MemoryChecker& val1, const MemoryChecker& val2){ return val1.value() < val2.value(); });
+    EXPECT_FALSE(MemoryChecker::alive_objects() < 0, "wrong effect from partial_sort_copy: number of ctors calls < num of dtors calls");
+    EXPECT_FALSE(MemoryChecker::alive_objects() > 0, "wrong effect from partial_sort_copy: number of ctors calls > num of dtors calls");
+
     std::cout << done() << std::endl;
     return 0;
 }
diff --git a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_sorting/set.cc b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_sorting/set.cc
index 5d411a86bed..0343739dfd1 100644
--- a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_sorting/set.cc
+++ b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_sorting/set.cc
@@ -60,7 +60,8 @@ struct Num
     }
 };
 
-struct test_one_policy
+template <typename Type>
+struct test_set_union
 {
     template <typename Policy, typename InputIterator1, typename InputIterator2, typename Compare>
     typename std::enable_if<!TestUtils::isReverse<InputIterator1>::value, void>::type
@@ -75,30 +76,98 @@ struct test_one_policy
         Sequence<T1> expect(n);
         Sequence<T1> out(n);
 
-        //1. set_union
         auto expect_res = std::set_union(first1, last1, first2, last2, expect.begin(), comp);
         auto res = std::set_union(exec, first1, last1, first2, last2, out.begin(), comp);
 
         EXPECT_TRUE(expect_res - expect.begin() == res - out.begin(), "wrong result for set_union");
         EXPECT_EQ_N(expect.begin(), out.begin(), std::distance(out.begin(), res), "wrong set_union effect");
+    }
 
-        //2. set_intersection
-        expect_res = std::set_intersection(first1, last1, first2, last2, expect.begin(), comp);
-        res = std::set_intersection(exec, first1, last1, first2, last2, out.begin(), comp);
+    template <typename Policy, typename InputIterator1, typename InputIterator2, typename Compare>
+    typename std::enable_if<TestUtils::isReverse<InputIterator1>::value, void>::type
+    operator()(Policy&&, InputIterator1, InputIterator1, InputIterator2, InputIterator2, Compare)
+    {
+    }
+};
+
+template <typename Type>
+struct test_set_intersection
+{
+    template <typename Policy, typename InputIterator1, typename InputIterator2, typename Compare>
+    typename std::enable_if<!TestUtils::isReverse<InputIterator1>::value, void>::type
+    operator()(Policy&& exec, InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2,
+               Compare comp)
+    {
+        using T1 = typename std::iterator_traits<InputIterator1>::value_type;
+
+        auto n1 = std::distance(first1, last1);
+        auto n2 = std::distance(first2, last2);
+        auto n = n1 + n2;
+        Sequence<T1> expect(n);
+        Sequence<T1> out(n);
+
+        auto expect_res = std::set_intersection(first1, last1, first2, last2, expect.begin(), comp);
+        auto res = std::set_intersection(exec, first1, last1, first2, last2, out.begin(), comp);
 
         EXPECT_TRUE(expect_res - expect.begin() == res - out.begin(), "wrong result for set_intersection");
         EXPECT_EQ_N(expect.begin(), out.begin(), std::distance(out.begin(), res), "wrong set_intersection effect");
+    }
 
-        //3. set_difference
-        expect_res = std::set_difference(first1, last1, first2, last2, expect.begin(), comp);
-        res = std::set_difference(exec, first1, last1, first2, last2, out.begin(), comp);
+    template <typename Policy, typename InputIterator1, typename InputIterator2, typename Compare>
+    typename std::enable_if<TestUtils::isReverse<InputIterator1>::value, void>::type
+    operator()(Policy&&, InputIterator1, InputIterator1, InputIterator2, InputIterator2, Compare)
+    {
+    }
+};
+
+template <typename Type>
+struct test_set_difference
+{
+    template <typename Policy, typename InputIterator1, typename InputIterator2, typename Compare>
+    typename std::enable_if<!TestUtils::isReverse<InputIterator1>::value, void>::type
+    operator()(Policy&& exec, InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2,
+               Compare comp)
+    {
+        using T1 = typename std::iterator_traits<InputIterator1>::value_type;
+
+        auto n1 = std::distance(first1, last1);
+        auto n2 = std::distance(first2, last2);
+        auto n = n1 + n2;
+        Sequence<T1> expect(n);
+        Sequence<T1> out(n);
+
+        auto expect_res = std::set_difference(first1, last1, first2, last2, expect.begin(), comp);
+        auto res = std::set_difference(exec, first1, last1, first2, last2, out.begin(), comp);
 
         EXPECT_TRUE(expect_res - expect.begin() == res - out.begin(), "wrong result for set_difference");
         EXPECT_EQ_N(expect.begin(), out.begin(), std::distance(out.begin(), res), "wrong set_difference effect");
+    }
 
-        //4. set_symmetric_difference
-        expect_res = std::set_symmetric_difference(first1, last1, first2, last2, expect.begin(), comp);
-        res = std::set_symmetric_difference(exec, first1, last1, first2, last2, out.begin(), comp);
+    template <typename Policy, typename InputIterator1, typename InputIterator2, typename Compare>
+    typename std::enable_if<TestUtils::isReverse<InputIterator1>::value, void>::type
+    operator()(Policy&&, InputIterator1, InputIterator1, InputIterator2, InputIterator2, Compare)
+    {
+    }
+};
+
+template <typename Type>
+struct test_set_symmetric_difference
+{
+    template <typename Policy, typename InputIterator1, typename InputIterator2, typename Compare>
+    typename std::enable_if<!TestUtils::isReverse<InputIterator1>::value, void>::type
+    operator()(Policy&& exec, InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2,
+               Compare comp)
+    {
+        using T1 = typename std::iterator_traits<InputIterator1>::value_type;
+
+        auto n1 = std::distance(first1, last1);
+        auto n2 = std::distance(first2, last2);
+        auto n = n1 + n2;
+        Sequence<T1> expect(n);
+        Sequence<T1> out(n);
+
+        auto expect_res = std::set_symmetric_difference(first1, last1, first2, last2, expect.begin(), comp);
+        auto res = std::set_symmetric_difference(exec, first1, last1, first2, last2, out.begin(), comp);
 
         EXPECT_TRUE(expect_res - expect.begin() == res - out.begin(), "wrong result for set_symmetric_difference");
         EXPECT_EQ_N(expect.begin(), out.begin(), std::distance(out.begin(), res),
@@ -107,8 +176,7 @@ struct test_one_policy
 
     template <typename Policy, typename InputIterator1, typename InputIterator2, typename Compare>
     typename std::enable_if<TestUtils::isReverse<InputIterator1>::value, void>::type
-    operator()(Policy&& exec, InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2,
-               Compare comp)
+    operator()(Policy&&, InputIterator1, InputIterator1, InputIterator2, InputIterator2, Compare)
     {
     }
 };
@@ -128,43 +196,92 @@ test_set(Compare compare)
         for (std::size_t m = 0; m < n_max; m = m <= 16 ? m + 1 : size_t(2.71828 * m))
         {
             //prepare the input ranges
-            Sequence<T1> in1(n, [n](std::size_t k) { return rand() % (2 * k + 1); });
+            Sequence<T1> in1(n, [](std::size_t k) { return rand() % (2 * k + 1); });
             Sequence<T2> in2(m, [m](std::size_t k) { return (m % 2) * rand() + rand() % (k + 1); });
 
             std::sort(in1.begin(), in1.end(), compare);
             std::sort(in2.begin(), in2.end(), compare);
 
-            invoke_on_all_policies(test_one_policy(), in1.begin(), in1.end(), in2.cbegin(), in2.cend(), compare);
+            invoke_on_all_policies(test_set_union<T1>(), in1.begin(), in1.end(), in2.cbegin(), in2.cend(),
+                                        compare);
+
+            invoke_on_all_policies(test_set_intersection<T1>(), in1.begin(), in1.end(), in2.cbegin(), in2.cend(),
+                                        compare);
+
+            invoke_on_all_policies(test_set_difference<T1>(), in1.begin(), in1.end(), in2.cbegin(), in2.cend(),
+                                        compare);
+
+            invoke_on_all_policies(test_set_symmetric_difference<T1>(), in1.begin(), in1.end(), in2.cbegin(),
+                                        in2.cend(), compare);
         }
     }
 }
 
 template <typename T>
-struct test_non_const
+struct test_non_const_set_difference
 {
     template <typename Policy, typename InputIterator, typename OutputInterator>
     void
     operator()(Policy&& exec, InputIterator input_iter, OutputInterator out_iter)
     {
         set_difference(exec, input_iter, input_iter, input_iter, input_iter, out_iter, non_const(std::less<T>()));
+    }
+};
 
+template <typename T>
+struct test_non_const_set_intersection
+{
+    template <typename Policy, typename InputIterator, typename OutputInterator>
+    void
+    operator()(Policy&& exec, InputIterator input_iter, OutputInterator out_iter)
+    {
         set_intersection(exec, input_iter, input_iter, input_iter, input_iter, out_iter, non_const(std::less<T>()));
+    }
+};
 
+template <typename T>
+struct test_non_const_set_symmetric_difference
+{
+    template <typename Policy, typename InputIterator, typename OutputInterator>
+    void
+    operator()(Policy&& exec, InputIterator input_iter, OutputInterator out_iter)
+    {
         set_symmetric_difference(exec, input_iter, input_iter, input_iter, input_iter, out_iter,
                                  non_const(std::less<T>()));
+    }
+};
 
+template <typename T>
+struct test_non_const_set_union
+{
+    template <typename Policy, typename InputIterator, typename OutputInterator>
+    void
+    operator()(Policy&& exec, InputIterator input_iter, OutputInterator out_iter)
+    {
         set_union(exec, input_iter, input_iter, input_iter, input_iter, out_iter, non_const(std::less<T>()));
     }
 };
 
-int32_t
+int
 main()
 {
 
-    test_set<float64_t, float64_t>(__pstl::__internal::__pstl_less());
+    test_set<float64_t, float64_t>(std::less<>());
     test_set<Num<int64_t>, Num<int32_t>>([](const Num<int64_t>& x, const Num<int32_t>& y) { return x < y; });
 
-    test_algo_basic_double<int32_t>(run_for_rnd_fw<test_non_const<int32_t>>());
+    test_set<MemoryChecker, MemoryChecker>([](const MemoryChecker& val1, const MemoryChecker& val2) -> bool {
+        return val1.value() < val2.value();
+    });
+    EXPECT_FALSE(MemoryChecker::alive_objects() < 0, "wrong effect from set algorithms: number of ctors calls < num of dtors calls");
+    EXPECT_FALSE(MemoryChecker::alive_objects() > 0, "wrong effect from set algorithms: number of ctors calls > num of dtors calls");
+
+    test_algo_basic_double<int32_t>(run_for_rnd_fw<test_non_const_set_difference<int32_t>>());
+
+    test_algo_basic_double<int32_t>(run_for_rnd_fw<test_non_const_set_intersection<int32_t>>());
+
+    test_algo_basic_double<int32_t>(run_for_rnd_fw<test_non_const_set_symmetric_difference<int32_t>>());
+
+    test_algo_basic_double<int32_t>(run_for_rnd_fw<test_non_const_set_union<int32_t>>());
 
     std::cout << done() << std::endl;
 
diff --git a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_sorting/sort.cc b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_sorting/sort.cc
index b460c595be9..94257bd1ac3 100644
--- a/libstdc++-v3/testsuite/25_algorithms/pstl/alg_sorting/sort.cc
+++ b/libstdc++-v3/testsuite/25_algorithms/pstl/alg_sorting/sort.cc
@@ -94,7 +94,7 @@ class ParanoidKey
         index = k.index;
         return *this;
     }
-    ParanoidKey(int32_t index, int32_t value, OddTag) : index(index), value(value) {}
+    ParanoidKey(int32_t index, int32_t value, OddTag) : value(value), index(index) {}
     ParanoidKey(ParanoidKey&& k) : value(k.value), index(k.index)
     {
         EXPECT_TRUE(k.isConstructed(), "source for move-construction is dead");
@@ -171,7 +171,7 @@ struct test_sort_with_compare
     typename std::enable_if<is_same_iterator_category<InputIterator, std::random_access_iterator_tag>::value,
                             void>::type
     operator()(Policy&& exec, OutputIterator tmp_first, OutputIterator tmp_last, OutputIterator2 expected_first,
-               OutputIterator2 expected_last, InputIterator first, InputIterator last, Size n, Compare compare)
+               OutputIterator2 expected_last, InputIterator first, InputIterator, Size n, Compare compare)
     {
         using namespace std;
         copy_n(first, n, expected_first);
@@ -198,8 +198,8 @@ struct test_sort_with_compare
               typename Compare>
     typename std::enable_if<!is_same_iterator_category<InputIterator, std::random_access_iterator_tag>::value,
                             void>::type
-    operator()(Policy&& exec, OutputIterator tmp_first, OutputIterator tmp_last, OutputIterator2 expected_first,
-               OutputIterator2 expected_last, InputIterator first, InputIterator last, Size n, Compare compare)
+    operator()(Policy&&, OutputIterator, OutputIterator, OutputIterator2, OutputIterator2, InputIterator, InputIterator,
+               Size, Compare)
     {
     }
 };
@@ -233,7 +233,7 @@ struct test_non_const
     }
 };
 
-int32_t
+int
 main()
 {
     std::srand(42);
diff --git a/libstdc++-v3/testsuite/26_numerics/pstl/numeric_ops/adjacent_difference.cc b/libstdc++-v3/testsuite/26_numerics/pstl/numeric_ops/adjacent_difference.cc
index b78410821fa..cf42b716acf 100644
--- a/libstdc++-v3/testsuite/26_numerics/pstl/numeric_ops/adjacent_difference.cc
+++ b/libstdc++-v3/testsuite/26_numerics/pstl/numeric_ops/adjacent_difference.cc
@@ -33,19 +33,19 @@ template <typename T>
 struct wrapper
 {
     T t;
-    explicit wrapper(T t_) : t(t_) {}
+    constexpr explicit wrapper(T t_) : t(t_) {}
     template <typename T2>
-    wrapper(const wrapper<T2>& a)
+    constexpr wrapper(const wrapper<T2>& a)
     {
         t = a.t;
     }
     template <typename T2>
-    void
+    constexpr void
     operator=(const wrapper<T2>& a)
     {
         t = a.t;
     }
-    wrapper<T>
+    constexpr wrapper<T>
     operator-(const wrapper<T>& a) const
     {
         return wrapper<T>(t - a.t);
@@ -75,9 +75,11 @@ compute_and_check(Iterator1 first, Iterator1 last, Iterator2 d_first, T, Functio
     if (first == last)
         return true;
 
-    T2 temp(*first);
-    if (!compare(temp, *d_first))
-        return false;
+    {
+        T2 temp(*first);
+        if (!compare(temp, *d_first))
+            return false;
+    }
     Iterator1 second = std::next(first);
 
     ++d_first;
@@ -94,25 +96,25 @@ compute_and_check(Iterator1 first, Iterator1 last, Iterator2 d_first, T, Functio
 // we don't want to check equality here
 // because we can't be sure it will be strictly equal for floating point types
 template <typename Iterator1, typename Iterator2, typename T, typename Function>
-typename std::enable_if<std::is_floating_point<T>::value, bool>::type
-compute_and_check(Iterator1 first, Iterator1 last, Iterator2 d_first, T, Function)
+typename std::enable_if<std::is_floating_point<T>::value, bool>::type compute_and_check(Iterator1, Iterator1, Iterator2,
+                                                                                        T, Function)
 {
     return true;
 }
 
 struct test_one_policy
 {
-#if _PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN ||                                                            \
-    _PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN // dummy specialization by policy type, in case of broken configuration
+#if defined(_PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN) ||                                                             \
+    defined(_PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN) // dummy specialization by policy type, in case of broken configuration
     template <typename Iterator1, typename Iterator2, typename T, typename Function>
     typename std::enable_if<is_same_iterator_category<Iterator1, std::random_access_iterator_tag>::value, void>::type
-    operator()(pstl::execution::unsequenced_policy, Iterator1 data_b, Iterator1 data_e, Iterator2 actual_b,
+    operator()(__pstl::execution::unsequenced_policy, Iterator1 data_b, Iterator1 data_e, Iterator2 actual_b,
                Iterator2 actual_e, T trash, Function f)
     {
     }
     template <typename Iterator1, typename Iterator2, typename T, typename Function>
     typename std::enable_if<is_same_iterator_category<Iterator1, std::random_access_iterator_tag>::value, void>::type
-    operator()(pstl::execution::parallel_unsequenced_policy, Iterator1 data_b, Iterator1 data_e, Iterator2 actual_b,
+    operator()(__pstl::execution::parallel_unsequenced_policy, Iterator1 data_b, Iterator1 data_e, Iterator2 actual_b,
                Iterator2 actual_e, T trash, Function f)
     {
     }
@@ -146,16 +148,14 @@ template <typename T1, typename T2, typename Pred>
 void
 test(Pred pred)
 {
-    typedef typename Sequence<T2>::iterator iterator_type;
-
     const std::size_t max_len = 100000;
 
-    const T2 value = T2(77);
-    const T1 trash = T1(31);
+    static constexpr T2 value = T2(77);
+    static constexpr T1 trash = T1(31);
 
     Sequence<T1> actual(max_len, [](std::size_t i) { return T1(i); });
 
-    Sequence<T2> data(max_len, [&value](std::size_t i) { return i % 3 == 2 ? T2(i * i) : value; });
+    Sequence<T2> data(max_len, [](std::size_t i) { return i % 3 == 2 ? T2(i * i) : value; });
 
     for (std::size_t len = 0; len < max_len; len = len <= 16 ? len + 1 : std::size_t(3.1415 * len))
     {
@@ -166,7 +166,7 @@ test(Pred pred)
     }
 }
 
-int32_t
+int
 main()
 {
     test<uint8_t, uint32_t>([](uint32_t a, uint32_t b) { return a - b; });
diff --git a/libstdc++-v3/testsuite/26_numerics/pstl/numeric_ops/reduce.cc b/libstdc++-v3/testsuite/26_numerics/pstl/numeric_ops/reduce.cc
index e9f506b370b..5a8f921e8cd 100644
--- a/libstdc++-v3/testsuite/26_numerics/pstl/numeric_ops/reduce.cc
+++ b/libstdc++-v3/testsuite/26_numerics/pstl/numeric_ops/reduce.cc
@@ -62,7 +62,7 @@ test_long_form(T init, BinaryOp binary_op, F f)
 struct test_two_short_forms
 {
 
-#if _PSTL_ICC_16_VC14_TEST_PAR_TBB_RT_RELEASE_64_BROKEN //dummy specialization by policy type, in case of broken configuration
+#if defined(_PSTL_ICC_16_VC14_TEST_PAR_TBB_RT_RELEASE_64_BROKEN) //dummy specialization by policy type, in case of broken configuration
     template <typename Iterator>
     void
     operator()(__pstl::execution::parallel_policy, Iterator first, Iterator last, Sum init, Sum expected)
@@ -105,7 +105,7 @@ test_short_forms()
     }
 }
 
-int32_t
+int
 main()
 {
     // Test for popular types
diff --git a/libstdc++-v3/testsuite/26_numerics/pstl/numeric_ops/scan.cc b/libstdc++-v3/testsuite/26_numerics/pstl/numeric_ops/scan.cc
index 2173d7b32ea..bcd5ad116d8 100644
--- a/libstdc++-v3/testsuite/26_numerics/pstl/numeric_ops/scan.cc
+++ b/libstdc++-v3/testsuite/26_numerics/pstl/numeric_ops/scan.cc
@@ -108,12 +108,13 @@ struct test_scan_with_plus
     template <typename Policy, typename Iterator1, typename Iterator2, typename Iterator3, typename Size, typename T>
     void
     operator()(Policy&& exec, Iterator1 in_first, Iterator1 in_last, Iterator2 out_first, Iterator2 out_last,
-               Iterator3 expected_first, Iterator3 expected_last, Size n, T init, T trash)
+               Iterator3 expected_first, Iterator3, Size n, T init, T trash)
     {
         using namespace std;
 
         auto orr1 = inclusive ? inclusive_scan_serial(in_first, in_last, expected_first)
                               : exclusive_scan_serial(in_first, in_last, expected_first, init);
+        (void)orr1;
         auto orr = inclusive ? inclusive_scan(exec, in_first, in_last, out_first)
                              : exclusive_scan(exec, in_first, in_last, out_first, init);
         EXPECT_TRUE(out_last == orr,
@@ -146,12 +147,13 @@ struct test_scan_with_binary_op
               typename BinaryOp>
     typename std::enable_if<!TestUtils::isReverse<Iterator1>::value, void>::type
     operator()(Policy&& exec, Iterator1 in_first, Iterator1 in_last, Iterator2 out_first, Iterator2 out_last,
-               Iterator3 expected_first, Iterator3 expected_last, Size n, T init, BinaryOp binary_op, T trash)
+               Iterator3 expected_first, Iterator3, Size n, T init, BinaryOp binary_op, T trash)
     {
         using namespace std;
 
         auto orr1 = inclusive ? inclusive_scan_serial(in_first, in_last, expected_first, binary_op, init)
                               : exclusive_scan_serial(in_first, in_last, expected_first, init, binary_op);
+        (void)orr1;
         auto orr = inclusive ? inclusive_scan(exec, in_first, in_last, out_first, binary_op, init)
                              : exclusive_scan(exec, in_first, in_last, out_first, init, binary_op);
 
@@ -162,8 +164,7 @@ struct test_scan_with_binary_op
     template <typename Policy, typename Iterator1, typename Iterator2, typename Iterator3, typename Size, typename T,
               typename BinaryOp>
     typename std::enable_if<TestUtils::isReverse<Iterator1>::value, void>::type
-    operator()(Policy&& exec, Iterator1 in_first, Iterator1 in_last, Iterator2 out_first, Iterator2 out_last,
-               Iterator3 expected_first, Iterator3 expected_last, Size n, T init, BinaryOp binary_op, T trash)
+    operator()(Policy&&, Iterator1, Iterator1, Iterator2, Iterator2, Iterator3, Iterator3, Size, T, BinaryOp, T)
     {
     }
 };
@@ -186,13 +187,13 @@ test_matrix(Out init, BinaryOp binary_op, Out trash)
     }
 }
 
-int32_t
+int
 main()
 {
     for (int32_t mode = 0; mode < 2; ++mode)
     {
         inclusive = mode != 0;
-#if !_PSTL_ICC_19_TEST_SIMD_UDS_WINDOWS_RELEASE_BROKEN
+#if !defined(_PSTL_ICC_19_TEST_SIMD_UDS_WINDOWS_RELEASE_BROKEN)
         // Test with highly restricted type and associative but not commutative operation
         test_matrix<Matrix2x2<int32_t>, Matrix2x2<int32_t>>(Matrix2x2<int32_t>(), multiply_matrix<int32_t>,
                                                             Matrix2x2<int32_t>(-666, 666));
diff --git a/libstdc++-v3/testsuite/26_numerics/pstl/numeric_ops/transform_reduce.cc b/libstdc++-v3/testsuite/26_numerics/pstl/numeric_ops/transform_reduce.cc
index ec020b42bbb..7497d60d8e9 100644
--- a/libstdc++-v3/testsuite/26_numerics/pstl/numeric_ops/transform_reduce.cc
+++ b/libstdc++-v3/testsuite/26_numerics/pstl/numeric_ops/transform_reduce.cc
@@ -54,7 +54,7 @@ class MyClass
     int32_t my_field;
     MyClass() { my_field = 0; }
     MyClass(int32_t in) { my_field = in; }
-    MyClass(const MyClass& in) { my_field = in.my_field; }
+    MyClass(const MyClass& in) = default;
 
     friend MyClass
     operator+(const MyClass& x, const MyClass& y)
@@ -66,11 +66,13 @@ class MyClass
     {
         return MyClass(-x.my_field);
     }
-    friend MyClass operator*(const MyClass& x, const MyClass& y) { return MyClass(x.my_field * y.my_field); }
-    bool
-    operator==(const MyClass& in)
+    friend MyClass operator*(const MyClass& x, const MyClass& y)
     {
-        return my_field == in.my_field;
+        return MyClass(x.my_field * y.my_field);
+    }
+    friend bool operator==(const MyClass& x, const MyClass& y)
+    {
+        return x.my_field == y.my_field;
     }
 };
 
@@ -78,13 +80,13 @@ template <typename T>
 void
 CheckResults(const T& expected, const T& in)
 {
-    EXPECT_TRUE(Equal(expected, in), "wrong result of transform_reduce");
+    EXPECT_TRUE(expected == in, "wrong result of transform_reduce");
 }
 
 // We need to check correctness only for "int" (for example) except cases
 // if we have "floating-point type"-specialization
 void
-CheckResults(const float32_t& expected, const float32_t& in)
+CheckResults(const float32_t&, const float32_t&)
 {
 }
 
@@ -94,7 +96,7 @@ struct test_transform_reduce
     template <typename Policy, typename InputIterator1, typename InputIterator2, typename T, typename BinaryOperation1,
               typename BinaryOperation2, typename UnaryOp>
     void
-    operator()(Policy&& exec, InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2,
+    operator()(Policy&& exec, InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2,
                T init, BinaryOperation1 opB1, BinaryOperation2 opB2, UnaryOp opU)
     {
 
@@ -125,20 +127,19 @@ test_by_type(T init, BinaryOperation1 opB1, BinaryOperation2 opB2, UnaryOp opU,
     }
 }
 
-int32_t
+int
 main()
 {
     test_by_type<int32_t>(42, std::plus<int32_t>(), std::multiplies<int32_t>(), std::negate<int32_t>(),
-                          [](std::size_t a) -> int32_t { return int32_t(rand() % 1000); });
+                          [](std::size_t) -> int32_t { return int32_t(rand() % 1000); });
     test_by_type<int64_t>(0, [](const int64_t& a, const int64_t& b) -> int64_t { return a | b; }, XOR(),
                           [](const int64_t& x) -> int64_t { return x * 2; },
-                          [](std::size_t a) -> int64_t { return int64_t(rand() % 1000); });
-    test_by_type<float32_t>(1.0f, std::multiplies<float32_t>(),
-                            [](const float32_t& a, const float32_t& b) -> float32_t { return a + b; },
-                            [](const float32_t& x) -> float32_t { return x + 2; },
-                            [](std::size_t a) -> float32_t { return rand() % 1000; });
+                          [](std::size_t) -> int64_t { return int64_t(rand() % 1000); });
+    test_by_type<float32_t>(
+        1.0f, std::multiplies<float32_t>(), [](const float32_t& a, const float32_t& b) -> float32_t { return a + b; },
+        [](const float32_t& x) -> float32_t { return x + 2; }, [](std::size_t) -> float32_t { return rand() % 1000; });
     test_by_type<MyClass>(MyClass(), std::plus<MyClass>(), std::multiplies<MyClass>(), std::negate<MyClass>(),
-                          [](std::size_t a) -> MyClass { return MyClass(rand() % 1000); });
+                          [](std::size_t) -> MyClass { return MyClass(rand() % 1000); });
 
     std::cout << done() << std::endl;
     return 0;
diff --git a/libstdc++-v3/testsuite/26_numerics/pstl/numeric_ops/transform_scan.cc b/libstdc++-v3/testsuite/26_numerics/pstl/numeric_ops/transform_scan.cc
index c9694af5bca..e785a95f450 100644
--- a/libstdc++-v3/testsuite/26_numerics/pstl/numeric_ops/transform_scan.cc
+++ b/libstdc++-v3/testsuite/26_numerics/pstl/numeric_ops/transform_scan.cc
@@ -47,15 +47,15 @@ struct test_transform_scan
               typename T, typename BinaryOp>
     typename std::enable_if<!TestUtils::isReverse<InputIterator>::value, void>::type
     operator()(Policy&& exec, InputIterator first, InputIterator last, OutputIterator out_first,
-               OutputIterator out_last, OutputIterator expected_first, OutputIterator expected_last, Size n,
-               UnaryOp unary_op, T init, BinaryOp binary_op, T trash)
+               OutputIterator out_last, OutputIterator expected_first, OutputIterator, Size n, UnaryOp unary_op, T init,
+               BinaryOp binary_op, T trash)
     {
         using namespace std;
 
-        auto orr1 = inclusive ? transform_inclusive_scan(__pstl::execution::seq, first, last, expected_first, binary_op,
-                                                         unary_op, init)
-                              : transform_exclusive_scan(__pstl::execution::seq, first, last, expected_first, init,
-                                                         binary_op, unary_op);
+        auto orr1 =
+            inclusive
+                ? transform_inclusive_scan(std::execution::seq, first, last, expected_first, binary_op, unary_op, init)
+                : transform_exclusive_scan(std::execution::seq, first, last, expected_first, init, binary_op, unary_op);
         auto orr2 = inclusive ? transform_inclusive_scan(exec, first, last, out_first, binary_op, unary_op, init)
                               : transform_exclusive_scan(exec, first, last, out_first, init, binary_op, unary_op);
         EXPECT_TRUE(out_last == orr2, "transform...scan returned wrong iterator");
@@ -64,7 +64,7 @@ struct test_transform_scan
         // Checks inclusive scan if init is not provided
         if (inclusive && n > 0)
         {
-            orr1 = transform_inclusive_scan(__pstl::execution::seq, first, last, expected_first, binary_op, unary_op);
+            orr1 = transform_inclusive_scan(std::execution::seq, first, last, expected_first, binary_op, unary_op);
             orr2 = transform_inclusive_scan(exec, first, last, out_first, binary_op, unary_op);
             EXPECT_TRUE(out_last == orr2, "transform...scan returned wrong iterator");
             check_and_reset(expected_first, out_first, n, trash);
@@ -74,9 +74,8 @@ struct test_transform_scan
     template <typename Policy, typename InputIterator, typename OutputIterator, typename Size, typename UnaryOp,
               typename T, typename BinaryOp>
     typename std::enable_if<TestUtils::isReverse<InputIterator>::value, void>::type
-    operator()(Policy&& exec, InputIterator first, InputIterator last, OutputIterator out_first,
-               OutputIterator out_last, OutputIterator expected_first, OutputIterator expected_last, Size n,
-               UnaryOp unary_op, T init, BinaryOp binary_op, T trash)
+    operator()(Policy&&, InputIterator, InputIterator, OutputIterator, OutputIterator, OutputIterator, OutputIterator,
+               Size, UnaryOp, T, BinaryOp, T)
     {
     }
 };
@@ -140,6 +139,7 @@ test(UnaryOp unary_op, Out init, BinaryOp binary_op, Out trash)
             inclusive
                 ? transform_inclusive_scan_serial(in.cbegin(), in.cend(), out.fbegin(), unary_op, init, binary_op)
                 : transform_exclusive_scan_serial(in.cbegin(), in.cend(), out.fbegin(), unary_op, init, binary_op);
+        (void)result;
         check_and_reset(expected.begin(), out.begin(), out.size(), trash);
 
         invoke_on_all_policies(test_transform_scan(), in.begin(), in.end(), out.begin(), out.end(), expected.begin(),
@@ -167,13 +167,13 @@ test_matrix(UnaryOp unary_op, Out init, BinaryOp binary_op, Out trash)
     }
 }
 
-int32_t
+int
 main()
 {
     for (int32_t mode = 0; mode < 2; ++mode)
     {
         inclusive = mode != 0;
-#if !_PSTL_ICC_19_TEST_SIMD_UDS_WINDOWS_RELEASE_BROKEN
+#if !defined(_PSTL_ICC_19_TEST_SIMD_UDS_WINDOWS_RELEASE_BROKEN)
         test_matrix<Matrix2x2<int32_t>, Matrix2x2<int32_t>>([](const Matrix2x2<int32_t> x) { return x; },
                                                             Matrix2x2<int32_t>(), multiply_matrix<int32_t>,
                                                             Matrix2x2<int32_t>(-666, 666));
diff --git a/libstdc++-v3/testsuite/util/pstl/test_utils.h b/libstdc++-v3/testsuite/util/pstl/test_utils.h
index 80a8f9c7b87..ed6d48b9471 100644
--- a/libstdc++-v3/testsuite/util/pstl/test_utils.h
+++ b/libstdc++-v3/testsuite/util/pstl/test_utils.h
@@ -30,7 +30,7 @@ typedef float float32_t;
 
 template <class T, std::size_t N>
 constexpr size_t
-const_size(const T (&array)[N]) noexcept
+const_size(const T (&)[N]) noexcept
 {
     return N;
 }
@@ -119,7 +119,7 @@ expect_equal(Iterator1 expected_first, Iterator2 actual_first, Size n, const cha
              const char* message)
 {
     size_t error_count = 0;
-    for (size_t k = 0; k < n && error_count < 10; ++k, ++expected_first, ++actual_first)
+    for (Size k = 0; k < n && error_count < 10; ++k, ++expected_first, ++actual_first)
     {
         if (!(*expected_first == *actual_first))
         {
@@ -231,6 +231,82 @@ fill_data(Iterator first, Iterator last, F f)
     }
 }
 
+struct MemoryChecker {
+    // static counters and state tags
+    static std::atomic<std::int64_t> alive_object_counter; // initialized outside
+    static constexpr std::int64_t alive_state = 0xAAAAAAAAAAAAAAAA;
+    static constexpr std::int32_t dead_state = 0; // only used as a set value to cancel alive_state
+
+    std::int32_t _value; // object value used for algorithms
+    std::int64_t _state; // state tag used for checks
+
+    // ctors, dtors, assign ops
+    explicit MemoryChecker(std::int32_t value = 0) : _value(value) {
+        // check for EXPECT_TRUE(state() != alive_state, ...) has not been done since we cannot guarantee that
+        // raw memory for object being constructed does not have a bit sequence being equal to alive_state
+
+        // set constructed state and increment counter for living object
+        inc_alive_objects();
+        _state = alive_state;
+    }
+    MemoryChecker(MemoryChecker&& other) : _value(other.value()) {
+        // check for EXPECT_TRUE(state() != alive_state, ...) has not been done since
+        // compiler can optimize out the move ctor call that results in false positive failure
+        EXPECT_TRUE(other.state() == alive_state, "wrong effect from MemoryChecker(MemoryChecker&&): attemp to construct an object from non-existing object");
+        // set constructed state and increment counter for living object
+        inc_alive_objects();
+        _state = alive_state;
+    }
+    MemoryChecker(const MemoryChecker& other) : _value(other.value()) {
+        // check for EXPECT_TRUE(state() != alive_state, ...) has not been done since
+        // compiler can optimize out the copy ctor call that results in false positive failure
+        EXPECT_TRUE(other.state() == alive_state, "wrong effect from MemoryChecker(const MemoryChecker&): attemp to construct an object from non-existing object");
+        // set constructed state and increment counter for living object
+        inc_alive_objects();
+        _state = alive_state;
+    }
+    MemoryChecker& operator=(MemoryChecker&& other) {
+        // check if we do not assign over uninitialized memory
+        EXPECT_TRUE(state() == alive_state, "wrong effect from MemoryChecker::operator=(MemoryChecker&& other): attemp to assign to non-existing object");
+        EXPECT_TRUE(other.state() == alive_state, "wrong effect from MemoryChecker::operator=(MemoryChecker&& other): attemp to assign from non-existing object");
+        // just assign new value, counter is the same, state is the same
+        _value = other.value();
+
+        return *this;
+    }
+    MemoryChecker& operator=(const MemoryChecker& other) {
+        // check if we do not assign over uninitialized memory
+        EXPECT_TRUE(state() == alive_state, "wrong effect from MemoryChecker::operator=(const MemoryChecker& other): attemp to assign to non-existing object");
+        EXPECT_TRUE(other.state() == alive_state, "wrong effect from MemoryChecker::operator=(const MemoryChecker& other): attemp to assign from non-existing object");
+        // just assign new value, counter is the same, state is the same
+        _value = other.value();
+
+        return *this;
+    }
+    ~MemoryChecker() {
+        // check if we do not double destruct the object
+        EXPECT_TRUE(state() == alive_state, "wrong effect from ~MemoryChecker(): attemp to destroy non-existing object");
+        // set destructed state and decrement counter for living object
+        static_cast<volatile std::int64_t&>(_state) = dead_state;
+        dec_alive_objects();
+    }
+
+    // getters
+    std::int32_t value() const { return _value; }
+    std::int64_t state() const { return _state; }
+    static std::int32_t alive_objects() { return alive_object_counter.load(); }
+private:
+    // setters
+    void inc_alive_objects() { alive_object_counter.fetch_add(1); }
+    void dec_alive_objects() { alive_object_counter.fetch_sub(1); }
+};
+
+std::atomic<std::int64_t> MemoryChecker::alive_object_counter{0};
+
+std::ostream& operator<<(std::ostream& os, const MemoryChecker& val) { return (os << val.value()); }
+bool operator==(const MemoryChecker& v1, const MemoryChecker& v2) { return v1.value() == v2.value(); }
+bool operator<(const MemoryChecker& v1, const MemoryChecker& v2) { return v1.value() < v2.value(); }
+
 // Sequence<T> is a container of a sequence of T with lots of kinds of iterators.
 // Prefixes on begin/end mean:
 //      c = "const"
@@ -572,7 +648,7 @@ struct Matrix2x2
     T a[2][2];
     Matrix2x2() : a{{1, 0}, {0, 1}} {}
     Matrix2x2(T x, T y) : a{{0, x}, {x, y}} {}
-#if !_PSTL_ICL_19_VC14_VC141_TEST_SCAN_RELEASE_BROKEN
+#if !defined(_PSTL_ICL_19_VC14_VC141_TEST_SCAN_RELEASE_BROKEN)
     Matrix2x2(const Matrix2x2& m) : a{{m.a[0][0], m.a[0][1]}, {m.a[1][0], m.a[1][1]}} {}
     Matrix2x2&
     operator=(const Matrix2x2& m)
@@ -651,7 +727,7 @@ struct ReverseAdapter
     iterator_type
     operator()(Iterator it)
     {
-#if _PSTL_CPP14_MAKE_REVERSE_ITERATOR_PRESENT
+#if defined(_PSTL_CPP14_MAKE_REVERSE_ITERATOR_PRESENT)
         return std::make_reverse_iterator(it);
 #else
         return iterator_type(it);
@@ -1191,7 +1267,7 @@ transform_reduce_serial(InputIterator first, InputIterator last, T init, BinaryO
 static const char*
 done()
 {
-#if _PSTL_TEST_SUCCESSFUL_KEYWORD
+#if defined(_PSTL_TEST_SUCCESSFUL_KEYWORD)
     return "done";
 #else
     return "passed";
@@ -1228,8 +1304,12 @@ template <typename Policy, typename F>
 static void
 invoke_if(Policy&&, F f)
 {
-#if _PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN || _PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN
-    __pstl::__internal::invoke_if_not(__pstl::__internal::allow_unsequenced<Policy>(), f);
+#if defined(_PSTL_ICC_16_VC14_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN) || defined(_PSTL_ICC_17_VC141_TEST_SIMD_LAMBDA_DEBUG_32_BROKEN)
+    using decay_policy = typename std::decay<Policy>::type;
+    using allow_unsequenced =
+        std::integral_constant<bool, (std::is_same<decay_policy, std::execution::unsequenced_policy>::value ||
+                                      std::is_same<decay_policy, std::execution::parallel_unsequenced_policy>::value)>;
+    __pstl::__internal::__invoke_if_not(allow_unsequenced{}, f);
 #else
     f();
 #endif
-- 
2.39.2


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH] libstdc++: Synchronize PSTL with upstream
  2023-04-20  3:39 [PATCH] libstdc++: Synchronize PSTL with upstream Thomas Rodgers
@ 2023-05-17 19:31 ` Jonathan Wakely
  2023-06-26 18:57   ` Thomas Rodgers
  0 siblings, 1 reply; 6+ messages in thread
From: Jonathan Wakely @ 2023-05-17 19:31 UTC (permalink / raw)
  To: Thomas Rodgers; +Cc: libstdc++, gcc Patches

[-- Attachment #1: Type: text/plain, Size: 2859 bytes --]

-template <class _OutputIterator, class _Size, class _Generator>
-  _OutputIterator
-__brick_generate_n(_OutputIterator __first, _Size __count, _Generator __g,
/* is_vector = */ std::true_type) noexcept
+template <class _RandomAccessIterator, class Size, class _Generator>

Missing uglification on Size.

+_RandomAccessIterator
+__brick_generate_n(_RandomAccessIterator __first, Size __count, _Generator
__g,
+                   /* is_vector = */ std::true_type) noexcept
 {
     return __unseq_backend::__simd_generate_n(__first, __count, __g);
 }

-template <class _OutputIterator, class _Size, class _Generator>
-  _OutputIterator
-__brick_generate_n(_OutputIterator __first, _Size __count, _Generator __g,
/* is_vector = */ std::false_type) noexcept
+template <class OutputIterator, class Size, class _Generator>

Missing uglification on OutputIterator and Size.

+OutputIterator
+__brick_generate_n(OutputIterator __first, Size __count, _Generator __g,
/* is_vector = */ std::false_type) noexcept


-template <class _ForwardIterator1, class _ForwardIterator2, class
_BinaryOperation>
-_ForwardIterator2
-__brick_adjacent_difference(_ForwardIterator1 __first, _ForwardIterator1
__last, _ForwardIterator2 __d_first,
-    _BinaryOperation __op, /*is_vector=*/std::true_type) noexcept
+template <class _RandomAccessIterator1, class _RandomAccessIterator2,
class BinaryOperation>

Missing uglification on BinaryOperation.

+_RandomAccessIterator2
+__brick_adjacent_difference(_RandomAccessIterator1 __first,
_RandomAccessIterator1 __last,
+                            _RandomAccessIterator2 __d_first,
BinaryOperation __op,
+                            /*is_vector=*/std::true_type) noexcept


The above problems exist on the declaration and the definitions.


--- a/libstdc++-v3/include/pstl/glue_execution_defs.h
+++ b/libstdc++-v3/include/pstl/glue_execution_defs.h
@@ -18,8 +18,8 @@ namespace std
 {
 // Type trait
 using __pstl::execution::is_execution_policy;
-#if _PSTL_CPP14_VARIABLE_TEMPLATES_PRESENT
-#    if __INTEL_COMPILER
+#if defined(_PSTL_CPP14_VARIABLE_TEMPLATES_PRESENT)
+#    if defined(__INTEL_COMPILER)
 template <class T>
 constexpr bool is_execution_policy_v = is_execution_policy<T>::value;
 #    else

Pre-existing, but that T should be _Tp, but it only affects the Intel
compiler branch, so meh.

Please fix these and report them upstream too.

All the actual code changes look good.

I think I'd prefer if __pattern_partial_sort_copy used
std::uninitialized_copy instead of a loop and placement-new, but that
doesn't need to hold this up. We could optimize some uses of
std::conjunction and std::conditional to use our own __and_ and
__conditional, but I'm not sure it's worth diverging from upstream to do
that.

Please fix the naming bugs noted above and push to trunk, thanks!

+Reviewed-by: Jonathan Wakely <jwakely@redhat.com>

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH] libstdc++: Synchronize PSTL with upstream
  2023-05-17 19:31 ` Jonathan Wakely
@ 2023-06-26 18:57   ` Thomas Rodgers
  2023-06-30  3:48     ` PR108672 re-fixed after " Hans-Peter Nilsson
  0 siblings, 1 reply; 6+ messages in thread
From: Thomas Rodgers @ 2023-06-26 18:57 UTC (permalink / raw)
  To: Jonathan Wakely; +Cc: libstdc++, gcc Patches

[-- Attachment #1: Type: text/plain, Size: 3474 bytes --]

On Wed, May 17, 2023 at 12:32 PM Jonathan Wakely <jwakely@redhat.com> wrote:

> -template <class _OutputIterator, class _Size, class _Generator>
> -  _OutputIterator
> -__brick_generate_n(_OutputIterator __first, _Size __count, _Generator
> __g, /* is_vector = */ std::true_type) noexcept
> +template <class _RandomAccessIterator, class Size, class _Generator>
>
> Missing uglification on Size.
>
> +_RandomAccessIterator
> +__brick_generate_n(_RandomAccessIterator __first, Size __count,
> _Generator __g,
> +                   /* is_vector = */ std::true_type) noexcept
>  {
>      return __unseq_backend::__simd_generate_n(__first, __count, __g);
>  }
>
> -template <class _OutputIterator, class _Size, class _Generator>
> -  _OutputIterator
> -__brick_generate_n(_OutputIterator __first, _Size __count, _Generator
> __g, /* is_vector = */ std::false_type) noexcept
> +template <class OutputIterator, class Size, class _Generator>
>
> Missing uglification on OutputIterator and Size.
>
> +OutputIterator
> +__brick_generate_n(OutputIterator __first, Size __count, _Generator __g,
> /* is_vector = */ std::false_type) noexcept
>
>
> -template <class _ForwardIterator1, class _ForwardIterator2, class
> _BinaryOperation>
> -_ForwardIterator2
> -__brick_adjacent_difference(_ForwardIterator1 __first, _ForwardIterator1
> __last, _ForwardIterator2 __d_first,
> -    _BinaryOperation __op, /*is_vector=*/std::true_type) noexcept
> +template <class _RandomAccessIterator1, class _RandomAccessIterator2,
> class BinaryOperation>
>
> Missing uglification on BinaryOperation.
>
> +_RandomAccessIterator2
> +__brick_adjacent_difference(_RandomAccessIterator1 __first,
> _RandomAccessIterator1 __last,
> +                            _RandomAccessIterator2 __d_first,
> BinaryOperation __op,
> +                            /*is_vector=*/std::true_type) noexcept
>
>
> The above problems exist on the declaration and the definitions.
>
>
> --- a/libstdc++-v3/include/pstl/glue_execution_defs.h
> +++ b/libstdc++-v3/include/pstl/glue_execution_defs.h
> @@ -18,8 +18,8 @@ namespace std
>  {
>  // Type trait
>  using __pstl::execution::is_execution_policy;
> -#if _PSTL_CPP14_VARIABLE_TEMPLATES_PRESENT
> -#    if __INTEL_COMPILER
> +#if defined(_PSTL_CPP14_VARIABLE_TEMPLATES_PRESENT)
> +#    if defined(__INTEL_COMPILER)
>  template <class T>
>  constexpr bool is_execution_policy_v = is_execution_policy<T>::value;
>  #    else
>
> Pre-existing, but that T should be _Tp, but it only affects the Intel
> compiler branch, so meh.
>
> Please fix these and report them upstream too.
>

Ack.


>
> All the actual code changes look good.
>
> I think I'd prefer if __pattern_partial_sort_copy used
> std::uninitialized_copy instead of a loop and placement-new, but that
> doesn't need to hold this up. We could optimize some uses of
> std::conjunction and std::conditional to use our own __and_ and
> __conditional, but I'm not sure it's worth diverging from upstream to do
> that.
>
> Please fix the naming bugs noted above and push to trunk, thanks!
>

There were a handful of additional missed uglifications in -
* libstdc++-v3/include/pstl/glue_algorithm_impl.h
* libstdc++-v3/include/pstl/unseq_backend_simd.h
That are in this commit, but not in the patch as reviewed.

Tested x86_64-linux. Pushed to trunk.


>
> +Reviewed-by: Jonathan Wakely <jwakely@redhat.com>
>
>
>
>
>
>

^ permalink raw reply	[flat|nested] 6+ messages in thread

* PR108672 re-fixed after [PATCH] libstdc++: Synchronize PSTL with upstream
  2023-06-26 18:57   ` Thomas Rodgers
@ 2023-06-30  3:48     ` Hans-Peter Nilsson
  2023-06-30  8:42       ` Jonathan Wakely
  0 siblings, 1 reply; 6+ messages in thread
From: Hans-Peter Nilsson @ 2023-06-30  3:48 UTC (permalink / raw)
  To: Thomas Rodgers; +Cc: jwakely, libstdc++, gcc-patches

> Date: Mon, 26 Jun 2023 11:57:49 -0700
> From: Thomas Rodgers via Gcc-patches <gcc-patches@gcc.gnu.org>

> On Wed, May 17, 2023 at 12:32 PM Jonathan Wakely <jwakely@redhat.com> wrote:
> > All the actual code changes look good.

Unfortunately, this overwrote the fix for PR108672.  I take
it there's a step missing from the synchronization process;
a check that no local commits are overwritten?  Sounds like
something that can be fully scripted (not volunteering) or
already available (like, "list all commits affecting
contents touched by/between two named commits").

I did *not* check whether any other local commits were also
overwritten.  Also, not sure about whether better try to get
this upstreamed: __INT32_TYPE__ seems gcc-specific.

Anyway, r13-5702-g72058eea9d407e was "re-committed" per
below as obvious after regtesting cris-elf.

brgds, H-P

-- >8 --
Subject: libstdc++: Re-apply PR108672 fix (avoid use of naked int32_t in unseq_backend_simd.h)

The fix was overwritten by r14-2109-g3162ca09dbdc2e "libstdc++:
Synchronize PSTL with upstream".

libstdc++-v3:

	PR libstdc++/108672
	* include/pstl/unseq_backend_simd.h (__simd_or): Re-apply using
	__INT32_TYPE__ instead of int32_t.
---
 libstdc++-v3/include/pstl/unseq_backend_simd.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libstdc++-v3/include/pstl/unseq_backend_simd.h b/libstdc++-v3/include/pstl/unseq_backend_simd.h
index 69784bcdbe66..f3c38fbbbc2a 100644
--- a/libstdc++-v3/include/pstl/unseq_backend_simd.h
+++ b/libstdc++-v3/include/pstl/unseq_backend_simd.h
@@ -74,7 +74,7 @@ __simd_or(_Index __first, _DifferenceType __n, _Pred __pred) noexcept
     const _Index __last = __first + __n;
     while (__last != __first)
     {
-        int32_t __flag = 1;
+        __INT32_TYPE__ __flag = 1;
         _PSTL_PRAGMA_SIMD_REDUCTION(& : __flag)
         for (_DifferenceType __i = 0; __i < __block_size; ++__i)
             if (__pred(*(__first + __i)))
-- 
2.30.2



^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: PR108672 re-fixed after [PATCH] libstdc++: Synchronize PSTL with upstream
  2023-06-30  3:48     ` PR108672 re-fixed after " Hans-Peter Nilsson
@ 2023-06-30  8:42       ` Jonathan Wakely
  2023-06-30  9:57         ` Jonathan Wakely
  0 siblings, 1 reply; 6+ messages in thread
From: Jonathan Wakely @ 2023-06-30  8:42 UTC (permalink / raw)
  To: Hans-Peter Nilsson; +Cc: Thomas Rodgers, libstdc++, gcc-patches

On Fri, 30 Jun 2023 at 04:48, Hans-Peter Nilsson wrote:
>
> > Date: Mon, 26 Jun 2023 11:57:49 -0700
> > From: Thomas Rodgers via Gcc-patches <gcc-patches@gcc.gnu.org>
>
> > On Wed, May 17, 2023 at 12:32 PM Jonathan Wakely <jwakely@redhat.com> wrote:
> > > All the actual code changes look good.
>
> Unfortunately, this overwrote the fix for PR108672.  I take
> it there's a step missing from the synchronization process;
> a check that no local commits are overwritten?  Sounds like
> something that can be fully scripted (not volunteering) or
> already available (like, "list all commits affecting
> contents touched by/between two named commits").
>
> I did *not* check whether any other local commits were also
> overwritten.  Also, not sure about whether better try to get
> this upstreamed: __INT32_TYPE__ seems gcc-specific.

Clang does support it too, but I agree that upstream might not want that change.


> Anyway, r13-5702-g72058eea9d407e was "re-committed" per
> below as obvious after regtesting cris-elf.

Thanks.

I'll add an include/pstl/LOCAL_PATCHES file listed the commits we
apply locally after importing the upstream sources.

Based on git history, the initial list of commits is:

r9-6908-g0360f9ad4048ea
r9-6942-g9eda9f9231f287
r9-7071-ga34d6343a758f6
r10-572-g34d878c7bc86d4
r10-1314-g32bab8b6ad0a90
r11-7339-g7e647d71d556b7
r12-7699-gac73c944eac88f
r13-3708-ge3b10249119fb4
r13-5702-g72058eea9d407e

But several of those have been incorporated upstream, or were
reapplied correctly to our downstream copies. We'll go through the
list and find which ones need to stay there.

It looks like r10-1314-g32bab8b6ad0a90 was lost and should be re-applied.


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: PR108672 re-fixed after [PATCH] libstdc++: Synchronize PSTL with upstream
  2023-06-30  8:42       ` Jonathan Wakely
@ 2023-06-30  9:57         ` Jonathan Wakely
  0 siblings, 0 replies; 6+ messages in thread
From: Jonathan Wakely @ 2023-06-30  9:57 UTC (permalink / raw)
  To: Hans-Peter Nilsson; +Cc: Thomas Rodgers, libstdc++, gcc-patches

On Fri, 30 Jun 2023 at 09:42, Jonathan Wakely <jwakely@redhat.com> wrote:
>
> On Fri, 30 Jun 2023 at 04:48, Hans-Peter Nilsson wrote:
> >
> > > Date: Mon, 26 Jun 2023 11:57:49 -0700
> > > From: Thomas Rodgers via Gcc-patches <gcc-patches@gcc.gnu.org>
> >
> > > On Wed, May 17, 2023 at 12:32 PM Jonathan Wakely <jwakely@redhat.com> wrote:
> > > > All the actual code changes look good.
> >
> > Unfortunately, this overwrote the fix for PR108672.  I take
> > it there's a step missing from the synchronization process;
> > a check that no local commits are overwritten?  Sounds like
> > something that can be fully scripted (not volunteering) or
> > already available (like, "list all commits affecting
> > contents touched by/between two named commits").
> >
> > I did *not* check whether any other local commits were also
> > overwritten.  Also, not sure about whether better try to get
> > this upstreamed: __INT32_TYPE__ seems gcc-specific.
>
> Clang does support it too, but I agree that upstream might not want that change.
>
>
> > Anyway, r13-5702-g72058eea9d407e was "re-committed" per
> > below as obvious after regtesting cris-elf.
>
> Thanks.
>
> I'll add an include/pstl/LOCAL_PATCHES file listed the commits we
> apply locally after importing the upstream sources.
>
> Based on git history, the initial list of commits is:

For the record:

> r9-6908-g0360f9ad4048ea
Upstream: c7c6413119380828d92e8beb5fb2f35d3f2e1572
> r9-6942-g9eda9f9231f287
Upstream: 2e15f4ac572bcf429ec12e8f3efbb8ad254042c7
> r9-7071-ga34d6343a758f6
Upstream: 8a497a958be1f4656eff9664e1be29491f3795d2
and 86d4ec756b5e0bc72d7e78fc574e05802959ead4
> r10-572-g34d878c7bc86d4
Not upstream (GCC-specific).
> r10-1314-g32bab8b6ad0a90
Not upstream (probably should be)
> r11-7339-g7e647d71d556b7
Upstream: b152f9f392d42e1c8e29f382f876480631575190
> r12-7699-gac73c944eac88f
Not upstream (GCC-specific)
> r13-3708-ge3b10249119fb4
Not upstream (GCC-specific)
> r13-5702-g72058eea9d407e
Not upstream (GCC-specific)
>
> But several of those have been incorporated upstream, or were
> reapplied correctly to our downstream copies. We'll go through the
> list and find which ones need to stay there.
>
> It looks like r10-1314-g32bab8b6ad0a90 was lost and should be re-applied.


^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2023-06-30  9:58 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-04-20  3:39 [PATCH] libstdc++: Synchronize PSTL with upstream Thomas Rodgers
2023-05-17 19:31 ` Jonathan Wakely
2023-06-26 18:57   ` Thomas Rodgers
2023-06-30  3:48     ` PR108672 re-fixed after " Hans-Peter Nilsson
2023-06-30  8:42       ` Jonathan Wakely
2023-06-30  9:57         ` Jonathan Wakely

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).