diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index 7ea34a2..7c9f6b9 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -1849,11 +1850,12 @@ s-mlib: $(srcdir)/genmultilib Makefile
 	    "$(MULTILIB_REQUIRED)" \
 	    "$(MULTIARCH_DIRNAME)" \
 	    "$(MULTILIB_REUSE)" \
+	    "$(MULTILIB_COMPATIBLE)" \
 	    "@enable_multilib@" \
 	    > tmp-mlib.h; \
 	else \
 	  $(SHELL) $(srcdir)/genmultilib '' '' '' '' '' '' '' '' \
-	    "$(MULTIARCH_DIRNAME)" '' no \
+	    "$(MULTIARCH_DIRNAME)" '' '' no \
 	    > tmp-mlib.h; \
 	fi
 	$(SHELL) $(srcdir)/../move-if-change tmp-mlib.h multilib.h
diff --git a/gcc/gcc.c b/gcc/gcc.c
index 7c15cf3..4337315 100644
--- a/gcc/gcc.c
+++ b/gcc/gcc.c
@@ -900,6 +900,7 @@ static const char *multilib_matches;
 static const char *multilib_defaults;
 static const char *multilib_exclusions;
 static const char *multilib_reuse;
+static const char *multilib_compatible;
 
 /* Check whether a particular argument is a default argument.  */
 
@@ -1221,20 +1222,28 @@ static const char *const standard_startfile_prefix_2
    relative to the driver.  */
 static const char *const tooldir_base_prefix = TOOLDIR_BASE_PREFIX;
 
-/* Subdirectory to use for locating libraries.  Set by
-   set_multilib_dir based on the compilation options.  */
+/* Subdirectories to use for locating libraries.  Set by
+   set_multilib_dir based on the compilation options.
+   Array length is in multilib_dir_cnt.  */
 
-static const char *multilib_dir;
+static const char **multilib_dir;
 
 /* Subdirectory to use for locating libraries in OS conventions.  Set by
-   set_multilib_dir based on the compilation options.  */
+   set_multilib_dir based on the compilation options.
+   Array length is in multilib_dir_cnt.  */
 
-static const char *multilib_os_dir;
+static const char **multilib_os_dir;
 
 /* Subdirectory to use for locating libraries in multiarch conventions.  Set by
-   set_multilib_dir based on the compilation options.  */
+   set_multilib_dir based on the compilation options.
+   Array length is in multilib_dir_cnt.  */
+
+static const char **multiarch_dir;
+
+/* Length of multilib_dir, multilib_os_dir, multiarch_dir.  Set by
+   set_multilib_dir.  */
+static int multilib_dir_cnt;
 
-static const char *multiarch_dir;
 
 /* Structure to keep track of the specs that have been defined so far.
    These are accessed using %(specname) in a compiler or link
@@ -1294,6 +1303,7 @@ static struct spec_list static_specs[] =
   INIT_STATIC_SPEC ("multilib_exclusions",	&multilib_exclusions),
   INIT_STATIC_SPEC ("multilib_options",		&multilib_options),
   INIT_STATIC_SPEC ("multilib_reuse",		&multilib_reuse),
+  INIT_STATIC_SPEC ("multilib_compatible",	&multilib_compatible),
   INIT_STATIC_SPEC ("linker",			&linker_name_spec),
   INIT_STATIC_SPEC ("linker_plugin_file",	&linker_plugin_file_spec),
   INIT_STATIC_SPEC ("lto_wrapper",		&lto_wrapper_spec),
@@ -2143,6 +2153,120 @@ clear_failure_queue (void)
   failure_delete_queue = 0;
 }
 
+
+/* Helper function for for_each_path.  Handles a single compatible
+   multidir set.  Paths without multilib suffix are handled only
+   when SKIP_NO_MULTILIB is 0.  */
+
+static void *
+for_each_path_1 (const struct path_prefix *paths,
+		 size_t extra_space,
+		 void *(*callback) (char *, void *),
+		 void *callback_info,
+		 const char *multi_dir,
+		 const char *multi_os_dir,
+		 const char *multiarch_suffix,
+		 const char *multi_suffix,
+		 const char *just_multi_suffix,
+		 bool skip_multi_dir,
+		 bool skip_multi_os_dir)
+{
+  struct prefix_list *pl;
+  char *path = NULL;
+  void *ret = NULL;
+  size_t multi_dir_len = 0;
+  size_t multi_os_dir_len = 0;
+  size_t multiarch_len = 0;
+  size_t suffix_len;
+  size_t just_suffix_len;
+  size_t len;
+
+  if (multi_dir)
+    multi_dir_len = strlen (multi_dir);
+  if (multi_os_dir)
+    multi_os_dir_len = strlen (multi_os_dir);
+  if (multiarch_suffix)
+    multiarch_len = strlen (multiarch_suffix);
+  suffix_len = strlen (multi_suffix);
+  just_suffix_len = strlen (just_multi_suffix);
+
+  if (path == NULL)
+    {
+      len = paths->max_len + extra_space + 1;
+      len += MAX (MAX (suffix_len, multi_os_dir_len), multiarch_len);
+      path = XNEWVEC (char, len);
+    }
+
+  for (pl = paths->plist; pl != 0; pl = pl->next)
+    {
+      len = strlen (pl->prefix);
+      memcpy (path, pl->prefix, len);
+
+      /* Look first in MACHINE/VERSION subdirectory.  */
+      if (!skip_multi_dir)
+	{
+	  memcpy (path + len, multi_suffix, suffix_len + 1);
+	  ret = callback (path, callback_info);
+	  if (ret)
+	    break;
+	}
+
+      /* Some paths are tried with just the machine (ie. target)
+	 subdir.  This is used for finding as, ld, etc.  */
+      if (!skip_multi_dir
+	  && pl->require_machine_suffix == 2)
+	{
+	  memcpy (path + len, just_multi_suffix, just_suffix_len + 1);
+	  ret = callback (path, callback_info);
+	  if (ret)
+	    break;
+	}
+
+      /* Now try the multiarch path.  */
+      if (!skip_multi_dir
+	  && !pl->require_machine_suffix && multiarch_suffix)
+	{
+	  memcpy (path + len, multiarch_suffix, multiarch_len + 1);
+	  ret = callback (path, callback_info);
+	  if (ret)
+	    break;
+	}
+
+      /* Now try the base path.  */
+      if (!pl->require_machine_suffix
+	  && !(pl->os_multilib ? skip_multi_os_dir : skip_multi_dir))
+	{
+	  const char *this_multi;
+	  size_t this_multi_len;
+
+	  if (pl->os_multilib)
+	    {
+	      this_multi = multi_os_dir;
+	      this_multi_len = multi_os_dir_len;
+	    }
+	  else
+	    {
+	      this_multi = multi_dir;
+	      this_multi_len = multi_dir_len;
+	    }
+
+	  if (this_multi_len)
+	    memcpy (path + len, this_multi, this_multi_len + 1);
+	  else
+	    path[len] = '\0';
+
+	  ret = callback (path, callback_info);
+	  if (ret)
+	    break;
+	}
+    }
+
+  if (ret != path)
+    free (path);
+
+  return ret;
+}
+
 /* Call CALLBACK for each path in PATHS, breaking out early if CALLBACK
    returns non-NULL.
    If DO_MULTI is true iterate over the paths twice, first with multilib
@@ -2163,156 +2287,80 @@ for_each_path (const struct path_prefix *paths,
 	       void *(*callback) (char *, void *),
 	       void *callback_info)
 {
-  struct prefix_list *pl;
-  const char *multi_dir = NULL;
-  const char *multi_os_dir = NULL;
-  const char *multiarch_suffix = NULL;
-  const char *multi_suffix;
-  const char *just_multi_suffix;
-  char *path = NULL;
+  bool skip_base_multi_dir = false;
+  bool skip_base_multi_os_dir = false;
   void *ret = NULL;
-  bool skip_multi_dir = false;
-  bool skip_multi_os_dir = false;
-
-  multi_suffix = machine_suffix;
-  just_multi_suffix = just_machine_suffix;
-  if (do_multi && multilib_dir && strcmp (multilib_dir, ".") != 0)
-    {
-      multi_dir = concat (multilib_dir, dir_separator_str, NULL);
-      multi_suffix = concat (multi_suffix, multi_dir, NULL);
-      just_multi_suffix = concat (just_multi_suffix, multi_dir, NULL);
-    }
-  if (do_multi && multilib_os_dir && strcmp (multilib_os_dir, ".") != 0)
-    multi_os_dir = concat (multilib_os_dir, dir_separator_str, NULL);
-  if (multiarch_dir)
-    multiarch_suffix = concat (multiarch_dir, dir_separator_str, NULL);
-
-  while (1)
-    {
-      size_t multi_dir_len = 0;
-      size_t multi_os_dir_len = 0;
-      size_t multiarch_len = 0;
-      size_t suffix_len;
-      size_t just_suffix_len;
-      size_t len;
-
-      if (multi_dir)
-	multi_dir_len = strlen (multi_dir);
-      if (multi_os_dir)
-	multi_os_dir_len = strlen (multi_os_dir);
-      if (multiarch_suffix)
-	multiarch_len = strlen (multiarch_suffix);
-      suffix_len = strlen (multi_suffix);
-      just_suffix_len = strlen (just_multi_suffix);
-
-      if (path == NULL)
-	{
-	  len = paths->max_len + extra_space + 1;
-	  len += MAX (MAX (suffix_len, multi_os_dir_len), multiarch_len);
-	  path = XNEWVEC (char, len);
-	}
-
-      for (pl = paths->plist; pl != 0; pl = pl->next)
-	{
-	  len = strlen (pl->prefix);
-	  memcpy (path, pl->prefix, len);
-
-	  /* Look first in MACHINE/VERSION subdirectory.  */
-	  if (!skip_multi_dir)
-	    {
-	      memcpy (path + len, multi_suffix, suffix_len + 1);
-	      ret = callback (path, callback_info);
-	      if (ret)
-		break;
-	    }
+  int i;
 
-	  /* Some paths are tried with just the machine (ie. target)
-	     subdir.  This is used for finding as, ld, etc.  */
-	  if (!skip_multi_dir
-	      && pl->require_machine_suffix == 2)
+  if (do_multi && multilib_dir)
+    for (i = 0; i < multilib_dir_cnt; i++)
+      {
+	const char *multi_dir = NULL;
+	const char *multi_os_dir = NULL;
+	const char *multiarch_suffix = NULL;
+	const char *multi_suffix = machine_suffix;
+	const char *just_multi_suffix = just_machine_suffix;
+	bool skip_multi_dir = false;
+	bool skip_multi_os_dir = false;
+	int j;
+
+	if (do_multi && multilib_dir[i] && strcmp (multilib_dir[i], ".") != 0)
+	  {
+	    multi_dir = concat (multilib_dir[i], dir_separator_str, NULL);
+	    multi_suffix = concat (multi_suffix, multi_dir, NULL);
+	    just_multi_suffix = concat (just_multi_suffix, multi_dir, NULL);
+	  }
+	if (do_multi && multilib_os_dir[i] && strcmp (multilib_os_dir[i], ".") != 0)
+	  multi_os_dir = concat (multilib_os_dir[i], dir_separator_str, NULL);
+	if (multiarch_dir[i])
+	  multiarch_suffix = concat (multiarch_dir[i], dir_separator_str, NULL);
+
+	if (!multi_dir)
+	  skip_base_multi_dir = true;
+	if (!skip_base_multi_os_dir)
+	  skip_base_multi_dir = true;
+
+	for (j = i - 1; j >= 0; j--)
+	  if (strcmp (multilib_dir[i], multilib_dir[j]) == 0)
 	    {
-	      memcpy (path + len, just_multi_suffix, just_suffix_len + 1);
-	      ret = callback (path, callback_info);
-	      if (ret)
-		break;
+	      skip_multi_dir = true;
+	      break;
 	    }
 
-	  /* Now try the multiarch path.  */
-	  if (!skip_multi_dir
-	      && !pl->require_machine_suffix && multiarch_dir)
+	for (j = i - 1; j >= 0; j--)
+	  if (strcmp (multilib_os_dir[i], multilib_os_dir[j]) == 0)
 	    {
-	      memcpy (path + len, multiarch_suffix, multiarch_len + 1);
-	      ret = callback (path, callback_info);
-	      if (ret)
-		break;
+	      skip_multi_os_dir = true;
+	      break;
 	    }
 
-	  /* Now try the base path.  */
-	  if (!pl->require_machine_suffix
-	      && !(pl->os_multilib ? skip_multi_os_dir : skip_multi_dir))
-	    {
-	      const char *this_multi;
-	      size_t this_multi_len;
-
-	      if (pl->os_multilib)
-		{
-		  this_multi = multi_os_dir;
-		  this_multi_len = multi_os_dir_len;
-		}
-	      else
-		{
-		  this_multi = multi_dir;
-		  this_multi_len = multi_dir_len;
-		}
-
-	      if (this_multi_len)
-		memcpy (path + len, this_multi, this_multi_len + 1);
-	      else
-		path[len] = '\0';
+	ret = for_each_path_1 (paths, extra_space, callback,
+			       callback_info, multi_dir, multi_os_dir,
+			       multiarch_suffix, multi_suffix,
+			       just_multi_suffix, skip_multi_dir,
+			       skip_multi_os_dir);
 
-	      ret = callback (path, callback_info);
-	      if (ret)
-		break;
-	    }
-	}
-      if (pl)
-	break;
+	if (multi_dir)
+	  {
+	    free (CONST_CAST (char *, multi_dir));
+	    free (CONST_CAST (char *, multi_suffix));
+	    free (CONST_CAST (char *, just_multi_suffix));
+	  }
+	if (multi_os_dir)
+	  free (CONST_CAST (char *, multi_os_dir));
+	if (multiarch_dir[i])
+	  free (CONST_CAST (char *, multiarch_suffix));
 
-      if (multi_dir == NULL && multi_os_dir == NULL)
-	break;
+	if (ret)
+	  break;
+      }
 
-      /* Run through the paths again, this time without multilibs.
-	 Don't repeat any we have already seen.  */
-      if (multi_dir)
-	{
-	  free (CONST_CAST (char *, multi_dir));
-	  multi_dir = NULL;
-	  free (CONST_CAST (char *, multi_suffix));
-	  multi_suffix = machine_suffix;
-	  free (CONST_CAST (char *, just_multi_suffix));
-	  just_multi_suffix = just_machine_suffix;
-	}
-      else
-	skip_multi_dir = true;
-      if (multi_os_dir)
-	{
-	  free (CONST_CAST (char *, multi_os_dir));
-	  multi_os_dir = NULL;
-	}
-      else
-	skip_multi_os_dir = true;
-    }
+  if (!ret)
+    ret = for_each_path_1 (paths, extra_space, callback, callback_info,
+			   NULL, NULL, NULL, machine_suffix,
+			   just_machine_suffix, skip_base_multi_dir,
+			   skip_base_multi_os_dir);
 
-  if (multi_dir)
-    {
-      free (CONST_CAST (char *, multi_dir));
-      free (CONST_CAST (char *, multi_suffix));
-      free (CONST_CAST (char *, just_multi_suffix));
-    }
-  if (multi_os_dir)
-    free (CONST_CAST (char *, multi_os_dir));
-  if (ret != path)
-    free (path);
   return ret;
 }
 
@@ -5003,21 +5051,21 @@ do_spec_1 (const char *spec, int inswitch, const char *soft_matched_part)
 	    {
 	      struct spec_path_info info;
 
-	      if (multilib_dir)
+	      if (multilib_dir && multilib_dir[0])
 		{
 		  do_spec_1 ("-imultilib", 1, NULL);
 		  /* Make this a separate argument.  */
 		  do_spec_1 (" ", 0, NULL);
-		  do_spec_1 (multilib_dir, 1, NULL);
+		  do_spec_1 (multilib_dir[0], 1, NULL);
 		  do_spec_1 (" ", 0, NULL);
 		}
 
-	      if (multiarch_dir)
+	      if (multiarch_dir && multiarch_dir[0])
 		{
 		  do_spec_1 ("-imultiarch", 1, NULL);
 		  /* Make this a separate argument.  */
 		  do_spec_1 (" ", 0, NULL);
-		  do_spec_1 (multiarch_dir, 1, NULL);
+		  do_spec_1 (multiarch_dir[0], 1, NULL);
 		  do_spec_1 (" ", 0, NULL);
 		}
 
@@ -5054,7 +5102,8 @@ do_spec_1 (const char *spec, int inswitch, const char *soft_matched_part)
 	      info.append = "include-fixed";
 	      if (*sysroot_hdrs_suffix_spec)
 		info.append = concat (info.append, dir_separator_str,
-				      multilib_dir, NULL);
+				      multilib_dir ? multilib_dir[0] : NULL,
+				      NULL);
 	      info.append_len = strlen (info.append);
 	      for_each_path (&include_prefixes, false, info.append_len,
 			     spec_path, &info);
@@ -5242,11 +5291,11 @@ do_spec_1 (const char *spec, int inswitch, const char *soft_matched_part)
 	    break;
 
 	  case 'M':
-	    if (multilib_os_dir == NULL)
+	    if (multilib_os_dir == NULL || multilib_os_dir[0] == NULL)
 	      obstack_1grow (&obstack, '.');
 	    else
-	      obstack_grow (&obstack, multilib_os_dir,
-			    strlen (multilib_os_dir));
+	      obstack_grow (&obstack, multilib_os_dir[0],
+			    strlen (multilib_os_dir[0]));
 	    break;
 
 	  case 'G':
@@ -6377,6 +6426,13 @@ main (int argc, char **argv)
     obstack_1grow (&multilib_obstack, 0);
     multilib_reuse = XOBFINISH (&multilib_obstack, const char *);
 
+    q = multilib_compatible_raw;
+    while ((p = *q++) != (char *) 0)
+      obstack_grow (&multilib_obstack, p, strlen (p));
+
+    obstack_1grow (&multilib_obstack, 0);
+    multilib_compatible = XOBFINISH (&multilib_obstack, const char *);
+
     need_space = FALSE;
     for (i = 0; i < ARRAY_SIZE (multilib_defaults_raw); i++)
       {
@@ -6691,19 +6747,19 @@ main (int argc, char **argv)
 
   if (print_multi_directory)
     {
-      if (multilib_dir == NULL)
+      if (multilib_dir == NULL || multilib_dir[0] == NULL)
 	printf (".\n");
       else
-	printf ("%s\n", multilib_dir);
+	printf ("%s\n", multilib_dir[0]);
       return (0);
     }
 
   if (print_multiarch)
     {
-      if (multiarch_dir == NULL)
+      if (multiarch_dir == NULL || multiarch_dir[0] == NULL)
 	printf ("\n");
       else
-	printf ("%s\n", multiarch_dir);
+	printf ("%s\n", multiarch_dir[0]);
       return (0);
     }
 
@@ -6721,10 +6777,10 @@ main (int argc, char **argv)
 
   if (print_multi_os_directory)
     {
-      if (multilib_os_dir == NULL)
+      if (multilib_os_dir == NULL || multilib_os_dir[0] == NULL)
 	printf (".\n");
       else
-	printf ("%s\n", multilib_os_dir);
+	printf ("%s\n", multilib_os_dir[0]);
       return (0);
     }
 
@@ -7491,7 +7547,10 @@ set_multilib_dir (void)
   const char *this_path, *this_arg;
   const char *start, *end;
   int not_arg;
-  int ok, ndfltok, first;
+  int ok, ndfltok, first, ndfltfirst;
+  int base_len;
+  const char *compatible_start;
+  int dirno;
 
   n_mdswitches = 0;
   start = multilib_defaults;
@@ -7590,7 +7649,20 @@ set_multilib_dir (void)
       ++p;
     }
 
+  multilib_dir_cnt = 1;
+  dirno = 0;
+  multilib_dir = CONST_CAST (const char **,
+			     XNEWVEC (char *, multilib_dir_cnt));
+  multilib_os_dir = CONST_CAST (const char **,
+				XNEWVEC (char *, multilib_dir_cnt));
+  multiarch_dir = CONST_CAST (const char **,
+			      XNEWVEC (char *, multilib_dir_cnt));
+  multilib_dir[dirno] = NULL;
+  multilib_os_dir[dirno] = NULL;
+  multiarch_dir[dirno] = NULL;
+
   first = 1;
+  ndfltfirst = 1;
   p = multilib_select;
 
   /* Append multilib reuse rules if any.  With those rules, we can reuse
@@ -7598,6 +7670,11 @@ set_multilib_dir (void)
   if (strlen (multilib_reuse) > 0)
     p = concat (p, multilib_reuse, NULL);
 
+  base_len = strlen (p);
+  if (strlen (multilib_compatible))
+    p = concat (p, multilib_compatible, NULL);
+  compatible_start = p + base_len;
+
   while (*p != '\0')
     {
       /* Ignore newlines.  */
@@ -7673,7 +7750,7 @@ set_multilib_dir (void)
 	    ++p;
 	}
 
-      if (ok && first)
+      if (ok && (first || p > compatible_start))
 	{
 	  if (this_path_len != 1
 	      || this_path[0] != '.')
@@ -7686,12 +7763,35 @@ set_multilib_dir (void)
 	      q = strchr (new_multilib_dir, ':');
 	      if (q != NULL)
 		*q = '\0';
-	      multilib_dir = new_multilib_dir;
+
+	      /* Allocate new set of dirs if we handle
+		 compatible multidir.  */
+	      if (!first)
+		{
+		  multilib_dir_cnt++;
+		  dirno++;
+		  multilib_dir = CONST_CAST (const char **,
+					     XRESIZEVEC (char *,
+							 multilib_dir,
+							 multilib_dir_cnt));
+		  multilib_os_dir = CONST_CAST (const char **,
+						XRESIZEVEC (char *,
+							    multilib_os_dir,
+							    multilib_dir_cnt));
+		  multiarch_dir = CONST_CAST (const char **,
+					      XRESIZEVEC (char *,
+							  multiarch_dir,
+							  multilib_dir_cnt));
+		  multilib_dir[dirno] = NULL;
+		  multilib_os_dir[dirno] = NULL;
+		  multiarch_dir[dirno] = NULL;
+		}
+	      multilib_dir[dirno] = new_multilib_dir;
 	    }
 	  first = 0;
 	}
 
-      if (ndfltok)
+      if (ndfltok && (ndfltfirst || p > compatible_start))
 	{
 	  const char *q = this_path, *end = this_path + this_path_len;
 
@@ -7709,30 +7809,34 @@ set_multilib_dir (void)
 	      new_multilib_os_dir = XNEWVEC (char, ml_end - q);
 	      memcpy (new_multilib_os_dir, q + 1, ml_end - q - 1);
 	      new_multilib_os_dir[ml_end - q - 1] = '\0';
-	      multilib_os_dir = *new_multilib_os_dir ? new_multilib_os_dir : ".";
+	      multilib_os_dir[dirno] =
+		*new_multilib_os_dir ? new_multilib_os_dir : ".";
 
 	      if (q2 < end && *q2 == ':')
 		{
 		  char *new_multiarch_dir = XNEWVEC (char, end - q2);
 		  memcpy (new_multiarch_dir, q2 + 1, end - q2 - 1);
 		  new_multiarch_dir[end - q2 - 1] = '\0';
-		  multiarch_dir = new_multiarch_dir;
+		  multiarch_dir[dirno] = new_multiarch_dir;
 		}
-	      break;
+	      ndfltfirst = 0;
 	    }
 	}
 
       ++p;
     }
 
-  if (multilib_dir == NULL && multilib_os_dir != NULL
-      && strcmp (multilib_os_dir, ".") == 0)
+  for (dirno = 0; dirno < multilib_dir_cnt; dirno++)
     {
-      free (CONST_CAST (char *, multilib_os_dir));
-      multilib_os_dir = NULL;
+      if (multilib_dir[dirno] == NULL && multilib_os_dir[dirno] != NULL
+	  && strcmp (multilib_os_dir[dirno], ".") == 0)
+	{
+	  free (CONST_CAST (char *, multilib_os_dir[dirno]));
+	  multilib_os_dir[dirno] = NULL;
+	}
+      else if (multilib_dir[dirno] != NULL && multilib_os_dir[dirno] == NULL)
+	multilib_os_dir[dirno] = multilib_dir[dirno];
     }
-  else if (multilib_dir != NULL && multilib_os_dir == NULL)
-    multilib_os_dir = multilib_dir;
 }
 
 /* Print out the multiple library subdirectory selection
diff --git a/gcc/genmultilib b/gcc/genmultilib
index 3e6046b..9a3f862 100644
--- a/gcc/genmultilib
+++ b/gcc/genmultilib
@@ -88,6 +88,9 @@
 # The optional tenth argument specifies how to reuse multilib for different
 # option sets.
 
+# The optional eleventh argument specifies which multilibs are compatible
+# to allow library re-use when required version is missing.
+
 # The last option should be "yes" if multilibs are enabled.  If it is not
 # "yes", all GCC multilib dir names will be ".".
 
@@ -139,7 +142,8 @@ osdirnames=$7
 multilib_required=$8
 multiarch=$9
 multilib_reuse=${10}
-enable_multilib=${11}
+multilib_compatible=${11}
+enable_multilib=${12}
 
 echo "static const char *const multilib_raw[] = {"
 
@@ -488,6 +492,35 @@ done
 echo "NULL"
 echo "};"
 
+# Output rules used for multilib compatibility.
+echo ""
+echo "static const char *const multilib_compatible_raw[] = {"
+for rrule in ${multilib_compatible}; do
+  # The left part of the rule are the options we used to build multilib.
+  # The right part of the rule are the options multilib is compatible with.
+  combo=`echo ${rrule} | sed -e 's/=.*$//' -e 's/\./=/g'`
+  copts=`echo ${rrule} | sed -e 's/^.*=//' -e 's/\./=/g'`
+  # The variable ${combinations} are the option combinations we will build
+  # multilib from.  If the combination in the left part of reuse rule isn't
+  # in this variable, it means no multilib will be built for current reuse
+  # rule.  Thus the reuse purpose specified by current rule is meaningless.
+  if expr "${combinations} " : ".*/${combo}/.*" > /dev/null; then
+    combo="/${combo}/"
+    dirout=`./tmpmultilib3 "${combo}" "${todirnames}" "${toosdirnames}" "${enable_multilib}"`
+    copts="/${copts}/"
+    optout=`./tmpmultilib4 "${copts}" "${options}"`
+    # Output the line with all appropriate matches.
+    dirout="${dirout}" optout="${optout}" ./tmpmultilib2
+  else
+    echo "The rule ${rrule} is declaring compatibility with nonexistent multilib."
+    exit 1
+  fi
+done
+
+# Terminate the list of string.
+echo "NULL"
+echo "};"
+
 # Output all of the matches now as option and that is the same as that, with
 # a semicolon trailer.  Include all of the normal options as well.
 # Note, the format of the matches is reversed compared
