diff --git a/gcc/builtins.cc b/gcc/builtins.cc
index b9d89b409b8..22269318e8c 100644
--- a/gcc/builtins.cc
+++ b/gcc/builtins.cc
@@ -81,6 +81,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "demangle.h"
 #include "gimple-range.h"
 #include "pointer-query.h"
+#include "opts.h"
 
 struct target_builtins default_target_builtins;
 #if SWITCHABLE_TARGET
@@ -7410,7 +7411,9 @@ expand_builtin (tree exp, rtx target, rtx subtarget, machine_mode mode,
 	return target;
       if (fcode == BUILT_IN_MEMCMP_EQ)
 	{
-	  tree newdecl = builtin_decl_explicit (BUILT_IN_MEMCMP);
+	  tree newdecl = builtin_decl_explicit
+	    (extra_libc_functions.has_memcmpeq
+	     ? BUILT_IN___MEMCMPEQ : BUILT_IN_MEMCMP);
 	  TREE_OPERAND (exp, 1) = build_fold_addr_expr (newdecl);
 	}
       break;
diff --git a/gcc/builtins.def b/gcc/builtins.def
index 005976f34e9..eb8d33b16e9 100644
--- a/gcc/builtins.def
+++ b/gcc/builtins.def
@@ -965,6 +965,10 @@ DEF_BUILTIN_STUB (BUILT_IN_ALLOCA_WITH_ALIGN_AND_MAX, "__builtin_alloca_with_ali
    equality with zero.  */
 DEF_BUILTIN_STUB (BUILT_IN_MEMCMP_EQ, "__builtin_memcmp_eq")
 
+/* Similar to BUILT_IN_MEMCMP_EQ, but is mapped to __memcmpeq only with
+   -fextra-libc-function=memcmpeq.  */
+DEF_EXT_LIB_BUILTIN (BUILT_IN___MEMCMPEQ, "__memcmpeq", BT_FN_INT_CONST_PTR_CONST_PTR_SIZE, ATTR_PURE_NOTHROW_NONNULL_LEAF)
+
 /* An internal version of strcmp/strncmp, used when the result is only 
    tested for equality with zero.  */
 DEF_BUILTIN_STUB (BUILT_IN_STRCMP_EQ, "__builtin_strcmp_eq")
diff --git a/gcc/common.opt b/gcc/common.opt
index 7ca0cceed82..7a7631682b0 100644
--- a/gcc/common.opt
+++ b/gcc/common.opt
@@ -1587,6 +1587,10 @@ Enum(excess_precision) String(standard) Value(EXCESS_PRECISION_STANDARD)
 EnumValue
 Enum(excess_precision) String(16) Value(EXCESS_PRECISION_FLOAT16)
 
+fextra-libc-function=
+Common Driver Joined
+Specify the extra function in the C library.
+
 ; Whether we permit the extended set of values for FLT_EVAL_METHOD
 ; introduced in ISO/IEC TS 18661-3, or limit ourselves to those in C99/C11.
 fpermitted-flt-eval-methods=
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 8cd5bdddc5d..fe1e3709953 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -676,6 +676,7 @@ Objective-C and Objective-C++ Dialects}.
 -ffixed-@var{reg}  -fexceptions @gol
 -fnon-call-exceptions  -fdelete-dead-exceptions  -funwind-tables @gol
 -fasynchronous-unwind-tables @gol
+-fextra-libc-function=memcmpeq @gol
 -fno-gnu-unique @gol
 -finhibit-size-directive  -fcommon  -fno-ident @gol
 -fpcc-struct-return  -fpic  -fPIC  -fpie  -fPIE  -fno-plt @gol
@@ -17250,6 +17251,11 @@ Generate unwind table in DWARF format, if supported by target machine.  The
 table is exact at each instruction boundary, so it can be used for stack
 unwinding from asynchronous events (such as debugger or garbage collector).
 
+@item -fextra-libc-function=memcmpeq
+@opindex fextra-libc-function
+Generate @code{__memcmpeq}, which was added to GLIBC 2.35, for
+@code{__builtin_memcmp_eq}.
+
 @item -fno-gnu-unique
 @opindex fno-gnu-unique
 @opindex fgnu-unique
diff --git a/gcc/opts.cc b/gcc/opts.cc
index bf06a55456a..e77f0922acc 100644
--- a/gcc/opts.cc
+++ b/gcc/opts.cc
@@ -38,6 +38,9 @@ along with GCC; see the file COPYING3.  If not see
 /* In this file all option sets are explicit.  */
 #undef OPTION_SET_P
 
+/* The list of extra functions in the C library.  */
+extra_libc_function_list extra_libc_functions;
+
 static void set_Wstrict_aliasing (struct gcc_options *opts, int onoff);
 
 /* Names of fundamental debug info formats indexed by enum
@@ -2269,6 +2272,22 @@ parse_no_sanitize_attribute (char *value)
   return flags;
 }
 
+/* Parse -fextra-libc-function= suboptions from ARG.  */
+
+static void
+parse_extra_libc_function (const char *arg)
+{
+  /* Check to see if the string matches a sub-option name.  */
+  if (strcmp (arg, "memcmpeq") == 0)
+    {
+      extra_libc_functions.has_memcmpeq = 1;
+      return;
+    }
+
+  error ("unrecognized argument to %<-fextra-libc-function=%>: %qs",
+	 arg);
+}
+
 /* Parse -fzero-call-used-regs suboptions from ARG, return the FLAGS.  */
 
 unsigned int
@@ -2940,6 +2959,10 @@ common_handle_option (struct gcc_options *opts,
       SET_OPTION_IF_UNSET (opts, opts_set, flag_profile_correction, value);
       break;
 
+    case OPT_fextra_libc_function_:
+      parse_extra_libc_function (arg);
+      break;
+
     case OPT_fprofile_generate_:
       opts->x_profile_data_prefix = xstrdup (arg);
       value = true;
diff --git a/gcc/opts.h b/gcc/opts.h
index a43ce66cffe..e8d8835ba23 100644
--- a/gcc/opts.h
+++ b/gcc/opts.h
@@ -345,6 +345,13 @@ struct cl_option_handlers
 extern const char *opt_fstack_limit_symbol_arg;
 extern int opt_fstack_limit_register_no;
 
+/* The list of extra functions in the C library.  */
+struct extra_libc_function_list
+{
+  unsigned int has_memcmpeq : 1;
+};
+extern extra_libc_function_list extra_libc_functions;
+
 /* Input file names.  */
 
 extern const char **in_fnames;
diff --git a/gcc/testsuite/c-c++-common/memcmpeq-1.c b/gcc/testsuite/c-c++-common/memcmpeq-1.c
new file mode 100644
index 00000000000..487f6cd98db
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/memcmpeq-1.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fextra-libc-function=memcmpeq" } */
+/* { dg-final { scan-assembler "__memcmpeq" } } */
+
+#include <stddef.h>
+
+int
+foo (const char *s1, const char *s2, size_t len)
+{
+  return __builtin_memcmp (s1, s2, len) != 0;
+}
diff --git a/gcc/testsuite/c-c++-common/memcmpeq-2.c b/gcc/testsuite/c-c++-common/memcmpeq-2.c
new file mode 100644
index 00000000000..1773dc2bee1
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/memcmpeq-2.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fextra-libc-function=memcmpeq" } */
+/* { dg-final { scan-assembler "__memcmpeq" } } */
+
+#include <string.h>
+
+int
+foo (const char *s1, const char *s2, size_t len)
+{
+  return memcmp (s1, s2, len) == 0;
+}
diff --git a/gcc/testsuite/c-c++-common/memcmpeq-3.c b/gcc/testsuite/c-c++-common/memcmpeq-3.c
new file mode 100644
index 00000000000..69c9537d572
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/memcmpeq-3.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fextra-libc-function=memcmpeq" } */
+/* { dg-final { scan-assembler-not "__memcmpeq" } } */
+
+#include <string.h>
+
+int
+foo (const char *s1, const char *s2, size_t len)
+{
+  return memcmp (s1, s2, len);
+}
diff --git a/gcc/testsuite/c-c++-common/memcmpeq-4.c b/gcc/testsuite/c-c++-common/memcmpeq-4.c
new file mode 100644
index 00000000000..a448312ea96
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/memcmpeq-4.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+/* { dg-final { scan-assembler-not "__memcmpeq" } } */
+
+#include <stddef.h>
+
+int
+foo (const char *s1, const char *s2, size_t len)
+{
+  return __builtin_memcmp (s1, s2, len) != 0;
+}
diff --git a/gcc/testsuite/c-c++-common/memcmpeq-5.c b/gcc/testsuite/c-c++-common/memcmpeq-5.c
new file mode 100644
index 00000000000..4ef33a1c238
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/memcmpeq-5.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+/* { dg-final { scan-assembler-not "__memcmpeq" } } */
+
+#include <string.h>
+
+int
+foo (const char *s1, const char *s2, size_t len)
+{
+  return memcmp (s1, s2, len) == 0;
+}
diff --git a/gcc/testsuite/c-c++-common/memcmpeq-6.c b/gcc/testsuite/c-c++-common/memcmpeq-6.c
new file mode 100644
index 00000000000..52304df7079
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/memcmpeq-6.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fextra-libc-function=memcmpeq" } */
+/* { dg-final { scan-assembler "__memcmpeq" } } */
+
+#include <stddef.h>
+
+int
+foo (const char *s1, const char *s2, size_t len)
+{
+  return __builtin_memcmp_eq (s1, s2, len) != 0;
+}
diff --git a/gcc/testsuite/c-c++-common/memcmpeq-7.c b/gcc/testsuite/c-c++-common/memcmpeq-7.c
new file mode 100644
index 00000000000..d59765894e7
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/memcmpeq-7.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+/* { dg-final { scan-assembler-not "__memcmpeq" } } */
+
+#include <stddef.h>
+
+int
+foo (const char *s1, const char *s2, size_t len)
+{
+  return __builtin_memcmp_eq (s1, s2, len) != 0;
+}
