diff --git a/gcc/config.gcc b/gcc/config.gcc
index 4808b698f3a..c348596b1ac 100644
--- a/gcc/config.gcc
+++ b/gcc/config.gcc
@@ -4615,6 +4615,7 @@ case "${target}" in
 			exit 1
 			;;
 		esac
+		with_arch=`${srcdir}/config/riscv/arch-canonicalize ${with_arch}`
 		tm_defines="${tm_defines} TARGET_RISCV_DEFAULT_ARCH=${with_arch}"
 
 		# Make sure --with-abi is valid.  If it was not specified,
diff --git a/gcc/config/riscv/arch-canonicalize b/gcc/config/riscv/arch-canonicalize
new file mode 100755
index 00000000000..2b4289e320d
--- /dev/null
+++ b/gcc/config/riscv/arch-canonicalize
@@ -0,0 +1,102 @@
+#!/usr/bin/env python
+
+# Tool for canonical RISC-V architecture string.
+# Copyright (C) 2011-2020 Free Software Foundation, Inc.
+# Contributed by Andrew Waterman (andrew@sifive.com).
+#
+# This file is part of GCC.
+#
+# GCC is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GCC is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GCC; see the file COPYING3.  If not see
+# <http://www.gnu.org/licenses/>.
+
+
+from __future__ import print_function
+import sys
+import collections
+import itertools
+from functools import reduce
+
+
+CANONICAL_ORDER = "mafdgqlcbjtpvn"
+LONG_EXT_PREFIXES = ['z', 's', 'h', 'x']
+
+#
+# IMPLIED_EXT(ext) -> implied extension list.
+#
+IMPLIED_EXT = {
+  "d" : ["f"],
+}
+
+def arch_canonicalize(arch):
+  # TODO: Support extension version.
+  new_arch = ""
+  if arch[:5] in ['rv32e', 'rv32i', 'rv32g', 'rv64i', 'rv64g']:
+    # TODO: We should expand g to imad_zifencei once we support newer spec.
+    new_arch = arch[:5].replace("g", "imafd")
+  else:
+    raise Exception("Unexpected arch: `%s`" % arch[:5])
+
+  # Find any Z, S, H or X
+  long_ext_prefixes_idx = map(lambda x: arch.find(x), LONG_EXT_PREFIXES)
+
+  # Filter out any non-existent index.
+  long_ext_prefixes_idx = list(filter(lambda x: x != -1, long_ext_prefixes_idx))
+  if long_ext_prefixes_idx:
+    first_long_ext_idx = min(long_ext_prefixes_idx)
+    long_exts = arch[first_long_ext_idx:].split("_")
+    std_exts = list(arch[5:first_long_ext_idx])
+  else:
+    long_exts = []
+    std_exts = list(arch[5:])
+
+  #
+  # Handle implied extensions.
+  #
+  for ext in std_exts + long_exts:
+    if ext in IMPLIED_EXT:
+      implied_exts = IMPLIED_EXT[ext]
+      for implied_ext in implied_exts:
+        if implied_ext not in std_exts + long_exts:
+          long_exts.append(implied_ext)
+
+  # Single letter extension might appear in the long_exts list,
+  # becasue we just append extensions list to the arch string.
+  std_exts += list(filter(lambda x:len(x) == 1, long_exts))
+
+  # Multi-letter extension must be in lexicographic order.
+  long_exts = list(sorted(filter(lambda x:len(x) != 1, long_exts)))
+
+  # Put extensions in canonical order.
+  for ext in CANONICAL_ORDER:
+    if ext in std_exts:
+      new_arch += ext
+
+  # Check every extension is processed.
+  for ext in std_exts:
+    if ext == '_':
+      continue
+    if ext not in CANONICAL_ORDER:
+      raise Exception("Unsupported extension `%s`" % ext)
+
+  # Concat rest of the multi-char extensions.
+  if long_exts:
+    new_arch += "_" + "_".join(long_exts)
+  return new_arch
+
+if len(sys.argv) < 2:
+  print ("Usage: %s <arch_str> [<arch_str>*]" % sys.argv)
+  sys.exit(1)
+
+for arg in sys.argv[1:]:
+  print (arch_canonicalize(arg))
diff --git a/gcc/config/riscv/multilib-generator b/gcc/config/riscv/multilib-generator
index 0d9ebcb321f..53c51dfa53f 100755
--- a/gcc/config/riscv/multilib-generator
+++ b/gcc/config/riscv/multilib-generator
@@ -35,9 +35,11 @@
 
 from __future__ import print_function
 import sys
+import os
 import collections
 import itertools
 from functools import reduce
+import subprocess
 
 #
 # TODO: Add test for this script.
@@ -48,82 +50,13 @@ abis = collections.OrderedDict()
 required = []
 reuse = []
 
-canonical_order = "mafdgqlcbjtpvn"
-LONG_EXT_PREFIXES = ['z', 's', 'h', 'x']
-
-#
-# IMPLIED_EXT(ext) -> implied extension list.
-#
-IMPLIED_EXT = {
-  "d" : ["f"],
-}
-
 def arch_canonicalize(arch):
-  # TODO: Support extension version.
-  new_arch = ""
-  if arch[:5] in ['rv32e', 'rv32i', 'rv32g', 'rv64i', 'rv64g']:
-    # TODO: We should expand g to imad_zifencei once we support newer spec.
-    new_arch = arch[:5].replace("g", "imafd")
-  else:
-    raise Exception("Unexpected arch: `%s`" % arch[:5])
-
-  # Find any Z, S, H or X
-  long_ext_prefixes_idx = map(lambda x: arch.find(x), LONG_EXT_PREFIXES)
-
-  # Filter out any non-existent index.
-  long_ext_prefixes_idx = list(filter(lambda x: x != -1, long_ext_prefixes_idx))
-  if long_ext_prefixes_idx:
-    first_long_ext_idx = min(long_ext_prefixes_idx)
-    long_exts = arch[first_long_ext_idx:].split("_")
-    std_exts = list(arch[5:first_long_ext_idx])
-  else:
-    long_exts = []
-    std_exts = list(arch[5:])
-
-  #
-  # Handle implied extensions.
-  #
-  for ext in std_exts + long_exts:
-    if ext in IMPLIED_EXT:
-      implied_exts = IMPLIED_EXT[ext]
-      for implied_ext in implied_exts:
-        if implied_ext not in std_exts + long_exts:
-          long_exts.append(implied_ext)
-
-  # Single letter extension might appear in the long_exts list,
-  # becasue we just append extensions list to the arch string.
-  std_exts += list(filter(lambda x:len(x) == 1, long_exts))
-
-  # Multi-letter extension must be in lexicographic order.
-  long_exts = list(sorted(filter(lambda x:len(x) != 1, long_exts)))
-
-  # Put extensions in canonical order.
-  for ext in canonical_order:
-    if ext in std_exts:
-      new_arch += ext
-
-  # Check every extension is processed.
-  for ext in std_exts:
-    if ext == '_':
-      continue
-    if ext not in canonical_order:
-      raise Exception("Unsupported extension `%s`" % ext)
-
-  # Concat rest of the multi-char extensions.
-  if long_exts:
-    new_arch += "_" + "_".join(long_exts)
-  return new_arch
-
-#
-# add underline for each multi-char extensions.
-# e.g. ["a", "zfh"] -> ["a", "_zfh"]
-#
-def add_underline_prefix(ext):
-  for long_ext_prefix in LONG_EXT_PREFIXES:
-    if ext.startswith(long_ext_prefix):
-      return "_" + ext
-
-  return ext
+  this_file = os.path.abspath(os.path.join( __file__))
+  arch_can_script = \
+    os.path.join(os.path.dirname(this_file), "arch-canonicalize")
+  proc = subprocess.Popen([arch_can_script, arch], stdout=subprocess.PIPE)
+  out, err = proc.communicate()
+  return out.strip()
 
 #
 # Handle expansion operation.
