diff --git a/libcxx/docs/Cxx2aStatus.rst b/libcxx/docs/Cxx2aStatus.rst
--- a/libcxx/docs/Cxx2aStatus.rst
+++ b/libcxx/docs/Cxx2aStatus.rst
@@ -40,7 +40,6 @@
 
 .. note::
 
-   .. [#note-P0202] P0202: The missing bits in P0202 are in ``copy`` and ``copy_backwards`` (and the ones that call them: ``copy_n``, ``set_union``, ``set_difference``, and ``set_symmetric_difference``). This is because the first two algorithms have specializations that call ``memmove`` which is not constexpr. See `Bug 25165 <https://bugs.llvm.org/show_bug.cgi?id=25165>`__
    .. [#note-P0600] P0600: The missing bits in P0600 are in |sect|\ [mem.res.class], |sect|\ [mem.poly.allocator.class], and |sect|\ [container.node.overview].
    .. [#note-P0966] P0966: It was previously erroneously marked as complete in version 8.0. See `bug 45368 <https://llvm.org/PR45368>`__.
 
diff --git a/libcxx/docs/Cxx2aStatusPaperStatus.csv b/libcxx/docs/Cxx2aStatusPaperStatus.csv
--- a/libcxx/docs/Cxx2aStatusPaperStatus.csv
+++ b/libcxx/docs/Cxx2aStatusPaperStatus.csv
@@ -4,7 +4,7 @@
 "","","","","",""
 "`P0020R6 <https://wg21.link/P0020R6>`__","LWG","Floating Point Atomic","Albuquerque","",""
 "`P0053R7 <https://wg21.link/P0053R7>`__","LWG","C++ Synchronized Buffered Ostream","Albuquerque","",""
-"`P0202R3 <https://wg21.link/P0202R3>`__","LWG","Add constexpr modifiers to functions in <algorithm> and <utility> Headers","Albuquerque","|In Progress| [#note-P0202]_","7.0"
+"`P0202R3 <https://wg21.link/P0202R3>`__","LWG","Add constexpr modifiers to functions in <algorithm> and <utility> Headers","Albuquerque","|Complete|","12.0"
 "`P0415R1 <https://wg21.link/P0415R1>`__","LWG","Constexpr for ``std::complex``\ ","Albuquerque","|In Progress|","7.0"
 "`P0439R0 <https://wg21.link/P0439R0>`__","LWG","Make ``std::memory_order``\  a scoped enumeration","Albuquerque","|Complete|",""
 "`P0457R2 <https://wg21.link/P0457R2>`__","LWG","String Prefix and Suffix Checking","Albuquerque","|Complete|","6.0"
diff --git a/libcxx/include/algorithm b/libcxx/include/algorithm
--- a/libcxx/include/algorithm
+++ b/libcxx/include/algorithm
@@ -47,16 +47,16 @@
     find_if(InputIterator first, InputIterator last, Predicate pred);
 
 template<class InputIterator, class Predicate>
-    InputIterator               // constexpr in C++20
+    constexpr InputIterator     // constexpr in C++20
     find_if_not(InputIterator first, InputIterator last, Predicate pred);
 
 template <class ForwardIterator1, class ForwardIterator2>
-    ForwardIterator1            // constexpr in C++20
+    constexpr ForwardIterator1  // constexpr in C++20
     find_end(ForwardIterator1 first1, ForwardIterator1 last1,
              ForwardIterator2 first2, ForwardIterator2 last2);
 
 template <class ForwardIterator1, class ForwardIterator2, class BinaryPredicate>
-    ForwardIterator1            // constexpr in C++20
+    constexpr ForwardIterator1  // constexpr in C++20
     find_end(ForwardIterator1 first1, ForwardIterator1 last1,
              ForwardIterator2 first2, ForwardIterator2 last2, BinaryPredicate pred);
 
@@ -185,11 +185,11 @@
                   BidirectionalIterator2 result);
 
 template <class ForwardIterator1, class ForwardIterator2>
-    ForwardIterator2
+    constexpr ForwardIterator2    // constexpr in C++20
     swap_ranges(ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2);
 
 template <class ForwardIterator1, class ForwardIterator2>
-    void
+    constexpr void                // constexpr in C++20
     iter_swap(ForwardIterator1 a, ForwardIterator2 b);
 
 template <class InputIterator, class OutputIterator, class UnaryOperation>
@@ -251,19 +251,19 @@
     remove_copy_if(InputIterator first, InputIterator last, OutputIterator result, Predicate pred);
 
 template <class ForwardIterator>
-    ForwardIterator
+    constexpr ForwardIterator    // constexpr in C++20
     unique(ForwardIterator first, ForwardIterator last);
 
 template <class ForwardIterator, class BinaryPredicate>
-    ForwardIterator
+    constexpr ForwardIterator    // constexpr in C++20
     unique(ForwardIterator first, ForwardIterator last, BinaryPredicate pred);
 
 template <class InputIterator, class OutputIterator>
-    OutputIterator
+    constexpr OutputIterator     // constexpr in C++20
     unique_copy(InputIterator first, InputIterator last, OutputIterator result);
 
 template <class InputIterator, class OutputIterator, class BinaryPredicate>
-    OutputIterator
+    constexpr OutputIterator     // constexpr in C++20
     unique_copy(InputIterator first, InputIterator last, OutputIterator result, BinaryPredicate pred);
 
 template <class BidirectionalIterator>
@@ -275,11 +275,11 @@
     reverse_copy(BidirectionalIterator first, BidirectionalIterator last, OutputIterator result);
 
 template <class ForwardIterator>
-    ForwardIterator
+    constexpr ForwardIterator      // constexpr in C++20
     rotate(ForwardIterator first, ForwardIterator middle, ForwardIterator last);
 
 template <class ForwardIterator, class OutputIterator>
-    OutputIterator
+    constexpr OutputIterator       // constexpr in C++20
     rotate_copy(ForwardIterator first, ForwardIterator middle, ForwardIterator last, OutputIterator result);
 
 template <class RandomAccessIterator>
@@ -329,7 +329,7 @@
     is_sorted(ForwardIterator first, ForwardIterator last);
 
 template <class ForwardIterator, class Compare>
-    bool
+    constexpr bool  // constexpr in C++20
     is_sorted(ForwardIterator first, ForwardIterator last, Compare comp);
 
 template<class ForwardIterator>
@@ -415,12 +415,12 @@
     binary_search(ForwardIterator first, ForwardIterator last, const T& value, Compare comp);
 
 template <class InputIterator1, class InputIterator2, class OutputIterator>
-    OutputIterator
+    constexpr OutputIterator                          // constexpr in C++20
     merge(InputIterator1 first1, InputIterator1 last1,
           InputIterator2 first2, InputIterator2 last2, OutputIterator result);
 
 template <class InputIterator1, class InputIterator2, class OutputIterator, class Compare>
-    OutputIterator
+    constexpr OutputIterator                          // constexpr in C++20
     merge(InputIterator1 first1, InputIterator1 last1,
           InputIterator2 first2, InputIterator2 last2, OutputIterator result, Compare comp);
 
@@ -441,12 +441,12 @@
     includes(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, Compare comp);
 
 template <class InputIterator1, class InputIterator2, class OutputIterator>
-    OutputIterator
+    constexpr OutputIterator                          // constexpr in C++20
     set_union(InputIterator1 first1, InputIterator1 last1,
               InputIterator2 first2, InputIterator2 last2, OutputIterator result);
 
 template <class InputIterator1, class InputIterator2, class OutputIterator, class Compare>
-    OutputIterator
+    constexpr OutputIterator                          // constexpr in C++20
     set_union(InputIterator1 first1, InputIterator1 last1,
               InputIterator2 first2, InputIterator2 last2, OutputIterator result, Compare comp);
 
@@ -461,22 +461,22 @@
                      InputIterator2 first2, InputIterator2 last2, OutputIterator result, Compare comp);
 
 template <class InputIterator1, class InputIterator2, class OutputIterator>
-    OutputIterator
+    constexpr OutputIterator                         // constexpr in C++20
     set_difference(InputIterator1 first1, InputIterator1 last1,
                    InputIterator2 first2, InputIterator2 last2, OutputIterator result);
 
 template <class InputIterator1, class InputIterator2, class OutputIterator, class Compare>
-    OutputIterator
+    constexpr OutputIterator                         // constexpr in C++20
     set_difference(InputIterator1 first1, InputIterator1 last1,
                    InputIterator2 first2, InputIterator2 last2, OutputIterator result, Compare comp);
 
 template <class InputIterator1, class InputIterator2, class OutputIterator>
-    OutputIterator
+    constexpr OutputIterator                         // constexpr in C++20
     set_symmetric_difference(InputIterator1 first1, InputIterator1 last1,
                              InputIterator2 first2, InputIterator2 last2, OutputIterator result);
 
 template <class InputIterator1, class InputIterator2, class OutputIterator, class Compare>
-    OutputIterator
+    constexpr OutputIterator                         // constexpr in C++20
     set_symmetric_difference(InputIterator1 first1, InputIterator1 last1,
                              InputIterator2 first2, InputIterator2 last2, OutputIterator result, Compare comp);
 
@@ -529,82 +529,82 @@
     is_heap_until(RandomAccessIterator first, RandomAccessiterator last, Compare comp);
 
 template <class ForwardIterator>
-    ForwardIterator
-    min_element(ForwardIterator first, ForwardIterator last);  // constexpr in C++14
+    constexpr ForwardIterator        // constexpr in C++14
+    min_element(ForwardIterator first, ForwardIterator last);
 
 template <class ForwardIterator, class Compare>
-    ForwardIterator
-    min_element(ForwardIterator first, ForwardIterator last, Compare comp);  // constexpr in C++14
+    constexpr ForwardIterator        // constexpr in C++14
+    min_element(ForwardIterator first, ForwardIterator last, Compare comp);
 
 template <class T>
-    const T&
-    min(const T& a, const T& b);  // constexpr in C++14
+    constexpr const T&               // constexpr in C++14
+    min(const T& a, const T& b);
 
 template <class T, class Compare>
-    const T&
-    min(const T& a, const T& b, Compare comp);  // constexpr in C++14
+    constexpr const T&               // constexpr in C++14
+    min(const T& a, const T& b, Compare comp);
 
 template<class T>
-    T
-    min(initializer_list<T> t);  // constexpr in C++14
+    constexpr T                      // constexpr in C++14
+    min(initializer_list<T> t);
 
 template<class T, class Compare>
-    T
-    min(initializer_list<T> t, Compare comp);  // constexpr in C++14
+    constexpr T                      // constexpr in C++14
+    min(initializer_list<T> t, Compare comp);
 
 template<class T>
-    constexpr const T& clamp( const T& v, const T& lo, const T& hi );               // C++17
+    constexpr const T& clamp(const T& v, const T& lo, const T& hi);               // C++17
 
 template<class T, class Compare>
-    constexpr const T& clamp( const T& v, const T& lo, const T& hi, Compare comp ); // C++17
+    constexpr const T& clamp(const T& v, const T& lo, const T& hi, Compare comp); // C++17
 
 template <class ForwardIterator>
-    ForwardIterator
-    max_element(ForwardIterator first, ForwardIterator last);  // constexpr in C++14
+    constexpr ForwardIterator        // constexpr in C++14
+    max_element(ForwardIterator first, ForwardIterator last);
 
 template <class ForwardIterator, class Compare>
-    ForwardIterator
-    max_element(ForwardIterator first, ForwardIterator last, Compare comp);  // constexpr in C++14
+    constexpr ForwardIterator        // constexpr in C++14
+    max_element(ForwardIterator first, ForwardIterator last, Compare comp);
 
 template <class T>
-    const T&
-    max(const T& a, const T& b); // constexpr in C++14
+    constexpr const T&               // constexpr in C++14
+    max(const T& a, const T& b);
 
 template <class T, class Compare>
-    const T&
-    max(const T& a, const T& b, Compare comp);  // constexpr in C++14
+    constexpr const T&               // constexpr in C++14
+    max(const T& a, const T& b, Compare comp);
 
 template<class T>
-    T
-    max(initializer_list<T> t);  // constexpr in C++14
+    constexpr T                      // constexpr in C++14
+    max(initializer_list<T> t);
 
 template<class T, class Compare>
-    T
-    max(initializer_list<T> t, Compare comp);  // constexpr in C++14
+    constexpr T                      // constexpr in C++14
+    max(initializer_list<T> t, Compare comp);
 
 template<class ForwardIterator>
-    pair<ForwardIterator, ForwardIterator>
-    minmax_element(ForwardIterator first, ForwardIterator last);   // constexpr in C++14
+    constexpr pair<ForwardIterator, ForwardIterator>  // constexpr in C++14
+    minmax_element(ForwardIterator first, ForwardIterator last);
 
 template<class ForwardIterator, class Compare>
-    pair<ForwardIterator, ForwardIterator>
-    minmax_element(ForwardIterator first, ForwardIterator last, Compare comp);   // constexpr in C++14
+    constexpr pair<ForwardIterator, ForwardIterator>  // constexpr in C++14
+    minmax_element(ForwardIterator first, ForwardIterator last, Compare comp);
 
 template<class T>
-    pair<const T&, const T&>
-    minmax(const T& a, const T& b);  // constexpr in C++14
+    constexpr pair<const T&, const T&>  // constexpr in C++14
+    minmax(const T& a, const T& b);
 
 template<class T, class Compare>
-    pair<const T&, const T&>
-    minmax(const T& a, const T& b, Compare comp);  // constexpr in C++14
+    constexpr pair<const T&, const T&>  // constexpr in C++14
+    minmax(const T& a, const T& b, Compare comp);
 
 template<class T>
-    pair<T, T>
-    minmax(initializer_list<T> t);  // constexpr in C++14
+    constexpr pair<T, T>                // constexpr in C++14
+    minmax(initializer_list<T> t);
 
 template<class T, class Compare>
-    pair<T, T>
-    minmax(initializer_list<T> t, Compare comp);  // constexpr in C++14
+    constexpr pair<T, T>                // constexpr in C++14
+    minmax(initializer_list<T> t, Compare comp);
 
 template <class InputIterator1, class InputIterator2>
     constexpr bool     // constexpr in C++20
@@ -5401,7 +5401,7 @@
 // set_union
 
 template <class _Compare, class _InputIterator1, class _InputIterator2, class _OutputIterator>
-_OutputIterator
+_LIBCPP_CONSTEXPR_AFTER_CXX17 _OutputIterator
 __set_union(_InputIterator1 __first1, _InputIterator1 __last1,
             _InputIterator2 __first2, _InputIterator2 __last2, _OutputIterator __result, _Compare __comp)
 {
@@ -5426,7 +5426,7 @@
 }
 
 template <class _InputIterator1, class _InputIterator2, class _OutputIterator, class _Compare>
-inline _LIBCPP_INLINE_VISIBILITY
+inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
 _OutputIterator
 set_union(_InputIterator1 __first1, _InputIterator1 __last1,
           _InputIterator2 __first2, _InputIterator2 __last2, _OutputIterator __result, _Compare __comp)
@@ -5436,7 +5436,7 @@
 }
 
 template <class _InputIterator1, class _InputIterator2, class _OutputIterator>
-inline _LIBCPP_INLINE_VISIBILITY
+inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
 _OutputIterator
 set_union(_InputIterator1 __first1, _InputIterator1 __last1,
           _InputIterator2 __first2, _InputIterator2 __last2, _OutputIterator __result)
@@ -5495,7 +5495,7 @@
 // set_difference
 
 template <class _Compare, class _InputIterator1, class _InputIterator2, class _OutputIterator>
-_OutputIterator
+_LIBCPP_CONSTEXPR_AFTER_CXX17 _OutputIterator
 __set_difference(_InputIterator1 __first1, _InputIterator1 __last1,
                  _InputIterator2 __first2, _InputIterator2 __last2, _OutputIterator __result, _Compare __comp)
 {
@@ -5520,7 +5520,7 @@
 }
 
 template <class _InputIterator1, class _InputIterator2, class _OutputIterator, class _Compare>
-inline _LIBCPP_INLINE_VISIBILITY
+inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
 _OutputIterator
 set_difference(_InputIterator1 __first1, _InputIterator1 __last1,
                _InputIterator2 __first2, _InputIterator2 __last2, _OutputIterator __result, _Compare __comp)
@@ -5530,7 +5530,7 @@
 }
 
 template <class _InputIterator1, class _InputIterator2, class _OutputIterator>
-inline _LIBCPP_INLINE_VISIBILITY
+inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
 _OutputIterator
 set_difference(_InputIterator1 __first1, _InputIterator1 __last1,
                _InputIterator2 __first2, _InputIterator2 __last2, _OutputIterator __result)
@@ -5543,7 +5543,7 @@
 // set_symmetric_difference
 
 template <class _Compare, class _InputIterator1, class _InputIterator2, class _OutputIterator>
-_OutputIterator
+_LIBCPP_CONSTEXPR_AFTER_CXX17 _OutputIterator
 __set_symmetric_difference(_InputIterator1 __first1, _InputIterator1 __last1,
                            _InputIterator2 __first2, _InputIterator2 __last2, _OutputIterator __result, _Compare __comp)
 {
@@ -5573,7 +5573,7 @@
 }
 
 template <class _InputIterator1, class _InputIterator2, class _OutputIterator, class _Compare>
-inline _LIBCPP_INLINE_VISIBILITY
+inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
 _OutputIterator
 set_symmetric_difference(_InputIterator1 __first1, _InputIterator1 __last1,
                          _InputIterator2 __first2, _InputIterator2 __last2, _OutputIterator __result, _Compare __comp)
@@ -5583,7 +5583,7 @@
 }
 
 template <class _InputIterator1, class _InputIterator2, class _OutputIterator>
-inline _LIBCPP_INLINE_VISIBILITY
+inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
 _OutputIterator
 set_symmetric_difference(_InputIterator1 __first1, _InputIterator1 __last1,
                          _InputIterator2 __first2, _InputIterator2 __last2, _OutputIterator __result)
diff --git a/libcxx/test/std/algorithms/alg.sorting/alg.merge/merge.pass.cpp b/libcxx/test/std/algorithms/alg.sorting/alg.merge/merge.pass.cpp
--- a/libcxx/test/std/algorithms/alg.sorting/alg.merge/merge.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.sorting/alg.merge/merge.pass.cpp
@@ -5,12 +5,8 @@
 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 //
 //===----------------------------------------------------------------------===//
-//
-// REQUIRES: long_tests
 
-// Older compilers don't support std::is_constant_evaluated
-// UNSUPPORTED: clang-4, clang-5, clang-6, clang-7, clang-8
-// UNSUPPORTED: apple-clang-9, apple-clang-10
+// UNSUPPORTED: clang-8
 
 // <algorithm>
 
@@ -18,233 +14,85 @@
 //   requires OutputIterator<OutIter, InIter1::reference>
 //         && OutputIterator<OutIter, InIter2::reference>
 //         && HasLess<InIter2::value_type, InIter1::value_type>
+//         && HasLess<InIter1::value_type, InIter2::value_type>
 //   constexpr OutIter       // constexpr after C++17
-//   merge(InIter1 first1, InIter1 last1, InIter2 first2, InIter2 last2, OutIter result);
+//   merge(InIter1 first1, InIter1 last1, InIter2 first2, InIter2 last2,
+//         OutIter result);
 
 #include <algorithm>
-#include <random>
 #include <cassert>
 
 #include "test_macros.h"
 #include "test_iterators.h"
+#include "../sortable_helpers.h"
 
-#if TEST_STD_VER > 17
-TEST_CONSTEXPR bool test_constexpr() {
-  int ia[] = {0, 1, 2, 3, 4};
-  int ib[] = {2, 4, 6, 8};
-  int ic[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
-  const int expected[] = {0, 1, 2, 2, 3, 4, 4, 6, 8};
-
-  auto it = std::merge(std::begin(ia), std::end(ia), std::begin(ib),
-                       std::end(ib), std::begin(ic));
-  assert(std::distance(std::begin(ic), it) == static_cast<int>(std::size(ia) + std::size(ib)));
-  assert(*it == 0);
-  assert(std::equal(std::begin(ic), it, std::begin(expected), std::end(expected)));
-  return true;
-}
-#endif
-
-std::mt19937 randomness;
-
-template <class InIter1, class InIter2, class OutIter>
-void test() {
+template<class T, class Iter1, class Iter2, class OutIter>
+TEST_CONSTEXPR_CXX20 void test4()
+{
+    const T a[] = {11, 33, 31, 41};
+    const T b[] = {22, 32, 43, 42, 52};
     {
-    unsigned N = 100000;
-    int* ia = new int[N];
-    int* ib = new int[N];
-    int* ic = new int[2*N];
-    for (unsigned i = 0; i < N; ++i)
-        ia[i] = 2*i;
-    for (unsigned i = 0; i < N; ++i)
-        ib[i] = 2*i+1;
-    OutIter r = std::merge(InIter1(ia), InIter1(ia+N),
-                           InIter2(ib), InIter2(ib+N), OutIter(ic));
-    assert(base(r) == ic+2*N);
-    assert(ic[0] == 0);
-    assert(ic[2*N-1] == static_cast<int>(2*N-1));
-    assert(std::is_sorted(ic, ic+2*N));
-    delete [] ic;
-    delete [] ib;
-    delete [] ia;
+        T result[20] = {};
+        T expected[] = {11, 22, 33, 31, 32, 41, 43, 42, 52};
+        OutIter end = std::merge(Iter1(a), Iter1(a+4), Iter2(b), Iter2(b+5), OutIter(result));
+        assert(std::lexicographical_compare(result, base(end), expected, expected+9, T::less) == 0);
+        for (const T *it = base(end); it != result+20; ++it) {
+            assert(it->value == 0);
+        }
     }
     {
-    unsigned N = 100;
-    int* ia = new int[N];
-    int* ib = new int[N];
-    int* ic = new int[2*N];
-    for (unsigned i = 0; i < 2*N; ++i)
-        ic[i] = i;
-    std::shuffle(ic, ic+2*N, randomness);
-    std::copy(ic, ic+N, ia);
-    std::copy(ic+N, ic+2*N, ib);
-    std::sort(ia, ia+N);
-    std::sort(ib, ib+N);
-    OutIter r = std::merge(InIter1(ia), InIter1(ia+N),
-                           InIter2(ib), InIter2(ib+N), OutIter(ic));
-    assert(base(r) == ic+2*N);
-    assert(ic[0] == 0);
-    assert(ic[2*N-1] == static_cast<int>(2*N-1));
-    assert(std::is_sorted(ic, ic+2*N));
-    delete [] ic;
-    delete [] ib;
-    delete [] ia;
+        T result[20] = {};
+        T expected[] = {11, 22, 32, 33, 31, 43, 42, 41, 52};
+        OutIter end = std::merge(Iter1(b), Iter1(b+5), Iter2(a), Iter2(a+4), OutIter(result));
+        assert(std::lexicographical_compare(result, base(end), expected, expected+9, T::less) == 0);
+        for (const T *it = base(end); it != result+20; ++it) {
+            assert(it->value == 0);
+        }
     }
 }
 
-int main(int, char**)
+template<class T, class Iter1, class Iter2>
+TEST_CONSTEXPR_CXX20 void test3()
 {
-    test<input_iterator<const int*>, input_iterator<const int*>, output_iterator<int*> >();
-    test<input_iterator<const int*>, input_iterator<const int*>, forward_iterator<int*> >();
-    test<input_iterator<const int*>, input_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<input_iterator<const int*>, input_iterator<const int*>, random_access_iterator<int*> >();
-    test<input_iterator<const int*>, input_iterator<const int*>, int*>();
-
-    test<input_iterator<const int*>, forward_iterator<const int*>, output_iterator<int*> >();
-    test<input_iterator<const int*>, forward_iterator<const int*>, forward_iterator<int*> >();
-    test<input_iterator<const int*>, forward_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<input_iterator<const int*>, forward_iterator<const int*>, random_access_iterator<int*> >();
-    test<input_iterator<const int*>, forward_iterator<const int*>, int*>();
-
-    test<input_iterator<const int*>, bidirectional_iterator<const int*>, output_iterator<int*> >();
-    test<input_iterator<const int*>, bidirectional_iterator<const int*>, forward_iterator<int*> >();
-    test<input_iterator<const int*>, bidirectional_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<input_iterator<const int*>, bidirectional_iterator<const int*>, random_access_iterator<int*> >();
-    test<input_iterator<const int*>, bidirectional_iterator<const int*>, int*>();
-
-    test<input_iterator<const int*>, random_access_iterator<const int*>, output_iterator<int*> >();
-    test<input_iterator<const int*>, random_access_iterator<const int*>, forward_iterator<int*> >();
-    test<input_iterator<const int*>, random_access_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<input_iterator<const int*>, random_access_iterator<const int*>, random_access_iterator<int*> >();
-    test<input_iterator<const int*>, random_access_iterator<const int*>, int*>();
-
-    test<input_iterator<const int*>, const int*, output_iterator<int*> >();
-    test<input_iterator<const int*>, const int*, forward_iterator<int*> >();
-    test<input_iterator<const int*>, const int*, bidirectional_iterator<int*> >();
-    test<input_iterator<const int*>, const int*, random_access_iterator<int*> >();
-    test<input_iterator<const int*>, const int*, int*>();
-
-    test<forward_iterator<const int*>, input_iterator<const int*>, output_iterator<int*> >();
-    test<forward_iterator<const int*>, input_iterator<const int*>, forward_iterator<int*> >();
-    test<forward_iterator<const int*>, input_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<forward_iterator<const int*>, input_iterator<const int*>, random_access_iterator<int*> >();
-    test<forward_iterator<const int*>, input_iterator<const int*>, int*>();
-
-    test<forward_iterator<const int*>, forward_iterator<const int*>, output_iterator<int*> >();
-    test<forward_iterator<const int*>, forward_iterator<const int*>, forward_iterator<int*> >();
-    test<forward_iterator<const int*>, forward_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<forward_iterator<const int*>, forward_iterator<const int*>, random_access_iterator<int*> >();
-    test<forward_iterator<const int*>, forward_iterator<const int*>, int*>();
-
-    test<forward_iterator<const int*>, bidirectional_iterator<const int*>, output_iterator<int*> >();
-    test<forward_iterator<const int*>, bidirectional_iterator<const int*>, forward_iterator<int*> >();
-    test<forward_iterator<const int*>, bidirectional_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<forward_iterator<const int*>, bidirectional_iterator<const int*>, random_access_iterator<int*> >();
-    test<forward_iterator<const int*>, bidirectional_iterator<const int*>, int*>();
-
-    test<forward_iterator<const int*>, random_access_iterator<const int*>, output_iterator<int*> >();
-    test<forward_iterator<const int*>, random_access_iterator<const int*>, forward_iterator<int*> >();
-    test<forward_iterator<const int*>, random_access_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<forward_iterator<const int*>, random_access_iterator<const int*>, random_access_iterator<int*> >();
-    test<forward_iterator<const int*>, random_access_iterator<const int*>, int*>();
-
-    test<forward_iterator<const int*>, const int*, output_iterator<int*> >();
-    test<forward_iterator<const int*>, const int*, forward_iterator<int*> >();
-    test<forward_iterator<const int*>, const int*, bidirectional_iterator<int*> >();
-    test<forward_iterator<const int*>, const int*, random_access_iterator<int*> >();
-    test<forward_iterator<const int*>, const int*, int*>();
-
-    test<bidirectional_iterator<const int*>, input_iterator<const int*>, output_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, input_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, input_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, input_iterator<const int*>, random_access_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, input_iterator<const int*>, int*>();
-
-    test<bidirectional_iterator<const int*>, forward_iterator<const int*>, output_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, forward_iterator<const int*>, forward_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, forward_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, forward_iterator<const int*>, random_access_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, forward_iterator<const int*>, int*>();
-
-    test<bidirectional_iterator<const int*>, bidirectional_iterator<const int*>, output_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, bidirectional_iterator<const int*>, forward_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, bidirectional_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, bidirectional_iterator<const int*>, random_access_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, bidirectional_iterator<const int*>, int*>();
-
-    test<bidirectional_iterator<const int*>, random_access_iterator<const int*>, output_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, random_access_iterator<const int*>, forward_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, random_access_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, random_access_iterator<const int*>, random_access_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, random_access_iterator<const int*>, int*>();
-
-    test<bidirectional_iterator<const int*>, const int*, output_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, const int*, forward_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, const int*, bidirectional_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, const int*, random_access_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, const int*, int*>();
-
-    test<random_access_iterator<const int*>, input_iterator<const int*>, output_iterator<int*> >();
-    test<random_access_iterator<const int*>, input_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<random_access_iterator<const int*>, input_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<random_access_iterator<const int*>, input_iterator<const int*>, random_access_iterator<int*> >();
-    test<random_access_iterator<const int*>, input_iterator<const int*>, int*>();
-
-    test<random_access_iterator<const int*>, forward_iterator<const int*>, output_iterator<int*> >();
-    test<random_access_iterator<const int*>, forward_iterator<const int*>, forward_iterator<int*> >();
-    test<random_access_iterator<const int*>, forward_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<random_access_iterator<const int*>, forward_iterator<const int*>, random_access_iterator<int*> >();
-    test<random_access_iterator<const int*>, forward_iterator<const int*>, int*>();
-
-    test<random_access_iterator<const int*>, bidirectional_iterator<const int*>, output_iterator<int*> >();
-    test<random_access_iterator<const int*>, bidirectional_iterator<const int*>, forward_iterator<int*> >();
-    test<random_access_iterator<const int*>, bidirectional_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<random_access_iterator<const int*>, bidirectional_iterator<const int*>, random_access_iterator<int*> >();
-    test<random_access_iterator<const int*>, bidirectional_iterator<const int*>, int*>();
-
-    test<random_access_iterator<const int*>, random_access_iterator<const int*>, output_iterator<int*> >();
-    test<random_access_iterator<const int*>, random_access_iterator<const int*>, forward_iterator<int*> >();
-    test<random_access_iterator<const int*>, random_access_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<random_access_iterator<const int*>, random_access_iterator<const int*>, random_access_iterator<int*> >();
-    test<random_access_iterator<const int*>, random_access_iterator<const int*>, int*>();
-
-    test<random_access_iterator<const int*>, const int*, output_iterator<int*> >();
-    test<random_access_iterator<const int*>, const int*, forward_iterator<int*> >();
-    test<random_access_iterator<const int*>, const int*, bidirectional_iterator<int*> >();
-    test<random_access_iterator<const int*>, const int*, random_access_iterator<int*> >();
-    test<random_access_iterator<const int*>, const int*, int*>();
-
-    test<const int*, input_iterator<const int*>, output_iterator<int*> >();
-    test<const int*, input_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<const int*, input_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<const int*, input_iterator<const int*>, random_access_iterator<int*> >();
-    test<const int*, input_iterator<const int*>, int*>();
-
-    test<const int*, forward_iterator<const int*>, output_iterator<int*> >();
-    test<const int*, forward_iterator<const int*>, forward_iterator<int*> >();
-    test<const int*, forward_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<const int*, forward_iterator<const int*>, random_access_iterator<int*> >();
-    test<const int*, forward_iterator<const int*>, int*>();
+    test4<T, Iter1, Iter2, output_iterator<T*> >();
+    test4<T, Iter1, Iter2, forward_iterator<T*> >();
+    test4<T, Iter1, Iter2, bidirectional_iterator<T*> >();
+    test4<T, Iter1, Iter2, random_access_iterator<T*> >();
+    test4<T, Iter1, Iter2, T*>();
+}
 
-    test<const int*, bidirectional_iterator<const int*>, output_iterator<int*> >();
-    test<const int*, bidirectional_iterator<const int*>, forward_iterator<int*> >();
-    test<const int*, bidirectional_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<const int*, bidirectional_iterator<const int*>, random_access_iterator<int*> >();
-    test<const int*, bidirectional_iterator<const int*>, int*>();
+template<class T, class Iter1>
+TEST_CONSTEXPR_CXX20 void test2()
+{
+    test3<T, Iter1, input_iterator<const T*> >();
+    test3<T, Iter1, forward_iterator<const T*> >();
+    test3<T, Iter1, bidirectional_iterator<const T*> >();
+    test3<T, Iter1, random_access_iterator<const T*> >();
+    test3<T, Iter1, const T*>();
+}
 
-    test<const int*, random_access_iterator<const int*>, output_iterator<int*> >();
-    test<const int*, random_access_iterator<const int*>, forward_iterator<int*> >();
-    test<const int*, random_access_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<const int*, random_access_iterator<const int*>, random_access_iterator<int*> >();
-    test<const int*, random_access_iterator<const int*>, int*>();
+template<class T>
+TEST_CONSTEXPR_CXX20 void test1()
+{
+    test2<T, input_iterator<const T*> >();
+    test2<T, forward_iterator<const T*> >();
+    test2<T, bidirectional_iterator<const T*> >();
+    test2<T, random_access_iterator<const T*> >();
+    test2<T, const T*>();
+}
 
-    test<const int*, const int*, output_iterator<int*> >();
-    test<const int*, const int*, forward_iterator<int*> >();
-    test<const int*, const int*, bidirectional_iterator<int*> >();
-    test<const int*, const int*, random_access_iterator<int*> >();
-    test<const int*, const int*, int*>();
+TEST_CONSTEXPR_CXX20 bool test()
+{
+    test1<TrivialSortable>();
+    test1<NonTrivialSortable>();
+    return true;
+}
 
+int main(int, char**)
+{
+    test();
 #if TEST_STD_VER > 17
-    static_assert(test_constexpr());
+    static_assert(test());
 #endif
 
     return 0;
diff --git a/libcxx/test/std/algorithms/alg.sorting/alg.merge/merge_comp.pass.cpp b/libcxx/test/std/algorithms/alg.sorting/alg.merge/merge_comp.pass.cpp
--- a/libcxx/test/std/algorithms/alg.sorting/alg.merge/merge_comp.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.sorting/alg.merge/merge_comp.pass.cpp
@@ -5,261 +5,96 @@
 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 //
 //===----------------------------------------------------------------------===//
-//
-// REQUIRES: long_tests
 
-// Older compilers don't support std::is_constant_evaluated
-// UNSUPPORTED: clang-4, clang-5, clang-6, clang-7, clang-8
-// UNSUPPORTED: apple-clang-9, apple-clang-10
+// UNSUPPORTED: clang-8
 
 // <algorithm>
 
 // template<InputIterator InIter1, InputIterator InIter2, typename OutIter,
-//          Predicate<auto, InIter2::value_type, InIter1::value_type> Compare>
+//          CopyConstructible Compare>
 //   requires OutputIterator<OutIter, InIter1::reference>
 //         && OutputIterator<OutIter, InIter2::reference>
-//         && CopyConstructible<Compare>
+//         && Predicate<Compare, InIter1::value_type, InIter2::value_type>
+//         && Predicate<Compare, InIter2::value_type, InIter1::value_type>
 //   constexpr OutIter       // constexpr after C++17
-//   merge(InIter1 first1, InIter1 last1,
-//         InIter2 first2, InIter2 last2, OutIter result, Compare comp);
+//   merge(InIter1 first1, InIter1 last1, InIter2 first2, InIter2 last2,
+//         OutIter result, Compare comp);
 
 #include <algorithm>
-#include <functional>
-#include <random>
 #include <cassert>
 
 #include "test_macros.h"
 #include "test_iterators.h"
-#include "counting_predicates.h"
-
-#if TEST_STD_VER > 17
-TEST_CONSTEXPR bool test_constexpr() {
-  int ia[] = {0, 1, 2, 3, 4};
-  int ib[] = {2, 4, 6, 8};
-  int ic[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
-  const int expected[] = {0, 1, 2, 2, 3, 4, 4, 6, 8};
-
-  auto it =
-      std::merge(std::begin(ia), std::end(ia), std::begin(ib), std::end(ib),
-                 std::begin(ic), std::less<>{});
-  assert(std::distance(std::begin(ic), it) == static_cast<int>(std::size(ia) + std::size(ib)));
-  assert(*it == 0);
-  assert(
-      std::equal(std::begin(ic), it, std::begin(expected), std::end(expected)));
-  return true;
-}
-#endif
-
-std::mt19937 randomness;
+#include "../sortable_helpers.h"
 
-template <class InIter1, class InIter2, class OutIter>
-void
-test()
+template<class T, class Iter1, class Iter2, class OutIter>
+TEST_CONSTEXPR_CXX20 void test4()
 {
+    const T a[] = {11, 33, 31, 41};
+    const T b[] = {22, 32, 43, 42, 52};
     {
-    unsigned N = 100000;
-    int* ia = new int[N];
-    int* ib = new int[N];
-    int* ic = new int[2*N];
-    for (unsigned i = 0; i < N; ++i)
-        ia[i] = 2*i;
-    for (unsigned i = 0; i < N; ++i)
-        ib[i] = 2*i+1;
-    std::reverse(ia, ia+N);
-    std::reverse(ib, ib+N);
-    binary_counting_predicate<std::greater<int>, int, int> pred((std::greater<int>()));
-    OutIter r = std::merge(InIter1(ia), InIter1(ia+N),
-                           InIter2(ib), InIter2(ib+N), OutIter(ic), pred);
-    assert(base(r) == ic+2*N);
-    assert(ic[0] == static_cast<int>(2*N-1));
-    assert(ic[2*N-1] == 0);
-    assert(std::is_sorted(ic, ic+2*N, std::greater<int>()));
-    assert(pred.count() <= (N + N - 1));
-    delete [] ic;
-    delete [] ib;
-    delete [] ia;
+        T result[20] = {};
+        T expected[] = {11, 22, 33, 31, 32, 41, 43, 42, 52};
+        OutIter end = std::merge(Iter1(a), Iter1(a+4), Iter2(b), Iter2(b+5), OutIter(result), typename T::Comparator());
+        assert(std::lexicographical_compare(result, base(end), expected, expected+9, T::less) == 0);
+        for (const T *it = base(end); it != result+20; ++it) {
+            assert(it->value == 0);
+        }
     }
     {
-    unsigned N = 100;
-    int* ia = new int[N];
-    int* ib = new int[N];
-    int* ic = new int[2*N];
-    for (unsigned i = 0; i < 2*N; ++i)
-        ic[i] = i;
-    std::shuffle(ic, ic+2*N, randomness);
-    std::copy(ic, ic+N, ia);
-    std::copy(ic+N, ic+2*N, ib);
-    std::sort(ia, ia+N, std::greater<int>());
-    std::sort(ib, ib+N, std::greater<int>());
-    binary_counting_predicate<std::greater<int>, int, int> pred((std::greater<int>()));
-    OutIter r = std::merge(InIter1(ia), InIter1(ia+N),
-                           InIter2(ib), InIter2(ib+N), OutIter(ic), pred);
-    assert(base(r) == ic+2*N);
-    assert(ic[0] == static_cast<int>(2*N-1));
-    assert(ic[2*N-1] == 0);
-    assert(std::is_sorted(ic, ic+2*N, std::greater<int>()));
-    assert(pred.count() <= (N + N - 1));
-    delete [] ic;
-    delete [] ib;
-    delete [] ia;
+        T result[20] = {};
+        T expected[] = {11, 22, 32, 33, 31, 43, 42, 41, 52};
+        OutIter end = std::merge(Iter1(b), Iter1(b+5), Iter2(a), Iter2(a+4), OutIter(result), typename T::Comparator());
+        assert(std::lexicographical_compare(result, base(end), expected, expected+9, T::less) == 0);
+        for (const T *it = base(end); it != result+20; ++it) {
+            assert(it->value == 0);
+        }
     }
 }
 
-int main(int, char**)
+template<class T, class Iter1, class Iter2>
+TEST_CONSTEXPR_CXX20 void test3()
 {
-    test<input_iterator<const int*>, input_iterator<const int*>, output_iterator<int*> >();
-    test<input_iterator<const int*>, input_iterator<const int*>, forward_iterator<int*> >();
-    test<input_iterator<const int*>, input_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<input_iterator<const int*>, input_iterator<const int*>, random_access_iterator<int*> >();
-    test<input_iterator<const int*>, input_iterator<const int*>, int*>();
-
-    test<input_iterator<const int*>, forward_iterator<const int*>, output_iterator<int*> >();
-    test<input_iterator<const int*>, forward_iterator<const int*>, forward_iterator<int*> >();
-    test<input_iterator<const int*>, forward_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<input_iterator<const int*>, forward_iterator<const int*>, random_access_iterator<int*> >();
-    test<input_iterator<const int*>, forward_iterator<const int*>, int*>();
-
-    test<input_iterator<const int*>, bidirectional_iterator<const int*>, output_iterator<int*> >();
-    test<input_iterator<const int*>, bidirectional_iterator<const int*>, forward_iterator<int*> >();
-    test<input_iterator<const int*>, bidirectional_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<input_iterator<const int*>, bidirectional_iterator<const int*>, random_access_iterator<int*> >();
-    test<input_iterator<const int*>, bidirectional_iterator<const int*>, int*>();
-
-    test<input_iterator<const int*>, random_access_iterator<const int*>, output_iterator<int*> >();
-    test<input_iterator<const int*>, random_access_iterator<const int*>, forward_iterator<int*> >();
-    test<input_iterator<const int*>, random_access_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<input_iterator<const int*>, random_access_iterator<const int*>, random_access_iterator<int*> >();
-    test<input_iterator<const int*>, random_access_iterator<const int*>, int*>();
-
-    test<input_iterator<const int*>, const int*, output_iterator<int*> >();
-    test<input_iterator<const int*>, const int*, forward_iterator<int*> >();
-    test<input_iterator<const int*>, const int*, bidirectional_iterator<int*> >();
-    test<input_iterator<const int*>, const int*, random_access_iterator<int*> >();
-    test<input_iterator<const int*>, const int*, int*>();
-
-    test<forward_iterator<const int*>, input_iterator<const int*>, output_iterator<int*> >();
-    test<forward_iterator<const int*>, input_iterator<const int*>, forward_iterator<int*> >();
-    test<forward_iterator<const int*>, input_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<forward_iterator<const int*>, input_iterator<const int*>, random_access_iterator<int*> >();
-    test<forward_iterator<const int*>, input_iterator<const int*>, int*>();
-
-    test<forward_iterator<const int*>, forward_iterator<const int*>, output_iterator<int*> >();
-    test<forward_iterator<const int*>, forward_iterator<const int*>, forward_iterator<int*> >();
-    test<forward_iterator<const int*>, forward_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<forward_iterator<const int*>, forward_iterator<const int*>, random_access_iterator<int*> >();
-    test<forward_iterator<const int*>, forward_iterator<const int*>, int*>();
-
-    test<forward_iterator<const int*>, bidirectional_iterator<const int*>, output_iterator<int*> >();
-    test<forward_iterator<const int*>, bidirectional_iterator<const int*>, forward_iterator<int*> >();
-    test<forward_iterator<const int*>, bidirectional_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<forward_iterator<const int*>, bidirectional_iterator<const int*>, random_access_iterator<int*> >();
-    test<forward_iterator<const int*>, bidirectional_iterator<const int*>, int*>();
-
-    test<forward_iterator<const int*>, random_access_iterator<const int*>, output_iterator<int*> >();
-    test<forward_iterator<const int*>, random_access_iterator<const int*>, forward_iterator<int*> >();
-    test<forward_iterator<const int*>, random_access_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<forward_iterator<const int*>, random_access_iterator<const int*>, random_access_iterator<int*> >();
-    test<forward_iterator<const int*>, random_access_iterator<const int*>, int*>();
-
-    test<forward_iterator<const int*>, const int*, output_iterator<int*> >();
-    test<forward_iterator<const int*>, const int*, forward_iterator<int*> >();
-    test<forward_iterator<const int*>, const int*, bidirectional_iterator<int*> >();
-    test<forward_iterator<const int*>, const int*, random_access_iterator<int*> >();
-    test<forward_iterator<const int*>, const int*, int*>();
-
-    test<bidirectional_iterator<const int*>, input_iterator<const int*>, output_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, input_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, input_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, input_iterator<const int*>, random_access_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, input_iterator<const int*>, int*>();
-
-    test<bidirectional_iterator<const int*>, forward_iterator<const int*>, output_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, forward_iterator<const int*>, forward_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, forward_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, forward_iterator<const int*>, random_access_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, forward_iterator<const int*>, int*>();
-
-    test<bidirectional_iterator<const int*>, bidirectional_iterator<const int*>, output_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, bidirectional_iterator<const int*>, forward_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, bidirectional_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, bidirectional_iterator<const int*>, random_access_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, bidirectional_iterator<const int*>, int*>();
-
-    test<bidirectional_iterator<const int*>, random_access_iterator<const int*>, output_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, random_access_iterator<const int*>, forward_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, random_access_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, random_access_iterator<const int*>, random_access_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, random_access_iterator<const int*>, int*>();
-
-    test<bidirectional_iterator<const int*>, const int*, output_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, const int*, forward_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, const int*, bidirectional_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, const int*, random_access_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, const int*, int*>();
-
-    test<random_access_iterator<const int*>, input_iterator<const int*>, output_iterator<int*> >();
-    test<random_access_iterator<const int*>, input_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<random_access_iterator<const int*>, input_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<random_access_iterator<const int*>, input_iterator<const int*>, random_access_iterator<int*> >();
-    test<random_access_iterator<const int*>, input_iterator<const int*>, int*>();
-
-    test<random_access_iterator<const int*>, forward_iterator<const int*>, output_iterator<int*> >();
-    test<random_access_iterator<const int*>, forward_iterator<const int*>, forward_iterator<int*> >();
-    test<random_access_iterator<const int*>, forward_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<random_access_iterator<const int*>, forward_iterator<const int*>, random_access_iterator<int*> >();
-    test<random_access_iterator<const int*>, forward_iterator<const int*>, int*>();
-
-    test<random_access_iterator<const int*>, bidirectional_iterator<const int*>, output_iterator<int*> >();
-    test<random_access_iterator<const int*>, bidirectional_iterator<const int*>, forward_iterator<int*> >();
-    test<random_access_iterator<const int*>, bidirectional_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<random_access_iterator<const int*>, bidirectional_iterator<const int*>, random_access_iterator<int*> >();
-    test<random_access_iterator<const int*>, bidirectional_iterator<const int*>, int*>();
-
-    test<random_access_iterator<const int*>, random_access_iterator<const int*>, output_iterator<int*> >();
-    test<random_access_iterator<const int*>, random_access_iterator<const int*>, forward_iterator<int*> >();
-    test<random_access_iterator<const int*>, random_access_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<random_access_iterator<const int*>, random_access_iterator<const int*>, random_access_iterator<int*> >();
-    test<random_access_iterator<const int*>, random_access_iterator<const int*>, int*>();
-
-    test<random_access_iterator<const int*>, const int*, output_iterator<int*> >();
-    test<random_access_iterator<const int*>, const int*, forward_iterator<int*> >();
-    test<random_access_iterator<const int*>, const int*, bidirectional_iterator<int*> >();
-    test<random_access_iterator<const int*>, const int*, random_access_iterator<int*> >();
-    test<random_access_iterator<const int*>, const int*, int*>();
-
-    test<const int*, input_iterator<const int*>, output_iterator<int*> >();
-    test<const int*, input_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<const int*, input_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<const int*, input_iterator<const int*>, random_access_iterator<int*> >();
-    test<const int*, input_iterator<const int*>, int*>();
-
-    test<const int*, forward_iterator<const int*>, output_iterator<int*> >();
-    test<const int*, forward_iterator<const int*>, forward_iterator<int*> >();
-    test<const int*, forward_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<const int*, forward_iterator<const int*>, random_access_iterator<int*> >();
-    test<const int*, forward_iterator<const int*>, int*>();
+    test4<T, Iter1, Iter2, output_iterator<T*> >();
+    test4<T, Iter1, Iter2, forward_iterator<T*> >();
+    test4<T, Iter1, Iter2, bidirectional_iterator<T*> >();
+    test4<T, Iter1, Iter2, random_access_iterator<T*> >();
+    test4<T, Iter1, Iter2, T*>();
+}
 
-    test<const int*, bidirectional_iterator<const int*>, output_iterator<int*> >();
-    test<const int*, bidirectional_iterator<const int*>, forward_iterator<int*> >();
-    test<const int*, bidirectional_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<const int*, bidirectional_iterator<const int*>, random_access_iterator<int*> >();
-    test<const int*, bidirectional_iterator<const int*>, int*>();
+template<class T, class Iter1>
+TEST_CONSTEXPR_CXX20 void test2()
+{
+    test3<T, Iter1, input_iterator<const T*> >();
+    test3<T, Iter1, forward_iterator<const T*> >();
+    test3<T, Iter1, bidirectional_iterator<const T*> >();
+    test3<T, Iter1, random_access_iterator<const T*> >();
+    test3<T, Iter1, const T*>();
+}
 
-    test<const int*, random_access_iterator<const int*>, output_iterator<int*> >();
-    test<const int*, random_access_iterator<const int*>, forward_iterator<int*> >();
-    test<const int*, random_access_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<const int*, random_access_iterator<const int*>, random_access_iterator<int*> >();
-    test<const int*, random_access_iterator<const int*>, int*>();
+template<class T>
+TEST_CONSTEXPR_CXX20 void test1()
+{
+    test2<T, input_iterator<const T*> >();
+    test2<T, forward_iterator<const T*> >();
+    test2<T, bidirectional_iterator<const T*> >();
+    test2<T, random_access_iterator<const T*> >();
+    test2<T, const T*>();
+}
 
-    test<const int*, const int*, output_iterator<int*> >();
-    test<const int*, const int*, forward_iterator<int*> >();
-    test<const int*, const int*, bidirectional_iterator<int*> >();
-    test<const int*, const int*, random_access_iterator<int*> >();
-    test<const int*, const int*, int*>();
+TEST_CONSTEXPR_CXX20 bool test()
+{
+    test1<TrivialSortableWithComp>();
+    test1<NonTrivialSortableWithComp>();
+    return true;
+}
 
+int main(int, char**)
+{
+    test();
 #if TEST_STD_VER > 17
-    static_assert(test_constexpr());
+    static_assert(test());
 #endif
 
-  return 0;
+    return 0;
 }
diff --git a/libcxx/test/std/algorithms/alg.sorting/alg.set.operations/includes/includes.pass.cpp b/libcxx/test/std/algorithms/alg.sorting/alg.set.operations/includes/includes.pass.cpp
--- a/libcxx/test/std/algorithms/alg.sorting/alg.set.operations/includes/includes.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.sorting/alg.set.operations/includes/includes.pass.cpp
@@ -20,21 +20,9 @@
 #include "test_macros.h"
 #include "test_iterators.h"
 
-#if TEST_STD_VER > 17
-TEST_CONSTEXPR bool test_constexpr() {
-    int ia[] = {1, 2, 2, 3, 3, 3, 4, 4, 4, 4};
-    int ib[] = {2, 4};
-    int ic[] = {3, 3, 3, 3};
-
-    return  std::includes(std::begin(ia), std::end(ia), std::begin(ib), std::end(ib))
-        && !std::includes(std::begin(ia), std::end(ia), std::begin(ic), std::end(ic))
-           ;
-    }
-#endif
-
 template <class Iter1, class Iter2>
-void
-test()
+TEST_CONSTEXPR_CXX20
+void test()
 {
     int ia[] = {1, 2, 2, 3, 3, 3, 4, 4, 4, 4};
     const unsigned sa = sizeof(ia)/sizeof(ia[0]);
@@ -62,7 +50,8 @@
     assert(!std::includes(Iter1(ia), Iter1(ia+sa), Iter2(id), Iter2(id+4)));
 }
 
-int main(int, char**)
+TEST_CONSTEXPR_CXX20
+bool do_tests()
 {
     test<input_iterator<const int*>, input_iterator<const int*> >();
     test<input_iterator<const int*>, forward_iterator<const int*> >();
@@ -94,9 +83,14 @@
     test<const int*, random_access_iterator<const int*> >();
     test<const int*, const int*>();
 
+    return true;
+}
+
+int main(int, char**)
+{
+    do_tests();
 #if TEST_STD_VER > 17
-   static_assert(test_constexpr());
+    static_assert(do_tests());
 #endif
-
-  return 0;
+    return 0;
 }
diff --git a/libcxx/test/std/algorithms/alg.sorting/alg.set.operations/includes/includes_comp.pass.cpp b/libcxx/test/std/algorithms/alg.sorting/alg.set.operations/includes/includes_comp.pass.cpp
--- a/libcxx/test/std/algorithms/alg.sorting/alg.set.operations/includes/includes_comp.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.sorting/alg.set.operations/includes/includes_comp.pass.cpp
@@ -21,51 +21,38 @@
 #include "test_macros.h"
 #include "test_iterators.h"
 
-#if TEST_STD_VER > 17
-TEST_CONSTEXPR bool test_constexpr() {
-    int ia[] = {1, 2, 2, 3, 3, 3, 4, 4, 4, 4};
-    int ib[] = {2, 4};
-    int ic[] = {3, 3, 3, 3};
-
-    auto comp = [](int a, int b) {return a < b; };
-    return  std::includes(std::begin(ia), std::end(ia), std::begin(ib), std::end(ib), comp)
-        && !std::includes(std::begin(ia), std::end(ia), std::begin(ic), std::end(ic), comp)
-           ;
-    }
-#endif
-
-
 template <class Iter1, class Iter2>
-void
-test()
+TEST_CONSTEXPR_CXX20
+void test()
 {
-    int ia[] = {1, 2, 2, 3, 3, 3, 4, 4, 4, 4};
+    int ia[] = {4, 4, 4, 4, 3, 3, 3, 2, 2, 1};
     const unsigned sa = sizeof(ia)/sizeof(ia[0]);
-    int ib[] = {2, 4};
+    int ib[] = {4, 2};
     const unsigned sb = sizeof(ib)/sizeof(ib[0]);
-    int ic[] = {1, 2};
+    int ic[] = {2, 1};
     const unsigned sc = sizeof(ic)/sizeof(ic[0]); ((void)sc);
     int id[] = {3, 3, 3, 3};
     const unsigned sd = sizeof(id)/sizeof(id[0]); ((void)sd);
 
-    assert(std::includes(Iter1(ia), Iter1(ia), Iter2(ib), Iter2(ib), std::less<int>()));
-    assert(!std::includes(Iter1(ia), Iter1(ia), Iter2(ib), Iter2(ib+1), std::less<int>()));
-    assert(std::includes(Iter1(ia), Iter1(ia+1), Iter2(ib), Iter2(ib), std::less<int>()));
-    assert(std::includes(Iter1(ia), Iter1(ia+sa), Iter2(ia), Iter2(ia+sa), std::less<int>()));
+    assert(std::includes(Iter1(ia), Iter1(ia), Iter2(ib), Iter2(ib), std::greater<int>()));
+    assert(!std::includes(Iter1(ia), Iter1(ia), Iter2(ib), Iter2(ib+1), std::greater<int>()));
+    assert(std::includes(Iter1(ia), Iter1(ia+1), Iter2(ib), Iter2(ib), std::greater<int>()));
+    assert(std::includes(Iter1(ia), Iter1(ia+sa), Iter2(ia), Iter2(ia+sa), std::greater<int>()));
 
-    assert(std::includes(Iter1(ia), Iter1(ia+sa), Iter2(ib), Iter2(ib+sb), std::less<int>()));
-    assert(!std::includes(Iter1(ib), Iter1(ib+sb), Iter2(ia), Iter2(ia+sa), std::less<int>()));
+    assert(std::includes(Iter1(ia), Iter1(ia+sa), Iter2(ib), Iter2(ib+sb), std::greater<int>()));
+    assert(!std::includes(Iter1(ib), Iter1(ib+sb), Iter2(ia), Iter2(ia+sa), std::greater<int>()));
 
-    assert(std::includes(Iter1(ia), Iter1(ia+2), Iter2(ic), Iter2(ic+2), std::less<int>()));
-    assert(!std::includes(Iter1(ia), Iter1(ia+2), Iter2(ib), Iter2(ib+2), std::less<int>()));
+    assert(std::includes(Iter1(ia+8), Iter1(ia+sa), Iter2(ic), Iter2(ic+sc), std::greater<int>()));
+    assert(!std::includes(Iter1(ia+8), Iter1(ia+sa), Iter2(ib), Iter2(ib+sb), std::greater<int>()));
 
-    assert(std::includes(Iter1(ia), Iter1(ia+sa), Iter2(id), Iter2(id+1), std::less<int>()));
-    assert(std::includes(Iter1(ia), Iter1(ia+sa), Iter2(id), Iter2(id+2), std::less<int>()));
-    assert(std::includes(Iter1(ia), Iter1(ia+sa), Iter2(id), Iter2(id+3), std::less<int>()));
-    assert(!std::includes(Iter1(ia), Iter1(ia+sa), Iter2(id), Iter2(id+4), std::less<int>()));
+    assert(std::includes(Iter1(ia), Iter1(ia+sa), Iter2(id), Iter2(id+1), std::greater<int>()));
+    assert(std::includes(Iter1(ia), Iter1(ia+sa), Iter2(id), Iter2(id+2), std::greater<int>()));
+    assert(std::includes(Iter1(ia), Iter1(ia+sa), Iter2(id), Iter2(id+3), std::greater<int>()));
+    assert(!std::includes(Iter1(ia), Iter1(ia+sa), Iter2(id), Iter2(id+4), std::greater<int>()));
 }
 
-int main(int, char**)
+TEST_CONSTEXPR_CXX20
+bool do_tests()
 {
     test<input_iterator<const int*>, input_iterator<const int*> >();
     test<input_iterator<const int*>, forward_iterator<const int*> >();
@@ -97,9 +84,14 @@
     test<const int*, random_access_iterator<const int*> >();
     test<const int*, const int*>();
 
+    return true;
+}
+
+int main(int, char**)
+{
+    do_tests();
 #if TEST_STD_VER > 17
-   static_assert(test_constexpr());
+    static_assert(do_tests());
 #endif
-
-  return 0;
+    return 0;
 }
diff --git a/libcxx/test/std/algorithms/alg.sorting/alg.set.operations/set.difference/set_difference.pass.cpp b/libcxx/test/std/algorithms/alg.sorting/alg.set.operations/set.difference/set_difference.pass.cpp
--- a/libcxx/test/std/algorithms/alg.sorting/alg.set.operations/set.difference/set_difference.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.sorting/alg.set.operations/set.difference/set_difference.pass.cpp
@@ -6,6 +6,8 @@
 //
 //===----------------------------------------------------------------------===//
 
+// UNSUPPORTED: clang-8
+
 // <algorithm>
 
 // template<InputIterator InIter1, InputIterator InIter2, typename OutIter>
@@ -13,7 +15,7 @@
 //         && OutputIterator<OutIter, InIter2::reference>
 //         && HasLess<InIter2::value_type, InIter1::value_type>
 //         && HasLess<InIter1::value_type, InIter2::value_type>
-//   OutIter
+//   constexpr OutIter       // constexpr after C++17
 //   set_difference(InIter1 first1, InIter1 last1, InIter2 first2, InIter2 last2,
 //                  OutIter result);
 
@@ -22,181 +24,76 @@
 
 #include "test_macros.h"
 #include "test_iterators.h"
+#include "../../sortable_helpers.h"
 
-template <class Iter1, class Iter2, class OutIter>
-void
-test()
+template<class T, class Iter1, class Iter2, class OutIter>
+TEST_CONSTEXPR_CXX20 void test4()
 {
-    int ia[] = {1, 2, 2, 3, 3, 3, 4, 4, 4, 4};
-    const int sa = sizeof(ia)/sizeof(ia[0]);
-    int ib[] = {2, 4, 4, 6};
-    const int sb = sizeof(ib)/sizeof(ib[0]);
-    int ic[20];
-    int ir[] = {1, 2, 3, 3, 3, 4, 4};
-    const int sr = sizeof(ir)/sizeof(ir[0]);
-    OutIter ce = std::set_difference(Iter1(ia), Iter1(ia+sa),
-                                     Iter2(ib), Iter2(ib+sb), OutIter(ic));
-    assert(base(ce) - ic == sr);
-    assert(std::lexicographical_compare(ic, base(ce), ir, ir+sr) == 0);
-    int irr[] = {6};
-    const int srr = sizeof(irr)/sizeof(irr[0]);
-    ce = std::set_difference(Iter1(ib), Iter1(ib+sb),
-                             Iter2(ia), Iter2(ia+sa), OutIter(ic));
-    assert(base(ce) - ic == srr);
-    assert(std::lexicographical_compare(ic, base(ce), irr, irr+srr) == 0);
+    const T a[] = {11, 33, 31, 41};
+    const T b[] = {22, 32, 43, 42, 52};
+    {
+        T result[20] = {};
+        T expected[] = {11, 31};
+        OutIter end = std::set_difference(Iter1(a), Iter1(a+4), Iter2(b), Iter2(b+5), OutIter(result));
+        assert(std::lexicographical_compare(result, base(end), expected, expected+2, T::less) == 0);
+        for (const T *it = base(end); it != result+20; ++it) {
+            assert(it->value == 0);
+        }
+    }
+    {
+        T result[20] = {};
+        T expected[] = {22, 42, 52};
+        OutIter end = std::set_difference(Iter1(b), Iter1(b+5), Iter2(a), Iter2(a+4), OutIter(result));
+        assert(std::lexicographical_compare(result, base(end), expected, expected+3, T::less) == 0);
+        for (const T *it = base(end); it != result+20; ++it) {
+            assert(it->value == 0);
+        }
+    }
 }
 
-int main(int, char**)
+template<class T, class Iter1, class Iter2>
+TEST_CONSTEXPR_CXX20 void test3()
 {
-    test<input_iterator<const int*>, input_iterator<const int*>, output_iterator<int*> >();
-    test<input_iterator<const int*>, input_iterator<const int*>, forward_iterator<int*> >();
-    test<input_iterator<const int*>, input_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<input_iterator<const int*>, input_iterator<const int*>, random_access_iterator<int*> >();
-    test<input_iterator<const int*>, input_iterator<const int*>, int*>();
-
-    test<input_iterator<const int*>, forward_iterator<const int*>, output_iterator<int*> >();
-    test<input_iterator<const int*>, forward_iterator<const int*>, forward_iterator<int*> >();
-    test<input_iterator<const int*>, forward_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<input_iterator<const int*>, forward_iterator<const int*>, random_access_iterator<int*> >();
-    test<input_iterator<const int*>, forward_iterator<const int*>, int*>();
-
-    test<input_iterator<const int*>, bidirectional_iterator<const int*>, output_iterator<int*> >();
-    test<input_iterator<const int*>, bidirectional_iterator<const int*>, forward_iterator<int*> >();
-    test<input_iterator<const int*>, bidirectional_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<input_iterator<const int*>, bidirectional_iterator<const int*>, random_access_iterator<int*> >();
-    test<input_iterator<const int*>, bidirectional_iterator<const int*>, int*>();
-
-    test<input_iterator<const int*>, random_access_iterator<const int*>, output_iterator<int*> >();
-    test<input_iterator<const int*>, random_access_iterator<const int*>, forward_iterator<int*> >();
-    test<input_iterator<const int*>, random_access_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<input_iterator<const int*>, random_access_iterator<const int*>, random_access_iterator<int*> >();
-    test<input_iterator<const int*>, random_access_iterator<const int*>, int*>();
-
-    test<input_iterator<const int*>, const int*, output_iterator<int*> >();
-    test<input_iterator<const int*>, const int*, forward_iterator<int*> >();
-    test<input_iterator<const int*>, const int*, bidirectional_iterator<int*> >();
-    test<input_iterator<const int*>, const int*, random_access_iterator<int*> >();
-    test<input_iterator<const int*>, const int*, int*>();
-
-    test<forward_iterator<const int*>, input_iterator<const int*>, output_iterator<int*> >();
-    test<forward_iterator<const int*>, input_iterator<const int*>, forward_iterator<int*> >();
-    test<forward_iterator<const int*>, input_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<forward_iterator<const int*>, input_iterator<const int*>, random_access_iterator<int*> >();
-    test<forward_iterator<const int*>, input_iterator<const int*>, int*>();
-
-    test<forward_iterator<const int*>, forward_iterator<const int*>, output_iterator<int*> >();
-    test<forward_iterator<const int*>, forward_iterator<const int*>, forward_iterator<int*> >();
-    test<forward_iterator<const int*>, forward_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<forward_iterator<const int*>, forward_iterator<const int*>, random_access_iterator<int*> >();
-    test<forward_iterator<const int*>, forward_iterator<const int*>, int*>();
-
-    test<forward_iterator<const int*>, bidirectional_iterator<const int*>, output_iterator<int*> >();
-    test<forward_iterator<const int*>, bidirectional_iterator<const int*>, forward_iterator<int*> >();
-    test<forward_iterator<const int*>, bidirectional_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<forward_iterator<const int*>, bidirectional_iterator<const int*>, random_access_iterator<int*> >();
-    test<forward_iterator<const int*>, bidirectional_iterator<const int*>, int*>();
-
-    test<forward_iterator<const int*>, random_access_iterator<const int*>, output_iterator<int*> >();
-    test<forward_iterator<const int*>, random_access_iterator<const int*>, forward_iterator<int*> >();
-    test<forward_iterator<const int*>, random_access_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<forward_iterator<const int*>, random_access_iterator<const int*>, random_access_iterator<int*> >();
-    test<forward_iterator<const int*>, random_access_iterator<const int*>, int*>();
-
-    test<forward_iterator<const int*>, const int*, output_iterator<int*> >();
-    test<forward_iterator<const int*>, const int*, forward_iterator<int*> >();
-    test<forward_iterator<const int*>, const int*, bidirectional_iterator<int*> >();
-    test<forward_iterator<const int*>, const int*, random_access_iterator<int*> >();
-    test<forward_iterator<const int*>, const int*, int*>();
-
-    test<bidirectional_iterator<const int*>, input_iterator<const int*>, output_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, input_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, input_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, input_iterator<const int*>, random_access_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, input_iterator<const int*>, int*>();
-
-    test<bidirectional_iterator<const int*>, forward_iterator<const int*>, output_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, forward_iterator<const int*>, forward_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, forward_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, forward_iterator<const int*>, random_access_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, forward_iterator<const int*>, int*>();
-
-    test<bidirectional_iterator<const int*>, bidirectional_iterator<const int*>, output_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, bidirectional_iterator<const int*>, forward_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, bidirectional_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, bidirectional_iterator<const int*>, random_access_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, bidirectional_iterator<const int*>, int*>();
-
-    test<bidirectional_iterator<const int*>, random_access_iterator<const int*>, output_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, random_access_iterator<const int*>, forward_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, random_access_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, random_access_iterator<const int*>, random_access_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, random_access_iterator<const int*>, int*>();
-
-    test<bidirectional_iterator<const int*>, const int*, output_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, const int*, forward_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, const int*, bidirectional_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, const int*, random_access_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, const int*, int*>();
-
-    test<random_access_iterator<const int*>, input_iterator<const int*>, output_iterator<int*> >();
-    test<random_access_iterator<const int*>, input_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<random_access_iterator<const int*>, input_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<random_access_iterator<const int*>, input_iterator<const int*>, random_access_iterator<int*> >();
-    test<random_access_iterator<const int*>, input_iterator<const int*>, int*>();
-
-    test<random_access_iterator<const int*>, forward_iterator<const int*>, output_iterator<int*> >();
-    test<random_access_iterator<const int*>, forward_iterator<const int*>, forward_iterator<int*> >();
-    test<random_access_iterator<const int*>, forward_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<random_access_iterator<const int*>, forward_iterator<const int*>, random_access_iterator<int*> >();
-    test<random_access_iterator<const int*>, forward_iterator<const int*>, int*>();
-
-    test<random_access_iterator<const int*>, bidirectional_iterator<const int*>, output_iterator<int*> >();
-    test<random_access_iterator<const int*>, bidirectional_iterator<const int*>, forward_iterator<int*> >();
-    test<random_access_iterator<const int*>, bidirectional_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<random_access_iterator<const int*>, bidirectional_iterator<const int*>, random_access_iterator<int*> >();
-    test<random_access_iterator<const int*>, bidirectional_iterator<const int*>, int*>();
-
-    test<random_access_iterator<const int*>, random_access_iterator<const int*>, output_iterator<int*> >();
-    test<random_access_iterator<const int*>, random_access_iterator<const int*>, forward_iterator<int*> >();
-    test<random_access_iterator<const int*>, random_access_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<random_access_iterator<const int*>, random_access_iterator<const int*>, random_access_iterator<int*> >();
-    test<random_access_iterator<const int*>, random_access_iterator<const int*>, int*>();
-
-    test<random_access_iterator<const int*>, const int*, output_iterator<int*> >();
-    test<random_access_iterator<const int*>, const int*, forward_iterator<int*> >();
-    test<random_access_iterator<const int*>, const int*, bidirectional_iterator<int*> >();
-    test<random_access_iterator<const int*>, const int*, random_access_iterator<int*> >();
-    test<random_access_iterator<const int*>, const int*, int*>();
-
-    test<const int*, input_iterator<const int*>, output_iterator<int*> >();
-    test<const int*, input_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<const int*, input_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<const int*, input_iterator<const int*>, random_access_iterator<int*> >();
-    test<const int*, input_iterator<const int*>, int*>();
+    test4<T, Iter1, Iter2, output_iterator<T*> >();
+    test4<T, Iter1, Iter2, forward_iterator<T*> >();
+    test4<T, Iter1, Iter2, bidirectional_iterator<T*> >();
+    test4<T, Iter1, Iter2, random_access_iterator<T*> >();
+    test4<T, Iter1, Iter2, T*>();
+}
 
-    test<const int*, forward_iterator<const int*>, output_iterator<int*> >();
-    test<const int*, forward_iterator<const int*>, forward_iterator<int*> >();
-    test<const int*, forward_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<const int*, forward_iterator<const int*>, random_access_iterator<int*> >();
-    test<const int*, forward_iterator<const int*>, int*>();
+template<class T, class Iter1>
+TEST_CONSTEXPR_CXX20 void test2()
+{
+    test3<T, Iter1, input_iterator<const T*> >();
+    test3<T, Iter1, forward_iterator<const T*> >();
+    test3<T, Iter1, bidirectional_iterator<const T*> >();
+    test3<T, Iter1, random_access_iterator<const T*> >();
+    test3<T, Iter1, const T*>();
+}
 
-    test<const int*, bidirectional_iterator<const int*>, output_iterator<int*> >();
-    test<const int*, bidirectional_iterator<const int*>, forward_iterator<int*> >();
-    test<const int*, bidirectional_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<const int*, bidirectional_iterator<const int*>, random_access_iterator<int*> >();
-    test<const int*, bidirectional_iterator<const int*>, int*>();
+template<class T>
+TEST_CONSTEXPR_CXX20 void test1()
+{
+    test2<T, input_iterator<const T*> >();
+    test2<T, forward_iterator<const T*> >();
+    test2<T, bidirectional_iterator<const T*> >();
+    test2<T, random_access_iterator<const T*> >();
+    test2<T, const T*>();
+}
 
-    test<const int*, random_access_iterator<const int*>, output_iterator<int*> >();
-    test<const int*, random_access_iterator<const int*>, forward_iterator<int*> >();
-    test<const int*, random_access_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<const int*, random_access_iterator<const int*>, random_access_iterator<int*> >();
-    test<const int*, random_access_iterator<const int*>, int*>();
+TEST_CONSTEXPR_CXX20 bool test()
+{
+    test1<TrivialSortable>();
+    test1<NonTrivialSortable>();
+    return true;
+}
 
-    test<const int*, const int*, output_iterator<int*> >();
-    test<const int*, const int*, forward_iterator<int*> >();
-    test<const int*, const int*, bidirectional_iterator<int*> >();
-    test<const int*, const int*, random_access_iterator<int*> >();
-    test<const int*, const int*, int*>();
+int main(int, char**)
+{
+    test();
+#if TEST_STD_VER > 17
+    static_assert(test());
+#endif
 
-  return 0;
+    return 0;
 }
diff --git a/libcxx/test/std/algorithms/alg.sorting/alg.set.operations/set.difference/set_difference_comp.pass.cpp b/libcxx/test/std/algorithms/alg.sorting/alg.set.operations/set.difference/set_difference_comp.pass.cpp
--- a/libcxx/test/std/algorithms/alg.sorting/alg.set.operations/set.difference/set_difference_comp.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.sorting/alg.set.operations/set.difference/set_difference_comp.pass.cpp
@@ -6,6 +6,8 @@
 //
 //===----------------------------------------------------------------------===//
 
+// UNSUPPORTED: clang-8
+
 // <algorithm>
 
 // template<InputIterator InIter1, InputIterator InIter2, typename OutIter,
@@ -14,191 +16,85 @@
 //         && OutputIterator<OutIter, InIter2::reference>
 //         && Predicate<Compare, InIter1::value_type, InIter2::value_type>
 //         && Predicate<Compare, InIter2::value_type, InIter1::value_type>
-//   OutIter
+//   constexpr OutIter       // constexpr after C++17
 //   set_difference(InIter1 first1, InIter1 last1, InIter2 first2, InIter2 last2,
 //                  OutIter result, Compare comp);
 
 #include <algorithm>
-#include <functional>
 #include <cassert>
 
 #include "test_macros.h"
 #include "test_iterators.h"
+#include "../../sortable_helpers.h"
 
-template <class Iter1, class Iter2, class OutIter>
-void
-test()
+template<class T, class Iter1, class Iter2, class OutIter>
+TEST_CONSTEXPR_CXX20 void test4()
 {
-    int ia[] = {1, 2, 2, 3, 3, 3, 4, 4, 4, 4};
-    const int sa = sizeof(ia)/sizeof(ia[0]);
-    int ib[] = {2, 4, 4, 6};
-    const int sb = sizeof(ib)/sizeof(ib[0]);
-    int ic[20];
-    int ir[] = {1, 2, 3, 3, 3, 4, 4};
-    const int sr = sizeof(ir)/sizeof(ir[0]);
-    OutIter ce = std::set_difference(Iter1(ia), Iter1(ia+sa),
-                                     Iter2(ib), Iter2(ib+sb), OutIter(ic), std::less<int>());
-    assert(base(ce) - ic == sr);
-    assert(std::lexicographical_compare(ic, base(ce), ir, ir+sr) == 0);
-    int irr[] = {6};
-    const int srr = sizeof(irr)/sizeof(irr[0]);
-    ce = std::set_difference(Iter1(ib), Iter1(ib+sb),
-                             Iter2(ia), Iter2(ia+sa), OutIter(ic), std::less<int>());
-    assert(base(ce) - ic == srr);
-    assert(std::lexicographical_compare(ic, base(ce), irr, irr+srr) == 0);
+    const T a[] = {11, 33, 31, 41};
+    const T b[] = {22, 32, 43, 42, 52};
+    {
+        T result[20] = {};
+        T expected[] = {11, 31};
+        OutIter end = std::set_difference(Iter1(a), Iter1(a+4), Iter2(b), Iter2(b+5), OutIter(result), typename T::Comparator());
+        assert(std::lexicographical_compare(result, base(end), expected, expected+2, T::less) == 0);
+        for (const T *it = base(end); it != result+20; ++it) {
+            assert(it->value == 0);
+        }
+    }
+    {
+        T result[20] = {};
+        T expected[] = {22, 42, 52};
+        OutIter end = std::set_difference(Iter1(b), Iter1(b+5), Iter2(a), Iter2(a+4), OutIter(result), typename T::Comparator());
+        assert(std::lexicographical_compare(result, base(end), expected, expected+3, T::less) == 0);
+        for (const T *it = base(end); it != result+20; ++it) {
+            assert(it->value == 0);
+        }
+    }
 }
 
-int main(int, char**)
+template<class T, class Iter1, class Iter2>
+TEST_CONSTEXPR_CXX20 void test3()
 {
-    test<input_iterator<const int*>, input_iterator<const int*>, output_iterator<int*> >();
-    test<input_iterator<const int*>, input_iterator<const int*>, forward_iterator<int*> >();
-    test<input_iterator<const int*>, input_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<input_iterator<const int*>, input_iterator<const int*>, random_access_iterator<int*> >();
-    test<input_iterator<const int*>, input_iterator<const int*>, int*>();
-
-    test<input_iterator<const int*>, forward_iterator<const int*>, output_iterator<int*> >();
-    test<input_iterator<const int*>, forward_iterator<const int*>, forward_iterator<int*> >();
-    test<input_iterator<const int*>, forward_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<input_iterator<const int*>, forward_iterator<const int*>, random_access_iterator<int*> >();
-    test<input_iterator<const int*>, forward_iterator<const int*>, int*>();
-
-    test<input_iterator<const int*>, bidirectional_iterator<const int*>, output_iterator<int*> >();
-    test<input_iterator<const int*>, bidirectional_iterator<const int*>, forward_iterator<int*> >();
-    test<input_iterator<const int*>, bidirectional_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<input_iterator<const int*>, bidirectional_iterator<const int*>, random_access_iterator<int*> >();
-    test<input_iterator<const int*>, bidirectional_iterator<const int*>, int*>();
-
-    test<input_iterator<const int*>, random_access_iterator<const int*>, output_iterator<int*> >();
-    test<input_iterator<const int*>, random_access_iterator<const int*>, forward_iterator<int*> >();
-    test<input_iterator<const int*>, random_access_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<input_iterator<const int*>, random_access_iterator<const int*>, random_access_iterator<int*> >();
-    test<input_iterator<const int*>, random_access_iterator<const int*>, int*>();
-
-    test<input_iterator<const int*>, const int*, output_iterator<int*> >();
-    test<input_iterator<const int*>, const int*, forward_iterator<int*> >();
-    test<input_iterator<const int*>, const int*, bidirectional_iterator<int*> >();
-    test<input_iterator<const int*>, const int*, random_access_iterator<int*> >();
-    test<input_iterator<const int*>, const int*, int*>();
-
-    test<forward_iterator<const int*>, input_iterator<const int*>, output_iterator<int*> >();
-    test<forward_iterator<const int*>, input_iterator<const int*>, forward_iterator<int*> >();
-    test<forward_iterator<const int*>, input_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<forward_iterator<const int*>, input_iterator<const int*>, random_access_iterator<int*> >();
-    test<forward_iterator<const int*>, input_iterator<const int*>, int*>();
-
-    test<forward_iterator<const int*>, forward_iterator<const int*>, output_iterator<int*> >();
-    test<forward_iterator<const int*>, forward_iterator<const int*>, forward_iterator<int*> >();
-    test<forward_iterator<const int*>, forward_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<forward_iterator<const int*>, forward_iterator<const int*>, random_access_iterator<int*> >();
-    test<forward_iterator<const int*>, forward_iterator<const int*>, int*>();
-
-    test<forward_iterator<const int*>, bidirectional_iterator<const int*>, output_iterator<int*> >();
-    test<forward_iterator<const int*>, bidirectional_iterator<const int*>, forward_iterator<int*> >();
-    test<forward_iterator<const int*>, bidirectional_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<forward_iterator<const int*>, bidirectional_iterator<const int*>, random_access_iterator<int*> >();
-    test<forward_iterator<const int*>, bidirectional_iterator<const int*>, int*>();
-
-    test<forward_iterator<const int*>, random_access_iterator<const int*>, output_iterator<int*> >();
-    test<forward_iterator<const int*>, random_access_iterator<const int*>, forward_iterator<int*> >();
-    test<forward_iterator<const int*>, random_access_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<forward_iterator<const int*>, random_access_iterator<const int*>, random_access_iterator<int*> >();
-    test<forward_iterator<const int*>, random_access_iterator<const int*>, int*>();
-
-    test<forward_iterator<const int*>, const int*, output_iterator<int*> >();
-    test<forward_iterator<const int*>, const int*, forward_iterator<int*> >();
-    test<forward_iterator<const int*>, const int*, bidirectional_iterator<int*> >();
-    test<forward_iterator<const int*>, const int*, random_access_iterator<int*> >();
-    test<forward_iterator<const int*>, const int*, int*>();
-
-    test<bidirectional_iterator<const int*>, input_iterator<const int*>, output_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, input_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, input_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, input_iterator<const int*>, random_access_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, input_iterator<const int*>, int*>();
-
-    test<bidirectional_iterator<const int*>, forward_iterator<const int*>, output_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, forward_iterator<const int*>, forward_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, forward_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, forward_iterator<const int*>, random_access_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, forward_iterator<const int*>, int*>();
-
-    test<bidirectional_iterator<const int*>, bidirectional_iterator<const int*>, output_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, bidirectional_iterator<const int*>, forward_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, bidirectional_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, bidirectional_iterator<const int*>, random_access_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, bidirectional_iterator<const int*>, int*>();
-
-    test<bidirectional_iterator<const int*>, random_access_iterator<const int*>, output_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, random_access_iterator<const int*>, forward_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, random_access_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, random_access_iterator<const int*>, random_access_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, random_access_iterator<const int*>, int*>();
-
-    test<bidirectional_iterator<const int*>, const int*, output_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, const int*, forward_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, const int*, bidirectional_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, const int*, random_access_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, const int*, int*>();
-
-    test<random_access_iterator<const int*>, input_iterator<const int*>, output_iterator<int*> >();
-    test<random_access_iterator<const int*>, input_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<random_access_iterator<const int*>, input_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<random_access_iterator<const int*>, input_iterator<const int*>, random_access_iterator<int*> >();
-    test<random_access_iterator<const int*>, input_iterator<const int*>, int*>();
-
-    test<random_access_iterator<const int*>, forward_iterator<const int*>, output_iterator<int*> >();
-    test<random_access_iterator<const int*>, forward_iterator<const int*>, forward_iterator<int*> >();
-    test<random_access_iterator<const int*>, forward_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<random_access_iterator<const int*>, forward_iterator<const int*>, random_access_iterator<int*> >();
-    test<random_access_iterator<const int*>, forward_iterator<const int*>, int*>();
-
-    test<random_access_iterator<const int*>, bidirectional_iterator<const int*>, output_iterator<int*> >();
-    test<random_access_iterator<const int*>, bidirectional_iterator<const int*>, forward_iterator<int*> >();
-    test<random_access_iterator<const int*>, bidirectional_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<random_access_iterator<const int*>, bidirectional_iterator<const int*>, random_access_iterator<int*> >();
-    test<random_access_iterator<const int*>, bidirectional_iterator<const int*>, int*>();
-
-    test<random_access_iterator<const int*>, random_access_iterator<const int*>, output_iterator<int*> >();
-    test<random_access_iterator<const int*>, random_access_iterator<const int*>, forward_iterator<int*> >();
-    test<random_access_iterator<const int*>, random_access_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<random_access_iterator<const int*>, random_access_iterator<const int*>, random_access_iterator<int*> >();
-    test<random_access_iterator<const int*>, random_access_iterator<const int*>, int*>();
-
-    test<random_access_iterator<const int*>, const int*, output_iterator<int*> >();
-    test<random_access_iterator<const int*>, const int*, forward_iterator<int*> >();
-    test<random_access_iterator<const int*>, const int*, bidirectional_iterator<int*> >();
-    test<random_access_iterator<const int*>, const int*, random_access_iterator<int*> >();
-    test<random_access_iterator<const int*>, const int*, int*>();
-
-    test<const int*, input_iterator<const int*>, output_iterator<int*> >();
-    test<const int*, input_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<const int*, input_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<const int*, input_iterator<const int*>, random_access_iterator<int*> >();
-    test<const int*, input_iterator<const int*>, int*>();
+    test4<T, Iter1, Iter2, output_iterator<T*> >();
+    test4<T, Iter1, Iter2, forward_iterator<T*> >();
+    test4<T, Iter1, Iter2, bidirectional_iterator<T*> >();
+    test4<T, Iter1, Iter2, random_access_iterator<T*> >();
+    test4<T, Iter1, Iter2, T*>();
+}
 
-    test<const int*, forward_iterator<const int*>, output_iterator<int*> >();
-    test<const int*, forward_iterator<const int*>, forward_iterator<int*> >();
-    test<const int*, forward_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<const int*, forward_iterator<const int*>, random_access_iterator<int*> >();
-    test<const int*, forward_iterator<const int*>, int*>();
+template<class T, class Iter1>
+TEST_CONSTEXPR_CXX20 void test2()
+{
+    test3<T, Iter1, input_iterator<const T*> >();
+    test3<T, Iter1, forward_iterator<const T*> >();
+    test3<T, Iter1, bidirectional_iterator<const T*> >();
+    test3<T, Iter1, random_access_iterator<const T*> >();
+    test3<T, Iter1, const T*>();
+}
 
-    test<const int*, bidirectional_iterator<const int*>, output_iterator<int*> >();
-    test<const int*, bidirectional_iterator<const int*>, forward_iterator<int*> >();
-    test<const int*, bidirectional_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<const int*, bidirectional_iterator<const int*>, random_access_iterator<int*> >();
-    test<const int*, bidirectional_iterator<const int*>, int*>();
+template<class T>
+TEST_CONSTEXPR_CXX20 void test1()
+{
+    test2<T, input_iterator<const T*> >();
+    test2<T, forward_iterator<const T*> >();
+    test2<T, bidirectional_iterator<const T*> >();
+    test2<T, random_access_iterator<const T*> >();
+    test2<T, const T*>();
+}
 
-    test<const int*, random_access_iterator<const int*>, output_iterator<int*> >();
-    test<const int*, random_access_iterator<const int*>, forward_iterator<int*> >();
-    test<const int*, random_access_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<const int*, random_access_iterator<const int*>, random_access_iterator<int*> >();
-    test<const int*, random_access_iterator<const int*>, int*>();
+TEST_CONSTEXPR_CXX20 bool test()
+{
+    test1<TrivialSortableWithComp>();
+    test1<NonTrivialSortableWithComp>();
+    return true;
+}
 
-    test<const int*, const int*, output_iterator<int*> >();
-    test<const int*, const int*, forward_iterator<int*> >();
-    test<const int*, const int*, bidirectional_iterator<int*> >();
-    test<const int*, const int*, random_access_iterator<int*> >();
-    test<const int*, const int*, int*>();
+int main(int, char**)
+{
+    test();
+#if TEST_STD_VER > 17
+    static_assert(test());
+#endif
 
-  return 0;
+    return 0;
 }
diff --git a/libcxx/test/std/algorithms/alg.sorting/alg.set.operations/set.intersection/set_intersection.pass.cpp b/libcxx/test/std/algorithms/alg.sorting/alg.set.operations/set.intersection/set_intersection.pass.cpp
--- a/libcxx/test/std/algorithms/alg.sorting/alg.set.operations/set.intersection/set_intersection.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.sorting/alg.set.operations/set.intersection/set_intersection.pass.cpp
@@ -22,201 +22,76 @@
 
 #include "test_macros.h"
 #include "test_iterators.h"
+#include "../../sortable_helpers.h"
 
-#if TEST_STD_VER > 17
-TEST_CONSTEXPR bool test_constexpr() {
-    const int ia[] = {1, 2, 2, 3, 3, 3, 4, 4, 4, 4};
-    const int ib[] = {2, 4, 4, 6};
-          int results[std::size(ia)] = {0};
-
-    auto it = std::set_intersection(std::begin(ia), std::end(ia),
-                                    std::begin(ib), std::end(ib), std::begin(results));
-
-    return std::includes(std::begin(ia), std::end(ia), std::begin(results), it)
-        && std::includes(std::begin(ib), std::end(ib), std::begin(results), it)
-        && std::is_sorted(std::begin(results), it)
-        && std::all_of(it, std::end(results), [](int a) {return a == 0; })
-           ;
+template<class T, class Iter1, class Iter2, class OutIter>
+TEST_CONSTEXPR_CXX20 void test4()
+{
+    const T a[] = {11, 33, 31, 41};
+    const T b[] = {22, 32, 43, 42, 52};
+    {
+        T result[20] = {};
+        T expected[] = {33, 41};
+        OutIter end = std::set_intersection(Iter1(a), Iter1(a+4), Iter2(b), Iter2(b+5), OutIter(result));
+        assert(std::lexicographical_compare(result, base(end), expected, expected+2, T::less) == 0);
+        for (const T *it = base(end); it != result+20; ++it) {
+            assert(it->value == 0);
+        }
     }
-#endif
-
+    {
+        T result[20] = {};
+        T expected[] = {32, 42};
+        OutIter end = std::set_intersection(Iter1(b), Iter1(b+5), Iter2(a), Iter2(a+4), OutIter(result));
+        assert(std::lexicographical_compare(result, base(end), expected, expected+2, T::less) == 0);
+        for (const T *it = base(end); it != result+20; ++it) {
+            assert(it->value == 0);
+        }
+    }
+}
 
-template <class Iter1, class Iter2, class OutIter>
-void
-test()
+template<class T, class Iter1, class Iter2>
+TEST_CONSTEXPR_CXX20 void test3()
 {
-    int ia[] = {1, 2, 2, 3, 3, 3, 4, 4, 4, 4};
-    const int sa = sizeof(ia)/sizeof(ia[0]);
-    int ib[] = {2, 4, 4, 6};
-    const int sb = sizeof(ib)/sizeof(ib[0]);
-    int ic[20];
-    int ir[] = {2, 4, 4};
-    const int sr = sizeof(ir)/sizeof(ir[0]);
-    OutIter ce = std::set_intersection(Iter1(ia), Iter1(ia+sa),
-                                       Iter2(ib), Iter2(ib+sb), OutIter(ic));
-    assert(base(ce) - ic == sr);
-    assert(std::lexicographical_compare(ic, base(ce), ir, ir+sr) == 0);
-    ce = std::set_intersection(Iter1(ib), Iter1(ib+sb),
-                               Iter2(ia), Iter2(ia+sa), OutIter(ic));
-    assert(base(ce) - ic == sr);
-    assert(std::lexicographical_compare(ic, base(ce), ir, ir+sr) == 0);
+    test4<T, Iter1, Iter2, output_iterator<T*> >();
+    test4<T, Iter1, Iter2, forward_iterator<T*> >();
+    test4<T, Iter1, Iter2, bidirectional_iterator<T*> >();
+    test4<T, Iter1, Iter2, random_access_iterator<T*> >();
+    test4<T, Iter1, Iter2, T*>();
 }
 
-int main(int, char**)
+template<class T, class Iter1>
+TEST_CONSTEXPR_CXX20 void test2()
 {
-    test<input_iterator<const int*>, input_iterator<const int*>, output_iterator<int*> >();
-    test<input_iterator<const int*>, input_iterator<const int*>, forward_iterator<int*> >();
-    test<input_iterator<const int*>, input_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<input_iterator<const int*>, input_iterator<const int*>, random_access_iterator<int*> >();
-    test<input_iterator<const int*>, input_iterator<const int*>, int*>();
-
-    test<input_iterator<const int*>, forward_iterator<const int*>, output_iterator<int*> >();
-    test<input_iterator<const int*>, forward_iterator<const int*>, forward_iterator<int*> >();
-    test<input_iterator<const int*>, forward_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<input_iterator<const int*>, forward_iterator<const int*>, random_access_iterator<int*> >();
-    test<input_iterator<const int*>, forward_iterator<const int*>, int*>();
-
-    test<input_iterator<const int*>, bidirectional_iterator<const int*>, output_iterator<int*> >();
-    test<input_iterator<const int*>, bidirectional_iterator<const int*>, forward_iterator<int*> >();
-    test<input_iterator<const int*>, bidirectional_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<input_iterator<const int*>, bidirectional_iterator<const int*>, random_access_iterator<int*> >();
-    test<input_iterator<const int*>, bidirectional_iterator<const int*>, int*>();
-
-    test<input_iterator<const int*>, random_access_iterator<const int*>, output_iterator<int*> >();
-    test<input_iterator<const int*>, random_access_iterator<const int*>, forward_iterator<int*> >();
-    test<input_iterator<const int*>, random_access_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<input_iterator<const int*>, random_access_iterator<const int*>, random_access_iterator<int*> >();
-    test<input_iterator<const int*>, random_access_iterator<const int*>, int*>();
-
-    test<input_iterator<const int*>, const int*, output_iterator<int*> >();
-    test<input_iterator<const int*>, const int*, forward_iterator<int*> >();
-    test<input_iterator<const int*>, const int*, bidirectional_iterator<int*> >();
-    test<input_iterator<const int*>, const int*, random_access_iterator<int*> >();
-    test<input_iterator<const int*>, const int*, int*>();
-
-    test<forward_iterator<const int*>, input_iterator<const int*>, output_iterator<int*> >();
-    test<forward_iterator<const int*>, input_iterator<const int*>, forward_iterator<int*> >();
-    test<forward_iterator<const int*>, input_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<forward_iterator<const int*>, input_iterator<const int*>, random_access_iterator<int*> >();
-    test<forward_iterator<const int*>, input_iterator<const int*>, int*>();
-
-    test<forward_iterator<const int*>, forward_iterator<const int*>, output_iterator<int*> >();
-    test<forward_iterator<const int*>, forward_iterator<const int*>, forward_iterator<int*> >();
-    test<forward_iterator<const int*>, forward_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<forward_iterator<const int*>, forward_iterator<const int*>, random_access_iterator<int*> >();
-    test<forward_iterator<const int*>, forward_iterator<const int*>, int*>();
-
-    test<forward_iterator<const int*>, bidirectional_iterator<const int*>, output_iterator<int*> >();
-    test<forward_iterator<const int*>, bidirectional_iterator<const int*>, forward_iterator<int*> >();
-    test<forward_iterator<const int*>, bidirectional_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<forward_iterator<const int*>, bidirectional_iterator<const int*>, random_access_iterator<int*> >();
-    test<forward_iterator<const int*>, bidirectional_iterator<const int*>, int*>();
-
-    test<forward_iterator<const int*>, random_access_iterator<const int*>, output_iterator<int*> >();
-    test<forward_iterator<const int*>, random_access_iterator<const int*>, forward_iterator<int*> >();
-    test<forward_iterator<const int*>, random_access_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<forward_iterator<const int*>, random_access_iterator<const int*>, random_access_iterator<int*> >();
-    test<forward_iterator<const int*>, random_access_iterator<const int*>, int*>();
-
-    test<forward_iterator<const int*>, const int*, output_iterator<int*> >();
-    test<forward_iterator<const int*>, const int*, forward_iterator<int*> >();
-    test<forward_iterator<const int*>, const int*, bidirectional_iterator<int*> >();
-    test<forward_iterator<const int*>, const int*, random_access_iterator<int*> >();
-    test<forward_iterator<const int*>, const int*, int*>();
-
-    test<bidirectional_iterator<const int*>, input_iterator<const int*>, output_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, input_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, input_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, input_iterator<const int*>, random_access_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, input_iterator<const int*>, int*>();
-
-    test<bidirectional_iterator<const int*>, forward_iterator<const int*>, output_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, forward_iterator<const int*>, forward_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, forward_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, forward_iterator<const int*>, random_access_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, forward_iterator<const int*>, int*>();
-
-    test<bidirectional_iterator<const int*>, bidirectional_iterator<const int*>, output_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, bidirectional_iterator<const int*>, forward_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, bidirectional_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, bidirectional_iterator<const int*>, random_access_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, bidirectional_iterator<const int*>, int*>();
-
-    test<bidirectional_iterator<const int*>, random_access_iterator<const int*>, output_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, random_access_iterator<const int*>, forward_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, random_access_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, random_access_iterator<const int*>, random_access_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, random_access_iterator<const int*>, int*>();
-
-    test<bidirectional_iterator<const int*>, const int*, output_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, const int*, forward_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, const int*, bidirectional_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, const int*, random_access_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, const int*, int*>();
-
-    test<random_access_iterator<const int*>, input_iterator<const int*>, output_iterator<int*> >();
-    test<random_access_iterator<const int*>, input_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<random_access_iterator<const int*>, input_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<random_access_iterator<const int*>, input_iterator<const int*>, random_access_iterator<int*> >();
-    test<random_access_iterator<const int*>, input_iterator<const int*>, int*>();
-
-    test<random_access_iterator<const int*>, forward_iterator<const int*>, output_iterator<int*> >();
-    test<random_access_iterator<const int*>, forward_iterator<const int*>, forward_iterator<int*> >();
-    test<random_access_iterator<const int*>, forward_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<random_access_iterator<const int*>, forward_iterator<const int*>, random_access_iterator<int*> >();
-    test<random_access_iterator<const int*>, forward_iterator<const int*>, int*>();
-
-    test<random_access_iterator<const int*>, bidirectional_iterator<const int*>, output_iterator<int*> >();
-    test<random_access_iterator<const int*>, bidirectional_iterator<const int*>, forward_iterator<int*> >();
-    test<random_access_iterator<const int*>, bidirectional_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<random_access_iterator<const int*>, bidirectional_iterator<const int*>, random_access_iterator<int*> >();
-    test<random_access_iterator<const int*>, bidirectional_iterator<const int*>, int*>();
-
-    test<random_access_iterator<const int*>, random_access_iterator<const int*>, output_iterator<int*> >();
-    test<random_access_iterator<const int*>, random_access_iterator<const int*>, forward_iterator<int*> >();
-    test<random_access_iterator<const int*>, random_access_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<random_access_iterator<const int*>, random_access_iterator<const int*>, random_access_iterator<int*> >();
-    test<random_access_iterator<const int*>, random_access_iterator<const int*>, int*>();
-
-    test<random_access_iterator<const int*>, const int*, output_iterator<int*> >();
-    test<random_access_iterator<const int*>, const int*, forward_iterator<int*> >();
-    test<random_access_iterator<const int*>, const int*, bidirectional_iterator<int*> >();
-    test<random_access_iterator<const int*>, const int*, random_access_iterator<int*> >();
-    test<random_access_iterator<const int*>, const int*, int*>();
-
-    test<const int*, input_iterator<const int*>, output_iterator<int*> >();
-    test<const int*, input_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<const int*, input_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<const int*, input_iterator<const int*>, random_access_iterator<int*> >();
-    test<const int*, input_iterator<const int*>, int*>();
-
-    test<const int*, forward_iterator<const int*>, output_iterator<int*> >();
-    test<const int*, forward_iterator<const int*>, forward_iterator<int*> >();
-    test<const int*, forward_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<const int*, forward_iterator<const int*>, random_access_iterator<int*> >();
-    test<const int*, forward_iterator<const int*>, int*>();
-
-    test<const int*, bidirectional_iterator<const int*>, output_iterator<int*> >();
-    test<const int*, bidirectional_iterator<const int*>, forward_iterator<int*> >();
-    test<const int*, bidirectional_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<const int*, bidirectional_iterator<const int*>, random_access_iterator<int*> >();
-    test<const int*, bidirectional_iterator<const int*>, int*>();
+    test3<T, Iter1, input_iterator<const T*> >();
+    test3<T, Iter1, forward_iterator<const T*> >();
+    test3<T, Iter1, bidirectional_iterator<const T*> >();
+    test3<T, Iter1, random_access_iterator<const T*> >();
+    test3<T, Iter1, const T*>();
+}
 
-    test<const int*, random_access_iterator<const int*>, output_iterator<int*> >();
-    test<const int*, random_access_iterator<const int*>, forward_iterator<int*> >();
-    test<const int*, random_access_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<const int*, random_access_iterator<const int*>, random_access_iterator<int*> >();
-    test<const int*, random_access_iterator<const int*>, int*>();
+template<class T>
+TEST_CONSTEXPR_CXX20 void test1()
+{
+    test2<T, input_iterator<const T*> >();
+    test2<T, forward_iterator<const T*> >();
+    test2<T, bidirectional_iterator<const T*> >();
+    test2<T, random_access_iterator<const T*> >();
+    test2<T, const T*>();
+}
 
-    test<const int*, const int*, output_iterator<int*> >();
-    test<const int*, const int*, forward_iterator<int*> >();
-    test<const int*, const int*, bidirectional_iterator<int*> >();
-    test<const int*, const int*, random_access_iterator<int*> >();
-    test<const int*, const int*, int*>();
+TEST_CONSTEXPR_CXX20 bool test()
+{
+    test1<TrivialSortable>();
+    test1<NonTrivialSortable>();
+    return true;
+}
 
+int main(int, char**)
+{
+    test();
 #if TEST_STD_VER > 17
-    static_assert(test_constexpr());
+    static_assert(test());
 #endif
 
-  return 0;
+    return 0;
 }
diff --git a/libcxx/test/std/algorithms/alg.sorting/alg.set.operations/set.intersection/set_intersection_comp.pass.cpp b/libcxx/test/std/algorithms/alg.sorting/alg.set.operations/set.intersection/set_intersection_comp.pass.cpp
--- a/libcxx/test/std/algorithms/alg.sorting/alg.set.operations/set.intersection/set_intersection_comp.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.sorting/alg.set.operations/set.intersection/set_intersection_comp.pass.cpp
@@ -19,207 +19,80 @@
 //                    OutIter result, Compare comp);
 
 #include <algorithm>
-#include <functional>
 #include <cassert>
 
 #include "test_macros.h"
 #include "test_iterators.h"
+#include "../../sortable_helpers.h"
 
-#if TEST_STD_VER > 17
-TEST_CONSTEXPR bool test_constexpr() {
-    const int ia[] = {1, 2, 2, 3, 3, 3, 4, 4, 4, 4};
-    const int ib[] = {2, 4, 4, 6};
-          int results[std::size(ia)] = {0};
-
-    auto comp = [](int a, int b) {return a < b; };
-    auto it = std::set_intersection(std::begin(ia), std::end(ia),
-                                    std::begin(ib), std::end(ib), std::begin(results), comp);
-
-    return std::includes(std::begin(ia), std::end(ia), std::begin(results), it)
-        && std::includes(std::begin(ib), std::end(ib), std::begin(results), it)
-        && std::is_sorted(std::begin(results), it, comp)
-        && std::all_of(it, std::end(results), [](int a) {return a == 0; })
-           ;
+template<class T, class Iter1, class Iter2, class OutIter>
+TEST_CONSTEXPR_CXX20 void test4()
+{
+    const T a[] = {11, 33, 31, 41};
+    const T b[] = {22, 32, 43, 42, 52};
+    {
+        T result[20] = {};
+        T expected[] = {33, 41};
+        OutIter end = std::set_intersection(Iter1(a), Iter1(a+4), Iter2(b), Iter2(b+5), OutIter(result), typename T::Comparator());
+        assert(std::lexicographical_compare(result, base(end), expected, expected+2, T::less) == 0);
+        for (const T *it = base(end); it != result+20; ++it) {
+            assert(it->value == 0);
+        }
     }
-#endif
-
+    {
+        T result[20] = {};
+        T expected[] = {32, 42};
+        OutIter end = std::set_intersection(Iter1(b), Iter1(b+5), Iter2(a), Iter2(a+4), OutIter(result), typename T::Comparator());
+        assert(std::lexicographical_compare(result, base(end), expected, expected+2, T::less) == 0);
+        for (const T *it = base(end); it != result+20; ++it) {
+            assert(it->value == 0);
+        }
+    }
+}
 
-template <class Iter1, class Iter2, class OutIter>
-void
-test()
+template<class T, class Iter1, class Iter2>
+TEST_CONSTEXPR_CXX20 void test3()
 {
-    int ia[] = {1, 2, 2, 3, 3, 3, 4, 4, 4, 4};
-    const int sa = sizeof(ia)/sizeof(ia[0]);
-    int ib[] = {2, 4, 4, 6};
-    const int sb = sizeof(ib)/sizeof(ib[0]);
-    int ic[20];
-    int ir[] = {2, 4, 4};
-    const int sr = sizeof(ir)/sizeof(ir[0]);
-    OutIter ce = std::set_intersection(Iter1(ia), Iter1(ia+sa),
-                                       Iter2(ib), Iter2(ib+sb), OutIter(ic), std::less<int>());
-    assert(base(ce) - ic == sr);
-    assert(std::lexicographical_compare(ic, base(ce), ir, ir+sr) == 0);
-    ce = std::set_intersection(Iter1(ib), Iter1(ib+sb),
-                               Iter2(ia), Iter2(ia+sa), OutIter(ic), std::less<int>());
-    assert(base(ce) - ic == sr);
-    assert(std::lexicographical_compare(ic, base(ce), ir, ir+sr) == 0);
+    test4<T, Iter1, Iter2, output_iterator<T*> >();
+    test4<T, Iter1, Iter2, forward_iterator<T*> >();
+    test4<T, Iter1, Iter2, bidirectional_iterator<T*> >();
+    test4<T, Iter1, Iter2, random_access_iterator<T*> >();
+    test4<T, Iter1, Iter2, T*>();
 }
 
-int main(int, char**)
+template<class T, class Iter1>
+TEST_CONSTEXPR_CXX20 void test2()
 {
-    test<input_iterator<const int*>, input_iterator<const int*>, output_iterator<int*> >();
-    test<input_iterator<const int*>, input_iterator<const int*>, forward_iterator<int*> >();
-    test<input_iterator<const int*>, input_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<input_iterator<const int*>, input_iterator<const int*>, random_access_iterator<int*> >();
-    test<input_iterator<const int*>, input_iterator<const int*>, int*>();
-
-    test<input_iterator<const int*>, forward_iterator<const int*>, output_iterator<int*> >();
-    test<input_iterator<const int*>, forward_iterator<const int*>, forward_iterator<int*> >();
-    test<input_iterator<const int*>, forward_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<input_iterator<const int*>, forward_iterator<const int*>, random_access_iterator<int*> >();
-    test<input_iterator<const int*>, forward_iterator<const int*>, int*>();
-
-    test<input_iterator<const int*>, bidirectional_iterator<const int*>, output_iterator<int*> >();
-    test<input_iterator<const int*>, bidirectional_iterator<const int*>, forward_iterator<int*> >();
-    test<input_iterator<const int*>, bidirectional_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<input_iterator<const int*>, bidirectional_iterator<const int*>, random_access_iterator<int*> >();
-    test<input_iterator<const int*>, bidirectional_iterator<const int*>, int*>();
-
-    test<input_iterator<const int*>, random_access_iterator<const int*>, output_iterator<int*> >();
-    test<input_iterator<const int*>, random_access_iterator<const int*>, forward_iterator<int*> >();
-    test<input_iterator<const int*>, random_access_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<input_iterator<const int*>, random_access_iterator<const int*>, random_access_iterator<int*> >();
-    test<input_iterator<const int*>, random_access_iterator<const int*>, int*>();
-
-    test<input_iterator<const int*>, const int*, output_iterator<int*> >();
-    test<input_iterator<const int*>, const int*, forward_iterator<int*> >();
-    test<input_iterator<const int*>, const int*, bidirectional_iterator<int*> >();
-    test<input_iterator<const int*>, const int*, random_access_iterator<int*> >();
-    test<input_iterator<const int*>, const int*, int*>();
-
-    test<forward_iterator<const int*>, input_iterator<const int*>, output_iterator<int*> >();
-    test<forward_iterator<const int*>, input_iterator<const int*>, forward_iterator<int*> >();
-    test<forward_iterator<const int*>, input_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<forward_iterator<const int*>, input_iterator<const int*>, random_access_iterator<int*> >();
-    test<forward_iterator<const int*>, input_iterator<const int*>, int*>();
-
-    test<forward_iterator<const int*>, forward_iterator<const int*>, output_iterator<int*> >();
-    test<forward_iterator<const int*>, forward_iterator<const int*>, forward_iterator<int*> >();
-    test<forward_iterator<const int*>, forward_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<forward_iterator<const int*>, forward_iterator<const int*>, random_access_iterator<int*> >();
-    test<forward_iterator<const int*>, forward_iterator<const int*>, int*>();
-
-    test<forward_iterator<const int*>, bidirectional_iterator<const int*>, output_iterator<int*> >();
-    test<forward_iterator<const int*>, bidirectional_iterator<const int*>, forward_iterator<int*> >();
-    test<forward_iterator<const int*>, bidirectional_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<forward_iterator<const int*>, bidirectional_iterator<const int*>, random_access_iterator<int*> >();
-    test<forward_iterator<const int*>, bidirectional_iterator<const int*>, int*>();
-
-    test<forward_iterator<const int*>, random_access_iterator<const int*>, output_iterator<int*> >();
-    test<forward_iterator<const int*>, random_access_iterator<const int*>, forward_iterator<int*> >();
-    test<forward_iterator<const int*>, random_access_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<forward_iterator<const int*>, random_access_iterator<const int*>, random_access_iterator<int*> >();
-    test<forward_iterator<const int*>, random_access_iterator<const int*>, int*>();
-
-    test<forward_iterator<const int*>, const int*, output_iterator<int*> >();
-    test<forward_iterator<const int*>, const int*, forward_iterator<int*> >();
-    test<forward_iterator<const int*>, const int*, bidirectional_iterator<int*> >();
-    test<forward_iterator<const int*>, const int*, random_access_iterator<int*> >();
-    test<forward_iterator<const int*>, const int*, int*>();
-
-    test<bidirectional_iterator<const int*>, input_iterator<const int*>, output_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, input_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, input_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, input_iterator<const int*>, random_access_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, input_iterator<const int*>, int*>();
-
-    test<bidirectional_iterator<const int*>, forward_iterator<const int*>, output_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, forward_iterator<const int*>, forward_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, forward_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, forward_iterator<const int*>, random_access_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, forward_iterator<const int*>, int*>();
-
-    test<bidirectional_iterator<const int*>, bidirectional_iterator<const int*>, output_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, bidirectional_iterator<const int*>, forward_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, bidirectional_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, bidirectional_iterator<const int*>, random_access_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, bidirectional_iterator<const int*>, int*>();
-
-    test<bidirectional_iterator<const int*>, random_access_iterator<const int*>, output_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, random_access_iterator<const int*>, forward_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, random_access_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, random_access_iterator<const int*>, random_access_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, random_access_iterator<const int*>, int*>();
-
-    test<bidirectional_iterator<const int*>, const int*, output_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, const int*, forward_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, const int*, bidirectional_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, const int*, random_access_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, const int*, int*>();
-
-    test<random_access_iterator<const int*>, input_iterator<const int*>, output_iterator<int*> >();
-    test<random_access_iterator<const int*>, input_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<random_access_iterator<const int*>, input_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<random_access_iterator<const int*>, input_iterator<const int*>, random_access_iterator<int*> >();
-    test<random_access_iterator<const int*>, input_iterator<const int*>, int*>();
-
-    test<random_access_iterator<const int*>, forward_iterator<const int*>, output_iterator<int*> >();
-    test<random_access_iterator<const int*>, forward_iterator<const int*>, forward_iterator<int*> >();
-    test<random_access_iterator<const int*>, forward_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<random_access_iterator<const int*>, forward_iterator<const int*>, random_access_iterator<int*> >();
-    test<random_access_iterator<const int*>, forward_iterator<const int*>, int*>();
-
-    test<random_access_iterator<const int*>, bidirectional_iterator<const int*>, output_iterator<int*> >();
-    test<random_access_iterator<const int*>, bidirectional_iterator<const int*>, forward_iterator<int*> >();
-    test<random_access_iterator<const int*>, bidirectional_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<random_access_iterator<const int*>, bidirectional_iterator<const int*>, random_access_iterator<int*> >();
-    test<random_access_iterator<const int*>, bidirectional_iterator<const int*>, int*>();
-
-    test<random_access_iterator<const int*>, random_access_iterator<const int*>, output_iterator<int*> >();
-    test<random_access_iterator<const int*>, random_access_iterator<const int*>, forward_iterator<int*> >();
-    test<random_access_iterator<const int*>, random_access_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<random_access_iterator<const int*>, random_access_iterator<const int*>, random_access_iterator<int*> >();
-    test<random_access_iterator<const int*>, random_access_iterator<const int*>, int*>();
-
-    test<random_access_iterator<const int*>, const int*, output_iterator<int*> >();
-    test<random_access_iterator<const int*>, const int*, forward_iterator<int*> >();
-    test<random_access_iterator<const int*>, const int*, bidirectional_iterator<int*> >();
-    test<random_access_iterator<const int*>, const int*, random_access_iterator<int*> >();
-    test<random_access_iterator<const int*>, const int*, int*>();
-
-    test<const int*, input_iterator<const int*>, output_iterator<int*> >();
-    test<const int*, input_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<const int*, input_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<const int*, input_iterator<const int*>, random_access_iterator<int*> >();
-    test<const int*, input_iterator<const int*>, int*>();
-
-    test<const int*, forward_iterator<const int*>, output_iterator<int*> >();
-    test<const int*, forward_iterator<const int*>, forward_iterator<int*> >();
-    test<const int*, forward_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<const int*, forward_iterator<const int*>, random_access_iterator<int*> >();
-    test<const int*, forward_iterator<const int*>, int*>();
-
-    test<const int*, bidirectional_iterator<const int*>, output_iterator<int*> >();
-    test<const int*, bidirectional_iterator<const int*>, forward_iterator<int*> >();
-    test<const int*, bidirectional_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<const int*, bidirectional_iterator<const int*>, random_access_iterator<int*> >();
-    test<const int*, bidirectional_iterator<const int*>, int*>();
+    test3<T, Iter1, input_iterator<const T*> >();
+    test3<T, Iter1, forward_iterator<const T*> >();
+    test3<T, Iter1, bidirectional_iterator<const T*> >();
+    test3<T, Iter1, random_access_iterator<const T*> >();
+    test3<T, Iter1, const T*>();
+}
 
-    test<const int*, random_access_iterator<const int*>, output_iterator<int*> >();
-    test<const int*, random_access_iterator<const int*>, forward_iterator<int*> >();
-    test<const int*, random_access_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<const int*, random_access_iterator<const int*>, random_access_iterator<int*> >();
-    test<const int*, random_access_iterator<const int*>, int*>();
+template<class T>
+TEST_CONSTEXPR_CXX20 void test1()
+{
+    test2<T, input_iterator<const T*> >();
+    test2<T, forward_iterator<const T*> >();
+    test2<T, bidirectional_iterator<const T*> >();
+    test2<T, random_access_iterator<const T*> >();
+    test2<T, const T*>();
+}
 
-    test<const int*, const int*, output_iterator<int*> >();
-    test<const int*, const int*, forward_iterator<int*> >();
-    test<const int*, const int*, bidirectional_iterator<int*> >();
-    test<const int*, const int*, random_access_iterator<int*> >();
-    test<const int*, const int*, int*>();
+TEST_CONSTEXPR_CXX20 bool test()
+{
+    test1<TrivialSortableWithComp>();
+    test1<NonTrivialSortableWithComp>();
+    return true;
+}
 
+int main(int, char**)
+{
+    test();
 #if TEST_STD_VER > 17
-    static_assert(test_constexpr());
+    static_assert(test());
 #endif
 
-  return 0;
+    return 0;
 }
diff --git a/libcxx/test/std/algorithms/alg.sorting/alg.set.operations/set.symmetric.difference/set_symmetric_difference.pass.cpp b/libcxx/test/std/algorithms/alg.sorting/alg.set.operations/set.symmetric.difference/set_symmetric_difference.pass.cpp
--- a/libcxx/test/std/algorithms/alg.sorting/alg.set.operations/set.symmetric.difference/set_symmetric_difference.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.sorting/alg.set.operations/set.symmetric.difference/set_symmetric_difference.pass.cpp
@@ -6,6 +6,8 @@
 //
 //===----------------------------------------------------------------------===//
 
+// UNSUPPORTED: clang-8
+
 // <algorithm>
 
 // template<InputIterator InIter1, InputIterator InIter2, typename OutIter>
@@ -13,9 +15,8 @@
 //         && OutputIterator<OutIter, InIter2::reference>
 //         && HasLess<InIter2::value_type, InIter1::value_type>
 //         && HasLess<InIter1::value_type, InIter2::value_type>
-//   OutIter
-//   set_symmetric_difference(InIter1 first1, InIter1 last1,
-//                            InIter2 first2, InIter2 last2,
+//   constexpr OutIter       // constexpr after C++17
+//   set_symmetric_difference(InIter1 first1, InIter1 last1, InIter2 first2, InIter2 last2,
 //                            OutIter result);
 
 #include <algorithm>
@@ -23,179 +24,76 @@
 
 #include "test_macros.h"
 #include "test_iterators.h"
+#include "../../sortable_helpers.h"
 
-template <class Iter1, class Iter2, class OutIter>
-void
-test()
+template<class T, class Iter1, class Iter2, class OutIter>
+TEST_CONSTEXPR_CXX20 void test4()
 {
-    int ia[] = {1, 2, 2, 3, 3, 3, 4, 4, 4, 4};
-    const int sa = sizeof(ia)/sizeof(ia[0]);
-    int ib[] = {2, 4, 4, 6};
-    const int sb = sizeof(ib)/sizeof(ib[0]);
-    int ic[20];
-    int ir[] = {1, 2, 3, 3, 3, 4, 4, 6};
-    const int sr = sizeof(ir)/sizeof(ir[0]);
-    OutIter ce = std::set_symmetric_difference(Iter1(ia), Iter1(ia+sa),
-                                               Iter2(ib), Iter2(ib+sb), OutIter(ic));
-    assert(base(ce) - ic == sr);
-    assert(std::lexicographical_compare(ic, base(ce), ir, ir+sr) == 0);
-    ce = std::set_symmetric_difference(Iter1(ib), Iter1(ib+sb),
-                                       Iter2(ia), Iter2(ia+sa), OutIter(ic));
-    assert(base(ce) - ic == sr);
-    assert(std::lexicographical_compare(ic, base(ce), ir, ir+sr) == 0);
+    const T a[] = {11, 33, 31, 41};
+    const T b[] = {22, 32, 43, 42, 52};
+    {
+        T result[20] = {};
+        T expected[] = {11, 22, 31, 42, 52};
+        OutIter end = std::set_symmetric_difference(Iter1(a), Iter1(a+4), Iter2(b), Iter2(b+5), OutIter(result));
+        assert(std::lexicographical_compare(result, base(end), expected, expected+5, T::less) == 0);
+        for (const T *it = base(end); it != result+20; ++it) {
+            assert(it->value == 0);
+        }
+    }
+    {
+        T result[20] = {};
+        T expected[] = {11, 22, 31, 42, 52};
+        OutIter end = std::set_symmetric_difference(Iter1(b), Iter1(b+5), Iter2(a), Iter2(a+4), OutIter(result));
+        assert(std::lexicographical_compare(result, base(end), expected, expected+5, T::less) == 0);
+        for (const T *it = base(end); it != result+20; ++it) {
+            assert(it->value == 0);
+        }
+    }
 }
 
-int main(int, char**)
+template<class T, class Iter1, class Iter2>
+TEST_CONSTEXPR_CXX20 void test3()
 {
-    test<input_iterator<const int*>, input_iterator<const int*>, output_iterator<int*> >();
-    test<input_iterator<const int*>, input_iterator<const int*>, forward_iterator<int*> >();
-    test<input_iterator<const int*>, input_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<input_iterator<const int*>, input_iterator<const int*>, random_access_iterator<int*> >();
-    test<input_iterator<const int*>, input_iterator<const int*>, int*>();
-
-    test<input_iterator<const int*>, forward_iterator<const int*>, output_iterator<int*> >();
-    test<input_iterator<const int*>, forward_iterator<const int*>, forward_iterator<int*> >();
-    test<input_iterator<const int*>, forward_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<input_iterator<const int*>, forward_iterator<const int*>, random_access_iterator<int*> >();
-    test<input_iterator<const int*>, forward_iterator<const int*>, int*>();
-
-    test<input_iterator<const int*>, bidirectional_iterator<const int*>, output_iterator<int*> >();
-    test<input_iterator<const int*>, bidirectional_iterator<const int*>, forward_iterator<int*> >();
-    test<input_iterator<const int*>, bidirectional_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<input_iterator<const int*>, bidirectional_iterator<const int*>, random_access_iterator<int*> >();
-    test<input_iterator<const int*>, bidirectional_iterator<const int*>, int*>();
-
-    test<input_iterator<const int*>, random_access_iterator<const int*>, output_iterator<int*> >();
-    test<input_iterator<const int*>, random_access_iterator<const int*>, forward_iterator<int*> >();
-    test<input_iterator<const int*>, random_access_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<input_iterator<const int*>, random_access_iterator<const int*>, random_access_iterator<int*> >();
-    test<input_iterator<const int*>, random_access_iterator<const int*>, int*>();
-
-    test<input_iterator<const int*>, const int*, output_iterator<int*> >();
-    test<input_iterator<const int*>, const int*, forward_iterator<int*> >();
-    test<input_iterator<const int*>, const int*, bidirectional_iterator<int*> >();
-    test<input_iterator<const int*>, const int*, random_access_iterator<int*> >();
-    test<input_iterator<const int*>, const int*, int*>();
-
-    test<forward_iterator<const int*>, input_iterator<const int*>, output_iterator<int*> >();
-    test<forward_iterator<const int*>, input_iterator<const int*>, forward_iterator<int*> >();
-    test<forward_iterator<const int*>, input_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<forward_iterator<const int*>, input_iterator<const int*>, random_access_iterator<int*> >();
-    test<forward_iterator<const int*>, input_iterator<const int*>, int*>();
-
-    test<forward_iterator<const int*>, forward_iterator<const int*>, output_iterator<int*> >();
-    test<forward_iterator<const int*>, forward_iterator<const int*>, forward_iterator<int*> >();
-    test<forward_iterator<const int*>, forward_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<forward_iterator<const int*>, forward_iterator<const int*>, random_access_iterator<int*> >();
-    test<forward_iterator<const int*>, forward_iterator<const int*>, int*>();
-
-    test<forward_iterator<const int*>, bidirectional_iterator<const int*>, output_iterator<int*> >();
-    test<forward_iterator<const int*>, bidirectional_iterator<const int*>, forward_iterator<int*> >();
-    test<forward_iterator<const int*>, bidirectional_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<forward_iterator<const int*>, bidirectional_iterator<const int*>, random_access_iterator<int*> >();
-    test<forward_iterator<const int*>, bidirectional_iterator<const int*>, int*>();
-
-    test<forward_iterator<const int*>, random_access_iterator<const int*>, output_iterator<int*> >();
-    test<forward_iterator<const int*>, random_access_iterator<const int*>, forward_iterator<int*> >();
-    test<forward_iterator<const int*>, random_access_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<forward_iterator<const int*>, random_access_iterator<const int*>, random_access_iterator<int*> >();
-    test<forward_iterator<const int*>, random_access_iterator<const int*>, int*>();
-
-    test<forward_iterator<const int*>, const int*, output_iterator<int*> >();
-    test<forward_iterator<const int*>, const int*, forward_iterator<int*> >();
-    test<forward_iterator<const int*>, const int*, bidirectional_iterator<int*> >();
-    test<forward_iterator<const int*>, const int*, random_access_iterator<int*> >();
-    test<forward_iterator<const int*>, const int*, int*>();
-
-    test<bidirectional_iterator<const int*>, input_iterator<const int*>, output_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, input_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, input_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, input_iterator<const int*>, random_access_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, input_iterator<const int*>, int*>();
-
-    test<bidirectional_iterator<const int*>, forward_iterator<const int*>, output_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, forward_iterator<const int*>, forward_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, forward_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, forward_iterator<const int*>, random_access_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, forward_iterator<const int*>, int*>();
-
-    test<bidirectional_iterator<const int*>, bidirectional_iterator<const int*>, output_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, bidirectional_iterator<const int*>, forward_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, bidirectional_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, bidirectional_iterator<const int*>, random_access_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, bidirectional_iterator<const int*>, int*>();
-
-    test<bidirectional_iterator<const int*>, random_access_iterator<const int*>, output_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, random_access_iterator<const int*>, forward_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, random_access_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, random_access_iterator<const int*>, random_access_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, random_access_iterator<const int*>, int*>();
-
-    test<bidirectional_iterator<const int*>, const int*, output_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, const int*, forward_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, const int*, bidirectional_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, const int*, random_access_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, const int*, int*>();
-
-    test<random_access_iterator<const int*>, input_iterator<const int*>, output_iterator<int*> >();
-    test<random_access_iterator<const int*>, input_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<random_access_iterator<const int*>, input_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<random_access_iterator<const int*>, input_iterator<const int*>, random_access_iterator<int*> >();
-    test<random_access_iterator<const int*>, input_iterator<const int*>, int*>();
-
-    test<random_access_iterator<const int*>, forward_iterator<const int*>, output_iterator<int*> >();
-    test<random_access_iterator<const int*>, forward_iterator<const int*>, forward_iterator<int*> >();
-    test<random_access_iterator<const int*>, forward_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<random_access_iterator<const int*>, forward_iterator<const int*>, random_access_iterator<int*> >();
-    test<random_access_iterator<const int*>, forward_iterator<const int*>, int*>();
-
-    test<random_access_iterator<const int*>, bidirectional_iterator<const int*>, output_iterator<int*> >();
-    test<random_access_iterator<const int*>, bidirectional_iterator<const int*>, forward_iterator<int*> >();
-    test<random_access_iterator<const int*>, bidirectional_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<random_access_iterator<const int*>, bidirectional_iterator<const int*>, random_access_iterator<int*> >();
-    test<random_access_iterator<const int*>, bidirectional_iterator<const int*>, int*>();
-
-    test<random_access_iterator<const int*>, random_access_iterator<const int*>, output_iterator<int*> >();
-    test<random_access_iterator<const int*>, random_access_iterator<const int*>, forward_iterator<int*> >();
-    test<random_access_iterator<const int*>, random_access_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<random_access_iterator<const int*>, random_access_iterator<const int*>, random_access_iterator<int*> >();
-    test<random_access_iterator<const int*>, random_access_iterator<const int*>, int*>();
-
-    test<random_access_iterator<const int*>, const int*, output_iterator<int*> >();
-    test<random_access_iterator<const int*>, const int*, forward_iterator<int*> >();
-    test<random_access_iterator<const int*>, const int*, bidirectional_iterator<int*> >();
-    test<random_access_iterator<const int*>, const int*, random_access_iterator<int*> >();
-    test<random_access_iterator<const int*>, const int*, int*>();
-
-    test<const int*, input_iterator<const int*>, output_iterator<int*> >();
-    test<const int*, input_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<const int*, input_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<const int*, input_iterator<const int*>, random_access_iterator<int*> >();
-    test<const int*, input_iterator<const int*>, int*>();
+    test4<T, Iter1, Iter2, output_iterator<T*> >();
+    test4<T, Iter1, Iter2, forward_iterator<T*> >();
+    test4<T, Iter1, Iter2, bidirectional_iterator<T*> >();
+    test4<T, Iter1, Iter2, random_access_iterator<T*> >();
+    test4<T, Iter1, Iter2, T*>();
+}
 
-    test<const int*, forward_iterator<const int*>, output_iterator<int*> >();
-    test<const int*, forward_iterator<const int*>, forward_iterator<int*> >();
-    test<const int*, forward_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<const int*, forward_iterator<const int*>, random_access_iterator<int*> >();
-    test<const int*, forward_iterator<const int*>, int*>();
+template<class T, class Iter1>
+TEST_CONSTEXPR_CXX20 void test2()
+{
+    test3<T, Iter1, input_iterator<const T*> >();
+    test3<T, Iter1, forward_iterator<const T*> >();
+    test3<T, Iter1, bidirectional_iterator<const T*> >();
+    test3<T, Iter1, random_access_iterator<const T*> >();
+    test3<T, Iter1, const T*>();
+}
 
-    test<const int*, bidirectional_iterator<const int*>, output_iterator<int*> >();
-    test<const int*, bidirectional_iterator<const int*>, forward_iterator<int*> >();
-    test<const int*, bidirectional_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<const int*, bidirectional_iterator<const int*>, random_access_iterator<int*> >();
-    test<const int*, bidirectional_iterator<const int*>, int*>();
+template<class T>
+TEST_CONSTEXPR_CXX20 void test1()
+{
+    test2<T, input_iterator<const T*> >();
+    test2<T, forward_iterator<const T*> >();
+    test2<T, bidirectional_iterator<const T*> >();
+    test2<T, random_access_iterator<const T*> >();
+    test2<T, const T*>();
+}
 
-    test<const int*, random_access_iterator<const int*>, output_iterator<int*> >();
-    test<const int*, random_access_iterator<const int*>, forward_iterator<int*> >();
-    test<const int*, random_access_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<const int*, random_access_iterator<const int*>, random_access_iterator<int*> >();
-    test<const int*, random_access_iterator<const int*>, int*>();
+TEST_CONSTEXPR_CXX20 bool test()
+{
+    test1<TrivialSortable>();
+    test1<NonTrivialSortable>();
+    return true;
+}
 
-    test<const int*, const int*, output_iterator<int*> >();
-    test<const int*, const int*, forward_iterator<int*> >();
-    test<const int*, const int*, bidirectional_iterator<int*> >();
-    test<const int*, const int*, random_access_iterator<int*> >();
-    test<const int*, const int*, int*>();
+int main(int, char**)
+{
+    test();
+#if TEST_STD_VER > 17
+    static_assert(test());
+#endif
 
-  return 0;
+    return 0;
 }
diff --git a/libcxx/test/std/algorithms/alg.sorting/alg.set.operations/set.symmetric.difference/set_symmetric_difference_comp.pass.cpp b/libcxx/test/std/algorithms/alg.sorting/alg.set.operations/set.symmetric.difference/set_symmetric_difference_comp.pass.cpp
--- a/libcxx/test/std/algorithms/alg.sorting/alg.set.operations/set.symmetric.difference/set_symmetric_difference_comp.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.sorting/alg.set.operations/set.symmetric.difference/set_symmetric_difference_comp.pass.cpp
@@ -6,6 +6,8 @@
 //
 //===----------------------------------------------------------------------===//
 
+// UNSUPPORTED: clang-8
+
 // <algorithm>
 
 // template<InputIterator InIter1, InputIterator InIter2, typename OutIter,
@@ -14,192 +16,85 @@
 //         && OutputIterator<OutIter, InIter2::reference>
 //         && Predicate<Compare, InIter1::value_type, InIter2::value_type>
 //         && Predicate<Compare, InIter2::value_type, InIter1::value_type>
-//   OutIter
-//   set_symmetric_difference(InIter1 first1, InIter1 last1,
-//                            InIter2 first2, InIter2 last2,
+//   constexpr OutIter       // constexpr after C++17
+//   set_symmetric_difference(InIter1 first1, InIter1 last1, InIter2 first2, InIter2 last2,
 //                            OutIter result, Compare comp);
 
 #include <algorithm>
-#include <functional>
 #include <cassert>
 
 #include "test_macros.h"
 #include "test_iterators.h"
+#include "../../sortable_helpers.h"
 
-template <class Iter1, class Iter2, class OutIter>
-void
-test()
+template<class T, class Iter1, class Iter2, class OutIter>
+TEST_CONSTEXPR_CXX20 void test4()
 {
-    int ia[] = {1, 2, 2, 3, 3, 3, 4, 4, 4, 4};
-    const int sa = sizeof(ia)/sizeof(ia[0]);
-    int ib[] = {2, 4, 4, 6};
-    const int sb = sizeof(ib)/sizeof(ib[0]);
-    int ic[20];
-    int ir[] = {1, 2, 3, 3, 3, 4, 4, 6};
-    const int sr = sizeof(ir)/sizeof(ir[0]);
-    OutIter ce = std::set_symmetric_difference(Iter1(ia), Iter1(ia+sa),
-                                               Iter2(ib), Iter2(ib+sb),
-                                               OutIter(ic), std::less<int>());
-    assert(base(ce) - ic == sr);
-    assert(std::lexicographical_compare(ic, base(ce), ir, ir+sr) == 0);
-    ce = std::set_symmetric_difference(Iter1(ib), Iter1(ib+sb),
-                                       Iter2(ia), Iter2(ia+sa),
-                                       OutIter(ic), std::less<int>());
-    assert(base(ce) - ic == sr);
-    assert(std::lexicographical_compare(ic, base(ce), ir, ir+sr) == 0);
+    const T a[] = {11, 33, 31, 41};
+    const T b[] = {22, 32, 43, 42, 52};
+    {
+        T result[20] = {};
+        T expected[] = {11, 22, 31, 42, 52};
+        OutIter end = std::set_symmetric_difference(Iter1(a), Iter1(a+4), Iter2(b), Iter2(b+5), OutIter(result), typename T::Comparator());
+        assert(std::lexicographical_compare(result, base(end), expected, expected+5, T::less) == 0);
+        for (const T *it = base(end); it != result+20; ++it) {
+            assert(it->value == 0);
+        }
+    }
+    {
+        T result[20] = {};
+        T expected[] = {11, 22, 31, 42, 52};
+        OutIter end = std::set_symmetric_difference(Iter1(b), Iter1(b+5), Iter2(a), Iter2(a+4), OutIter(result), typename T::Comparator());
+        assert(std::lexicographical_compare(result, base(end), expected, expected+5, T::less) == 0);
+        for (const T *it = base(end); it != result+20; ++it) {
+            assert(it->value == 0);
+        }
+    }
 }
 
-int main(int, char**)
+template<class T, class Iter1, class Iter2>
+TEST_CONSTEXPR_CXX20 void test3()
 {
-    test<input_iterator<const int*>, input_iterator<const int*>, output_iterator<int*> >();
-    test<input_iterator<const int*>, input_iterator<const int*>, forward_iterator<int*> >();
-    test<input_iterator<const int*>, input_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<input_iterator<const int*>, input_iterator<const int*>, random_access_iterator<int*> >();
-    test<input_iterator<const int*>, input_iterator<const int*>, int*>();
-
-    test<input_iterator<const int*>, forward_iterator<const int*>, output_iterator<int*> >();
-    test<input_iterator<const int*>, forward_iterator<const int*>, forward_iterator<int*> >();
-    test<input_iterator<const int*>, forward_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<input_iterator<const int*>, forward_iterator<const int*>, random_access_iterator<int*> >();
-    test<input_iterator<const int*>, forward_iterator<const int*>, int*>();
-
-    test<input_iterator<const int*>, bidirectional_iterator<const int*>, output_iterator<int*> >();
-    test<input_iterator<const int*>, bidirectional_iterator<const int*>, forward_iterator<int*> >();
-    test<input_iterator<const int*>, bidirectional_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<input_iterator<const int*>, bidirectional_iterator<const int*>, random_access_iterator<int*> >();
-    test<input_iterator<const int*>, bidirectional_iterator<const int*>, int*>();
-
-    test<input_iterator<const int*>, random_access_iterator<const int*>, output_iterator<int*> >();
-    test<input_iterator<const int*>, random_access_iterator<const int*>, forward_iterator<int*> >();
-    test<input_iterator<const int*>, random_access_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<input_iterator<const int*>, random_access_iterator<const int*>, random_access_iterator<int*> >();
-    test<input_iterator<const int*>, random_access_iterator<const int*>, int*>();
-
-    test<input_iterator<const int*>, const int*, output_iterator<int*> >();
-    test<input_iterator<const int*>, const int*, forward_iterator<int*> >();
-    test<input_iterator<const int*>, const int*, bidirectional_iterator<int*> >();
-    test<input_iterator<const int*>, const int*, random_access_iterator<int*> >();
-    test<input_iterator<const int*>, const int*, int*>();
-
-    test<forward_iterator<const int*>, input_iterator<const int*>, output_iterator<int*> >();
-    test<forward_iterator<const int*>, input_iterator<const int*>, forward_iterator<int*> >();
-    test<forward_iterator<const int*>, input_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<forward_iterator<const int*>, input_iterator<const int*>, random_access_iterator<int*> >();
-    test<forward_iterator<const int*>, input_iterator<const int*>, int*>();
-
-    test<forward_iterator<const int*>, forward_iterator<const int*>, output_iterator<int*> >();
-    test<forward_iterator<const int*>, forward_iterator<const int*>, forward_iterator<int*> >();
-    test<forward_iterator<const int*>, forward_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<forward_iterator<const int*>, forward_iterator<const int*>, random_access_iterator<int*> >();
-    test<forward_iterator<const int*>, forward_iterator<const int*>, int*>();
-
-    test<forward_iterator<const int*>, bidirectional_iterator<const int*>, output_iterator<int*> >();
-    test<forward_iterator<const int*>, bidirectional_iterator<const int*>, forward_iterator<int*> >();
-    test<forward_iterator<const int*>, bidirectional_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<forward_iterator<const int*>, bidirectional_iterator<const int*>, random_access_iterator<int*> >();
-    test<forward_iterator<const int*>, bidirectional_iterator<const int*>, int*>();
-
-    test<forward_iterator<const int*>, random_access_iterator<const int*>, output_iterator<int*> >();
-    test<forward_iterator<const int*>, random_access_iterator<const int*>, forward_iterator<int*> >();
-    test<forward_iterator<const int*>, random_access_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<forward_iterator<const int*>, random_access_iterator<const int*>, random_access_iterator<int*> >();
-    test<forward_iterator<const int*>, random_access_iterator<const int*>, int*>();
-
-    test<forward_iterator<const int*>, const int*, output_iterator<int*> >();
-    test<forward_iterator<const int*>, const int*, forward_iterator<int*> >();
-    test<forward_iterator<const int*>, const int*, bidirectional_iterator<int*> >();
-    test<forward_iterator<const int*>, const int*, random_access_iterator<int*> >();
-    test<forward_iterator<const int*>, const int*, int*>();
-
-    test<bidirectional_iterator<const int*>, input_iterator<const int*>, output_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, input_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, input_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, input_iterator<const int*>, random_access_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, input_iterator<const int*>, int*>();
-
-    test<bidirectional_iterator<const int*>, forward_iterator<const int*>, output_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, forward_iterator<const int*>, forward_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, forward_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, forward_iterator<const int*>, random_access_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, forward_iterator<const int*>, int*>();
-
-    test<bidirectional_iterator<const int*>, bidirectional_iterator<const int*>, output_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, bidirectional_iterator<const int*>, forward_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, bidirectional_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, bidirectional_iterator<const int*>, random_access_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, bidirectional_iterator<const int*>, int*>();
-
-    test<bidirectional_iterator<const int*>, random_access_iterator<const int*>, output_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, random_access_iterator<const int*>, forward_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, random_access_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, random_access_iterator<const int*>, random_access_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, random_access_iterator<const int*>, int*>();
-
-    test<bidirectional_iterator<const int*>, const int*, output_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, const int*, forward_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, const int*, bidirectional_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, const int*, random_access_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, const int*, int*>();
-
-    test<random_access_iterator<const int*>, input_iterator<const int*>, output_iterator<int*> >();
-    test<random_access_iterator<const int*>, input_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<random_access_iterator<const int*>, input_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<random_access_iterator<const int*>, input_iterator<const int*>, random_access_iterator<int*> >();
-    test<random_access_iterator<const int*>, input_iterator<const int*>, int*>();
-
-    test<random_access_iterator<const int*>, forward_iterator<const int*>, output_iterator<int*> >();
-    test<random_access_iterator<const int*>, forward_iterator<const int*>, forward_iterator<int*> >();
-    test<random_access_iterator<const int*>, forward_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<random_access_iterator<const int*>, forward_iterator<const int*>, random_access_iterator<int*> >();
-    test<random_access_iterator<const int*>, forward_iterator<const int*>, int*>();
-
-    test<random_access_iterator<const int*>, bidirectional_iterator<const int*>, output_iterator<int*> >();
-    test<random_access_iterator<const int*>, bidirectional_iterator<const int*>, forward_iterator<int*> >();
-    test<random_access_iterator<const int*>, bidirectional_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<random_access_iterator<const int*>, bidirectional_iterator<const int*>, random_access_iterator<int*> >();
-    test<random_access_iterator<const int*>, bidirectional_iterator<const int*>, int*>();
-
-    test<random_access_iterator<const int*>, random_access_iterator<const int*>, output_iterator<int*> >();
-    test<random_access_iterator<const int*>, random_access_iterator<const int*>, forward_iterator<int*> >();
-    test<random_access_iterator<const int*>, random_access_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<random_access_iterator<const int*>, random_access_iterator<const int*>, random_access_iterator<int*> >();
-    test<random_access_iterator<const int*>, random_access_iterator<const int*>, int*>();
-
-    test<random_access_iterator<const int*>, const int*, output_iterator<int*> >();
-    test<random_access_iterator<const int*>, const int*, forward_iterator<int*> >();
-    test<random_access_iterator<const int*>, const int*, bidirectional_iterator<int*> >();
-    test<random_access_iterator<const int*>, const int*, random_access_iterator<int*> >();
-    test<random_access_iterator<const int*>, const int*, int*>();
-
-    test<const int*, input_iterator<const int*>, output_iterator<int*> >();
-    test<const int*, input_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<const int*, input_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<const int*, input_iterator<const int*>, random_access_iterator<int*> >();
-    test<const int*, input_iterator<const int*>, int*>();
+    test4<T, Iter1, Iter2, output_iterator<T*> >();
+    test4<T, Iter1, Iter2, forward_iterator<T*> >();
+    test4<T, Iter1, Iter2, bidirectional_iterator<T*> >();
+    test4<T, Iter1, Iter2, random_access_iterator<T*> >();
+    test4<T, Iter1, Iter2, T*>();
+}
 
-    test<const int*, forward_iterator<const int*>, output_iterator<int*> >();
-    test<const int*, forward_iterator<const int*>, forward_iterator<int*> >();
-    test<const int*, forward_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<const int*, forward_iterator<const int*>, random_access_iterator<int*> >();
-    test<const int*, forward_iterator<const int*>, int*>();
+template<class T, class Iter1>
+TEST_CONSTEXPR_CXX20 void test2()
+{
+    test3<T, Iter1, input_iterator<const T*> >();
+    test3<T, Iter1, forward_iterator<const T*> >();
+    test3<T, Iter1, bidirectional_iterator<const T*> >();
+    test3<T, Iter1, random_access_iterator<const T*> >();
+    test3<T, Iter1, const T*>();
+}
 
-    test<const int*, bidirectional_iterator<const int*>, output_iterator<int*> >();
-    test<const int*, bidirectional_iterator<const int*>, forward_iterator<int*> >();
-    test<const int*, bidirectional_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<const int*, bidirectional_iterator<const int*>, random_access_iterator<int*> >();
-    test<const int*, bidirectional_iterator<const int*>, int*>();
+template<class T>
+TEST_CONSTEXPR_CXX20 void test1()
+{
+    test2<T, input_iterator<const T*> >();
+    test2<T, forward_iterator<const T*> >();
+    test2<T, bidirectional_iterator<const T*> >();
+    test2<T, random_access_iterator<const T*> >();
+    test2<T, const T*>();
+}
 
-    test<const int*, random_access_iterator<const int*>, output_iterator<int*> >();
-    test<const int*, random_access_iterator<const int*>, forward_iterator<int*> >();
-    test<const int*, random_access_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<const int*, random_access_iterator<const int*>, random_access_iterator<int*> >();
-    test<const int*, random_access_iterator<const int*>, int*>();
+TEST_CONSTEXPR_CXX20 bool test()
+{
+    test1<TrivialSortableWithComp>();
+    test1<NonTrivialSortableWithComp>();
+    return true;
+}
 
-    test<const int*, const int*, output_iterator<int*> >();
-    test<const int*, const int*, forward_iterator<int*> >();
-    test<const int*, const int*, bidirectional_iterator<int*> >();
-    test<const int*, const int*, random_access_iterator<int*> >();
-    test<const int*, const int*, int*>();
+int main(int, char**)
+{
+    test();
+#if TEST_STD_VER > 17
+    static_assert(test());
+#endif
 
-  return 0;
+    return 0;
 }
diff --git a/libcxx/test/std/algorithms/alg.sorting/alg.set.operations/set.union/set_union.pass.cpp b/libcxx/test/std/algorithms/alg.sorting/alg.set.operations/set.union/set_union.pass.cpp
--- a/libcxx/test/std/algorithms/alg.sorting/alg.set.operations/set.union/set_union.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.sorting/alg.set.operations/set.union/set_union.pass.cpp
@@ -6,6 +6,8 @@
 //
 //===----------------------------------------------------------------------===//
 
+// UNSUPPORTED: clang-8
+
 // <algorithm>
 
 // template<InputIterator InIter1, InputIterator InIter2, typename OutIter>
@@ -13,188 +15,85 @@
 //         && OutputIterator<OutIter, InIter2::reference>
 //         && HasLess<InIter2::value_type, InIter1::value_type>
 //         && HasLess<InIter1::value_type, InIter2::value_type>
-//   OutIter
-//   set_union(InIter1 first1, InIter1 last1,
-//             InIter2 first2, InIter2 last2, OutIter result);
+//   constexpr OutIter       // constexpr after C++17
+//   set_union(InIter1 first1, InIter1 last1, InIter2 first2, InIter2 last2,
+//             OutIter result);
 
 #include <algorithm>
 #include <cassert>
 
 #include "test_macros.h"
 #include "test_iterators.h"
+#include "../../sortable_helpers.h"
 
-template <class Iter1, class Iter2, class OutIter>
-void
-test()
+template<class T, class Iter1, class Iter2, class OutIter>
+TEST_CONSTEXPR_CXX20 void test4()
 {
-    int ia[] = {1, 2, 2, 3, 3, 3, 4, 4, 4, 4};
-    const int sa = sizeof(ia)/sizeof(ia[0]);
-    int ib[] = {2, 4, 4, 6};
-    const int sb = sizeof(ib)/sizeof(ib[0]);
-    int ic[20];
-    int ir[] = {1, 2, 2, 3, 3, 3, 4, 4, 4, 4, 6};
-    const int sr = sizeof(ir)/sizeof(ir[0]);
-    OutIter ce = std::set_union(Iter1(ia), Iter1(ia+sa),
-                                Iter2(ib), Iter2(ib+sb), OutIter(ic));
-    assert(base(ce) - ic == sr);
-    assert(std::lexicographical_compare(ic, base(ce), ir, ir+sr) == 0);
-    ce = std::set_union(Iter1(ib), Iter1(ib+sb),
-                        Iter2(ia), Iter2(ia+sa), OutIter(ic));
-    assert(base(ce) - ic == sr);
-    assert(std::lexicographical_compare(ic, base(ce), ir, ir+sr) == 0);
+    const T a[] = {11, 33, 31, 41};
+    const T b[] = {22, 32, 43, 42, 52};
+    {
+        T result[20] = {};
+        T expected[] = {11, 22, 33, 31, 41, 42, 52};
+        OutIter end = std::set_union(Iter1(a), Iter1(a+4), Iter2(b), Iter2(b+5), OutIter(result));
+        assert(std::lexicographical_compare(result, base(end), expected, expected+7, T::less) == 0);
+        for (const T *it = base(end); it != result+20; ++it) {
+            assert(it->value == 0);
+        }
+    }
+    {
+        T result[20] = {};
+        T expected[] = {11, 22, 32, 31, 43, 42, 52};
+        OutIter end = std::set_union(Iter1(b), Iter1(b+5), Iter2(a), Iter2(a+4), OutIter(result));
+        assert(std::lexicographical_compare(result, base(end), expected, expected+7, T::less) == 0);
+        for (const T *it = base(end); it != result+20; ++it) {
+            assert(it->value == 0);
+        }
+    }
 }
 
-int main(int, char**)
+template<class T, class Iter1, class Iter2>
+TEST_CONSTEXPR_CXX20 void test3()
 {
-    test<input_iterator<const int*>, input_iterator<const int*>, output_iterator<int*> >();
-    test<input_iterator<const int*>, input_iterator<const int*>, forward_iterator<int*> >();
-    test<input_iterator<const int*>, input_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<input_iterator<const int*>, input_iterator<const int*>, random_access_iterator<int*> >();
-    test<input_iterator<const int*>, input_iterator<const int*>, int*>();
-
-    test<input_iterator<const int*>, forward_iterator<const int*>, output_iterator<int*> >();
-    test<input_iterator<const int*>, forward_iterator<const int*>, forward_iterator<int*> >();
-    test<input_iterator<const int*>, forward_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<input_iterator<const int*>, forward_iterator<const int*>, random_access_iterator<int*> >();
-    test<input_iterator<const int*>, forward_iterator<const int*>, int*>();
-
-    test<input_iterator<const int*>, bidirectional_iterator<const int*>, output_iterator<int*> >();
-    test<input_iterator<const int*>, bidirectional_iterator<const int*>, forward_iterator<int*> >();
-    test<input_iterator<const int*>, bidirectional_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<input_iterator<const int*>, bidirectional_iterator<const int*>, random_access_iterator<int*> >();
-    test<input_iterator<const int*>, bidirectional_iterator<const int*>, int*>();
-
-    test<input_iterator<const int*>, random_access_iterator<const int*>, output_iterator<int*> >();
-    test<input_iterator<const int*>, random_access_iterator<const int*>, forward_iterator<int*> >();
-    test<input_iterator<const int*>, random_access_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<input_iterator<const int*>, random_access_iterator<const int*>, random_access_iterator<int*> >();
-    test<input_iterator<const int*>, random_access_iterator<const int*>, int*>();
-
-    test<input_iterator<const int*>, const int*, output_iterator<int*> >();
-    test<input_iterator<const int*>, const int*, forward_iterator<int*> >();
-    test<input_iterator<const int*>, const int*, bidirectional_iterator<int*> >();
-    test<input_iterator<const int*>, const int*, random_access_iterator<int*> >();
-    test<input_iterator<const int*>, const int*, int*>();
-
-    test<forward_iterator<const int*>, input_iterator<const int*>, output_iterator<int*> >();
-    test<forward_iterator<const int*>, input_iterator<const int*>, forward_iterator<int*> >();
-    test<forward_iterator<const int*>, input_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<forward_iterator<const int*>, input_iterator<const int*>, random_access_iterator<int*> >();
-    test<forward_iterator<const int*>, input_iterator<const int*>, int*>();
-
-    test<forward_iterator<const int*>, forward_iterator<const int*>, output_iterator<int*> >();
-    test<forward_iterator<const int*>, forward_iterator<const int*>, forward_iterator<int*> >();
-    test<forward_iterator<const int*>, forward_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<forward_iterator<const int*>, forward_iterator<const int*>, random_access_iterator<int*> >();
-    test<forward_iterator<const int*>, forward_iterator<const int*>, int*>();
-
-    test<forward_iterator<const int*>, bidirectional_iterator<const int*>, output_iterator<int*> >();
-    test<forward_iterator<const int*>, bidirectional_iterator<const int*>, forward_iterator<int*> >();
-    test<forward_iterator<const int*>, bidirectional_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<forward_iterator<const int*>, bidirectional_iterator<const int*>, random_access_iterator<int*> >();
-    test<forward_iterator<const int*>, bidirectional_iterator<const int*>, int*>();
-
-    test<forward_iterator<const int*>, random_access_iterator<const int*>, output_iterator<int*> >();
-    test<forward_iterator<const int*>, random_access_iterator<const int*>, forward_iterator<int*> >();
-    test<forward_iterator<const int*>, random_access_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<forward_iterator<const int*>, random_access_iterator<const int*>, random_access_iterator<int*> >();
-    test<forward_iterator<const int*>, random_access_iterator<const int*>, int*>();
-
-    test<forward_iterator<const int*>, const int*, output_iterator<int*> >();
-    test<forward_iterator<const int*>, const int*, forward_iterator<int*> >();
-    test<forward_iterator<const int*>, const int*, bidirectional_iterator<int*> >();
-    test<forward_iterator<const int*>, const int*, random_access_iterator<int*> >();
-    test<forward_iterator<const int*>, const int*, int*>();
-
-    test<bidirectional_iterator<const int*>, input_iterator<const int*>, output_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, input_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, input_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, input_iterator<const int*>, random_access_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, input_iterator<const int*>, int*>();
-
-    test<bidirectional_iterator<const int*>, forward_iterator<const int*>, output_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, forward_iterator<const int*>, forward_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, forward_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, forward_iterator<const int*>, random_access_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, forward_iterator<const int*>, int*>();
-
-    test<bidirectional_iterator<const int*>, bidirectional_iterator<const int*>, output_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, bidirectional_iterator<const int*>, forward_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, bidirectional_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, bidirectional_iterator<const int*>, random_access_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, bidirectional_iterator<const int*>, int*>();
-
-    test<bidirectional_iterator<const int*>, random_access_iterator<const int*>, output_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, random_access_iterator<const int*>, forward_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, random_access_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, random_access_iterator<const int*>, random_access_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, random_access_iterator<const int*>, int*>();
-
-    test<bidirectional_iterator<const int*>, const int*, output_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, const int*, forward_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, const int*, bidirectional_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, const int*, random_access_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, const int*, int*>();
-
-    test<random_access_iterator<const int*>, input_iterator<const int*>, output_iterator<int*> >();
-    test<random_access_iterator<const int*>, input_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<random_access_iterator<const int*>, input_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<random_access_iterator<const int*>, input_iterator<const int*>, random_access_iterator<int*> >();
-    test<random_access_iterator<const int*>, input_iterator<const int*>, int*>();
-
-    test<random_access_iterator<const int*>, forward_iterator<const int*>, output_iterator<int*> >();
-    test<random_access_iterator<const int*>, forward_iterator<const int*>, forward_iterator<int*> >();
-    test<random_access_iterator<const int*>, forward_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<random_access_iterator<const int*>, forward_iterator<const int*>, random_access_iterator<int*> >();
-    test<random_access_iterator<const int*>, forward_iterator<const int*>, int*>();
-
-    test<random_access_iterator<const int*>, bidirectional_iterator<const int*>, output_iterator<int*> >();
-    test<random_access_iterator<const int*>, bidirectional_iterator<const int*>, forward_iterator<int*> >();
-    test<random_access_iterator<const int*>, bidirectional_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<random_access_iterator<const int*>, bidirectional_iterator<const int*>, random_access_iterator<int*> >();
-    test<random_access_iterator<const int*>, bidirectional_iterator<const int*>, int*>();
-
-    test<random_access_iterator<const int*>, random_access_iterator<const int*>, output_iterator<int*> >();
-    test<random_access_iterator<const int*>, random_access_iterator<const int*>, forward_iterator<int*> >();
-    test<random_access_iterator<const int*>, random_access_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<random_access_iterator<const int*>, random_access_iterator<const int*>, random_access_iterator<int*> >();
-    test<random_access_iterator<const int*>, random_access_iterator<const int*>, int*>();
-
-    test<random_access_iterator<const int*>, const int*, output_iterator<int*> >();
-    test<random_access_iterator<const int*>, const int*, forward_iterator<int*> >();
-    test<random_access_iterator<const int*>, const int*, bidirectional_iterator<int*> >();
-    test<random_access_iterator<const int*>, const int*, random_access_iterator<int*> >();
-    test<random_access_iterator<const int*>, const int*, int*>();
-
-    test<const int*, input_iterator<const int*>, output_iterator<int*> >();
-    test<const int*, input_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<const int*, input_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<const int*, input_iterator<const int*>, random_access_iterator<int*> >();
-    test<const int*, input_iterator<const int*>, int*>();
+    test4<T, Iter1, Iter2, output_iterator<T*> >();
+    test4<T, Iter1, Iter2, forward_iterator<T*> >();
+    test4<T, Iter1, Iter2, bidirectional_iterator<T*> >();
+    test4<T, Iter1, Iter2, random_access_iterator<T*> >();
+    test4<T, Iter1, Iter2, T*>();
+}
 
-    test<const int*, forward_iterator<const int*>, output_iterator<int*> >();
-    test<const int*, forward_iterator<const int*>, forward_iterator<int*> >();
-    test<const int*, forward_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<const int*, forward_iterator<const int*>, random_access_iterator<int*> >();
-    test<const int*, forward_iterator<const int*>, int*>();
+template<class T, class Iter1>
+TEST_CONSTEXPR_CXX20 void test2()
+{
+    test3<T, Iter1, input_iterator<const T*> >();
+    test3<T, Iter1, forward_iterator<const T*> >();
+    test3<T, Iter1, bidirectional_iterator<const T*> >();
+    test3<T, Iter1, random_access_iterator<const T*> >();
+    test3<T, Iter1, const T*>();
+}
 
-    test<const int*, bidirectional_iterator<const int*>, output_iterator<int*> >();
-    test<const int*, bidirectional_iterator<const int*>, forward_iterator<int*> >();
-    test<const int*, bidirectional_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<const int*, bidirectional_iterator<const int*>, random_access_iterator<int*> >();
-    test<const int*, bidirectional_iterator<const int*>, int*>();
+template<class T>
+TEST_CONSTEXPR_CXX20 void test1()
+{
+    test2<T, input_iterator<const T*> >();
+    test2<T, forward_iterator<const T*> >();
+    test2<T, bidirectional_iterator<const T*> >();
+    test2<T, random_access_iterator<const T*> >();
+    test2<T, const T*>();
+}
 
-    test<const int*, random_access_iterator<const int*>, output_iterator<int*> >();
-    test<const int*, random_access_iterator<const int*>, forward_iterator<int*> >();
-    test<const int*, random_access_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<const int*, random_access_iterator<const int*>, random_access_iterator<int*> >();
-    test<const int*, random_access_iterator<const int*>, int*>();
+TEST_CONSTEXPR_CXX20 bool test()
+{
+    test1<TrivialSortable>();
+    test1<NonTrivialSortable>();
+    return true;
+}
 
-    test<const int*, const int*, output_iterator<int*> >();
-    test<const int*, const int*, forward_iterator<int*> >();
-    test<const int*, const int*, bidirectional_iterator<int*> >();
-    test<const int*, const int*, random_access_iterator<int*> >();
-    test<const int*, const int*, int*>();
+int main(int, char**)
+{
+    test();
+#if TEST_STD_VER > 17
+    static_assert(test());
+#endif
 
-  return 0;
+    return 0;
 }
diff --git a/libcxx/test/std/algorithms/alg.sorting/alg.set.operations/set.union/set_union_comp.pass.cpp b/libcxx/test/std/algorithms/alg.sorting/alg.set.operations/set.union/set_union_comp.pass.cpp
--- a/libcxx/test/std/algorithms/alg.sorting/alg.set.operations/set.union/set_union_comp.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.sorting/alg.set.operations/set.union/set_union_comp.pass.cpp
@@ -6,6 +6,8 @@
 //
 //===----------------------------------------------------------------------===//
 
+// UNSUPPORTED: clang-8
+
 // <algorithm>
 
 // template<InputIterator InIter1, InputIterator InIter2, typename OutIter,
@@ -14,189 +16,85 @@
 //         && OutputIterator<OutIter, InIter2::reference>
 //         && Predicate<Compare, InIter1::value_type, InIter2::value_type>
 //         && Predicate<Compare, InIter2::value_type, InIter1::value_type>
-//   OutIter
+//   constexpr OutIter       // constexpr after C++17
 //   set_union(InIter1 first1, InIter1 last1, InIter2 first2, InIter2 last2,
 //             OutIter result, Compare comp);
 
 #include <algorithm>
-#include <functional>
 #include <cassert>
 
 #include "test_macros.h"
 #include "test_iterators.h"
+#include "../../sortable_helpers.h"
 
-template <class Iter1, class Iter2, class OutIter>
-void
-test()
+template<class T, class Iter1, class Iter2, class OutIter>
+TEST_CONSTEXPR_CXX20 void test4()
 {
-    int ia[] = {1, 2, 2, 3, 3, 3, 4, 4, 4, 4};
-    const int sa = sizeof(ia)/sizeof(ia[0]);
-    int ib[] = {2, 4, 4, 6};
-    const int sb = sizeof(ib)/sizeof(ib[0]);
-    int ic[20];
-    int ir[] = {1, 2, 2, 3, 3, 3, 4, 4, 4, 4, 6};
-    const int sr = sizeof(ir)/sizeof(ir[0]);
-    OutIter ce = std::set_union(Iter1(ia), Iter1(ia+sa),
-                                Iter2(ib), Iter2(ib+sb), OutIter(ic), std::less<int>());
-    assert(base(ce) - ic == sr);
-    assert(std::lexicographical_compare(ic, base(ce), ir, ir+sr) == 0);
-    ce = std::set_union(Iter1(ib), Iter1(ib+sb),
-                        Iter2(ia), Iter2(ia+sa), OutIter(ic), std::less<int>());
-    assert(base(ce) - ic == sr);
-    assert(std::lexicographical_compare(ic, base(ce), ir, ir+sr) == 0);
+    const T a[] = {11, 33, 31, 41};
+    const T b[] = {22, 32, 43, 42, 52};
+    {
+        T result[20] = {};
+        T expected[] = {11, 22, 33, 31, 41, 42, 52};
+        OutIter end = std::set_union(Iter1(a), Iter1(a+4), Iter2(b), Iter2(b+5), OutIter(result), typename T::Comparator());
+        assert(std::lexicographical_compare(result, base(end), expected, expected+7, T::less) == 0);
+        for (const T *it = base(end); it != result+20; ++it) {
+            assert(it->value == 0);
+        }
+    }
+    {
+        T result[20] = {};
+        T expected[] = {11, 22, 32, 31, 43, 42, 52};
+        OutIter end = std::set_union(Iter1(b), Iter1(b+5), Iter2(a), Iter2(a+4), OutIter(result), typename T::Comparator());
+        assert(std::lexicographical_compare(result, base(end), expected, expected+7, T::less) == 0);
+        for (const T *it = base(end); it != result+20; ++it) {
+            assert(it->value == 0);
+        }
+    }
 }
 
-int main(int, char**)
+template<class T, class Iter1, class Iter2>
+TEST_CONSTEXPR_CXX20 void test3()
 {
-    test<input_iterator<const int*>, input_iterator<const int*>, output_iterator<int*> >();
-    test<input_iterator<const int*>, input_iterator<const int*>, forward_iterator<int*> >();
-    test<input_iterator<const int*>, input_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<input_iterator<const int*>, input_iterator<const int*>, random_access_iterator<int*> >();
-    test<input_iterator<const int*>, input_iterator<const int*>, int*>();
-
-    test<input_iterator<const int*>, forward_iterator<const int*>, output_iterator<int*> >();
-    test<input_iterator<const int*>, forward_iterator<const int*>, forward_iterator<int*> >();
-    test<input_iterator<const int*>, forward_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<input_iterator<const int*>, forward_iterator<const int*>, random_access_iterator<int*> >();
-    test<input_iterator<const int*>, forward_iterator<const int*>, int*>();
-
-    test<input_iterator<const int*>, bidirectional_iterator<const int*>, output_iterator<int*> >();
-    test<input_iterator<const int*>, bidirectional_iterator<const int*>, forward_iterator<int*> >();
-    test<input_iterator<const int*>, bidirectional_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<input_iterator<const int*>, bidirectional_iterator<const int*>, random_access_iterator<int*> >();
-    test<input_iterator<const int*>, bidirectional_iterator<const int*>, int*>();
-
-    test<input_iterator<const int*>, random_access_iterator<const int*>, output_iterator<int*> >();
-    test<input_iterator<const int*>, random_access_iterator<const int*>, forward_iterator<int*> >();
-    test<input_iterator<const int*>, random_access_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<input_iterator<const int*>, random_access_iterator<const int*>, random_access_iterator<int*> >();
-    test<input_iterator<const int*>, random_access_iterator<const int*>, int*>();
-
-    test<input_iterator<const int*>, const int*, output_iterator<int*> >();
-    test<input_iterator<const int*>, const int*, forward_iterator<int*> >();
-    test<input_iterator<const int*>, const int*, bidirectional_iterator<int*> >();
-    test<input_iterator<const int*>, const int*, random_access_iterator<int*> >();
-    test<input_iterator<const int*>, const int*, int*>();
-
-    test<forward_iterator<const int*>, input_iterator<const int*>, output_iterator<int*> >();
-    test<forward_iterator<const int*>, input_iterator<const int*>, forward_iterator<int*> >();
-    test<forward_iterator<const int*>, input_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<forward_iterator<const int*>, input_iterator<const int*>, random_access_iterator<int*> >();
-    test<forward_iterator<const int*>, input_iterator<const int*>, int*>();
-
-    test<forward_iterator<const int*>, forward_iterator<const int*>, output_iterator<int*> >();
-    test<forward_iterator<const int*>, forward_iterator<const int*>, forward_iterator<int*> >();
-    test<forward_iterator<const int*>, forward_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<forward_iterator<const int*>, forward_iterator<const int*>, random_access_iterator<int*> >();
-    test<forward_iterator<const int*>, forward_iterator<const int*>, int*>();
-
-    test<forward_iterator<const int*>, bidirectional_iterator<const int*>, output_iterator<int*> >();
-    test<forward_iterator<const int*>, bidirectional_iterator<const int*>, forward_iterator<int*> >();
-    test<forward_iterator<const int*>, bidirectional_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<forward_iterator<const int*>, bidirectional_iterator<const int*>, random_access_iterator<int*> >();
-    test<forward_iterator<const int*>, bidirectional_iterator<const int*>, int*>();
-
-    test<forward_iterator<const int*>, random_access_iterator<const int*>, output_iterator<int*> >();
-    test<forward_iterator<const int*>, random_access_iterator<const int*>, forward_iterator<int*> >();
-    test<forward_iterator<const int*>, random_access_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<forward_iterator<const int*>, random_access_iterator<const int*>, random_access_iterator<int*> >();
-    test<forward_iterator<const int*>, random_access_iterator<const int*>, int*>();
-
-    test<forward_iterator<const int*>, const int*, output_iterator<int*> >();
-    test<forward_iterator<const int*>, const int*, forward_iterator<int*> >();
-    test<forward_iterator<const int*>, const int*, bidirectional_iterator<int*> >();
-    test<forward_iterator<const int*>, const int*, random_access_iterator<int*> >();
-    test<forward_iterator<const int*>, const int*, int*>();
-
-    test<bidirectional_iterator<const int*>, input_iterator<const int*>, output_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, input_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, input_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, input_iterator<const int*>, random_access_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, input_iterator<const int*>, int*>();
-
-    test<bidirectional_iterator<const int*>, forward_iterator<const int*>, output_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, forward_iterator<const int*>, forward_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, forward_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, forward_iterator<const int*>, random_access_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, forward_iterator<const int*>, int*>();
-
-    test<bidirectional_iterator<const int*>, bidirectional_iterator<const int*>, output_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, bidirectional_iterator<const int*>, forward_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, bidirectional_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, bidirectional_iterator<const int*>, random_access_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, bidirectional_iterator<const int*>, int*>();
-
-    test<bidirectional_iterator<const int*>, random_access_iterator<const int*>, output_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, random_access_iterator<const int*>, forward_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, random_access_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, random_access_iterator<const int*>, random_access_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, random_access_iterator<const int*>, int*>();
-
-    test<bidirectional_iterator<const int*>, const int*, output_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, const int*, forward_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, const int*, bidirectional_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, const int*, random_access_iterator<int*> >();
-    test<bidirectional_iterator<const int*>, const int*, int*>();
-
-    test<random_access_iterator<const int*>, input_iterator<const int*>, output_iterator<int*> >();
-    test<random_access_iterator<const int*>, input_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<random_access_iterator<const int*>, input_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<random_access_iterator<const int*>, input_iterator<const int*>, random_access_iterator<int*> >();
-    test<random_access_iterator<const int*>, input_iterator<const int*>, int*>();
-
-    test<random_access_iterator<const int*>, forward_iterator<const int*>, output_iterator<int*> >();
-    test<random_access_iterator<const int*>, forward_iterator<const int*>, forward_iterator<int*> >();
-    test<random_access_iterator<const int*>, forward_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<random_access_iterator<const int*>, forward_iterator<const int*>, random_access_iterator<int*> >();
-    test<random_access_iterator<const int*>, forward_iterator<const int*>, int*>();
-
-    test<random_access_iterator<const int*>, bidirectional_iterator<const int*>, output_iterator<int*> >();
-    test<random_access_iterator<const int*>, bidirectional_iterator<const int*>, forward_iterator<int*> >();
-    test<random_access_iterator<const int*>, bidirectional_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<random_access_iterator<const int*>, bidirectional_iterator<const int*>, random_access_iterator<int*> >();
-    test<random_access_iterator<const int*>, bidirectional_iterator<const int*>, int*>();
-
-    test<random_access_iterator<const int*>, random_access_iterator<const int*>, output_iterator<int*> >();
-    test<random_access_iterator<const int*>, random_access_iterator<const int*>, forward_iterator<int*> >();
-    test<random_access_iterator<const int*>, random_access_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<random_access_iterator<const int*>, random_access_iterator<const int*>, random_access_iterator<int*> >();
-    test<random_access_iterator<const int*>, random_access_iterator<const int*>, int*>();
-
-    test<random_access_iterator<const int*>, const int*, output_iterator<int*> >();
-    test<random_access_iterator<const int*>, const int*, forward_iterator<int*> >();
-    test<random_access_iterator<const int*>, const int*, bidirectional_iterator<int*> >();
-    test<random_access_iterator<const int*>, const int*, random_access_iterator<int*> >();
-    test<random_access_iterator<const int*>, const int*, int*>();
-
-    test<const int*, input_iterator<const int*>, output_iterator<int*> >();
-    test<const int*, input_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<const int*, input_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<const int*, input_iterator<const int*>, random_access_iterator<int*> >();
-    test<const int*, input_iterator<const int*>, int*>();
+    test4<T, Iter1, Iter2, output_iterator<T*> >();
+    test4<T, Iter1, Iter2, forward_iterator<T*> >();
+    test4<T, Iter1, Iter2, bidirectional_iterator<T*> >();
+    test4<T, Iter1, Iter2, random_access_iterator<T*> >();
+    test4<T, Iter1, Iter2, T*>();
+}
 
-    test<const int*, forward_iterator<const int*>, output_iterator<int*> >();
-    test<const int*, forward_iterator<const int*>, forward_iterator<int*> >();
-    test<const int*, forward_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<const int*, forward_iterator<const int*>, random_access_iterator<int*> >();
-    test<const int*, forward_iterator<const int*>, int*>();
+template<class T, class Iter1>
+TEST_CONSTEXPR_CXX20 void test2()
+{
+    test3<T, Iter1, input_iterator<const T*> >();
+    test3<T, Iter1, forward_iterator<const T*> >();
+    test3<T, Iter1, bidirectional_iterator<const T*> >();
+    test3<T, Iter1, random_access_iterator<const T*> >();
+    test3<T, Iter1, const T*>();
+}
 
-    test<const int*, bidirectional_iterator<const int*>, output_iterator<int*> >();
-    test<const int*, bidirectional_iterator<const int*>, forward_iterator<int*> >();
-    test<const int*, bidirectional_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<const int*, bidirectional_iterator<const int*>, random_access_iterator<int*> >();
-    test<const int*, bidirectional_iterator<const int*>, int*>();
+template<class T>
+TEST_CONSTEXPR_CXX20 void test1()
+{
+    test2<T, input_iterator<const T*> >();
+    test2<T, forward_iterator<const T*> >();
+    test2<T, bidirectional_iterator<const T*> >();
+    test2<T, random_access_iterator<const T*> >();
+    test2<T, const T*>();
+}
 
-    test<const int*, random_access_iterator<const int*>, output_iterator<int*> >();
-    test<const int*, random_access_iterator<const int*>, forward_iterator<int*> >();
-    test<const int*, random_access_iterator<const int*>, bidirectional_iterator<int*> >();
-    test<const int*, random_access_iterator<const int*>, random_access_iterator<int*> >();
-    test<const int*, random_access_iterator<const int*>, int*>();
+TEST_CONSTEXPR_CXX20 bool test()
+{
+    test1<TrivialSortableWithComp>();
+    test1<NonTrivialSortableWithComp>();
+    return true;
+}
 
-    test<const int*, const int*, output_iterator<int*> >();
-    test<const int*, const int*, forward_iterator<int*> >();
-    test<const int*, const int*, bidirectional_iterator<int*> >();
-    test<const int*, const int*, random_access_iterator<int*> >();
-    test<const int*, const int*, int*>();
+int main(int, char**)
+{
+    test();
+#if TEST_STD_VER > 17
+    static_assert(test());
+#endif
 
-  return 0;
+    return 0;
 }
diff --git a/libcxx/test/std/algorithms/alg.sorting/sortable_helpers.h b/libcxx/test/std/algorithms/alg.sorting/sortable_helpers.h
new file mode 100644
--- /dev/null
+++ b/libcxx/test/std/algorithms/alg.sorting/sortable_helpers.h
@@ -0,0 +1,78 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SORTABLE_HELPERS_H
+#define SORTABLE_HELPERS_H
+
+#include <type_traits>
+
+#include "test_macros.h"
+
+struct TrivialSortable {
+    int value;
+    TEST_CONSTEXPR TrivialSortable() : value(0) {}
+    TEST_CONSTEXPR TrivialSortable(int v) : value(v) {}
+    friend TEST_CONSTEXPR bool operator<(const TrivialSortable& a, const TrivialSortable& b) {
+        return a.value / 10 < b.value / 10;
+    }
+    static TEST_CONSTEXPR bool less(const TrivialSortable& a, const TrivialSortable& b) {
+        return a.value < b.value;
+    }
+};
+
+struct NonTrivialSortable {
+    int value;
+    TEST_CONSTEXPR NonTrivialSortable() : value(0) {}
+    TEST_CONSTEXPR NonTrivialSortable(int v) : value(v) {}
+    TEST_CONSTEXPR NonTrivialSortable(const NonTrivialSortable& rhs) : value(rhs.value) {}
+    TEST_CONSTEXPR_CXX14 NonTrivialSortable& operator=(const NonTrivialSortable& rhs) { value = rhs.value; return *this; }
+    friend TEST_CONSTEXPR bool operator<(const NonTrivialSortable& a, const NonTrivialSortable& b) {
+        return a.value / 10 < b.value / 10;
+    }
+    static TEST_CONSTEXPR bool less(const NonTrivialSortable& a, const NonTrivialSortable& b) {
+        return a.value < b.value;
+    }
+};
+
+
+struct TrivialSortableWithComp {
+    int value;
+    TEST_CONSTEXPR TrivialSortableWithComp() : value(0) {}
+    TEST_CONSTEXPR TrivialSortableWithComp(int v) : value(v) {}
+    struct Comparator {
+        TEST_CONSTEXPR bool operator()(const TrivialSortableWithComp& a, const TrivialSortableWithComp& b) const {
+            return a.value / 10 < b.value / 10;
+        }
+    };
+    static TEST_CONSTEXPR bool less(const TrivialSortableWithComp& a, const TrivialSortableWithComp& b) {
+        return a.value < b.value;
+    }
+};
+
+struct NonTrivialSortableWithComp {
+    int value;
+    TEST_CONSTEXPR NonTrivialSortableWithComp() : value(0) {}
+    TEST_CONSTEXPR NonTrivialSortableWithComp(int v) : value(v) {}
+    TEST_CONSTEXPR NonTrivialSortableWithComp(const NonTrivialSortableWithComp& rhs) : value(rhs.value) {}
+    TEST_CONSTEXPR_CXX14 NonTrivialSortableWithComp& operator=(const NonTrivialSortableWithComp& rhs) { value = rhs.value; return *this; }
+    struct Comparator {
+        TEST_CONSTEXPR bool operator()(const NonTrivialSortableWithComp& a, const NonTrivialSortableWithComp& b) const {
+            return a.value / 10 < b.value / 10;
+        }
+    };
+    static TEST_CONSTEXPR bool less(const NonTrivialSortableWithComp& a, const NonTrivialSortableWithComp& b) {
+        return a.value < b.value;
+    }
+};
+
+static_assert(std::is_trivially_copyable<TrivialSortable>::value, "");
+static_assert(std::is_trivially_copyable<TrivialSortableWithComp>::value, "");
+static_assert(!std::is_trivially_copyable<NonTrivialSortable>::value, "");
+static_assert(!std::is_trivially_copyable<NonTrivialSortableWithComp>::value, "");
+
+#endif  // SORTABLE_HELPERS_H