Index: libcxx/include/__string
===================================================================
--- libcxx/include/__string
+++ libcxx/include/__string
@@ -58,6 +58,10 @@
 #include <cstdio>     // For EOF.
 #include <memory>     // for __murmur2_or_cityhash
 
+#if __cplusplus > 201703L && defined(__cpp_impl_three_way_comparison) && __cpp_impl_three_way_comparison >= 201907
+#include <compare>
+#endif // __cplusplus
+
 #include <__debug>
 
 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
@@ -356,6 +360,9 @@
     typedef streamoff off_type;
     typedef streampos pos_type;
     typedef mbstate_t state_type;
+    #if __cplusplus > 201703L && defined(__cpp_impl_three_way_comparison) && __cpp_impl_three_way_comparison >= 201907
+    using comparison_category = strong_ordering;
+    #endif // __cplusplus
 
     static inline _LIBCPP_CONSTEXPR_AFTER_CXX14
     void assign(char_type& __c1, const char_type& __c2) _NOEXCEPT {__c1 = __c2;}
@@ -459,6 +466,9 @@
     typedef streamoff off_type;
     typedef streampos pos_type;
     typedef mbstate_t state_type;
+    #if __cplusplus > 201703L && defined(__cpp_impl_three_way_comparison) && __cpp_impl_three_way_comparison >= 201907
+    using comparison_category = strong_ordering;
+    #endif // __cplusplus
 
     static inline _LIBCPP_CONSTEXPR_AFTER_CXX14
     void assign(char_type& __c1, const char_type& __c2) _NOEXCEPT {__c1 = __c2;}
@@ -589,6 +599,9 @@
     typedef streamoff      off_type;
     typedef u8streampos    pos_type;
     typedef mbstate_t      state_type;
+    #if __cplusplus > 201703L && defined(__cpp_impl_three_way_comparison) && __cpp_impl_three_way_comparison >= 201907
+    using comparison_category = strong_ordering;
+    #endif // __cplusplus
 
     static inline constexpr void assign(char_type& __c1, const char_type& __c2) noexcept
         {__c1 = __c2;}
@@ -698,6 +711,9 @@
     typedef streamoff      off_type;
     typedef u16streampos   pos_type;
     typedef mbstate_t      state_type;
+    #if __cplusplus > 201703L && defined(__cpp_impl_three_way_comparison) && __cpp_impl_three_way_comparison >= 201907
+    using comparison_category = strong_ordering;
+    #endif // __cplusplus
 
     static inline _LIBCPP_CONSTEXPR_AFTER_CXX14
     void assign(char_type& __c1, const char_type& __c2) _NOEXCEPT {__c1 = __c2;}
@@ -818,6 +834,9 @@
     typedef streamoff      off_type;
     typedef u32streampos   pos_type;
     typedef mbstate_t      state_type;
+    #if __cplusplus > 201703L && defined(__cpp_impl_three_way_comparison) && __cpp_impl_three_way_comparison >= 201907
+    using comparison_category = strong_ordering;
+    #endif // __cplusplus
 
     static inline _LIBCPP_CONSTEXPR_AFTER_CXX14
     void assign(char_type& __c1, const char_type& __c2) _NOEXCEPT {__c1 = __c2;}
Index: libcxx/include/compare
===================================================================
--- libcxx/include/compare
+++ libcxx/include/compare
@@ -247,6 +247,8 @@
   _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator> (_CmpUnspecifiedParam, partial_ordering __v) noexcept;
   _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator>=(_CmpUnspecifiedParam, partial_ordering __v) noexcept;
 
+  friend constexpr bool operator==(partial_ordering, partial_ordering) noexcept = default;
+
 #ifndef _LIBCPP_HAS_NO_SPACESHIP_OPERATOR
   _LIBCPP_INLINE_VISIBILITY friend constexpr partial_ordering operator<=>(partial_ordering __v, _CmpUnspecifiedParam) noexcept;
   _LIBCPP_INLINE_VISIBILITY friend constexpr partial_ordering operator<=>(_CmpUnspecifiedParam, partial_ordering __v) noexcept;
@@ -363,6 +365,8 @@
   _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator> (_CmpUnspecifiedParam, weak_ordering __v) noexcept;
   _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator>=(_CmpUnspecifiedParam, weak_ordering __v) noexcept;
 
+  friend constexpr bool operator==(weak_ordering, weak_ordering) noexcept = default;
+
 #ifndef _LIBCPP_HAS_NO_SPACESHIP_OPERATOR
   _LIBCPP_INLINE_VISIBILITY friend constexpr weak_ordering operator<=>(weak_ordering __v, _CmpUnspecifiedParam) noexcept;
   _LIBCPP_INLINE_VISIBILITY friend constexpr weak_ordering operator<=>(_CmpUnspecifiedParam, weak_ordering __v) noexcept;
@@ -489,6 +493,8 @@
   _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator> (_CmpUnspecifiedParam, strong_ordering __v) noexcept;
   _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator>=(_CmpUnspecifiedParam, strong_ordering __v) noexcept;
 
+  _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator==(strong_ordering, strong_ordering) noexcept = default;
+
 #ifndef _LIBCPP_HAS_NO_SPACESHIP_OPERATOR
   _LIBCPP_INLINE_VISIBILITY friend constexpr strong_ordering operator<=>(strong_ordering __v, _CmpUnspecifiedParam) noexcept;
   _LIBCPP_INLINE_VISIBILITY friend constexpr strong_ordering operator<=>(_CmpUnspecifiedParam, strong_ordering __v) noexcept;
Index: libcxx/include/string_view
===================================================================
--- libcxx/include/string_view
+++ libcxx/include/string_view
@@ -24,20 +24,8 @@
     constexpr bool operator==(basic_string_view<charT, traits> x,
                               basic_string_view<charT, traits> y) noexcept;
     template<class charT, class traits>
-    constexpr bool operator!=(basic_string_view<charT, traits> x,
-                              basic_string_view<charT, traits> y) noexcept;
-    template<class charT, class traits>
-    constexpr bool operator< (basic_string_view<charT, traits> x,
-                                 basic_string_view<charT, traits> y) noexcept;
-    template<class charT, class traits>
-    constexpr bool operator> (basic_string_view<charT, traits> x,
-                              basic_string_view<charT, traits> y) noexcept;
-    template<class charT, class traits>
-    constexpr bool operator<=(basic_string_view<charT, traits> x,
-                                 basic_string_view<charT, traits> y) noexcept;
-    template<class charT, class traits>
-    constexpr bool operator>=(basic_string_view<charT, traits> x,
-                              basic_string_view<charT, traits> y) noexcept;
+    constexpr bool operator<=>(basic_string_view<charT, traits> x,
+                               basic_string_view<charT, traits> y) noexcept;
     // see below, sufficient additional overloads of comparison functions
 
     // 7.10, Inserters and extractors
@@ -608,6 +596,7 @@
 
 
 // [string.view.comparison]
+#ifdef _LIBCPP_HAS_NO_SPACESHIP_OPERATOR
 // operator ==
 template<class _CharT, class _Traits>
 _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
@@ -767,6 +756,46 @@
 {
     return __lhs.compare(__rhs) >= 0;
 }
+#else
+template<class _CharT, class _Traits>
+_LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
+bool operator==(basic_string_view<_CharT, _Traits> __lhs,
+                basic_string_view<_CharT, _Traits> __rhs) _NOEXCEPT
+{
+    if ( __lhs.size() != __rhs.size()) return false;
+    return __lhs.compare(__rhs) == 0;
+}
+
+template<class _CharT, class _Traits>
+_LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
+bool operator==(basic_string_view<_CharT, _Traits> __lhs,
+                typename common_type<basic_string_view<_CharT, _Traits> >::type __rhs) _NOEXCEPT
+{
+    return __lhs == basic_string_view<_CharT, _Traits>(__rhs);
+}
+
+template<class _CharT, class _Traits>
+_LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
+auto operator<=>(basic_string_view<_CharT, _Traits> __lhs,
+                 basic_string_view<_CharT, _Traits> __rhs) _NOEXCEPT
+{
+    const auto result = __lhs.compare(__rhs) <=> 0;
+    if constexpr (requires { typename _Traits::comparison_category; }) {
+        return static_cast<typename _Traits::comparison_category>(result);
+    }
+    else {
+        return static_cast<weak_ordering>(result);
+    }
+}
+
+template<class _CharT, class _Traits>
+_LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
+auto operator<=>(basic_string_view<_CharT, _Traits> __lhs,
+                 typename common_type<basic_string_view<_CharT, _Traits> >::type __rhs) _NOEXCEPT
+{
+    return __lhs <=> basic_string_view<_CharT, _Traits>(__rhs);
+}
+#endif // _LIBCPP_HAS_NO_SPACESHIP_OPERATOR
 
 
 template<class _CharT, class _Traits>
Index: libcxx/test/std/strings/string.view/string.view.comparison/opcmp.string_view.pointer.pass.cpp
===================================================================
--- /dev/null
+++ libcxx/test/std/strings/string.view/string.view.comparison/opcmp.string_view.pointer.pass.cpp
@@ -0,0 +1,83 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17
+
+// <string>
+
+// template<class charT, class traits, class Allocator>
+//   constexpr bool operator<=>(const charT* lhs, basic_string_view<charT,traits> rhs);
+// template<class charT, class traits, class Allocator>
+//   constexpr bool operator<=>(basic_string_view<charT,traits> lhs, const charT* rhs);
+
+#include <string_view>
+#include <compare>
+#include <cassert>
+
+#include "test_macros.h"
+#include "constexpr_char_traits.h"
+
+template <class S>
+void test(const typename S::value_type* lhs, const S& rhs,
+          std::strong_ordering x, std::strong_ordering y) {
+  assert((lhs <=> rhs) == x);
+  assert((rhs <=> lhs) == y);
+}
+
+int main(int, char**) {
+  {
+    using std::strong_ordering;
+    typedef std::string_view S;
+    test("", S(""), strong_ordering::equal, strong_ordering::equal);
+    test("", S("abcde"), strong_ordering::less, strong_ordering::greater);
+    test("", S("abcdefghij"), strong_ordering::less, strong_ordering::greater);
+    test("", S("abcdefghijklmnopqrst"), strong_ordering::less,
+         strong_ordering::greater);
+    test("abcde", S(""), strong_ordering::greater, strong_ordering::less);
+    test("abcde", S("abcde"), strong_ordering::equal, strong_ordering::equal);
+    test("abcde", S("abcdefghij"), strong_ordering::less,
+         strong_ordering::greater);
+    test("abcde", S("abcdefghijklmnopqrst"), strong_ordering::less,
+         strong_ordering::greater);
+    test("abcdefghij", S(""), strong_ordering::greater, strong_ordering::less);
+    test("abcdefghij", S("abcde"), strong_ordering::greater,
+         strong_ordering::less);
+    test("abcdefghij", S("abcdefghij"), strong_ordering::equal,
+         strong_ordering::equal);
+    test("abcdefghij", S("abcdefghijklmnopqrst"), strong_ordering::less,
+         strong_ordering::greater);
+    test("abcdefghijklmnopqrst", S(""), strong_ordering::greater,
+         strong_ordering::less);
+    test("abcdefghijklmnopqrst", S("abcde"), strong_ordering::greater,
+         strong_ordering::less);
+    test("abcdefghijklmnopqrst", S("abcdefghij"), strong_ordering::greater,
+         strong_ordering::less);
+    test("abcdefghijklmnopqrst", S("abcdefghijklmnopqrst"),
+         strong_ordering::equal, strong_ordering::equal);
+  }
+
+  {
+    typedef std::basic_string_view<char, constexpr_char_traits<char> > SV;
+    constexpr SV sv1;
+    constexpr SV sv2{"abcde", 5};
+
+    static_assert((sv1 <=> "") == std::weak_ordering::equivalent);
+    static_assert(("" <=> sv1) == std::weak_ordering::equivalent);
+    static_assert((sv1 <=> "abcde") == std::weak_ordering::less);
+    static_assert(("abcde" <=> sv1) == std::weak_ordering::greater);
+
+    static_assert((sv2 <=> "") == std::weak_ordering::greater);
+    static_assert(("" <=> sv2) == std::weak_ordering::less);
+    static_assert((sv2 <=> "abcde") == std::weak_ordering::equivalent);
+    static_assert(("abcde" <=> sv2) == std::weak_ordering::equivalent);
+    static_assert((sv2 <=> "abcde0") == std::weak_ordering::less);
+    static_assert(("abcde0" <=> sv2) == std::weak_ordering::greater);
+  }
+
+  return 0;
+}
Index: libcxx/test/std/strings/string.view/string.view.comparison/opcmp.string_view.string_view.pass.cpp
===================================================================
--- /dev/null
+++ libcxx/test/std/strings/string.view/string.view.comparison/opcmp.string_view.string_view.pass.cpp
@@ -0,0 +1,82 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17
+
+// <string>
+
+// template<class charT, class traits, class Allocator>
+//   constexpr bool operator<=>(const charT* lhs, basic_string_view<charT,traits> rhs);
+// template<class charT, class traits, class Allocator>
+//   constexpr bool operator<=>(basic_string_view<charT,traits> lhs, const charT* rhs);
+
+#include <string_view>
+#include <compare>
+#include <cassert>
+
+#include "test_macros.h"
+#include "constexpr_char_traits.h"
+
+template <class S>
+void test(const S lhs, const S& rhs, std::strong_ordering x,
+          std::strong_ordering y) {
+  assert((lhs <=> rhs) == x);
+  assert((rhs <=> lhs) == y);
+}
+
+int main(int, char**) {
+  {
+    typedef std::string_view S;
+    test(S(""), S(""), std::strong_ordering::equal,
+         std::strong_ordering::equal);
+    test(S(""), S("abcde"), std::strong_ordering::less,
+         std::strong_ordering::greater);
+    test(S(""), S("abcdefghij"), std::strong_ordering::less,
+         std::strong_ordering::greater);
+    test(S(""), S("abcdefghijklmnopqrst"), std::strong_ordering::less,
+         std::strong_ordering::greater);
+    test(S("abcde"), S(""), std::strong_ordering::greater,
+         std::strong_ordering::less);
+    test(S("abcde"), S("abcde"), std::strong_ordering::equal,
+         std::strong_ordering::equal);
+    test(S("abcde"), S("abcdefghij"), std::strong_ordering::less,
+         std::strong_ordering::greater);
+    test(S("abcde"), S("abcdefghijklmnopqrst"), std::strong_ordering::less,
+         std::strong_ordering::greater);
+    test(S("abcdefghij"), S(""), std::strong_ordering::greater,
+         std::strong_ordering::less);
+    test(S("abcdefghij"), S("abcde"), std::strong_ordering::greater,
+         std::strong_ordering::less);
+    test(S("abcdefghij"), S("abcdefghij"), std::strong_ordering::equal,
+         std::strong_ordering::equal);
+    test(S("abcdefghij"), S("abcdefghijklmnopqrst"), std::strong_ordering::less,
+         std::strong_ordering::greater);
+    test(S("abcdefghijklmnopqrst"), S(""), std::strong_ordering::greater,
+         std::strong_ordering::less);
+    test(S("abcdefghijklmnopqrst"), S("abcde"), std::strong_ordering::greater,
+         std::strong_ordering::less);
+    test(S("abcdefghijklmnopqrst"), S("abcdefghij"),
+         std::strong_ordering::greater, std::strong_ordering::less);
+    test(S("abcdefghijklmnopqrst"), S("abcdefghijklmnopqrst"),
+         std::strong_ordering::equal, std::strong_ordering::equal);
+  }
+
+  {
+    typedef std::basic_string_view<char, constexpr_char_traits<char> > SV;
+    constexpr SV sv1;
+    constexpr SV sv2{"abcde", 5};
+
+    static_assert((sv1 <=> sv2) == std::weak_ordering::less);
+    static_assert((sv2 <=> sv1) == std::weak_ordering::greater);
+
+    static_assert((sv1 <=> sv1) == std::weak_ordering::equivalent);
+    static_assert((sv2 <=> sv2) == std::weak_ordering::equivalent);
+  }
+
+  return 0;
+}