diff --git a/libstdc++-v3/include/bits/char_traits.h b/libstdc++-v3/include/bits/char_traits.h
index 018eac28d0d723529ca623e2652ffb098cd1296d..3074e9bb77e25d2ecfeee8190bf686c4291fa933 100644
--- a/libstdc++-v3/include/bits/char_traits.h
+++ b/libstdc++-v3/include/bits/char_traits.h
@@ -227,19 +227,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 #if __cplusplus >= 202002L
       if (std::__is_constant_evaluated())
 	{
-	  if (__s1 == __s2) // unlikely, but saves a lot of work
-	    return __s1;
-	  const auto __end = __s2 + __n - 1;
-	  bool __overlap = false;
-	  for (std::size_t __i = 0; __i < __n - 1; ++__i)
-	    {
-	      if (__s1 + __i == __end)
-		{
-		  __overlap = true;
-		  break;
-		}
-	    }
-	  if (__overlap)
+	  // Use __builtin_constant_p to avoid comparing unrelated pointers.
+	  if (__builtin_constant_p(__s2 < __s1)
+		&& __s1 > __s2 && __s1 < (__s2 + __n))
 	    {
 	      do
 		{
diff --git a/libstdc++-v3/testsuite/21_strings/char_traits/requirements/113200.cc b/libstdc++-v3/testsuite/21_strings/char_traits/requirements/113200.cc
new file mode 100644
index 0000000000000000000000000000000000000000..0fe765d53bcce4806bb39f8e6d9f9ce11150d568
--- /dev/null
+++ b/libstdc++-v3/testsuite/21_strings/char_traits/requirements/113200.cc
@@ -0,0 +1,20 @@
+// { dg-do compile { target c++20 } }
+
+// PR libstdc++/113200
+// char_traits::move is not constexpr when the argument is a string literal
+
+#include <string_view>
+
+template<std::size_t N> struct S
+{
+  char data_[ N ];
+
+  constexpr S( char const* p ): data_{}
+  {
+    std::char_traits<char>::move( data_, p, N );
+  }
+};
+
+template<std::size_t N> S( char const(&)[N] ) -> S<N>;
+
+constexpr S s( "test" );