public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH v1 1/6] LoongArch: a symmetric multilib subdir layout
@ 2023-08-14  3:57 Yang Yujie
  2023-08-14  3:57 ` [PATCH v1 2/6] LoongArch: improved target configuration interface Yang Yujie
                   ` (5 more replies)
  0 siblings, 6 replies; 27+ messages in thread
From: Yang Yujie @ 2023-08-14  3:57 UTC (permalink / raw)
  To: gcc-patches; +Cc: xry111, xuchenghua, panchenghui, chenglulu, Yang Yujie

Multilib in gcc is asymmetric. i.e. a "default" / "toplevel"
library variant is always built and installed, and:

 * it is installed directly under the gcc libdir (with no suffix);
 * it is selected / searched / linked against when the gcc driver
   does not receive any option from MULTILIB_OPTIONS.

Meanwhile, multilib options from MULTILIB_OPTIONS may add suffixes
(--print-multi-lib) to this base directory and find compatible
library variants there.

However, for LoongArch, we do not want such a "toplevel" library
installation since the default ABI may change.  We expect all
multilib variants of libraries to be installed to their designated
ABI-specific subdirs (e.g. base/lp64d) of the GCC libdir, so that
the default ABI can be configured arbitrarily (with --with-abi)
while the gcc libdir layout stays consistent.  This could be
helpful for the distribution packaging of GCC libraries.

This patch achieves this by overriding ${with_multisubdir} of
the "toplevel" library and disabling the duplicate "multilib"
variant (which exists because LA's driver always generates a
normalized "-mabi=" option from self_spec even if it is not
given on the command line, causing the semantics of "toplevel"
library to be duplicate with a non-toplevel one).

Other architectures stay unaffected as long as they do not override
${with_multisubdir} in config-ml.in.

ChangeLog:

        * config-ml.in: add loongarch support.  Allow overriding
        toplevel multisubdir.

libgcc/ChangeLog:

        * config/loongarch/t-loongarch: make symlinks of toplevel
        libgcc.a under gcc/ for passing regression tests.
---
 config-ml.in                        | 39 ++++++++++++++++++++++++++++-
 libgcc/config/loongarch/t-loongarch | 16 ++++++++++++
 2 files changed, 54 insertions(+), 1 deletion(-)

diff --git a/config-ml.in b/config-ml.in
index 68854a4f16c..914cafb4b50 100644
--- a/config-ml.in
+++ b/config-ml.in
@@ -383,6 +383,18 @@ mips*-*-*)
 	  done
 	fi
 	;;
+loongarch*-*-*)
+	old_multidirs="${multidirs}"
+	multidirs=""
+	for x in ${old_multidirs}; do
+	  case "$x" in
+	    `${CC-gcc} --print-multi-directory`) : ;;
+	    *) multidirs="${multidirs} ${x}" ;;
+	  esac
+	done
+
+	with_multisubdir=`${CC-gcc} --print-multi-directory`
+	;;
 msp430-*-*)
 	if [ x$enable_no_exceptions = xno ]
 	then
@@ -509,7 +521,7 @@ multi-do:
 	  compiler="$(CC)"; \
 	  for i in `$${compiler} --print-multi-lib 2>/dev/null`; do \
 	    dir=`echo $$i | sed -e 's/;.*$$//'`; \
-	    if [ "$${dir}" = "." ]; then \
+	    if [ "$${dir}" = "." ] || [ "/$${dir}" = "$(MULTISUBDIR)" ]; then \
 	      true; \
 	    else \
 	      if [ -d ../$${dir}/$${lib} ]; then \
@@ -595,6 +607,12 @@ if [ -z "${with_multisubdir}" ]; then
   ml_subdir=
   ml_builddotdot=
   : # ml_srcdotdot= # already set
+elif [ "${ml_toplevel_p}" = yes ]; then
+  : # When ml_* is set by ${host}.
+  ml_subdir="/${with_multisubdir}"
+  ml_builddotdot=
+  ml_builddotdot_link=`echo ${with_multisubdir} | sed -e 's:[^/][^/]*:..:g'`/
+  : # ml_srcdotdot= # already set
 else
   ml_subdir="/${with_multisubdir}"
   # The '[^/][^/]*' appears that way to work around a SunOS sed bug.
@@ -654,6 +672,25 @@ mv Makefile.tem ${Makefile}
 
 if [ "${ml_toplevel_p}" = yes ]; then
 
+# If multisubdir is set on the top level, create a symbolic link
+# to cope with in-tree regression tests (see dejagnu: libgloss.exp).
+
+if [ -n "${with_multisubdir}" ]; then
+  if [ "${ml_verbose}" = --verbose ]; then
+    echo "Creating multilib link (${with_multisubdir}) for the default library."
+    echo "pwd: `${PWDCMD-pwd}`"
+  fi
+
+  ml_origdir=`${PWDCMD-pwd}`
+  ml_libdir=`echo "$ml_origdir" | sed -e 's,^.*/,,'`
+  # cd to top-level-build-dir/${with_target_subdir}
+  cd ..
+
+  mkdir -p "${with_multisubdir}"
+  ln -sf "${ml_builddotdot_link}${ml_libdir}" "${with_multisubdir}/"
+  cd "${ml_origdir}"
+fi
+
 # We must freshly configure each subdirectory.  This bit of code is
 # actually partially stolen from the main configure script.  FIXME.
 
diff --git a/libgcc/config/loongarch/t-loongarch b/libgcc/config/loongarch/t-loongarch
index 2a7dbf6ca83..791a8c52f24 100644
--- a/libgcc/config/loongarch/t-loongarch
+++ b/libgcc/config/loongarch/t-loongarch
@@ -5,3 +5,19 @@ softfp_int_modes := si di
 softfp_extensions :=
 softfp_truncations :=
 softfp_exclude_libgcc2 := n
+
+# Since we employ a symmetric multilib layout, i.e. the default lib
+# always gets installed to its ${multisubdir} (see config-ml.in),
+# we need to copy it (again) into the GCC directory
+# (without the multilib suffix) in order to keep some regression
+# tests working (libstdc++), because "too many things knows
+# about the layout of the build tree" for now (libgcc/Makefile.in).
+
+# If we are on the top level (default library),
+# copy libgcc into gcc build directory.
+ifneq ($(MULTIDO),true)
+all: install-default-lib
+.PHONY: install-default-lib
+install-default-lib: libgcc.a
+	-$(LN_S) .$(MULTISUBDIR)/libgcc.a $(gcc_objdir)/libgcc.a
+endif
-- 
2.41.0


^ permalink raw reply	[flat|nested] 27+ messages in thread

* [PATCH v1 2/6] LoongArch: improved target configuration interface
  2023-08-14  3:57 [PATCH v1 1/6] LoongArch: a symmetric multilib subdir layout Yang Yujie
@ 2023-08-14  3:57 ` Yang Yujie
  2023-08-14  5:22   ` Xi Ruoyao
                     ` (3 more replies)
  2023-08-14  3:57 ` [PATCH v1 3/6] LoongArch: define preprocessing macros "__loongarch_{arch,tune}" Yang Yujie
                   ` (4 subsequent siblings)
  5 siblings, 4 replies; 27+ messages in thread
From: Yang Yujie @ 2023-08-14  3:57 UTC (permalink / raw)
  To: gcc-patches; +Cc: xry111, xuchenghua, panchenghui, chenglulu, Yang Yujie

The configure script and the GCC driver are updated so that
it is easier to customize and control GCC builds for targeting
different LoongArch implementations.

* Support options for LoongArch SIMD extensions:
  new configure options --with-simd={none,lsx,lasx};
  new driver options -m[no]-l[a]sx / -msimd={none,lsx,lasx}.

* Mark some LoongArch-specific "flags" with overlapping state-changing
  semantics as "driver deferred" so that they could be processed in the
  order they appear in the GCC driver. In this way, the final result can
  be canonicalized into "parameters" (options with "=") for reliable use in
  specs rules or by the compiler proper.

* Enforce the priority of configuration paths (for <parm>={fpu,tune,simd}):
  -m<parm> > -march-implied > --with-<parm> > --with-arch-implied.

* Allow the user to control the compiler options used when building
  GCC libraries for each multilib variant via --with-multilib-list
  and --with-multilib-default.  This could become more useful when
  we have 32-bit support later.

  Example 1: the following configure option
    --with-multilib-list=lp64d/la464/mno-strict-align/msimd=lsx,lp64s/mfpu=32
                          |     |            |         |
                    -mabi=ABI  -march=ARCH  a list of other options
                  (mandatory)  (optional)     (optional)

       builds two sets of libraries:
          lp64d ABI (the default ABI if no --with-abi is given,
                     built with "-march=la464 -mno-strict-align")
          lp64s ABI (built with "-march=abi-default -mfpu=32")

  Example 2: the following 3 configure options

    --with-arch=loongarch64
    --with-multilib-list=lp64d,lp64f,lp64s/la464
    --with-multilib-default=fixed/mno-strict-align/mfpu=64
                             |            |           |
                        -march=ARCH   a list of other options
                         (optional)        (optional)

    is equivalent to (in terms of building libraries):

    --with-multilib-list=\
    lp64d/loongarch64/mno-strict-align/mfpu=64,\
    lp64f/loongarch64/mno-strict-align/mfpu=64,\
    lp64s/la464

  Note:
    1. the GCC driver and compiler proper does not support
       "-march=fixed". "fixed" that appear here acts as a placeholder for
       "use whatever ARCH in --with-arch=ARCH" (or the default value
       of --with-arch=ARCH if --with-arch is not explicitly configured).

    2. if the ARCH part is omitted, "-march=abi-default"
       is used for building all library variants, which
       practically means enabling the minimal ISA features
       that can support the given ABI.

gcc/ChangeLog:

	* gcc/config.gcc: Add new configuration options --with-arch
        and --with-multilib-default; slightly adjust the handling
        of configure-time defaults.
	* gcc/config/loongarch/genopts/loongarch-strings: Add keyword
        "abi-default" as in "-march=abi-default".
	* gcc/config/loongarch/loongarch-str.h: Likewise
	* gcc/config/loongarch/genopts/loongarch.opt.in: Mark flags
        as "driver deferred" so that a state machine could be applied.
	* gcc/config/loongarch/loongarch.opt: Likewise.
	* gcc/config/loongarch/loongarch-cpu.cc: refactor code for
        the new internal representation of -march=native.
	* gcc/config/loongarch/loongarch-cpu.h: Likewise.
	* gcc/config/loongarch/loongarch-c.cc: Likewise.
	* gcc/config/loongarch/loongarch-def.c: add SIMD attributes
        for struct loongarch_target.
	* gcc/config/loongarch/loongarch-def.h: Likewise.
	* gcc/config/loongarch/loongarch-driver.cc: Implement a state
        machine to canonicalize flags into parameters.
	* gcc/config/loongarch/loongarch-driver.h: Likewise.
	* gcc/config/loongarch/loongarch-opts.cc: Use the new internal
        target representation as input as well as the output.
	* gcc/config/loongarch/loongarch-opts.h: Likewise.
	* gcc/config/loongarch/loongarch.cc: Likewise
	* gcc/config/loongarch/t-linux: Support building GCC libraries
        with customized compiler options using specs.
        * gcc/doc/invoke.texi: document -m[no-]l[a]sx and -msimd=.
        * gcc/doc/install.texi: document --with-multilib-default
        and --with-multilib list.
---
 gcc/config.gcc                                | 253 +++++++++----
 .../loongarch/genopts/loongarch-strings       |   8 +-
 gcc/config/loongarch/genopts/loongarch.opt.in |  62 +--
 gcc/config/loongarch/la464.md                 |  32 +-
 gcc/config/loongarch/loongarch-c.cc           |   4 +-
 gcc/config/loongarch/loongarch-cpu.cc         | 260 ++++++++-----
 gcc/config/loongarch/loongarch-cpu.h          |   3 +-
 gcc/config/loongarch/loongarch-def.c          |  55 ++-
 gcc/config/loongarch/loongarch-def.h          |  57 +--
 gcc/config/loongarch/loongarch-driver.cc      | 205 +++++-----
 gcc/config/loongarch/loongarch-driver.h       |  40 +-
 gcc/config/loongarch/loongarch-opts.cc        | 352 +++++++++++++-----
 gcc/config/loongarch/loongarch-opts.h         |  61 +--
 gcc/config/loongarch/loongarch-str.h          |   7 +-
 gcc/config/loongarch/loongarch.cc             |  87 +++--
 gcc/config/loongarch/loongarch.opt            |  60 +--
 gcc/config/loongarch/t-linux                  |  25 +-
 gcc/doc/install.texi                          |  44 ++-
 gcc/doc/invoke.texi                           |  29 +-
 19 files changed, 1058 insertions(+), 586 deletions(-)

diff --git a/gcc/config.gcc b/gcc/config.gcc
index 415e0e1ebc5..9412f73fe35 100644
--- a/gcc/config.gcc
+++ b/gcc/config.gcc
@@ -4891,8 +4891,8 @@ case "${target}" in
 		esac
 		;;
 
-	loongarch*-*-*)
-		supported_defaults="abi arch tune fpu"
+	loongarch*-*)
+		supported_defaults="abi arch tune fpu simd multilib-default"
 
 		# Local variables
 		unset \
@@ -4900,7 +4900,6 @@ case "${target}" in
 			abiext_pattern   abiext_default \
 			arch_pattern     arch_default   \
 			fpu_pattern      fpu_default    \
-			tune_pattern     tune_default   \
 			triplet_os       triplet_abi
 
 		# Infer ABI from the triplet.
@@ -4937,20 +4936,17 @@ case "${target}" in
 			  ;;
 		esac
 
+
+
 		# Perform initial sanity checks on --with-* options.
 		case ${with_arch} in
-		"" | loongarch64 | la464) ;; # OK, append here.
+		"" | abi-default | loongarch64 | la464) ;; # OK, append here.
 		native)
 			if test x${host} != x${target}; then
 				echo "--with-arch=native is illegal for cross-compiler." 1>&2
 				exit 1
 			fi
 			;;
-		"")
-			echo "Please set a default value for \${with_arch}" \
-			     "according to your target triplet \"${target}\"." 1>&2
-			exit 1
-			;;
 		*)
 			echo "Unknown arch in --with-arch=$with_arch" 1>&2
 			exit 1
@@ -4985,6 +4981,25 @@ case "${target}" in
 			;;
 		esac
 
+		case ${with_simd} in
+		"" | none) ;;
+		lsx | lasx)  # OK, append here.
+			case ${with_fpu} in
+			64) ;;
+			"") with_fpu=64 ;;
+			*)
+				echo "--with-simd=${with_simd} conflicts with --with-fpu=${with_fpu}" 1>&2
+				exit 1
+				;;
+			esac
+			;;
+
+		*)
+			echo "Unknown SIMD extension in --with-simd=$with_simd" 1>&2
+			exit 1
+			;;
+		esac
+
 
 		# Set default value for with_abi.
 		case ${with_abi} in
@@ -5040,9 +5055,9 @@ case "${target}" in
 		case ${with_abi}/${with_abiext} in
 		lp64*/base)
 			# architectures that support lp64* ABI
-			arch_pattern="native|loongarch64|la464"
+			arch_pattern="native|abi-default|loongarch64|la464"
 			# default architecture for lp64* ABI
-			arch_default="loongarch64"
+			arch_default="abi-default"
 			;;
 		*)
 			echo "Unsupported ABI type ${with_abi}/${with_abiext}." 1>&2
@@ -5112,32 +5127,19 @@ case "${target}" in
 		esac
 
 
-		# Infer default with_tune from with_arch: pass 1
+		# Check default with_tune configuration using with_arch.
 		case ${with_arch} in
-		native)
-			tune_pattern="*"
-			tune_default="native"
-			;;
 		loongarch64)
-			tune_pattern="loongarch64|la464"
-			tune_default="la464"
+			tune_pattern="native|abi-default|loongarch64|la464"
 			;;
 		*)
 			# By default, $with_tune == $with_arch
-			tune_pattern="$with_arch"
+			tune_pattern="*"
 			;;
 		esac
 
-		## Set default value for with_tune.
 		case ${with_tune} in
-		"")
-			if test x${tune_default} != x; then
-				with_tune=${tune_default}
-			else
-				with_tune=${tune_pattern}
-			fi
-			;;
-
+		"") ;; # OK
 		*)
 			if echo "${with_tune}" | grep -E "^${tune_pattern}$" > /dev/null; then
 				: # OK
@@ -5149,6 +5151,46 @@ case "${target}" in
 			;;
 		esac
 
+		# Handle --with-multilib-default
+		if echo "${with_multilib_default}" \
+		| grep -E -e '[[:space:]]' -e '//' -e '/$' -e '^/' > /dev/null 2>&1; then
+			echo "Invalid argument to --with-multilib-default." 1>&2
+			exit 1
+		fi
+
+		if test x${with_multilib_default} = x; then
+			# Use -march=abi-default by default when building libraries.
+			with_multilib_default="/march=abi-default"
+		else
+			unset parse_state component
+			parse_state=arch
+			for component in $(echo "${with_multilib_default}" | tr '/' ' '); do
+				case ${parse_state},${component} in
+				arch,|arch,abi-default)
+					# ABI-default: use the ABI's default ARCH configuration for
+					# multilib library builds, unless otherwise specified
+					# in --with-multilib-list.
+					with_multilib_default="/march=abi-default" ;;
+				arch,fixed)
+					# Fixed: use the default gcc configuration for all multilib
+					# builds by default.
+					with_multilib_default="" ;;
+				arch,native|arch,loongarch64|arch,la464) # OK, append here.
+					with_multilib_default="/march=${component}" ;;
+				arch,*)
+					with_multilib_default="/march=abi-default"
+					with_multilib_default="${with_multilib_default}/${component}" ;;
+				opts,*)
+					with_multilib_default="${with_multilib_default}/${component}" ;;
+				esac
+
+				if test x${parse_state} = xarch; then
+					parse_state=opt;
+				fi
+			done
+			unset parse_state component
+		fi
+
 		# Handle --with-multilib-list.
 		if test x"${with_multilib_list}" = x \
 		   || test x"${with_multilib_list}" = xno \
@@ -5171,25 +5213,21 @@ case "${target}" in
 		# ${with_multilib_list} should not contain whitespaces,
 		# consecutive commas or slashes.
 		if echo "${with_multilib_list}" \
-		| grep -E -e "[[:space:]]" -e '[,/][,/]' -e '[,/]$' -e '^[,/]' > /dev/null; then
+		| grep -E -e "[[:space:]]" -e '[,/][,/]' -e '[,/]$' -e '^[,/]' > /dev/null 2>&1; then
 			echo "Invalid argument to --with-multilib-list." 1>&2
 			exit 1
 		fi
 
-		unset component idx elem_abi_base elem_abi_ext elem_tmp
+		unset component elem_abi_base elem_abi_ext elem_tmp parse_state all_abis
 		for elem in $(echo "${with_multilib_list}" | tr ',' ' '); do
-			idx=0
-			while true; do
-				idx=$((idx + 1))
-				component=$(echo "${elem}" | awk -F'/' '{print $'"${idx}"'}')
-
-				case ${idx} in
-				1)
-					# Component 1: Base ABI type
+			unset elem_abi_base elem_abi_ext
+			parse_state="abi-base"
+
+			for component in $(echo "${elem}" | tr '/' ' '); do
+				if test x${parse_state} = x"abi-base"; then
+					# Base ABI type
 					case ${component} in
-					lp64d) elem_tmp="ABI_BASE_LP64D,";;
-					lp64f) elem_tmp="ABI_BASE_LP64F,";;
-					lp64s) elem_tmp="ABI_BASE_LP64S,";;
+					lp64d | lp64f | lp64s) elem_tmp="ABI_BASE_$(tr a-z A-Z <<< ${component}),";;
 					*)
 						echo "Unknown base ABI \"${component}\" in --with-multilib-list." 1>&2
 						exit 1
@@ -5198,47 +5236,101 @@ case "${target}" in
 					loongarch_multilib_list_c="${loongarch_multilib_list_c}${elem_tmp}"
 					loongarch_multilib_list_make="${loongarch_multilib_list_make}mabi=${component}"
 					elem_abi_base="${component}"
-					;;
 
-				2)
-					# Component 2: ABI extension type
+					parse_state="abi-ext"
+					continue
+				fi
+
+				if test x${parse_state} = x"abi-ext"; then
+					# ABI extension type
 					case ${component} in
-					"" | base)
-						component="base"
-						elem_tmp="ABI_EXT_BASE,"
-						;;
-					*)
-						echo "Unknown ABI extension \"${component}\" in --with-multilib-list." 1>&2
-						exit 1
+					base)
+						elem_abi_ext="base"
+						loongarch_multilib_list_c="${loongarch_multilib_list_c}ABI_EXT_BASE,"
+						loongarch_multilib_list_make="${loongarch_multilib_list_make}" # Add nothing for now.
+						parse_state="arch"
+						continue;
 						;;
 					esac
-					loongarch_multilib_list_c="${loongarch_multilib_list_c}${elem_tmp}"
+
+					# The default ABI extension is "base" if unspecified.
+					elem_abi_ext="base"
+					loongarch_multilib_list_c="${loongarch_multilib_list_c}ABI_EXT_BASE,"
 					loongarch_multilib_list_make="${loongarch_multilib_list_make}" # Add nothing for now.
-					elem_abi_ext="${component}"
-					;;
+					parse_state="arch"
+				fi
 
-				*)
-					# Component 3 and on: optional stuff
+				if test x${parse_state} = x"arch"; then
+					# -march option
 					case ${component} in
-					"")
-						# End of component list.
-						break
+					native | abi-default | loongarch64 | la464) # OK, append here.
+						# Append -march spec for each multilib variant.
+						loongarch_multilib_list_make="${loongarch_multilib_list_make}/march=${component}"
+						parse_state="opts"
+						continue
+						;;
+
+					default)
+						# "/default" is equivalent to --with-multilib-default=fixed
+						parse_state="opts"
+						continue
 						;;
+					esac
+
+					# If ARCH is unspecified for this multilib variant, use ${with_multllib_default}.
+					loongarch_multilib_list_make="${loongarch_multilib_list_make}${with_multilib_default}"
+					parse_state="opts"
+				fi
+
+				if test x${parse_state} = x"opts"; then
+					# Other compiler options for building libraries.
+					# (no static sanity check performed)
+					case ${component} in
 					*)
-						echo "Unknown ABI \"${elem}\" in --with-multilib-list." 1>&2
-						exit 1
+						# Append other components as additional build options
+						# (without the prepending dash).
+						# Their validity should be examined by the compiler.
+						loongarch_multilib_list_make="${loongarch_multilib_list_make}/${component}"
 						;;
 					esac
-					;;
-				esac
+				fi
 			done
 
+			case ${parse_state} in
+			    "abi-ext")
+					elem_abi_ext="base"
+					loongarch_multilib_list_c="${loongarch_multilib_list_c}ABI_EXT_BASE,"
+					loongarch_multilib_list_make="${loongarch_multilib_list_make}" # Add nothing for now.
+					loongarch_multilib_list_make="${loongarch_multilib_list_make}${with_multilib_default}"
+					;;
+			    "arch")
+					# If ARCH is unspecified for this multilib variant, use ${with_multllib_default}.
+					loongarch_multilib_list_make="${loongarch_multilib_list_make}${with_multilib_default}"
+					;;
+			    "opts")
+					:
+					;;
+			esac
+
+			# Check for repeated configuration of the same multilib variant.
+			if echo "${elem_abi_base}/${elem_abi_ext}" \
+			 | grep -E "^(${all_abis%|})$" >/dev/null 2>&1; then
+				echo "Repeated multilib config of \"${elem_abi_base}/${elem_abi_ext}\" in --with-multilib-list."
+				exit 1
+			fi
+			all_abis="${all_abis}${elem_abi_base}/${elem_abi_ext}|"
+
+
+			# Check if the default ABI configuration of the GCC binary
+			# is included in the enabled multilib variants.
 			if test x${elem_abi_base} = x${with_abi} \
 			&& test x${elem_abi_ext} = x${with_abiext}; then
 				loongarch_multilib_list_sane=yes
 			fi
 			loongarch_multilib_list_make="${loongarch_multilib_list_make},"
 		done
+		unset component elem_abi_base elem_abi_ext elem_tmp parse_state all_abis
+
 
 		# Check if the default ABI combination is in the default list.
 		if test x${loongarch_multilib_list_sane} = xno; then
@@ -5739,34 +5831,37 @@ case ${target} in
 
 		# Let --with- flags initialize the enum variables from loongarch.opt.
 		# See macro definitions from loongarch-opts.h and loongarch-cpu.h.
-		case ${with_arch} in
-		native)		tm_defines="${tm_defines} DEFAULT_CPU_ARCH=CPU_NATIVE" ;;
-		la464)		tm_defines="${tm_defines} DEFAULT_CPU_ARCH=CPU_LA464" ;;
-		loongarch64)	tm_defines="${tm_defines} DEFAULT_CPU_ARCH=CPU_LOONGARCH64" ;;
-		esac
 
-		case ${with_tune} in
-		native)		tm_defines="${tm_defines} DEFAULT_CPU_TUNE=CPU_NATIVE" ;;
-		la464)		tm_defines="${tm_defines} DEFAULT_CPU_TUNE=CPU_LA464" ;;
-		loongarch64)	tm_defines="${tm_defines} DEFAULT_CPU_TUNE=CPU_LOONGARCH64" ;;
-		esac
+		# Architecture
+		tm_defines="${tm_defines} DEFAULT_CPU_ARCH=CPU_$(echo ${with_arch} | tr a-z- A-Z_)"
 
-		case ${with_abi} in
-		lp64d)     tm_defines="${tm_defines} DEFAULT_ABI_BASE=ABI_BASE_LP64D" ;;
-		lp64f)     tm_defines="${tm_defines} DEFAULT_ABI_BASE=ABI_BASE_LP64F" ;;
-		lp64s)     tm_defines="${tm_defines} DEFAULT_ABI_BASE=ABI_BASE_LP64S" ;;
-		esac
+		# Base ABI type
+		tm_defines="${tm_defines} DEFAULT_ABI_BASE=ABI_BASE_$(echo ${with_abi} | tr a-z- A-Z_)"
 
+		# ABI Extension
 		case ${with_abiext} in
 		base)      tm_defines="${tm_defines} DEFAULT_ABI_EXT=ABI_EXT_BASE" ;;
 		esac
 
+		# Microarchitecture
+		if test x${with_tune} != x; then
+		  tm_defines="${tm_defines} DEFAULT_CPU_TUNE=CPU_$(echo ${with_tune} | tr a-z- A-Z_)"
+		fi
+
+		# FPU adjustment
 		case ${with_fpu} in
-		none)    tm_defines="$tm_defines DEFAULT_ISA_EXT_FPU=ISA_EXT_NOFPU" ;;
+		none)    tm_defines="$tm_defines DEFAULT_ISA_EXT_FPU=ISA_EXT_NONE" ;;
 		32)      tm_defines="$tm_defines DEFAULT_ISA_EXT_FPU=ISA_EXT_FPU32" ;;
 		64)      tm_defines="$tm_defines DEFAULT_ISA_EXT_FPU=ISA_EXT_FPU64" ;;
 		esac
 
+		# SIMD extensions
+		case ${with_simd} in
+		none)    tm_defines="$tm_defines DEFAULT_ISA_EXT_SIMD=ISA_EXT_NONE" ;;
+		lsx)     tm_defines="$tm_defines DEFAULT_ISA_EXT_SIMD=ISA_EXT_SIMD_LSX" ;;
+		lasx)    tm_defines="$tm_defines DEFAULT_ISA_EXT_SIMD=ISA_EXT_SIMD_LASX" ;;
+		esac
+
 		tmake_file="loongarch/t-loongarch $tmake_file"
 		;;
 
diff --git a/gcc/config/loongarch/genopts/loongarch-strings b/gcc/config/loongarch/genopts/loongarch-strings
index a40998ead97..a536be5e708 100644
--- a/gcc/config/loongarch/genopts/loongarch-strings
+++ b/gcc/config/loongarch/genopts/loongarch-strings
@@ -23,6 +23,7 @@ OPTSTR_ARCH	      arch
 OPTSTR_TUNE	      tune
 
 STR_CPU_NATIVE	      native
+STR_CPU_ABI_DEFAULT   abi-default
 STR_CPU_LOONGARCH64   loongarch64
 STR_CPU_LA464	      la464
 
@@ -31,7 +32,7 @@ STR_ISA_BASE_LA64V100 la64
 
 # -mfpu
 OPTSTR_ISA_EXT_FPU    fpu
-STR_ISA_EXT_NOFPU     none
+STR_NONE              none
 STR_ISA_EXT_FPU0      0
 STR_ISA_EXT_FPU32     32
 STR_ISA_EXT_FPU64     64
@@ -40,6 +41,11 @@ OPTSTR_SOFT_FLOAT     soft-float
 OPTSTR_SINGLE_FLOAT   single-float
 OPTSTR_DOUBLE_FLOAT   double-float
 
+# SIMD extensions
+OPTSTR_ISA_EXT_SIMD   simd
+STR_ISA_EXT_LSX       lsx
+STR_ISA_EXT_LASX      lasx
+
 # -mabi=
 OPTSTR_ABI_BASE	      abi
 STR_ABI_BASE_LP64D    lp64d
diff --git a/gcc/config/loongarch/genopts/loongarch.opt.in b/gcc/config/loongarch/genopts/loongarch.opt.in
index 4b9b4ac273e..f3567b27935 100644
--- a/gcc/config/loongarch/genopts/loongarch.opt.in
+++ b/gcc/config/loongarch/genopts/loongarch.opt.in
@@ -17,22 +17,12 @@
 ; <http://www.gnu.org/licenses/>.
 ;
 
-; Variables (macros) that should be exported by loongarch.opt:
-;   la_opt_switches,
-;   la_opt_abi_base, la_opt_abi_ext,
-;   la_opt_cpu_arch, la_opt_cpu_tune,
-;   la_opt_fpu,
-;   la_cmodel.
-
 HeaderInclude
 config/loongarch/loongarch-opts.h
 
 HeaderInclude
 config/loongarch/loongarch-str.h
 
-Variable
-HOST_WIDE_INT la_opt_switches = 0
-
 ; ISA related options
 ;; Base ISA
 Enum
@@ -42,14 +32,13 @@ Basic ISAs of LoongArch:
 EnumValue
 Enum(isa_base) String(@@STR_ISA_BASE_LA64V100@@) Value(ISA_BASE_LA64V100)
 
-
 ;; ISA extensions / adjustments
 Enum
 Name(isa_ext_fpu) Type(int)
 FPU types of LoongArch:
 
 EnumValue
-Enum(isa_ext_fpu) String(@@STR_ISA_EXT_NOFPU@@) Value(ISA_EXT_NOFPU)
+Enum(isa_ext_fpu) String(@@STR_NONE@@) Value(ISA_EXT_NONE)
 
 EnumValue
 Enum(isa_ext_fpu) String(@@STR_ISA_EXT_FPU32@@) Value(ISA_EXT_FPU32)
@@ -58,24 +47,48 @@ EnumValue
 Enum(isa_ext_fpu) String(@@STR_ISA_EXT_FPU64@@) Value(ISA_EXT_FPU64)
 
 m@@OPTSTR_ISA_EXT_FPU@@=
-Target RejectNegative Joined ToLower Enum(isa_ext_fpu) Var(la_opt_fpu) Init(M_OPTION_NOT_SEEN)
+Target RejectNegative Joined ToLower Enum(isa_ext_fpu) Var(la_opt_fpu) Init(M_OPT_UNSET)
 -m@@OPTSTR_ISA_EXT_FPU@@=FPU	Generate code for the given FPU.
 
 m@@OPTSTR_ISA_EXT_FPU@@=@@STR_ISA_EXT_FPU0@@
-Target RejectNegative Alias(m@@OPTSTR_ISA_EXT_FPU@@=,@@STR_ISA_EXT_NOFPU@@)
+Target RejectNegative Alias(m@@OPTSTR_ISA_EXT_FPU@@=,@@STR_NONE@@)
 
 m@@OPTSTR_SOFT_FLOAT@@
-Target Driver RejectNegative Var(la_opt_switches) Mask(FORCE_SOFTF) Negative(m@@OPTSTR_SINGLE_FLOAT@@)
+Target Driver Defer Var(la_deferred_options) RejectNegative Negative(m@@OPTSTR_SINGLE_FLOAT@@)
 Prevent the use of all hardware floating-point instructions.
 
 m@@OPTSTR_SINGLE_FLOAT@@
-Target Driver RejectNegative Var(la_opt_switches) Mask(FORCE_F32) Negative(m@@OPTSTR_DOUBLE_FLOAT@@)
+Target Driver Defer Var(la_deferred_options) RejectNegative Negative(m@@OPTSTR_DOUBLE_FLOAT@@)
 Restrict the use of hardware floating-point instructions to 32-bit operations.
 
 m@@OPTSTR_DOUBLE_FLOAT@@
-Target Driver RejectNegative Var(la_opt_switches) Mask(FORCE_F64) Negative(m@@OPTSTR_SOFT_FLOAT@@)
+Target Driver Defer Var(la_deferred_options) RejectNegative Negative(m@@OPTSTR_SOFT_FLOAT@@)
 Allow hardware floating-point instructions to cover both 32-bit and 64-bit operations.
 
+Enum
+Name(isa_ext_simd) Type(int)
+SIMD extension levels of LoongArch:
+
+EnumValue
+Enum(isa_ext_simd) String(@@STR_NONE@@) Value(ISA_EXT_NONE)
+
+EnumValue
+Enum(isa_ext_simd) String(@@STR_ISA_EXT_LSX@@) Value(ISA_EXT_SIMD_LSX)
+
+EnumValue
+Enum(isa_ext_simd) String(@@STR_ISA_EXT_LASX@@) Value(ISA_EXT_SIMD_LASX)
+
+m@@OPTSTR_ISA_EXT_SIMD@@=
+Target RejectNegative Joined ToLower Enum(isa_ext_simd) Var(la_opt_simd) Init(M_OPT_UNSET)
+-m@@OPTSTR_ISA_EXT_SIMD@@=SIMD	Generate code for the given SIMD extension.
+
+m@@STR_ISA_EXT_LSX@@
+Target Driver Defer Var(la_deferred_options)
+Enable LoongArch SIMD Extension (LSX, 128-bit).
+
+m@@STR_ISA_EXT_LASX@@
+Target Driver Defer Var(la_deferred_options)
+Enable LoongArch Advanced SIMD Extension (LASX, 256-bit).
 
 ;; Base target models (implies ISA & tune parameters)
 Enum
@@ -85,6 +98,9 @@ LoongArch CPU types:
 EnumValue
 Enum(cpu_type) String(@@STR_CPU_NATIVE@@) Value(CPU_NATIVE)
 
+EnumValue
+Enum(cpu_type) String(@@STR_CPU_ABI_DEFAULT@@) Value(CPU_ABI_DEFAULT)
+
 EnumValue
 Enum(cpu_type) String(@@STR_CPU_LOONGARCH64@@) Value(CPU_LOONGARCH64)
 
@@ -92,11 +108,11 @@ EnumValue
 Enum(cpu_type) String(@@STR_CPU_LA464@@) Value(CPU_LA464)
 
 m@@OPTSTR_ARCH@@=
-Target RejectNegative Joined Enum(cpu_type) Var(la_opt_cpu_arch) Init(M_OPTION_NOT_SEEN)
+Target RejectNegative Joined Enum(cpu_type) Var(la_opt_cpu_arch) Init(M_OPT_UNSET)
 -m@@OPTSTR_ARCH@@=PROCESSOR	Generate code for the given PROCESSOR ISA.
 
 m@@OPTSTR_TUNE@@=
-Target RejectNegative Joined Enum(cpu_type) Var(la_opt_cpu_tune) Init(M_OPTION_NOT_SEEN)
+Target RejectNegative Joined Enum(cpu_type) Var(la_opt_cpu_tune) Init(M_OPT_UNSET)
 -m@@OPTSTR_TUNE@@=PROCESSOR	Generate optimized code for PROCESSOR.
 
 
@@ -118,13 +134,13 @@ EnumValue
 Enum(abi_base) String(@@STR_ABI_BASE_LP64S@@) Value(ABI_BASE_LP64S)
 
 m@@OPTSTR_ABI_BASE@@=
-Target RejectNegative Joined ToLower Enum(abi_base) Var(la_opt_abi_base) Init(M_OPTION_NOT_SEEN)
+Target RejectNegative Joined ToLower Enum(abi_base) Var(la_opt_abi_base) Init(M_OPT_UNSET)
 -m@@OPTSTR_ABI_BASE@@=BASEABI	Generate code that conforms to the given BASEABI.
 
+
 ;; ABI Extension
 Variable
-int la_opt_abi_ext = M_OPTION_NOT_SEEN
-
+int la_opt_abi_ext = M_OPT_UNSET
 
 mbranch-cost=
 Target RejectNegative Joined UInteger Var(loongarch_branch_cost)
@@ -182,7 +198,7 @@ EnumValue
 Enum(cmodel) String(@@STR_CMODEL_EXTREME@@) Value(CMODEL_EXTREME)
 
 mcmodel=
-Target RejectNegative Joined Enum(cmodel) Var(la_opt_cmodel) Init(CMODEL_NORMAL)
+Target RejectNegative Joined Enum(cmodel) Var(la_opt_cmodel) Init(M_OPT_UNSET)
 Specify the code model.
 
 mdirect-extern-access
diff --git a/gcc/config/loongarch/la464.md b/gcc/config/loongarch/la464.md
index 541040fdfa8..3b4d14f0b3c 100644
--- a/gcc/config/loongarch/la464.md
+++ b/gcc/config/loongarch/la464.md
@@ -43,88 +43,88 @@
 ;; Describe instruction reservations.
 
 (define_insn_reservation "la464_arith" 1
-  (and (match_test "TARGET_TUNE_LA464")
+  (and (match_test "TARGET_uARCH_LA464")
        (eq_attr "type" "arith,clz,const,logical,
 			move,nop,shift,signext,slt"))
   "la464_alu1 | la464_alu2")
 
 (define_insn_reservation "la464_branch" 1
-  (and (match_test "TARGET_TUNE_LA464")
+  (and (match_test "TARGET_uARCH_LA464")
        (eq_attr "type" "branch,jump,call,condmove,trap"))
   "la464_alu1 | la464_alu2")
 
 (define_insn_reservation "la464_imul" 7
-  (and (match_test "TARGET_TUNE_LA464")
+  (and (match_test "TARGET_uARCH_LA464")
        (eq_attr "type" "imul"))
   "la464_alu1 | la464_alu2")
 
 (define_insn_reservation "la464_idiv_si" 12
-  (and (match_test "TARGET_TUNE_LA464")
+  (and (match_test "TARGET_uARCH_LA464")
        (and (eq_attr "type" "idiv")
 	    (eq_attr "mode" "SI")))
   "la464_alu1 | la464_alu2")
 
 (define_insn_reservation "la464_idiv_di" 25
-  (and (match_test "TARGET_TUNE_LA464")
+  (and (match_test "TARGET_uARCH_LA464")
        (and (eq_attr "type" "idiv")
 	    (eq_attr "mode" "DI")))
   "la464_alu1 | la464_alu2")
 
 (define_insn_reservation "la464_load" 4
-  (and (match_test "TARGET_TUNE_LA464")
+  (and (match_test "TARGET_uARCH_LA464")
        (eq_attr "type" "load"))
   "la464_mem1 | la464_mem2")
 
 (define_insn_reservation "la464_gpr_fp" 16
-  (and (match_test "TARGET_TUNE_LA464")
+  (and (match_test "TARGET_uARCH_LA464")
        (eq_attr "type" "mftg,mgtf"))
   "la464_mem1")
 
 (define_insn_reservation "la464_fpload" 4
-  (and (match_test "TARGET_TUNE_LA464")
+  (and (match_test "TARGET_uARCH_LA464")
        (eq_attr "type" "fpload"))
   "la464_mem1 | la464_mem2")
 
 (define_insn_reservation "la464_prefetch" 0
-  (and (match_test "TARGET_TUNE_LA464")
+  (and (match_test "TARGET_uARCH_LA464")
        (eq_attr "type" "prefetch,prefetchx"))
   "la464_mem1 | la464_mem2")
 
 (define_insn_reservation "la464_store" 0
-  (and (match_test "TARGET_TUNE_LA464")
+  (and (match_test "TARGET_uARCH_LA464")
        (eq_attr "type" "store,fpstore,fpidxstore"))
   "la464_mem1 | la464_mem2")
 
 (define_insn_reservation "la464_fadd" 4
-  (and (match_test "TARGET_TUNE_LA464")
+  (and (match_test "TARGET_uARCH_LA464")
        (eq_attr "type" "fadd,fmul,fmadd"))
   "la464_falu1 | la464_falu2")
 
 (define_insn_reservation "la464_fcmp" 2
-  (and (match_test "TARGET_TUNE_LA464")
+  (and (match_test "TARGET_uARCH_LA464")
        (eq_attr "type" "fabs,fcmp,fmove,fneg"))
   "la464_falu1 | la464_falu2")
 
 (define_insn_reservation "la464_fcvt" 4
-  (and (match_test "TARGET_TUNE_LA464")
+  (and (match_test "TARGET_uARCH_LA464")
        (eq_attr "type" "fcvt"))
   "la464_falu1 | la464_falu2")
 
 (define_insn_reservation "la464_fdiv_sf" 12
-  (and (match_test "TARGET_TUNE_LA464")
+  (and (match_test "TARGET_uARCH_LA464")
        (and (eq_attr "type" "fdiv,frdiv,fsqrt,frsqrt")
 	    (eq_attr "mode" "SF")))
   "la464_falu1 | la464_falu2")
 
 (define_insn_reservation "la464_fdiv_df" 19
-  (and (match_test "TARGET_TUNE_LA464")
+  (and (match_test "TARGET_uARCH_LA464")
        (and (eq_attr "type" "fdiv,frdiv,fsqrt,frsqrt")
 	    (eq_attr "mode" "DF")))
   "la464_falu1 | la464_falu2")
 
 ;; Force single-dispatch for unknown or multi.
 (define_insn_reservation "la464_unknown" 1
-  (and (match_test "TARGET_TUNE_LA464")
+  (and (match_test "TARGET_uARCH_LA464")
        (eq_attr "type" "unknown,multi,atomic,syncloop"))
   "la464_alu1 + la464_alu2 + la464_falu1
    + la464_falu2 + la464_mem1 + la464_mem2")
diff --git a/gcc/config/loongarch/loongarch-c.cc b/gcc/config/loongarch/loongarch-c.cc
index 67911b78f28..660c68f0e06 100644
--- a/gcc/config/loongarch/loongarch-c.cc
+++ b/gcc/config/loongarch/loongarch-c.cc
@@ -61,8 +61,8 @@ loongarch_cpu_cpp_builtins (cpp_reader *pfile)
   builtin_assert ("cpu=loongarch");
   builtin_define ("__loongarch__");
 
-  LARCH_CPP_SET_PROCESSOR ("_LOONGARCH_ARCH", LARCH_ACTUAL_ARCH);
-  LARCH_CPP_SET_PROCESSOR ("_LOONGARCH_TUNE", LARCH_ACTUAL_TUNE);
+  LARCH_CPP_SET_PROCESSOR ("_LOONGARCH_ARCH", la_target.cpu_arch);
+  LARCH_CPP_SET_PROCESSOR ("_LOONGARCH_TUNE", la_target.cpu_tune);
 
   /* Base architecture / ABI.  */
   if (TARGET_64BIT)
diff --git a/gcc/config/loongarch/loongarch-cpu.cc b/gcc/config/loongarch/loongarch-cpu.cc
index 34905f3de30..f76efd7c66f 100644
--- a/gcc/config/loongarch/loongarch-cpu.cc
+++ b/gcc/config/loongarch/loongarch-cpu.cc
@@ -26,6 +26,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "tm.h"
 #include "diagnostic-core.h"
 
+#include "loongarch-def.h"
 #include "loongarch-opts.h"
 #include "loongarch-cpu.h"
 #include "loongarch-str.h"
@@ -80,127 +81,188 @@ get_native_prid_str (void)
 }
 
 /* Fill property tables for CPU_NATIVE.  */
-unsigned int
-fill_native_cpu_config (int p_arch_native, int p_tune_native)
+void
+fill_native_cpu_config (struct loongarch_target *tgt)
 {
-  int ret_cpu_type;
+  int arch_native_p = tgt->cpu_arch == CPU_NATIVE;
+  int tune_native_p = tgt->cpu_tune == CPU_NATIVE;
+  int native_cpu_type = CPU_NATIVE;
 
   /* Nothing needs to be done unless "-march/tune=native"
      is given or implied.  */
-  if (!(p_arch_native || p_tune_native))
-    return CPU_NATIVE;
+  if (!arch_native_p && !tune_native_p)
+    return;
 
   /* Fill cpucfg_cache with the "cpucfg" instruction.  */
   cache_cpucfg ();
 
-
-  /* Fill: loongarch_cpu_default_isa[CPU_NATIVE].base
-     With: base architecture (ARCH)
-     At:   cpucfg_words[1][1:0] */
-
-  #define NATIVE_BASE_ISA (loongarch_cpu_default_isa[CPU_NATIVE].base)
-  switch (cpucfg_cache[1] & 0x3)
-    {
-      case 0x02:
-	NATIVE_BASE_ISA = ISA_BASE_LA64V100;
-	break;
-
-      default:
-	if (p_arch_native)
-	  fatal_error (UNKNOWN_LOCATION,
-		       "unknown base architecture %<0x%x%>, %qs failed",
-		       (unsigned int) (cpucfg_cache[1] & 0x3),
-		       "-m" OPTSTR_ARCH "=" STR_CPU_NATIVE);
-    }
-
-  /* Fill: loongarch_cpu_default_isa[CPU_NATIVE].fpu
-     With: FPU type (FP, FP_SP, FP_DP)
-     At:   cpucfg_words[2][2:0] */
-
-  #define NATIVE_FPU (loongarch_cpu_default_isa[CPU_NATIVE].fpu)
-  switch (cpucfg_cache[2] & 0x7)
-    {
-      case 0x07:
-	NATIVE_FPU = ISA_EXT_FPU64;
-	break;
-
-      case 0x03:
-	NATIVE_FPU = ISA_EXT_FPU32;
-	break;
-
-      case 0x00:
-	NATIVE_FPU = ISA_EXT_NOFPU;
-	break;
-
-      default:
-	if (p_arch_native)
-	  fatal_error (UNKNOWN_LOCATION,
-		       "unknown FPU type %<0x%x%>, %qs failed",
-		       (unsigned int) (cpucfg_cache[2] & 0x7),
-		       "-m" OPTSTR_ARCH "=" STR_CPU_NATIVE);
-    }
-
-  /* Fill: loongarch_cpu_cache[CPU_NATIVE]
-     With: cache size info
-     At:   cpucfg_words[16:20][31:0] */
-
-  int l1d_present = 0, l1u_present = 0;
-  int l2d_present = 0;
-  uint32_t l1_szword, l2_szword;
-
-  l1u_present |= cpucfg_cache[16] & 3;	      /* bit[1:0]: unified l1 cache */
-  l1d_present |= cpucfg_cache[16] & 4;	      /* bit[2:2]: l1 dcache */
-  l1_szword = l1d_present ? 18 : (l1u_present ? 17 : 0);
-  l1_szword = l1_szword ? cpucfg_cache[l1_szword]: 0;
-
-  l2d_present |= cpucfg_cache[16] & 24;	      /* bit[4:3]: unified l2 cache */
-  l2d_present |= cpucfg_cache[16] & 128;      /* bit[7:7]: l2 dcache */
-  l2_szword = l2d_present ? cpucfg_cache[19]: 0;
-
-  loongarch_cpu_cache[CPU_NATIVE].l1d_line_size
-    = 1 << ((l1_szword & 0x7f000000) >> 24);  /* bit[30:24]: log2(linesize) */
-
-  loongarch_cpu_cache[CPU_NATIVE].l1d_size
-    = (1 << ((l1_szword & 0x00ff0000) >> 16)) /* bit[23:16]: log2(idx) */
-    * ((l1_szword & 0x0000ffff) + 1)	      /* bit[15:0]:  sets - 1 */
-    * (1 << ((l1_szword & 0x7f000000) >> 24)) /* bit[30:24]: log2(linesize) */
-    >> 10;				      /* in kilobytes */
-
-  loongarch_cpu_cache[CPU_NATIVE].l2d_size
-    = (1 << ((l2_szword & 0x00ff0000) >> 16)) /* bit[23:16]: log2(idx) */
-    * ((l2_szword & 0x0000ffff) + 1)	      /* bit[15:0]:  sets - 1 */
-    * (1 << ((l2_szword & 0x7f000000) >> 24)) /* bit[30:24]: log2(linesize) */
-    >> 10;				      /* in kilobytes */
-
-  /* Fill: ret_cpu_type
+  /* Fill: tgt->cpu_arch | tgt->cpu_tune
      With: processor ID (PRID)
      At:   cpucfg_words[0][31:0] */
 
   switch (cpucfg_cache[0] & 0x00ffff00)
   {
     case 0x0014c000:   /* LA464 */
-      ret_cpu_type = CPU_LA464;
+      native_cpu_type = CPU_LA464;
       break;
 
     default:
-      /* Unknown PRID.  This is generally harmless as long as
-	 the properties above can be obtained via "cpucfg".  */
-      if (p_tune_native)
+      /* Unknown PRID.  */
+      if (tune_native_p)
 	inform (UNKNOWN_LOCATION, "unknown processor ID %<0x%x%>, "
 		"some tuning parameters will fall back to default",
 		cpucfg_cache[0]);
       break;
   }
 
-  /* Properties that cannot be looked up directly using cpucfg.  */
-  loongarch_cpu_issue_rate[CPU_NATIVE]
-    = loongarch_cpu_issue_rate[ret_cpu_type];
-
-  loongarch_cpu_multipass_dfa_lookahead[CPU_NATIVE]
-    = loongarch_cpu_multipass_dfa_lookahead[ret_cpu_type];
-
-  loongarch_cpu_rtx_cost_data[CPU_NATIVE]
-    = loongarch_cpu_rtx_cost_data[ret_cpu_type];
+  /* if -march=native */
+  if (arch_native_p)
+    {
+      int tmp;
+      tgt->cpu_arch = native_cpu_type;
+
+      /* Fill: loongarch_cpu_default_isa[tgt->cpu_arch].base
+	 With: base architecture (ARCH)
+	 At:   cpucfg_words[1][1:0] */
+
+      #define PRESET_ARCH (loongarch_cpu_default_isa[tgt->cpu_arch].base)
+      switch (cpucfg_cache[1] & 0x3)
+	{
+	  case 0x02:
+	    tmp = ISA_BASE_LA64V100;
+	    break;
+
+	  default:
+	    fatal_error (UNKNOWN_LOCATION,
+			 "unknown native base architecture %<0x%x%>, %qs failed",
+			 (unsigned int) (cpucfg_cache[1] & 0x3),
+			 "-m" OPTSTR_ARCH "=" STR_CPU_NATIVE);
+	}
+
+      /* Check consistency with PRID presets.  */
+      if (native_cpu_type != CPU_NATIVE && tmp != PRESET_ARCH)
+	warning (0, "base architecture %qs differs from PRID preset %qs",
+		 loongarch_isa_base_strings[tmp],
+		 loongarch_isa_base_strings[PRESET_ARCH]);
+
+      /* Use the native value anyways.  */
+      PRESET_ARCH = tmp;
+
+      /* Fill: loongarch_cpu_default_isa[tgt->cpu_arch].fpu
+	 With: FPU type (FP, FP_SP, FP_DP)
+	 At:   cpucfg_words[2][2:0] */
+
+      #define PRESET_FPU (loongarch_cpu_default_isa[tgt->cpu_arch].fpu)
+      switch (cpucfg_cache[2] & 0x7)
+	{
+	  case 0x07:
+	    tmp = ISA_EXT_FPU64;
+	    break;
+
+	  case 0x03:
+	    tmp = ISA_EXT_FPU32;
+	    break;
+
+	  case 0x00:
+	    tmp = ISA_EXT_NONE;
+	    break;
+
+	  default:
+	    fatal_error (UNKNOWN_LOCATION,
+			 "unknown native FPU type %<0x%x%>, %qs failed",
+			 (unsigned int) (cpucfg_cache[2] & 0x7),
+			 "-m" OPTSTR_ARCH "=" STR_CPU_NATIVE);
+	}
+
+      /* Check consistency with PRID presets.  */
+      if (native_cpu_type != CPU_NATIVE && tmp != PRESET_FPU)
+	warning (0, "floating-point unit %qs differs from PRID preset %qs",
+		 loongarch_isa_ext_strings[tmp],
+		 loongarch_isa_ext_strings[PRESET_FPU]);
+
+      /* Use the native value anyways.  */
+      PRESET_FPU = tmp;
+
+
+      /* Fill: loongarch_cpu_default_isa[CPU_NATIVE].simd
+	 With: SIMD extension type (LSX, LASX)
+	 At:   cpucfg_words[2][7:6] */
+
+      #define PRESET_SIMD (loongarch_cpu_default_isa[tgt->cpu_arch].simd)
+      switch (cpucfg_cache[2] & 0xc0)
+	{
+	  case 0xc0:
+	    tmp = ISA_EXT_SIMD_LASX;
+	    break;
+
+	  case 0x40:
+	    tmp = ISA_EXT_SIMD_LSX;
+	    break;
+
+	  case 0x80:
+	    warning (0, "unknown SIMD extension "
+			"(%qs disabled while %qs is enabled), disabling SIMD",
+			loongarch_isa_ext_strings[ISA_EXT_SIMD_LSX],
+			loongarch_isa_ext_strings[ISA_EXT_SIMD_LASX]);
+
+	  case 0x00:
+	    tmp = 0;
+	    break;
+	}
+
+      /* Check consistency with PRID presets.  */
+      /*
+      if (native_cpu_type != CPU_NATIVE && tmp != PRESET_SIMD)
+	warning (0, "SIMD extension %qs differs from PRID preset %qs",
+		 loongarch_isa_ext_strings[tmp],
+		 loongarch_isa_ext_strings[PRESET_SIMD]);
+      */
+
+      /* Use the native value anyways.  */
+      PRESET_SIMD = tmp;
+    }
 
-  return ret_cpu_type;
+  if (tune_native_p)
+    {
+      tgt->cpu_tune = native_cpu_type;
+
+      /* Fill: loongarch_cpu_cache[tgt->cpu_tune]
+	 With: cache size info
+	 At:   cpucfg_words[16:20][31:0] */
+
+      #define PRESET_CACHE (loongarch_cpu_cache[tgt->cpu_tune])
+      struct loongarch_cache native_cache;
+      int l1d_present = 0, l1u_present = 0;
+      int l2d_present = 0;
+      uint32_t l1_szword, l2_szword;
+
+      l1u_present |= cpucfg_cache[16] & 3;	  /* bit[1:0]: unified l1 */
+      l1d_present |= cpucfg_cache[16] & 4;	  /* bit[2:2]: l1d */
+      l1_szword = l1d_present ? 18 : (l1u_present ? 17 : 0);
+      l1_szword = l1_szword ? cpucfg_cache[l1_szword]: 0;
+
+      l2d_present |= cpucfg_cache[16] & 24;	  /* bit[4:3]: unified l2 */
+      l2d_present |= cpucfg_cache[16] & 128;	  /* bit[7:7]: l2d */
+      l2_szword = l2d_present ? cpucfg_cache[19]: 0;
+
+      native_cache.l1d_line_size
+	= 1 << ((l1_szword & 0x7f000000) >> 24);  /* bit[30:24]: log2(line) */
+
+      native_cache.l1d_size
+	= (1 << ((l1_szword & 0x00ff0000) >> 16)) /* bit[23:16]: log2(idx) */
+	* ((l1_szword & 0x0000ffff) + 1)	  /* bit[15:0]:  sets - 1 */
+	* (1 << ((l1_szword & 0x7f000000) >> 24)) /* bit[30:24]: log2(line) */
+	>> 10;					  /* in kibibytes */
+
+      native_cache.l2d_size
+	= (1 << ((l2_szword & 0x00ff0000) >> 16)) /* bit[23:16]: log2(idx) */
+	* ((l2_szword & 0x0000ffff) + 1)	  /* bit[15:0]:  sets - 1 */
+	* (1 << ((l2_szword & 0x7f000000) >> 24)) /* bit[30:24]: log2(linesz) */
+	>> 10;					  /* in kibibytes */
+
+      /* Use the native value anyways.  */
+      PRESET_CACHE.l1d_line_size = native_cache.l1d_line_size;
+      PRESET_CACHE.l1d_size = native_cache.l1d_size;
+      PRESET_CACHE.l2d_size = native_cache.l2d_size;
+    }
 }
diff --git a/gcc/config/loongarch/loongarch-cpu.h b/gcc/config/loongarch/loongarch-cpu.h
index 57ad8456ffa..28618f3cf6c 100644
--- a/gcc/config/loongarch/loongarch-cpu.h
+++ b/gcc/config/loongarch/loongarch-cpu.h
@@ -21,9 +21,10 @@ along with GCC; see the file COPYING3.  If not see
 #define LOONGARCH_CPU_H
 
 #include "system.h"
+#include "loongarch-def.h"
 
 void cache_cpucfg (void);
-unsigned int fill_native_cpu_config (int p_arch_native, int p_tune_native);
+void fill_native_cpu_config (struct loongarch_target *tgt);
 uint32_t get_native_prid (void);
 const char* get_native_prid_str (void);
 
diff --git a/gcc/config/loongarch/loongarch-def.c b/gcc/config/loongarch/loongarch-def.c
index 6729c857f7c..5bbc6923a7f 100644
--- a/gcc/config/loongarch/loongarch-def.c
+++ b/gcc/config/loongarch/loongarch-def.c
@@ -21,25 +21,11 @@ along with GCC; see the file COPYING3.  If not see
 #include "loongarch-def.h"
 #include "loongarch-str.h"
 
-/* Default RTX cost initializer.  */
-#define COSTS_N_INSNS(N) ((N) * 4)
-#define DEFAULT_COSTS				\
-    .fp_add		= COSTS_N_INSNS (1),	\
-    .fp_mult_sf		= COSTS_N_INSNS (2),	\
-    .fp_mult_df		= COSTS_N_INSNS (4),	\
-    .fp_div_sf		= COSTS_N_INSNS (6),	\
-    .fp_div_df		= COSTS_N_INSNS (8),	\
-    .int_mult_si	= COSTS_N_INSNS (1),	\
-    .int_mult_di	= COSTS_N_INSNS (1),	\
-    .int_div_si		= COSTS_N_INSNS (4),	\
-    .int_div_di		= COSTS_N_INSNS (6),	\
-    .branch_cost	= 2,			\
-    .memory_latency	= 4
-
 /* CPU property tables.  */
 const char*
 loongarch_cpu_strings[N_TUNE_TYPES] = {
   [CPU_NATIVE]		  = STR_CPU_NATIVE,
+  [CPU_ABI_DEFAULT]	  = STR_CPU_ABI_DEFAULT,
   [CPU_LOONGARCH64]	  = STR_CPU_LOONGARCH64,
   [CPU_LA464]		  = STR_CPU_LA464,
 };
@@ -49,10 +35,12 @@ loongarch_cpu_default_isa[N_ARCH_TYPES] = {
   [CPU_LOONGARCH64] = {
       .base = ISA_BASE_LA64V100,
       .fpu = ISA_EXT_FPU64,
+      .simd = 0,
   },
   [CPU_LA464] = {
       .base = ISA_BASE_LA64V100,
       .fpu = ISA_EXT_FPU64,
+      .simd = ISA_EXT_SIMD_LASX,
   },
 };
 
@@ -84,6 +72,22 @@ loongarch_cpu_align[N_TUNE_TYPES] = {
   },
 };
 
+
+/* Default RTX cost initializer.  */
+#define COSTS_N_INSNS(N) ((N) * 4)
+#define DEFAULT_COSTS				\
+    .fp_add		= COSTS_N_INSNS (1),	\
+    .fp_mult_sf		= COSTS_N_INSNS (2),	\
+    .fp_mult_df		= COSTS_N_INSNS (4),	\
+    .fp_div_sf		= COSTS_N_INSNS (6),	\
+    .fp_div_df		= COSTS_N_INSNS (8),	\
+    .int_mult_si	= COSTS_N_INSNS (1),	\
+    .int_mult_di	= COSTS_N_INSNS (1),	\
+    .int_div_si		= COSTS_N_INSNS (4),	\
+    .int_div_di		= COSTS_N_INSNS (6),	\
+    .branch_cost	= 2,			\
+    .memory_latency	= 4
+
 /* The following properties cannot be looked up directly using "cpucfg".
  So it is necessary to provide a default value for "unknown native"
  tune targets (i.e. -mtune=native while PRID does not correspond to
@@ -103,7 +107,7 @@ loongarch_cpu_rtx_cost_data[N_TUNE_TYPES] = {
 };
 
 /* RTX costs to use when optimizing for size.  */
-extern const struct loongarch_rtx_cost_data
+const struct loongarch_rtx_cost_data
 loongarch_rtx_cost_optimize_size = {
     .fp_add	      = 4,
     .fp_mult_sf	      = 4,
@@ -144,9 +148,11 @@ loongarch_isa_base_strings[N_ISA_BASE_TYPES] = {
 
 const char*
 loongarch_isa_ext_strings[N_ISA_EXT_TYPES] = {
-  [ISA_EXT_FPU64] = STR_ISA_EXT_FPU64,
+  [ISA_EXT_NONE] = STR_NONE,
   [ISA_EXT_FPU32] = STR_ISA_EXT_FPU32,
-  [ISA_EXT_NOFPU] = STR_ISA_EXT_NOFPU,
+  [ISA_EXT_FPU64] = STR_ISA_EXT_FPU64,
+  [ISA_EXT_SIMD_LSX] = STR_ISA_EXT_LSX,
+  [ISA_EXT_SIMD_LASX] = STR_ISA_EXT_LASX,
 };
 
 const char*
@@ -171,24 +177,17 @@ loongarch_cmodel_strings[] = {
   [CMODEL_EXTREME]	  = STR_CMODEL_EXTREME,
 };
 
-const char*
-loongarch_switch_strings[] = {
-  [SW_SOFT_FLOAT]	  = OPTSTR_SOFT_FLOAT,
-  [SW_SINGLE_FLOAT]	  = OPTSTR_SINGLE_FLOAT,
-  [SW_DOUBLE_FLOAT]	  = OPTSTR_DOUBLE_FLOAT,
-};
-
 
 /* ABI-related definitions.  */
 const struct loongarch_isa
 abi_minimal_isa[N_ABI_BASE_TYPES][N_ABI_EXT_TYPES] = {
   [ABI_BASE_LP64D] = {
-      [ABI_EXT_BASE] = {.base = ISA_BASE_LA64V100, .fpu = ISA_EXT_FPU64},
+      [ABI_EXT_BASE] = {.base = ISA_BASE_LA64V100, .fpu = ISA_EXT_FPU64, .simd = 0},
   },
   [ABI_BASE_LP64F] = {
-      [ABI_EXT_BASE] = {.base = ISA_BASE_LA64V100, .fpu = ISA_EXT_FPU32},
+      [ABI_EXT_BASE] = {.base = ISA_BASE_LA64V100, .fpu = ISA_EXT_FPU32, .simd = 0},
   },
   [ABI_BASE_LP64S] = {
-      [ABI_EXT_BASE] = {.base = ISA_BASE_LA64V100, .fpu = ISA_EXT_NOFPU},
+      [ABI_EXT_BASE] = {.base = ISA_BASE_LA64V100, .fpu = ISA_EXT_NONE, .simd = 0},
   },
 };
diff --git a/gcc/config/loongarch/loongarch-def.h b/gcc/config/loongarch/loongarch-def.h
index fb8bb88eb52..769efcb70fb 100644
--- a/gcc/config/loongarch/loongarch-def.h
+++ b/gcc/config/loongarch/loongarch-def.h
@@ -59,11 +59,13 @@ extern const char* loongarch_isa_base_strings[];
 
 /* enum isa_ext_* */
 extern const char* loongarch_isa_ext_strings[];
-#define ISA_EXT_NOFPU	      0
+#define ISA_EXT_NONE	      0
 #define ISA_EXT_FPU32	      1
 #define ISA_EXT_FPU64	      2
 #define N_ISA_EXT_FPU_TYPES   3
-#define N_ISA_EXT_TYPES	      3
+#define ISA_EXT_SIMD_LSX      3
+#define ISA_EXT_SIMD_LASX     4
+#define N_ISA_EXT_TYPES	      5
 
 /* enum abi_base */
 extern const char* loongarch_abi_base_strings[];
@@ -72,6 +74,16 @@ extern const char* loongarch_abi_base_strings[];
 #define ABI_BASE_LP64S	      2
 #define N_ABI_BASE_TYPES      3
 
+#define TO_LP64_ABI_BASE(C) (C)
+
+#define ABI_FPU_64(abi_base) \
+  (abi_base == ABI_BASE_LP64D)
+#define ABI_FPU_32(abi_base) \
+  (abi_base == ABI_BASE_LP64F)
+#define ABI_FPU_NONE(abi_base) \
+  (abi_base == ABI_BASE_LP64S)
+
+
 /* enum abi_ext */
 extern const char* loongarch_abi_ext_strings[];
 #define ABI_EXT_BASE	      0
@@ -87,55 +99,44 @@ extern const char* loongarch_cmodel_strings[];
 #define CMODEL_EXTREME	      5
 #define N_CMODEL_TYPES	      6
 
-/* enum switches */
-/* The "SW_" codes represent command-line switches (options that
-   accept no parameters). Definition for other switches that affects
-   the target ISA / ABI configuration will also be appended here
-   in the future.  */
-
-extern const char* loongarch_switch_strings[];
-#define SW_SOFT_FLOAT	      0
-#define SW_SINGLE_FLOAT	      1
-#define SW_DOUBLE_FLOAT	      2
-#define N_SWITCH_TYPES	      3
-
 /* The common default value for variables whose assignments
    are triggered by command-line options.  */
 
-#define M_OPTION_NOT_SEEN -1
-#define M_OPT_ABSENT(opt_enum)  ((opt_enum) == M_OPTION_NOT_SEEN)
+#define M_OPT_UNSET -1
+#define M_OPT_ABSENT(opt_enum)  ((opt_enum) == M_OPT_UNSET)
 
 
 /* Internal representation of the target.  */
 struct loongarch_isa
 {
-  unsigned char base;	    /* ISA_BASE_ */
-  unsigned char fpu;	    /* ISA_EXT_FPU_ */
+  int base;	    /* ISA_BASE_ */
+  int fpu;	    /* ISA_EXT_FPU_ */
+  int simd;	    /* ISA_EXT_SIMD_ */
 };
 
 struct loongarch_abi
 {
-  unsigned char base;	    /* ABI_BASE_ */
-  unsigned char ext;	    /* ABI_EXT_ */
+  int base;	    /* ABI_BASE_ */
+  int ext;	    /* ABI_EXT_ */
 };
 
 struct loongarch_target
 {
   struct loongarch_isa isa;
   struct loongarch_abi abi;
-  unsigned char cpu_arch;   /* CPU_ */
-  unsigned char cpu_tune;   /* same */
-  unsigned char cpu_native; /* same */
-  unsigned char cmodel;	    /* CMODEL_ */
+  int cpu_arch;	    /* CPU_ */
+  int cpu_tune;	    /* same */
+  int cmodel;	    /* CMODEL_ */
 };
 
 /* CPU properties.  */
 /* index */
 #define CPU_NATIVE	  0
-#define CPU_LOONGARCH64	  1
-#define CPU_LA464	  2
-#define N_ARCH_TYPES	  3
-#define N_TUNE_TYPES	  3
+#define CPU_ABI_DEFAULT   1
+#define CPU_LOONGARCH64	  2
+#define CPU_LA464	  3
+#define N_ARCH_TYPES	  4
+#define N_TUNE_TYPES	  4
 
 /* parallel tables.  */
 extern const char* loongarch_cpu_strings[];
diff --git a/gcc/config/loongarch/loongarch-driver.cc b/gcc/config/loongarch/loongarch-driver.cc
index 11ce082417f..89ebca59975 100644
--- a/gcc/config/loongarch/loongarch-driver.cc
+++ b/gcc/config/loongarch/loongarch-driver.cc
@@ -26,122 +26,134 @@ along with GCC; see the file COPYING3.  If not see
 #include "tm.h"
 #include "obstack.h"
 #include "diagnostic-core.h"
+#include "opts.h"
 
 #include "loongarch-opts.h"
 #include "loongarch-driver.h"
 
-static int
-  opt_arch_driver = M_OPTION_NOT_SEEN,
-  opt_tune_driver = M_OPTION_NOT_SEEN,
-  opt_fpu_driver = M_OPTION_NOT_SEEN,
-  opt_abi_base_driver = M_OPTION_NOT_SEEN,
-  opt_abi_ext_driver = M_OPTION_NOT_SEEN,
-  opt_cmodel_driver = M_OPTION_NOT_SEEN;
-
-int opt_switches = 0;
-
 /* This flag is set to 1 if we believe that the user might be avoiding
    linking (implicitly) against something from the startfile search paths.  */
 static int no_link = 0;
 
-#define LARCH_DRIVER_SET_M_FLAG(OPTS_ARRAY, N_OPTS, FLAG, STR)	\
-  for (int i = 0; i < (N_OPTS); i++)				\
-  {								\
-    if ((OPTS_ARRAY)[i] != 0)					\
-      if (strcmp ((STR), (OPTS_ARRAY)[i]) == 0)			\
-	(FLAG) = i;						\
-  }
-
 /* Use the public obstack from the gcc driver (defined in gcc.c).
    This is for allocating space for the returned string.  */
 extern struct obstack opts_obstack;
 
-#define APPEND_LTR(S)				      \
-  obstack_grow (&opts_obstack, (const void*) (S),     \
-		sizeof ((S)) / sizeof (char) -1)
-
-#define APPEND_VAL(S) \
-  obstack_grow (&opts_obstack, (const void*) (S), strlen ((S)))
+const char*
+la_driver_init (int argc ATTRIBUTE_UNUSED, const char **argv ATTRIBUTE_UNUSED)
+{
+  /* Initialize all fields of la_target to -1 */
+  loongarch_init_target (&la_target, M_OPT_UNSET, M_OPT_UNSET, M_OPT_UNSET,
+			 M_OPT_UNSET, M_OPT_UNSET, M_OPT_UNSET, M_OPT_UNSET);
+  return "";
+}
 
+const char*
+driver_set_no_link (int argc, const char **argv)
+{
+  no_link = 1;
+  return "";
+}
 
 const char*
-driver_set_m_flag (int argc, const char **argv)
+driver_set_m_parm (int argc, const char **argv)
 {
-  int parm_off = 0;
+  gcc_assert (argc == 2);
+
+#define LARCH_DRIVER_PARSE_PARM(OPT_IDX, NAME, OPTSTR_LIST, \
+				OPT_IDX_LO, OPT_IDX_HI)	    \
+  if (strcmp (argv[0], OPTSTR_##NAME) == 0)		    \
+    for (int i = (OPT_IDX_LO); i < (OPT_IDX_HI); i++)	    \
+    {							    \
+      if ((OPTSTR_LIST)[i] != 0)			    \
+	if (strcmp (argv[1], (OPTSTR_LIST)[i]) == 0)	    \
+	  {						    \
+	    (OPT_IDX) = i;				    \
+	    return 0;					    \
+	  }						    \
+    }
 
-  if (argc != 1)
-    return "%eset_m_flag requires exactly 1 argument.";
+  LARCH_DRIVER_PARSE_PARM (la_target.abi.base, ABI_BASE, \
+			   loongarch_abi_base_strings, 0, N_ABI_BASE_TYPES)
 
-#undef PARM
-#define PARM (argv[0] + parm_off)
+  LARCH_DRIVER_PARSE_PARM (la_target.isa.fpu, ISA_EXT_FPU, \
+			   loongarch_isa_ext_strings, 0, N_ISA_EXT_FPU_TYPES)
 
-/* Note: sizeof (OPTSTR_##NAME) equals the length of "<option>=".  */
-#undef MATCH_OPT
-#define MATCH_OPT(NAME) \
-  (strncmp (argv[0], OPTSTR_##NAME "=", \
-	    (parm_off = sizeof (OPTSTR_##NAME))) == 0)
+  LARCH_DRIVER_PARSE_PARM (la_target.isa.simd, ISA_EXT_SIMD, \
+			   loongarch_isa_ext_strings, 0, N_ISA_EXT_TYPES)
 
-  if (strcmp (argv[0], "no_link") == 0)
-    {
-      no_link = 1;
-    }
-  else if (MATCH_OPT (ABI_BASE))
-    {
-      LARCH_DRIVER_SET_M_FLAG (
-	loongarch_abi_base_strings, N_ABI_BASE_TYPES,
-	opt_abi_base_driver, PARM)
-    }
-  else if (MATCH_OPT (ISA_EXT_FPU))
-    {
-      LARCH_DRIVER_SET_M_FLAG (loongarch_isa_ext_strings, N_ISA_EXT_FPU_TYPES,
-			       opt_fpu_driver, PARM)
-    }
-  else if (MATCH_OPT (ARCH))
-    {
-      LARCH_DRIVER_SET_M_FLAG (loongarch_cpu_strings, N_ARCH_TYPES,
-			       opt_arch_driver, PARM)
-    }
-  else if (MATCH_OPT (TUNE))
-    {
-      LARCH_DRIVER_SET_M_FLAG (loongarch_cpu_strings, N_TUNE_TYPES,
-			       opt_tune_driver, PARM)
-    }
-  else if (MATCH_OPT (CMODEL))
-    {
-      LARCH_DRIVER_SET_M_FLAG (loongarch_cmodel_strings, N_CMODEL_TYPES,
-			       opt_cmodel_driver, PARM)
-    }
-  else /* switches */
-    {
-      int switch_idx = M_OPTION_NOT_SEEN;
+  LARCH_DRIVER_PARSE_PARM (la_target.cpu_arch, ARCH, \
+			   loongarch_cpu_strings, 0, N_ARCH_TYPES)
 
-      LARCH_DRIVER_SET_M_FLAG (loongarch_switch_strings, N_SWITCH_TYPES,
-			       switch_idx, argv[0])
+  LARCH_DRIVER_PARSE_PARM (la_target.cpu_tune, TUNE, \
+			   loongarch_cpu_strings, 0, N_TUNE_TYPES)
 
-      if (switch_idx != M_OPTION_NOT_SEEN)
-	opt_switches |= loongarch_switch_mask[switch_idx];
-    }
-  return "";
+  LARCH_DRIVER_PARSE_PARM (la_target.cmodel, CMODEL, \
+			   loongarch_cmodel_strings, 0, N_CMODEL_TYPES)
+
+  gcc_unreachable ();
+}
+
+static void
+driver_record_deferred_opts (struct loongarch_flags *flags)
+{
+  unsigned int i;
+  cl_deferred_option *opt;
+  vec<cl_deferred_option> *v = (vec<cl_deferred_option> *) la_deferred_options;
+
+  gcc_assert (flags);
+
+  /* Initialize flags */
+  flags->flt = M_OPT_UNSET;
+  flags->flt_str = NULL;
+  flags->sx[0] = flags->sx[1] = 0;
+
+  int sx_flag_idx = 0;
+
+  if (v)
+    FOR_EACH_VEC_ELT (*v, i, opt)
+      {
+	switch (opt->opt_index)
+	  {
+	  case OPT_mlsx:
+	    flags->sx[sx_flag_idx++] = ISA_EXT_SIMD_LSX * (opt->value ? 1 : -1);
+	    break;
+
+	  case OPT_mlasx:
+	    flags->sx[sx_flag_idx++] = ISA_EXT_SIMD_LASX * (opt->value ? 1 : -1);
+	    break;
+
+	  case OPT_msoft_float:
+	    flags->flt = ISA_EXT_NONE;
+	    flags->flt_str = OPTSTR_SOFT_FLOAT;
+	    break;
+
+	  case OPT_msingle_float:
+	    flags->flt = ISA_EXT_FPU32;
+	    flags->flt_str = OPTSTR_SINGLE_FLOAT;
+	    break;
+
+	  case OPT_mdouble_float:
+	    flags->flt = ISA_EXT_FPU64;
+	    flags->flt_str = OPTSTR_DOUBLE_FLOAT;
+	    break;
+
+	  default:
+	    gcc_unreachable ();
+	  }
+	gcc_assert (sx_flag_idx <= 2);
+      }
 }
 
 const char*
-driver_get_normalized_m_opts (int argc, const char **argv)
+driver_get_normalized_m_opts (int argc, const char **argv ATTRIBUTE_UNUSED)
 {
   if (argc != 0)
-    {
-      (void) argv;  /* To make compiler shut up about unused argument.  */
-      return " %eget_normalized_m_opts requires no argument.\n";
-    }
+    return " %eget_normalized_m_opts requires no argument.\n";
 
-  loongarch_config_target (& la_target,
-			   opt_switches,
-			   opt_arch_driver,
-			   opt_tune_driver,
-			   opt_fpu_driver,
-			   opt_abi_base_driver,
-			   opt_abi_ext_driver,
-			   opt_cmodel_driver,
-			   !no_link /* follow_multilib_list */);
+  struct loongarch_flags flags;
+  driver_record_deferred_opts (&flags);
+  loongarch_config_target (&la_target, &flags, !no_link /* follow_multilib_list */);
 
   /* Output normalized option strings.  */
   obstack_blank (&opts_obstack, 0);
@@ -160,11 +172,15 @@ driver_get_normalized_m_opts (int argc, const char **argv)
    APPEND_LTR (" %<m" OPTSTR_##NAME "=* " \
 	       " -m" OPTSTR_##NAME "=")
 
-  for (int i = 0; i < N_SWITCH_TYPES; i++)
-    {
-      APPEND_LTR (" %<m");
-      APPEND_VAL (loongarch_switch_strings[i]);
-    }
+#undef CLEAR_FLAG
+#define CLEAR_FLAG(NAME) \
+  APPEND_LTR ( " %<m" NAME " %<mno-" NAME )
+
+  CLEAR_FLAG (STR_ISA_EXT_LSX);
+  CLEAR_FLAG (STR_ISA_EXT_LASX);
+  CLEAR_FLAG (OPTSTR_SOFT_FLOAT);
+  CLEAR_FLAG (OPTSTR_SINGLE_FLOAT);
+  CLEAR_FLAG (OPTSTR_DOUBLE_FLOAT);
 
   APPEND_OPT (ABI_BASE);
   APPEND_VAL (loongarch_abi_base_strings[la_target.abi.base]);
@@ -175,6 +191,9 @@ driver_get_normalized_m_opts (int argc, const char **argv)
   APPEND_OPT (ISA_EXT_FPU);
   APPEND_VAL (loongarch_isa_ext_strings[la_target.isa.fpu]);
 
+  APPEND_OPT (ISA_EXT_SIMD);
+  APPEND_VAL (loongarch_isa_ext_strings[la_target.isa.simd]);
+
   APPEND_OPT (CMODEL);
   APPEND_VAL (loongarch_cmodel_strings[la_target.cmodel]);
 
diff --git a/gcc/config/loongarch/loongarch-driver.h b/gcc/config/loongarch/loongarch-driver.h
index ba8817a4621..b39b96dec36 100644
--- a/gcc/config/loongarch/loongarch-driver.h
+++ b/gcc/config/loongarch/loongarch-driver.h
@@ -24,33 +24,37 @@ along with GCC; see the file COPYING3.  If not see
 #include "loongarch-str.h"
 
 extern const char*
-driver_set_m_flag (int argc, const char **argv);
+la_driver_init (int argc, const char **argv);
+
+extern const char*
+driver_set_m_parm (int argc, const char **argv);
+
+extern const char*
+driver_set_no_link (int argc, const char **argv);
 
 extern const char*
 driver_get_normalized_m_opts (int argc, const char **argv);
 
 #define EXTRA_SPEC_FUNCTIONS \
-  { "set_m_flag", driver_set_m_flag  }, \
+  { "driver_init", la_driver_init }, \
+  { "set_m_parm", driver_set_m_parm  }, \
+  { "set_no_link", driver_set_no_link }, \
   { "get_normalized_m_opts", driver_get_normalized_m_opts  },
 
 /* Pre-process ABI-related options.  */
 #define LA_SET_PARM_SPEC(NAME) \
-  " %{m" OPTSTR_##NAME  "=*: %:set_m_flag(" OPTSTR_##NAME "=%*)}" \
-
-#define LA_SET_FLAG_SPEC(NAME) \
-  " %{m" OPTSTR_##NAME  ": %:set_m_flag(" OPTSTR_##NAME ")}" \
-
-#define DRIVER_HANDLE_MACHINE_OPTIONS			      \
-  " %{c|S|E|nostdlib: %:set_m_flag(no_link)}"		      \
-  " %{nostartfiles: %{nodefaultlibs: %:set_m_flag(no_link)}}" \
-  LA_SET_PARM_SPEC (ABI_BASE)				      \
-  LA_SET_PARM_SPEC (ARCH)				      \
-  LA_SET_PARM_SPEC (TUNE)				      \
-  LA_SET_PARM_SPEC (ISA_EXT_FPU)			      \
-  LA_SET_PARM_SPEC (CMODEL)				      \
-  LA_SET_FLAG_SPEC (SOFT_FLOAT)				      \
-  LA_SET_FLAG_SPEC (SINGLE_FLOAT)			      \
-  LA_SET_FLAG_SPEC (DOUBLE_FLOAT)			      \
+  " %{m" OPTSTR_##NAME  "=*: %:set_m_parm(" OPTSTR_##NAME " %*)}" \
+
+#define DRIVER_HANDLE_MACHINE_OPTIONS \
+  " %:driver_init()" \
+  " %{c|S|E|nostdlib: %:set_no_link()}" \
+  " %{nostartfiles: %{nodefaultlibs: %:set_no_link()}}" \
+  LA_SET_PARM_SPEC (ABI_BASE) \
+  LA_SET_PARM_SPEC (ARCH) \
+  LA_SET_PARM_SPEC (TUNE) \
+  LA_SET_PARM_SPEC (ISA_EXT_FPU) \
+  LA_SET_PARM_SPEC (ISA_EXT_SIMD) \
+  LA_SET_PARM_SPEC (CMODEL) \
   " %:get_normalized_m_opts()"
 
 #define DRIVER_SELF_SPECS \
diff --git a/gcc/config/loongarch/loongarch-opts.cc b/gcc/config/loongarch/loongarch-opts.cc
index a52e25236ea..a2d5a98a679 100644
--- a/gcc/config/loongarch/loongarch-opts.cc
+++ b/gcc/config/loongarch/loongarch-opts.cc
@@ -26,9 +26,11 @@ along with GCC; see the file COPYING3.  If not see
 #include "tm.h"
 #include "obstack.h"
 #include "diagnostic-core.h"
+
 #include "loongarch-cpu.h"
 #include "loongarch-opts.h"
 #include "loongarch-str.h"
+#include "loongarch-def.h"
 
 struct loongarch_target la_target;
 
@@ -76,16 +78,6 @@ init_enabled_abi_types ()
 #endif
 }
 
-/* Switch masks.  */
-#undef M
-#define M(NAME) OPTION_MASK_##NAME
-const int loongarch_switch_mask[N_SWITCH_TYPES] = {
-  /* SW_SOFT_FLOAT */    M(FORCE_SOFTF),
-  /* SW_SINGLE_FLOAT */  M(FORCE_F32),
-  /* SW_DOUBLE_FLOAT */  M(FORCE_F64),
-};
-#undef M
-
 /* String processing.  */
 static struct obstack msg_obstack;
 #define APPEND_STRING(STR) obstack_grow (&msg_obstack, STR, strlen(STR));
@@ -104,9 +96,9 @@ static int isa_fpu_compat_p (const struct loongarch_isa *set1,
 			     const struct loongarch_isa *set2);
 static int abi_compat_p (const struct loongarch_isa *isa,
 			 struct loongarch_abi abi);
-static int abi_default_cpu_arch (struct loongarch_abi abi);
+static int abi_default_cpu_arch (struct loongarch_abi abi, struct loongarch_isa *isa);
 
-/* Checking configure-time defaults.  */
+/* Mandatory configure-time defaults.  */
 #ifndef DEFAULT_ABI_BASE
 #error missing definition of DEFAULT_ABI_BASE in ${tm_defines}.
 #endif
@@ -119,21 +111,57 @@ static int abi_default_cpu_arch (struct loongarch_abi abi);
 #error missing definition of DEFAULT_CPU_ARCH in ${tm_defines}.
 #endif
 
-#ifndef DEFAULT_ISA_EXT_FPU
-#error missing definition of DEFAULT_ISA_EXT_FPU in ${tm_defines}.
+/* Optional configure-time defaults.  */
+#ifdef DEFAULT_CPU_TUNE
+static int with_default_tune = 1;
+#else
+#define DEFAULT_CPU_TUNE -1
+static int with_default_tune = 0;
+#endif
+
+#ifdef DEFAULT_ISA_EXT_FPU
+static int with_default_fpu = 1;
+#else
+#define DEFAULT_ISA_EXT_FPU -1
+static int with_default_fpu = 0;
+#endif
+
+#ifdef DEFAULT_ISA_EXT_SIMD
+static int with_default_simd = 1;
+#else
+#define DEFAULT_ISA_EXT_SIMD -1
+static int with_default_simd = 0;
 #endif
 
-/* Handle combinations of -m machine option values
+
+/* Initialize loongarch_target from separate option variables.  */
+
+void
+loongarch_init_target (struct loongarch_target *target,
+		       int cpu_arch, int cpu_tune, int fpu, int simd,
+		       int abi_base, int abi_ext, int cmodel)
+{
+  if (!target)
+    return;
+  target->cpu_arch = cpu_arch;
+  target->cpu_tune = cpu_tune;
+  target->isa.fpu = fpu;
+  target->isa.simd = simd;
+  target->abi.base = abi_base;
+  target->abi.ext = abi_ext;
+  target->cmodel = cmodel;
+}
+
+
+/* Handle combinations of -m parameters
    (see loongarch.opt and loongarch-opts.h).  */
+
 void
 loongarch_config_target (struct loongarch_target *target,
-			 HOST_WIDE_INT opt_switches,
-			 int opt_arch, int opt_tune, int opt_fpu,
-			 int opt_abi_base, int opt_abi_ext,
-			 int opt_cmodel, int follow_multilib_list)
+			 struct loongarch_flags *flags,
+			 int follow_multilib_list_p)
 {
   struct loongarch_target t;
-
   if (!target)
     return;
 
@@ -142,67 +170,63 @@ loongarch_config_target (struct loongarch_target *target,
   obstack_init (&msg_obstack);
 
   struct {
-    int arch, tune, fpu, abi_base, abi_ext, cmodel;
+    int arch, tune, fpu, simd, abi_base, abi_ext, cmodel, abi_flt;
   } constrained = {
-      M_OPT_ABSENT(opt_arch)     ? 0 : 1,
-      M_OPT_ABSENT(opt_tune)     ? 0 : 1,
-      M_OPT_ABSENT(opt_fpu)      ? 0 : 1,
-      M_OPT_ABSENT(opt_abi_base) ? 0 : 1,
-      M_OPT_ABSENT(opt_abi_ext)  ? 0 : 1,
-      M_OPT_ABSENT(opt_cmodel)   ? 0 : 1,
+      M_OPT_ABSENT (target->cpu_arch)	  ? 0 : 1,
+      M_OPT_ABSENT (target->cpu_tune)	  ? 0 : 1,
+      M_OPT_ABSENT (target->isa.fpu)	  ? 0 : 1,
+      M_OPT_ABSENT (target->isa.simd)	  ? 0 : 1,
+      M_OPT_ABSENT (target->abi.base)	  ? 0 : 1,
+      M_OPT_ABSENT (target->abi.ext)	  ? 0 : 1,
+      M_OPT_ABSENT (target->cmodel)	  ? 0 : 1,
+      M_OPT_ABSENT (target->abi.base)	  ? 0 : 1,
   };
 
-#define on(NAME) ((loongarch_switch_mask[(SW_##NAME)] & opt_switches) \
-		  && (on_switch = (SW_##NAME), 1))
-  int on_switch;
-
   /* 1.  Target ABI */
-  t.abi.base = constrained.abi_base ? opt_abi_base : DEFAULT_ABI_BASE;
+  if (constrained.abi_base)
+    t.abi.base = target->abi.base;
+  else
+    t.abi.base = DEFAULT_ABI_BASE;
 
-  t.abi.ext = constrained.abi_ext ? opt_abi_ext : DEFAULT_ABI_EXT;
+  t.abi.ext = constrained.abi_ext ? target->abi.ext : DEFAULT_ABI_EXT;
 
-  /* Extra switch handling.  */
-  if (on (SOFT_FLOAT) || on (SINGLE_FLOAT) || on (DOUBLE_FLOAT))
+  /* Process -m*-float flags */
+  if (flags && !M_OPT_ABSENT (flags->flt))
     {
-      switch (on_switch)
-	{
-	  case SW_SOFT_FLOAT:
-	    opt_fpu = ISA_EXT_NOFPU;
-	    break;
-
-	  case SW_SINGLE_FLOAT:
-	    opt_fpu = ISA_EXT_FPU32;
-	    break;
-
-	  case SW_DOUBLE_FLOAT:
-	    opt_fpu = ISA_EXT_FPU64;
-	    break;
+      /* Modifying the original "target" here makes it easier to write the
+	 t.isa.fpu assignment below, because otherwise there would be three
+	 levels of precedence (-m*-float / -mfpu / -march) to be handled
+	 (now the first two are merged). */
 
-	  default:
-	    gcc_unreachable();
-	}
+      target->isa.fpu = flags->flt;
       constrained.fpu = 1;
 
       /* The target ISA is not ready yet, but (isa_required (t.abi)
 	 + forced fpu) is enough for computing the forced base ABI.  */
-      struct loongarch_isa default_isa = isa_required (t.abi);
-      struct loongarch_isa force_isa = default_isa;
-      struct loongarch_abi force_abi = t.abi;
-      force_isa.fpu = opt_fpu;
+
+      struct loongarch_isa force_isa = isa_required (t.abi);
+      force_isa.fpu = flags->flt;
+
+      struct loongarch_abi force_abi;
       force_abi.base = isa_default_abi (&force_isa).base;
 
-      if (constrained.abi_base && (t.abi.base != force_abi.base))
-	inform (UNKNOWN_LOCATION,
-		"%<-m%s%> overrides %<-m%s=%s%>, adjusting ABI to %qs",
-		loongarch_switch_strings[on_switch],
-		OPTSTR_ABI_BASE, loongarch_abi_base_strings[t.abi.base],
-		abi_str (force_abi));
+      if (constrained.abi_base && constrained.abi_flt
+	  && (t.abi.base != force_abi.base))
+	{
+	  force_abi.ext = t.abi.ext;
+	  inform (UNKNOWN_LOCATION,
+		  "%<-m%s%> overrides %<-m%s=%s%>, adjusting ABI to %qs",
+		  flags->flt_str, OPTSTR_ABI_BASE,
+		  loongarch_abi_base_strings[t.abi.base],
+		  abi_str (force_abi));
+	}
 
       t.abi.base = force_abi.base;
+      constrained.abi_flt = 1;
     }
 
 #ifdef LA_DISABLE_MULTILIB
-  if (follow_multilib_list)
+  if (follow_multilib_list_p)
     if (t.abi.base != DEFAULT_ABI_BASE || t.abi.ext != DEFAULT_ABI_EXT)
       {
 	static const struct loongarch_abi default_abi
@@ -214,18 +238,22 @@ loongarch_config_target (struct loongarch_target *target,
 #endif
 
   /* 2.  Target CPU */
-  t.cpu_arch = constrained.arch ? opt_arch : DEFAULT_CPU_ARCH;
+  t.cpu_arch = constrained.arch ? target->cpu_arch : DEFAULT_CPU_ARCH;
+
+  /* If cpu_tune is not set using neither -mtune nor --with-tune,
+     the current cpu_arch is used as its default. */
+  t.cpu_tune = constrained.tune ? target->cpu_tune
+    : (constrained.arch ? target->cpu_arch :
+       (with_default_tune ? DEFAULT_CPU_TUNE : DEFAULT_CPU_ARCH));
 
-  t.cpu_tune = constrained.tune ? opt_tune
-    : (constrained.arch ? DEFAULT_CPU_ARCH : DEFAULT_CPU_TUNE);
 
+  /* Handle -march/tune=native */
 #ifdef __loongarch__
   /* For native compilers, gather local CPU information
      and fill the "CPU_NATIVE" index of arrays defined in
      loongarch-cpu.c.  */
 
-  t.cpu_native = fill_native_cpu_config (t.cpu_arch == CPU_NATIVE,
-					 t.cpu_tune == CPU_NATIVE);
+  fill_native_cpu_config (&t);
 
 #else
   if (t.cpu_arch == CPU_NATIVE)
@@ -239,17 +267,111 @@ loongarch_config_target (struct loongarch_target *target,
 		 "-m" OPTSTR_TUNE "=" STR_CPU_NATIVE);
 #endif
 
-  /* 3.  Target ISA */
+  /* Handle -march/tune=abi-default */
+  if (t.cpu_tune == CPU_ABI_DEFAULT)
+    t.cpu_tune = abi_default_cpu_arch (t.abi, NULL);
+
+  if (t.cpu_arch == CPU_ABI_DEFAULT)
+    {
+      t.cpu_arch = abi_default_cpu_arch (t.abi, &(t.isa));
+      loongarch_cpu_default_isa[t.cpu_arch] = t.isa;
+    }
+
+  /* 3.  Target base ISA */
 config_target_isa:
 
   /* Get default ISA from "-march" or its default value.  */
-  t.isa = loongarch_cpu_default_isa[LARCH_ACTUAL_ARCH];
+  t.isa = loongarch_cpu_default_isa[t.cpu_arch];
 
   /* Apply incremental changes.  */
   /* "-march=native" overrides the default FPU type.  */
-  t.isa.fpu = constrained.fpu ? opt_fpu :
-    ((t.cpu_arch == CPU_NATIVE && constrained.arch) ?
-     t.isa.fpu : DEFAULT_ISA_EXT_FPU);
+
+  t.isa.fpu = constrained.fpu ? target->isa.fpu :
+    (constrained.arch ? t.isa.fpu :
+    (with_default_fpu ? DEFAULT_ISA_EXT_FPU : t.isa.fpu));
+
+  t.isa.simd = constrained.simd ? target->isa.simd :
+    (constrained.arch ? t.isa.simd :
+    (with_default_simd ? DEFAULT_ISA_EXT_SIMD : t.isa.simd));
+
+  /* apply -m[no-]lsx and -m[no-]lasx flags */
+  if (flags)
+    for (int i = 0; i < 2; i++)
+      {
+	switch (SX_FLAG_TYPE (flags->sx[i]))
+	  {
+	  case ISA_EXT_SIMD_LSX:
+	    constrained.simd = 1;
+	    if (flags->sx[i] > 0 && t.isa.simd != ISA_EXT_SIMD_LASX)
+	      t.isa.simd = ISA_EXT_SIMD_LSX;
+	    else if (flags->sx[i] < 0)
+	      t.isa.simd = ISA_EXT_NONE;
+	    break;
+
+	  case ISA_EXT_SIMD_LASX:
+	    constrained.simd = 1;
+	    if (flags->sx[i] < 0 && t.isa.simd == ISA_EXT_SIMD_LASX)
+	      t.isa.simd = ISA_EXT_SIMD_LSX;
+	    else if (flags->sx[i] > 0)
+	      t.isa.simd = ISA_EXT_SIMD_LASX;
+	    break;
+
+	  case 0:
+	    break;
+
+	  default:
+	    gcc_unreachable();
+	  }
+      }
+
+  /* All SIMD extensions imply a 64-bit FPU:
+     - silently adjust t.isa.fpu to "fpu64" if it is unconstrained.
+     - warn if -msingle-float / -msoft-float is on,
+       then disable SIMD extensions (done in driver)
+     - abort if -mfpu=0 / -mfpu=32 is forced.  */
+
+  if (t.isa.simd != ISA_EXT_NONE && t.isa.fpu != ISA_EXT_FPU64)
+    {
+      if (!constrained.fpu)
+	{
+	  /* As long as the arch-default "t.isa.simd" is set to non-zero
+	     for an element "t" in loongarch_cpu_default_isa, "t.isa.fpu"
+	     should be set to "ISA_EXT_FPU64" accordingly.  Thus reaching
+	     here must be the result of forcing -mlsx/-mlasx explicitly.  */
+	  gcc_assert (constrained.simd);
+
+	  inform (UNKNOWN_LOCATION,
+		  "enabing %qs promotes %<%s%s%> to %<%s%s%>",
+		  loongarch_isa_ext_strings[t.isa.simd],
+		  OPTSTR_ISA_EXT_FPU, loongarch_isa_ext_strings[t.isa.fpu],
+		  OPTSTR_ISA_EXT_FPU, loongarch_isa_ext_strings[ISA_EXT_FPU64]);
+
+	  t.isa.fpu = ISA_EXT_FPU64;
+	}
+      else if (flags && (flags->flt == ISA_EXT_NONE || flags->flt == ISA_EXT_FPU32))
+	{
+	  if (constrained.simd)
+	    inform (UNKNOWN_LOCATION,
+		    "%qs is disabled by %<-m%s%>, because it requires %<%s%s%>",
+		    loongarch_isa_ext_strings[t.isa.simd], flags->flt_str,
+		    OPTSTR_ISA_EXT_FPU, loongarch_isa_ext_strings[ISA_EXT_FPU64]);
+
+	  t.isa.simd = ISA_EXT_NONE;
+	}
+      else
+	{
+	  /* -mfpu=0 / -mfpu=32 is set.  */
+	  if (constrained.simd)
+	    fatal_error (UNKNOWN_LOCATION,
+			 "%<-m%s=%s%> conflicts with %qs, which requires %<%s%s%>",
+			 OPTSTR_ISA_EXT_FPU, loongarch_isa_ext_strings[t.isa.fpu],
+			 loongarch_isa_ext_strings[t.isa.simd],
+			 OPTSTR_ISA_EXT_FPU, loongarch_isa_ext_strings[ISA_EXT_FPU64]);
+
+	  /* Same as above.  */
+	  t.isa.simd = ISA_EXT_NONE;
+	}
+    }
 
 
   /* 4.  ABI-ISA compatibility */
@@ -272,7 +394,7 @@ config_target_isa:
     {
       /* Base architecture can only be implied by -march,
 	 so we adjust that first if it is not constrained.  */
-      int fallback_arch = abi_default_cpu_arch (t.abi);
+      int fallback_arch = abi_default_cpu_arch (t.abi, NULL);
 
       if (t.cpu_arch == CPU_NATIVE)
 	warning (0, "your native CPU architecture (%qs) "
@@ -319,7 +441,7 @@ fatal:
   if (abi_tmp.base != t.abi.base || abi_tmp.ext != t.abi.ext)
     {
       /* This flag is only set in the GCC driver.  */
-      if (follow_multilib_list)
+      if (follow_multilib_list_p)
 	{
 
 	  /* Continue falling back until we find a feasible ABI type
@@ -360,7 +482,7 @@ fatal:
 fallback:
       t.abi = abi_tmp;
     }
-  else if (follow_multilib_list)
+  else if (follow_multilib_list_p)
     {
       if (!is_multilib_enabled (t.abi))
 	{
@@ -375,7 +497,7 @@ fallback:
 
 
   /* 5.  Target code model */
-  t.cmodel = constrained.cmodel ? opt_cmodel : CMODEL_NORMAL;
+  t.cmodel = constrained.cmodel ? target->cmodel : CMODEL_NORMAL;
 
   switch (t.cmodel)
     {
@@ -419,7 +541,7 @@ isa_default_abi (const struct loongarch_isa *isa)
 	  abi.base = ABI_BASE_LP64F;
 	break;
 
-      case ISA_EXT_NOFPU:
+      case ISA_EXT_NONE:
 	if (isa->base == ISA_BASE_LA64V100)
 	  abi.base = ABI_BASE_LP64S;
 	break;
@@ -459,7 +581,7 @@ isa_fpu_compat_p (const struct loongarch_isa *set1,
       case ISA_EXT_FPU32:
 	return set1->fpu == ISA_EXT_FPU32 || set1->fpu == ISA_EXT_FPU64;
 
-      case ISA_EXT_NOFPU:
+      case ISA_EXT_NONE:
 	return 1;
 
       default:
@@ -483,16 +605,22 @@ abi_compat_p (const struct loongarch_isa *isa, struct loongarch_abi abi)
 /* The behavior of this function should be consistent
    with config.gcc.  */
 static inline int
-abi_default_cpu_arch (struct loongarch_abi abi)
+abi_default_cpu_arch (struct loongarch_abi abi,
+		      struct loongarch_isa *isa)
 {
-  switch (abi.base)
-    {
-      case ABI_BASE_LP64D:
-      case ABI_BASE_LP64F:
-      case ABI_BASE_LP64S:
-	if (abi.ext == ABI_EXT_BASE)
+  static struct loongarch_isa tmp;
+  if (!isa)
+    isa = &tmp;
+
+  if (abi.ext == ABI_EXT_BASE)
+    switch (abi.base)
+      {
+	case ABI_BASE_LP64D:
+	case ABI_BASE_LP64F:
+	case ABI_BASE_LP64S:
+	  *isa = isa_required (abi);
 	  return CPU_LOONGARCH64;
-    }
+      }
   gcc_unreachable ();
 }
 
@@ -521,7 +649,7 @@ isa_str (const struct loongarch_isa *isa, char separator)
   APPEND_STRING (loongarch_isa_base_strings[isa->base])
   APPEND1 (separator)
 
-  if (isa->fpu == ISA_EXT_NOFPU)
+  if (isa->fpu == ISA_EXT_NONE)
     {
       APPEND_STRING ("no" OPTSTR_ISA_EXT_FPU)
     }
@@ -530,6 +658,18 @@ isa_str (const struct loongarch_isa *isa, char separator)
       APPEND_STRING (OPTSTR_ISA_EXT_FPU)
       APPEND_STRING (loongarch_isa_ext_strings[isa->fpu])
     }
+
+  switch (isa->simd)
+    {
+      case ISA_EXT_SIMD_LSX:
+      case ISA_EXT_SIMD_LASX:
+	APPEND1 (separator);
+	APPEND_STRING (loongarch_isa_ext_strings[isa->simd]);
+	break;
+
+      default:
+	gcc_assert (isa->simd == 0);
+    }
   APPEND1 ('\0')
 
   /* Add more here.  */
@@ -542,18 +682,12 @@ arch_str (const struct loongarch_target *target)
 {
   if (target->cpu_arch == CPU_NATIVE)
     {
-      if (target->cpu_native == CPU_NATIVE)
-	{
-	  /* Describe a native CPU with unknown PRID.  */
-	  const char* isa_string = isa_str (&target->isa, ',');
-	  APPEND_STRING ("PRID: 0x")
-	  APPEND_STRING (get_native_prid_str ())
-	  APPEND_STRING (", ISA features: ")
-	  APPEND_STRING (isa_string)
-	  APPEND1 ('\0')
-	}
-      else
-	APPEND_STRING (loongarch_cpu_strings[target->cpu_native]);
+      /* Describe a native CPU with unknown PRID.  */
+      const char* isa_string = isa_str (&target->isa, ',');
+      APPEND_STRING ("PRID: 0x")
+      APPEND_STRING (get_native_prid_str ())
+      APPEND_STRING (", ISA features: ")
+      APPEND_STRING (isa_string)
     }
   else
     APPEND_STRING (loongarch_cpu_strings[target->cpu_arch]);
@@ -594,3 +728,23 @@ multilib_enabled_abi_list ()
 
   return XOBFINISH (&msg_obstack, const char *);
 }
+
+/* option status feedback for "gcc --help=target -Q" */
+void
+loongarch_update_gcc_opt_status (struct loongarch_target *target,
+				 struct gcc_options *opts,
+				 struct gcc_options *opts_set)
+{
+  (void) opts_set;
+
+  /* status of -mabi */
+  opts->x_la_opt_abi_base = target->abi.base;
+
+  /* status of -march and -mtune */
+  opts->x_la_opt_cpu_arch = target->cpu_arch;
+  opts->x_la_opt_cpu_tune = target->cpu_tune;
+
+  /* status of -mfpu */
+  opts->x_la_opt_fpu = target->isa.fpu;
+  opts->x_la_opt_simd = target->isa.simd;
+}
diff --git a/gcc/config/loongarch/loongarch-opts.h b/gcc/config/loongarch/loongarch-opts.h
index b1ff54426e4..a116f15e8be 100644
--- a/gcc/config/loongarch/loongarch-opts.h
+++ b/gcc/config/loongarch/loongarch-opts.h
@@ -21,24 +21,39 @@ along with GCC; see the file COPYING3.  If not see
 #ifndef LOONGARCH_OPTS_H
 #define LOONGARCH_OPTS_H
 
+#include "loongarch-def.h"
 
 /* Target configuration */
 extern struct loongarch_target la_target;
 
-/* Switch masks */
-extern const int loongarch_switch_mask[];
-
-#include "loongarch-def.h"
+/* Flag status */
+struct loongarch_flags {
+    int flt; const char* flt_str;
+#define SX_FLAG_TYPE(x) ((x) < 0 ? -(x) : (x))
+    int sx[2];
+};
 
 #if !defined(IN_LIBGCC2) && !defined(IN_TARGET_LIBS) && !defined(IN_RTS)
+
+/* Initialize loongarch_target from separate option variables.  */
+void
+loongarch_init_target (struct loongarch_target *target,
+		       int cpu_arch, int cpu_tune, int fpu, int simd,
+		       int abi_base, int abi_ext, int cmodel);
+
+
 /* Handler for "-m" option combinations,
    shared by the driver and the compiler proper.  */
 void
 loongarch_config_target (struct loongarch_target *target,
-			 HOST_WIDE_INT opt_switches,
-			 int opt_arch, int opt_tune, int opt_fpu,
-			 int opt_abi_base, int opt_abi_ext,
-			 int opt_cmodel, int follow_multilib_list);
+			 struct loongarch_flags *flags,
+			 int follow_multilib_list_p);
+
+/* option status feedback for "gcc --help=target -Q" */
+void
+loongarch_update_gcc_opt_status (struct loongarch_target *target,
+				 struct gcc_options *opts,
+				 struct gcc_options *opts_set);
 #endif
 
 
@@ -46,15 +61,15 @@ loongarch_config_target (struct loongarch_target *target,
 #define TARGET_CMODEL_NORMAL	    (la_target.cmodel == CMODEL_NORMAL)
 #define TARGET_CMODEL_TINY	    (la_target.cmodel == CMODEL_TINY)
 #define TARGET_CMODEL_TINY_STATIC   (la_target.cmodel == CMODEL_TINY_STATIC)
-#define TARGET_CMODEL_MEDIUM	    (la_target.cmodel == CMODEL_MEDIUM)
+#define TARGET_CMODEL_MEDIUM        (la_target.cmodel == CMODEL_MEDIUM)
 #define TARGET_CMODEL_LARGE	    (la_target.cmodel == CMODEL_LARGE)
 #define TARGET_CMODEL_EXTREME	    (la_target.cmodel == CMODEL_EXTREME)
 
-#define TARGET_HARD_FLOAT	    (la_target.isa.fpu != ISA_EXT_NOFPU)
+#define TARGET_HARD_FLOAT	    (la_target.isa.fpu != ISA_EXT_NONE)
 #define TARGET_HARD_FLOAT_ABI	    (la_target.abi.base == ABI_BASE_LP64D \
 				     || la_target.abi.base == ABI_BASE_LP64F)
 
-#define TARGET_SOFT_FLOAT	  (la_target.isa.fpu == ISA_EXT_NOFPU)
+#define TARGET_SOFT_FLOAT	  (la_target.isa.fpu == ISA_EXT_NONE)
 #define TARGET_SOFT_FLOAT_ABI	  (la_target.abi.base == ABI_BASE_LP64S)
 #define TARGET_SINGLE_FLOAT	  (la_target.isa.fpu == ISA_EXT_FPU32)
 #define TARGET_SINGLE_FLOAT_ABI	  (la_target.abi.base == ABI_BASE_LP64F)
@@ -66,30 +81,16 @@ loongarch_config_target (struct loongarch_target *target,
 				   || la_target.abi.base == ABI_BASE_LP64F \
 				   || la_target.abi.base == ABI_BASE_LP64S)
 
-#define TARGET_ARCH_NATIVE	  (la_target.cpu_arch == CPU_NATIVE)
-#define LARCH_ACTUAL_ARCH	  (TARGET_ARCH_NATIVE \
-				   ? (la_target.cpu_native < N_ARCH_TYPES \
-				      ? (la_target.cpu_native) : (CPU_NATIVE)) \
-				      : (la_target.cpu_arch))
+#define ISA_HAS_LSX		  (la_target.isa.simd == ISA_EXT_SIMD_LSX \
+				   || la_target.isa.simd == ISA_EXT_SIMD_LASX)
+#define ISA_HAS_LASX		  (la_target.isa.simd == ISA_EXT_SIMD_LASX)
 
-#define TARGET_TUNE_NATIVE	(la_target.cpu_tune == CPU_NATIVE)
-#define LARCH_ACTUAL_TUNE		(TARGET_TUNE_NATIVE \
-				 ? (la_target.cpu_native < N_TUNE_TYPES \
-				    ? (la_target.cpu_native) : (CPU_NATIVE)) \
-				    : (la_target.cpu_tune))
 
-#define TARGET_ARCH_LOONGARCH64	  (LARCH_ACTUAL_ARCH == CPU_LOONGARCH64)
-#define TARGET_ARCH_LA464	  (LARCH_ACTUAL_ARCH == CPU_LA464)
-
-#define TARGET_TUNE_LOONGARCH64	  (LARCH_ACTUAL_TUNE == CPU_LOONGARCH64)
-#define TARGET_TUNE_LA464	  (LARCH_ACTUAL_TUNE == CPU_LA464)
+/* TARGET_ macros for use in *.md template conditionals */
+#define TARGET_uARCH_LA464	  (la_target.cpu_tune == CPU_LA464)
 
 /* Note: optimize_size may vary across functions,
    while -m[no]-memcpy imposes a global constraint.  */
 #define TARGET_DO_OPTIMIZE_BLOCK_MOVE_P  loongarch_do_optimize_block_move_p()
 
-#ifndef HAVE_AS_EXPLICIT_RELOCS
-#define HAVE_AS_EXPLICIT_RELOCS 0
-#endif
-
 #endif /* LOONGARCH_OPTS_H */
diff --git a/gcc/config/loongarch/loongarch-str.h b/gcc/config/loongarch/loongarch-str.h
index af2e82a321f..a3e0510493b 100644
--- a/gcc/config/loongarch/loongarch-str.h
+++ b/gcc/config/loongarch/loongarch-str.h
@@ -27,13 +27,14 @@ along with GCC; see the file COPYING3.  If not see
 #define OPTSTR_TUNE "tune"
 
 #define STR_CPU_NATIVE "native"
+#define STR_CPU_ABI_DEFAULT "abi-default"
 #define STR_CPU_LOONGARCH64 "loongarch64"
 #define STR_CPU_LA464 "la464"
 
 #define STR_ISA_BASE_LA64V100 "la64"
 
 #define OPTSTR_ISA_EXT_FPU "fpu"
-#define STR_ISA_EXT_NOFPU "none"
+#define STR_NONE "none"
 #define STR_ISA_EXT_FPU0 "0"
 #define STR_ISA_EXT_FPU32 "32"
 #define STR_ISA_EXT_FPU64 "64"
@@ -42,6 +43,10 @@ along with GCC; see the file COPYING3.  If not see
 #define OPTSTR_SINGLE_FLOAT "single-float"
 #define OPTSTR_DOUBLE_FLOAT "double-float"
 
+#define OPTSTR_ISA_EXT_SIMD "simd"
+#define STR_ISA_EXT_LSX "lsx"
+#define STR_ISA_EXT_LASX "lasx"
+
 #define OPTSTR_ABI_BASE "abi"
 #define STR_ABI_BASE_LP64D "lp64d"
 #define STR_ABI_BASE_LP64F "lp64f"
diff --git a/gcc/config/loongarch/loongarch.cc b/gcc/config/loongarch/loongarch.cc
index 86d58784113..4fefa2d8b15 100644
--- a/gcc/config/loongarch/loongarch.cc
+++ b/gcc/config/loongarch/loongarch.cc
@@ -2553,7 +2553,7 @@ loongarch_call_tls_get_addr (rtx sym, enum loongarch_symbol_type type, rtx v0)
 
   if (flag_plt)
     {
-      switch (la_opt_cmodel)
+      switch (la_target.cmodel)
 	{
 	case CMODEL_NORMAL:
 	  insn = emit_call_insn (gen_call_value_internal (v0,
@@ -2595,7 +2595,7 @@ loongarch_call_tls_get_addr (rtx sym, enum loongarch_symbol_type type, rtx v0)
     {
       rtx dest = gen_reg_rtx (Pmode);
 
-      switch (la_opt_cmodel)
+      switch (la_target.cmodel)
 	{
 	case CMODEL_NORMAL:
 	case CMODEL_MEDIUM:
@@ -6007,8 +6007,8 @@ loongarch_adjust_cost (rtx_insn *, int dep_type, rtx_insn *, int cost,
 static int
 loongarch_issue_rate (void)
 {
-  if ((unsigned long) LARCH_ACTUAL_TUNE < N_TUNE_TYPES)
-    return loongarch_cpu_issue_rate[LARCH_ACTUAL_TUNE];
+  if ((unsigned long) la_target.cpu_tune < N_TUNE_TYPES)
+    return loongarch_cpu_issue_rate[la_target.cpu_tune];
   else
     return 1;
 }
@@ -6019,8 +6019,8 @@ loongarch_issue_rate (void)
 static int
 loongarch_multipass_dfa_lookahead (void)
 {
-  if ((unsigned long) LARCH_ACTUAL_TUNE < N_ARCH_TYPES)
-    return loongarch_cpu_multipass_dfa_lookahead[LARCH_ACTUAL_TUNE];
+  if ((unsigned long) la_target.cpu_tune < N_ARCH_TYPES)
+    return loongarch_cpu_multipass_dfa_lookahead[la_target.cpu_tune];
   else
     return 0;
 }
@@ -6197,17 +6197,54 @@ loongarch_init_machine_status (void)
 }
 
 static void
-loongarch_option_override_internal (struct gcc_options *opts)
+loongarch_cpu_option_override (struct loongarch_target *target,
+			       struct gcc_options *opts,
+			       struct gcc_options *opts_set)
+{
+  /* alignments */
+  if (opts->x_flag_align_functions && !opts->x_str_align_functions)
+    opts->x_str_align_functions
+      = loongarch_cpu_align[target->cpu_tune].function;
+
+  if (opts->x_flag_align_labels && !opts->x_str_align_labels)
+    opts->x_str_align_labels = loongarch_cpu_align[target->cpu_tune].label;
+
+  /* Set up parameters to be used in prefetching algorithm.  */
+  int simultaneous_prefetches
+    = loongarch_cpu_cache[target->cpu_tune].simultaneous_prefetches;
+
+  SET_OPTION_IF_UNSET (opts, opts_set, param_simultaneous_prefetches,
+		       simultaneous_prefetches);
+
+  SET_OPTION_IF_UNSET (opts, opts_set, param_l1_cache_line_size,
+		       loongarch_cpu_cache[target->cpu_tune].l1d_line_size);
+
+  SET_OPTION_IF_UNSET (opts, opts_set, param_l1_cache_size,
+		       loongarch_cpu_cache[target->cpu_tune].l1d_size);
+
+  SET_OPTION_IF_UNSET (opts, opts_set, param_l2_cache_size,
+		       loongarch_cpu_cache[target->cpu_tune].l2d_size);
+}
+
+static void
+loongarch_option_override_internal (struct gcc_options *opts,
+				    struct gcc_options *opts_set)
 {
   int i, regno, mode;
 
   if (flag_pic)
     g_switch_value = 0;
 
+  loongarch_init_target (&la_target,
+			 la_opt_cpu_arch, la_opt_cpu_tune, la_opt_fpu,
+			 la_opt_simd, la_opt_abi_base, la_opt_abi_ext,
+			 la_opt_cmodel);
+
   /* Handle target-specific options: compute defaults/conflicts etc.  */
-  loongarch_config_target (&la_target, la_opt_switches,
-			   la_opt_cpu_arch, la_opt_cpu_tune, la_opt_fpu,
-			   la_opt_abi_base, la_opt_abi_ext, la_opt_cmodel, 0);
+  loongarch_config_target (&la_target, NULL, 0);
+
+  loongarch_update_gcc_opt_status (&la_target, opts, opts_set);
+  loongarch_cpu_option_override (&la_target, opts, opts_set);
 
   if (TARGET_ABI_LP64)
     flag_pcc_struct_return = 0;
@@ -6216,33 +6253,13 @@ loongarch_option_override_internal (struct gcc_options *opts)
   if (optimize_size)
     loongarch_cost = &loongarch_rtx_cost_optimize_size;
   else
-    loongarch_cost = &loongarch_cpu_rtx_cost_data[LARCH_ACTUAL_TUNE];
+    loongarch_cost = &loongarch_cpu_rtx_cost_data[la_target.cpu_tune];
 
   /* If the user hasn't specified a branch cost, use the processor's
      default.  */
   if (loongarch_branch_cost == 0)
     loongarch_branch_cost = loongarch_cost->branch_cost;
 
-  /* Set up parameters to be used in prefetching algorithm.  */
-  int simultaneous_prefetches
-    = loongarch_cpu_cache[LARCH_ACTUAL_TUNE].simultaneous_prefetches;
-
-  SET_OPTION_IF_UNSET (opts, &global_options_set,
-		       param_simultaneous_prefetches,
-		       simultaneous_prefetches);
-
-  SET_OPTION_IF_UNSET (opts, &global_options_set,
-		       param_l1_cache_line_size,
-		       loongarch_cpu_cache[LARCH_ACTUAL_TUNE].l1d_line_size);
-
-  SET_OPTION_IF_UNSET (opts, &global_options_set,
-		       param_l1_cache_size,
-		       loongarch_cpu_cache[LARCH_ACTUAL_TUNE].l1d_size);
-
-  SET_OPTION_IF_UNSET (opts, &global_options_set,
-		       param_l2_cache_size,
-		       loongarch_cpu_cache[LARCH_ACTUAL_TUNE].l2d_size);
-
 
   /* Enable sw prefetching at -O3 and higher.  */
   if (opts->x_flag_prefetch_loop_arrays < 0
@@ -6250,12 +6267,6 @@ loongarch_option_override_internal (struct gcc_options *opts)
       && !opts->x_optimize_size)
     opts->x_flag_prefetch_loop_arrays = 1;
 
-  if (opts->x_flag_align_functions && !opts->x_str_align_functions)
-    opts->x_str_align_functions = loongarch_cpu_align[LARCH_ACTUAL_TUNE].function;
-
-  if (opts->x_flag_align_labels && !opts->x_str_align_labels)
-    opts->x_str_align_labels = loongarch_cpu_align[LARCH_ACTUAL_TUNE].label;
-
   if (TARGET_DIRECT_EXTERN_ACCESS && flag_shlib)
     error ("%qs cannot be used for compiling a shared library",
 	   "-mdirect-extern-access");
@@ -6325,7 +6336,7 @@ loongarch_option_override_internal (struct gcc_options *opts)
 static void
 loongarch_option_override (void)
 {
-  loongarch_option_override_internal (&global_options);
+  loongarch_option_override_internal (&global_options, &global_options_set);
 }
 
 /* Implement TARGET_CONDITIONAL_REGISTER_USAGE.  */
diff --git a/gcc/config/loongarch/loongarch.opt b/gcc/config/loongarch/loongarch.opt
index 68018ade73f..8be2b0bcb4f 100644
--- a/gcc/config/loongarch/loongarch.opt
+++ b/gcc/config/loongarch/loongarch.opt
@@ -24,22 +24,12 @@
 ; <http://www.gnu.org/licenses/>.
 ;
 
-; Variables (macros) that should be exported by loongarch.opt:
-;   la_opt_switches,
-;   la_opt_abi_base, la_opt_abi_ext,
-;   la_opt_cpu_arch, la_opt_cpu_tune,
-;   la_opt_fpu,
-;   la_cmodel.
-
 HeaderInclude
 config/loongarch/loongarch-opts.h
 
 HeaderInclude
 config/loongarch/loongarch-str.h
 
-Variable
-HOST_WIDE_INT la_opt_switches = 0
-
 ; ISA related options
 ;; Base ISA
 Enum
@@ -49,14 +39,13 @@ Basic ISAs of LoongArch:
 EnumValue
 Enum(isa_base) String(la64) Value(ISA_BASE_LA64V100)
 
-
 ;; ISA extensions / adjustments
 Enum
 Name(isa_ext_fpu) Type(int)
 FPU types of LoongArch:
 
 EnumValue
-Enum(isa_ext_fpu) String(none) Value(ISA_EXT_NOFPU)
+Enum(isa_ext_fpu) String(none) Value(ISA_EXT_NONE)
 
 EnumValue
 Enum(isa_ext_fpu) String(32) Value(ISA_EXT_FPU32)
@@ -65,24 +54,48 @@ EnumValue
 Enum(isa_ext_fpu) String(64) Value(ISA_EXT_FPU64)
 
 mfpu=
-Target RejectNegative Joined ToLower Enum(isa_ext_fpu) Var(la_opt_fpu) Init(M_OPTION_NOT_SEEN)
+Target RejectNegative Joined ToLower Enum(isa_ext_fpu) Var(la_opt_fpu) Init(M_OPT_UNSET)
 -mfpu=FPU	Generate code for the given FPU.
 
 mfpu=0
 Target RejectNegative Alias(mfpu=,none)
 
 msoft-float
-Target Driver RejectNegative Var(la_opt_switches) Mask(FORCE_SOFTF) Negative(msingle-float)
+Target Driver Defer Var(la_deferred_options) RejectNegative Negative(msingle-float)
 Prevent the use of all hardware floating-point instructions.
 
 msingle-float
-Target Driver RejectNegative Var(la_opt_switches) Mask(FORCE_F32) Negative(mdouble-float)
+Target Driver Defer Var(la_deferred_options) RejectNegative Negative(mdouble-float)
 Restrict the use of hardware floating-point instructions to 32-bit operations.
 
 mdouble-float
-Target Driver RejectNegative Var(la_opt_switches) Mask(FORCE_F64) Negative(msoft-float)
+Target Driver Defer Var(la_deferred_options) RejectNegative Negative(msoft-float)
 Allow hardware floating-point instructions to cover both 32-bit and 64-bit operations.
 
+Enum
+Name(isa_ext_simd) Type(int)
+SIMD extension levels of LoongArch:
+
+EnumValue
+Enum(isa_ext_simd) String(none) Value(ISA_EXT_NONE)
+
+EnumValue
+Enum(isa_ext_simd) String(lsx) Value(ISA_EXT_SIMD_LSX)
+
+EnumValue
+Enum(isa_ext_simd) String(lasx) Value(ISA_EXT_SIMD_LASX)
+
+msimd=
+Target RejectNegative Joined ToLower Enum(isa_ext_simd) Var(la_opt_simd) Init(M_OPT_UNSET)
+-msimd=SIMD	Generate code for the given SIMD extension.
+
+mlsx
+Target Driver Defer Var(la_deferred_options)
+Enable LoongArch SIMD Extension (LSX, 128-bit).
+
+mlasx
+Target Driver Defer Var(la_deferred_options)
+Enable LoongArch Advanced SIMD Extension (LASX, 256-bit).
 
 ;; Base target models (implies ISA & tune parameters)
 Enum
@@ -92,6 +105,9 @@ LoongArch CPU types:
 EnumValue
 Enum(cpu_type) String(native) Value(CPU_NATIVE)
 
+EnumValue
+Enum(cpu_type) String(abi-default) Value(CPU_ABI_DEFAULT)
+
 EnumValue
 Enum(cpu_type) String(loongarch64) Value(CPU_LOONGARCH64)
 
@@ -99,11 +115,11 @@ EnumValue
 Enum(cpu_type) String(la464) Value(CPU_LA464)
 
 march=
-Target RejectNegative Joined Enum(cpu_type) Var(la_opt_cpu_arch) Init(M_OPTION_NOT_SEEN)
+Target RejectNegative Joined Enum(cpu_type) Var(la_opt_cpu_arch) Init(M_OPT_UNSET)
 -march=PROCESSOR	Generate code for the given PROCESSOR ISA.
 
 mtune=
-Target RejectNegative Joined Enum(cpu_type) Var(la_opt_cpu_tune) Init(M_OPTION_NOT_SEEN)
+Target RejectNegative Joined Enum(cpu_type) Var(la_opt_cpu_tune) Init(M_OPT_UNSET)
 -mtune=PROCESSOR	Generate optimized code for PROCESSOR.
 
 
@@ -125,13 +141,13 @@ EnumValue
 Enum(abi_base) String(lp64s) Value(ABI_BASE_LP64S)
 
 mabi=
-Target RejectNegative Joined ToLower Enum(abi_base) Var(la_opt_abi_base) Init(M_OPTION_NOT_SEEN)
+Target RejectNegative Joined ToLower Enum(abi_base) Var(la_opt_abi_base) Init(M_OPT_UNSET)
 -mabi=BASEABI	Generate code that conforms to the given BASEABI.
 
+
 ;; ABI Extension
 Variable
-int la_opt_abi_ext = M_OPTION_NOT_SEEN
-
+int la_opt_abi_ext = M_OPT_UNSET
 
 mbranch-cost=
 Target RejectNegative Joined UInteger Var(loongarch_branch_cost)
@@ -189,7 +205,7 @@ EnumValue
 Enum(cmodel) String(extreme) Value(CMODEL_EXTREME)
 
 mcmodel=
-Target RejectNegative Joined Enum(cmodel) Var(la_opt_cmodel) Init(CMODEL_NORMAL)
+Target RejectNegative Joined Enum(cmodel) Var(la_opt_cmodel) Init(M_OPT_UNSET)
 Specify the code model.
 
 mdirect-extern-access
diff --git a/gcc/config/loongarch/t-linux b/gcc/config/loongarch/t-linux
index e40da179203..75bb430c555 100644
--- a/gcc/config/loongarch/t-linux
+++ b/gcc/config/loongarch/t-linux
@@ -23,7 +23,30 @@ MULTILIB_DIRNAMES = base/lp64d base/lp64f base/lp64s
 # The GCC driver always gets all abi-related options on the command line.
 # (see loongarch-driver.c:driver_get_normalized_m_opts)
 comma=,
-MULTILIB_REQUIRED = $(subst $(comma), ,$(TM_MULTILIB_CONFIG))
+MULTILIB_REQUIRED = $(foreach mlib,$(subst $(comma), ,$(TM_MULTILIB_CONFIG)),\
+		    $(firstword $(subst /, ,$(mlib))))
+
+SPECS = specs.install
+
+# temporary self_spec when building libraries (e.g. libgcc)
+gen_mlib_spec = $(if $(word 2,$1),\
+		%{$(firstword $1):$(patsubst %,-%,$(wordlist 2,$(words $1),$1))})
+
+# clean up the result of DRIVER_SELF_SPEC to avoid conflict
+lib_build_self_spec  = %<march=* %<mtune=* %<mcmodel=* %<mfpu=* %<msimd=*
+
+# append user-specified build options from --with-multilib-list
+lib_build_self_spec += $(foreach mlib,$(subst $(comma), ,$(TM_MULTILIB_CONFIG)),\
+			$(call gen_mlib_spec,$(subst /, ,$(mlib))))
+
+specs: specs.install
+	sed '/^*self_spec:$$/{ n;s/^$$/$(lib_build_self_spec)/g; }' $< > $@
+
+# Remove lib_build_self_specs before regression tests.
+.PHONY: remove-lib-specs
+check check-host check-target $(CHECK_TARGETS) $(lang_checks): remove-lib-specs
+remove-lib-specs:
+	-mv -f specs.install specs 2>/dev/null
 
 # Multiarch
 ifneq ($(call if_multiarch,yes),yes)
diff --git a/gcc/doc/install.texi b/gcc/doc/install.texi
index e099cd0b568..73b7ec8ee5c 100644
--- a/gcc/doc/install.texi
+++ b/gcc/doc/install.texi
@@ -1326,12 +1326,31 @@ profile.  The union of these options is considered when specifying both
 @end multitable
 
 @item loongarch*-*-*
-@var{list} is a comma-separated list of the following ABI identifiers:
-@code{lp64d[/base]} @code{lp64f[/base]} @code{lp64d[/base]}, where the
-@code{/base} suffix may be omitted, to enable their respective run-time
-libraries.  If @var{list} is empty or @code{default},
-or if @option{--with-multilib-list} is not specified, then the default ABI
-as specified by @option{--with-abi} or implied by @option{--target} is selected.
+@var{list} is a comma-separated list, with each of the element starting with
+the following ABI identifiers: @code{lp64d[/base]} @code{lp64f[/base]}
+@code{lp64d[/base]} (the @code{/base} suffix may be omitted)
+to enable their respective run-time libraries.
+
+A suffix @code{[/ARCH][/OPTION]...]} may follow immediately after the ABI
+identifier to customize the compiler options for building the given set of libraries.
+@code{ARCH} denotes the architecture name recognized by the @code{-march=ARCH}
+compiler option, which acts as a basic target ISA configuration that can be adjusted
+using the subsequent @code{OPTION} suffixes, where each @code{OPTION} is a compiler
+option itself.
+
+If none of such suffix is present, the configured value of
+@option{--with-multilib-default} can be used as a common default suffix
+for all library ABI variants.  Otherwise, the default build option
+@code{-march=abi-default} is applied when building the variants without
+a suffix.
+
+As a special case, @code{fixed} may be used in the position of @code{ARCH}, which
+means use the architecture configured with @option{--with-arch=ARCH}, or its default
+value (e.g. @code{loongarch64} for @code{loongarch64-*} targets).
+
+If @var{list} is empty or @code{default}, or if @option{--with-multilib-list}
+is not specified, then the default ABI as specified by @option{--with-abi} or
+implied by @option{--target}.
 
 @item riscv*-*-*
 @var{list} is a single ABI name.  The target architecture must be either
@@ -1382,6 +1401,18 @@ If @option{--with-multilib-list} is not given, then only 32-bit and
 64-bit run-time libraries will be enabled.
 @end table
 
+@item --with-multilib-default
+On LoongArch targets, set the default build options for enabled multilibs
+without build options appended to their corresponding @option{--with-multilib-list}
+items.  The format of this value is @code{[/ARCH][/OPTION]...}, where @code{ARCH}
+is an architecture name recognized by @code{-march=ARCH} compiler option,
+and @code{OPTION} can be filled with a compiler option itself.
+
+Multiple @code{OPTION}s may appear consecutively while @code{ARCH} may only
+appear in the beginning or be omitted (which means @code{-march=abi-default}
+is applied when building the libraries).
+
+
 @item --with-multilib-generator=@var{config}
 Specify what multilibs to build.  @var{config} is a semicolon separated list of
 values, possibly consisting of a single value.  Currently only implemented
@@ -1531,6 +1562,7 @@ x86-64, PowerPC, and SPARC@.
 @itemx --with-abi=@var{abi}
 @itemx --with-fpu=@var{type}
 @itemx --with-float=@var{type}
+@itemx --with-simd=@var{type}
 These configure options provide default values for the @option{-mschedule=},
 @option{-march=}, @option{-mtune=}, @option{-mabi=}, and @option{-mfpu=}
 options and for @option{-mhard-float} or @option{-msoft-float}.  As with
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 10f3466052f..259965a2a09 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -1028,7 +1028,8 @@ Objective-C and Objective-C++ Dialects}.
 
 @emph{LoongArch Options}
 @gccoptlist{-march=@var{cpu-type}  -mtune=@var{cpu-type} -mabi=@var{base-abi-type}
--mfpu=@var{fpu-type} -msoft-float -msingle-float -mdouble-float
+-mfpu=@var{fpu-type} -msimd=@var{simd-type}
+-msoft-float -msingle-float -mdouble-float -mlsx -mno-lsx -mlasx -mno-lasx
 -mbranch-cost=@var{n}  -mcheck-zero-division -mno-check-zero-division
 -mcond-move-int  -mno-cond-move-int
 -mcond-move-float  -mno-cond-move-float
@@ -25970,6 +25971,20 @@ operations.
 Prevent the use of hardware floating-point instructions.
 @end table
 
+@opindex msimd
+@item -msimd=@var{simd-type}
+Generate code for the specified SIMD extension(s) when doing vectorization,
+which can be one of:
+@table @samp
+@item lasx
+256-bit LoongArch Advanced SIMD Extension (LASX) and 128-bit LoongArch
+SIMD Extension (LSX).
+@item lsx
+128-bit LoongArch SIMD Extension (LSX).
+@item none
+Disable vectorization.
+@end table
+
 @opindex msoft-float
 @item -msoft-float
 Force @option{-mfpu=none} and prevents the use of floating-point
@@ -25988,6 +26003,18 @@ Force @option{-mfpu=64} and allow the use of 32/64-bit floating-point
 registers for parameter passing.  This option may change the target
 ABI.
 
+@opindex mlasx
+@item -mlasx
+@itemx -mno-lasx
+Use (do not use) LoongArch Advanced SIMD Extension (LASX) for vectorization.
+Enabling LASX with @option{mlasx} automatically enables LSX.
+
+@opindex mlsx
+@item -mlsx
+@itemx -mno-lsx
+Use (do not use) LoongArch SIMD Extension for vectorization.
+Disabling LSX with @option{mlsx} automatically disables LASX.
+
 @opindex mbranch-cost
 @item -mbranch-cost=@var{n}
 Set the cost of branches to roughly @var{n} instructions.
-- 
2.41.0


^ permalink raw reply	[flat|nested] 27+ messages in thread

* [PATCH v1 3/6] LoongArch: define preprocessing macros "__loongarch_{arch,tune}"
  2023-08-14  3:57 [PATCH v1 1/6] LoongArch: a symmetric multilib subdir layout Yang Yujie
  2023-08-14  3:57 ` [PATCH v1 2/6] LoongArch: improved target configuration interface Yang Yujie
@ 2023-08-14  3:57 ` Yang Yujie
  2023-08-14  5:24   ` Xi Ruoyao
  2023-08-14  3:57 ` [PATCH v1 4/6] LoongArch: use -mstrict-align by default when building libraries Yang Yujie
                   ` (3 subsequent siblings)
  5 siblings, 1 reply; 27+ messages in thread
From: Yang Yujie @ 2023-08-14  3:57 UTC (permalink / raw)
  To: gcc-patches; +Cc: xry111, xuchenghua, panchenghui, chenglulu, Yang Yujie

These are exported according to the LoongArch Toolchain Conventions[1]
as a replacement of the obsolete "_LOONGARCH_{ARCH,TUNE}" macros,
which are expanded to strings representing the actual architecture
and microarchitecture of the target.

[1] currently relased at https://github.com/loongson/LoongArch-Documentation
    /blob/main/docs/LoongArch-toolchain-conventions-EN.adoc

gcc/ChangeLog:

        * gcc/config/loongarch/loongarch-c.cc: Export macros
        "__loongarch_{arch,tune}" in the preprocessor.
---
 gcc/config/loongarch/loongarch-c.cc | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/gcc/config/loongarch/loongarch-c.cc b/gcc/config/loongarch/loongarch-c.cc
index 660c68f0e06..7bee037cc4a 100644
--- a/gcc/config/loongarch/loongarch-c.cc
+++ b/gcc/config/loongarch/loongarch-c.cc
@@ -64,6 +64,9 @@ loongarch_cpu_cpp_builtins (cpp_reader *pfile)
   LARCH_CPP_SET_PROCESSOR ("_LOONGARCH_ARCH", la_target.cpu_arch);
   LARCH_CPP_SET_PROCESSOR ("_LOONGARCH_TUNE", la_target.cpu_tune);
 
+  LARCH_CPP_SET_PROCESSOR ("__loongarch_arch", la_target.cpu_arch);
+  LARCH_CPP_SET_PROCESSOR ("__loongarch_tune", la_target.cpu_tune);
+
   /* Base architecture / ABI.  */
   if (TARGET_64BIT)
     {
-- 
2.41.0


^ permalink raw reply	[flat|nested] 27+ messages in thread

* [PATCH v1 4/6] LoongArch: use -mstrict-align by default when building libraries
  2023-08-14  3:57 [PATCH v1 1/6] LoongArch: a symmetric multilib subdir layout Yang Yujie
  2023-08-14  3:57 ` [PATCH v1 2/6] LoongArch: improved target configuration interface Yang Yujie
  2023-08-14  3:57 ` [PATCH v1 3/6] LoongArch: define preprocessing macros "__loongarch_{arch,tune}" Yang Yujie
@ 2023-08-14  3:57 ` Yang Yujie
  2023-08-14  5:18   ` Xi Ruoyao
  2023-08-14  3:57 ` [PATCH v1 5/6] LoongArch: export headers for building GCC plugins Yang Yujie
                   ` (2 subsequent siblings)
  5 siblings, 1 reply; 27+ messages in thread
From: Yang Yujie @ 2023-08-14  3:57 UTC (permalink / raw)
  To: gcc-patches; +Cc: xry111, xuchenghua, panchenghui, chenglulu, Yang Yujie

LoongArch processors may not support memory accesses without natural
alignments.  Building libraries with -mstrict-align may help with
toolchain binary compatiblity and performance on these implementations
(e.g. Loongson 2K1000LA).

With this patch, no significant performance degredation is observed on
current mainstream LoongArch processors.

gcc/ChangeLog:

        * gcc/config/t-linux: add -mstrict-align via self_specs
        when building GCC libraries.
---
 gcc/config/loongarch/t-linux | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/gcc/config/loongarch/t-linux b/gcc/config/loongarch/t-linux
index 75bb430c555..2a170d600a9 100644
--- a/gcc/config/loongarch/t-linux
+++ b/gcc/config/loongarch/t-linux
@@ -35,6 +35,9 @@ gen_mlib_spec = $(if $(word 2,$1),\
 # clean up the result of DRIVER_SELF_SPEC to avoid conflict
 lib_build_self_spec  = %<march=* %<mtune=* %<mcmodel=* %<mfpu=* %<msimd=*
 
+# build libraries with -mstrict-align by default
+lib_build_self_spec += -mstrict-align
+
 # append user-specified build options from --with-multilib-list
 lib_build_self_spec += $(foreach mlib,$(subst $(comma), ,$(TM_MULTILIB_CONFIG)),\
 			$(call gen_mlib_spec,$(subst /, ,$(mlib))))
-- 
2.41.0


^ permalink raw reply	[flat|nested] 27+ messages in thread

* [PATCH v1 5/6] LoongArch: export headers for building GCC plugins
  2023-08-14  3:57 [PATCH v1 1/6] LoongArch: a symmetric multilib subdir layout Yang Yujie
                   ` (2 preceding siblings ...)
  2023-08-14  3:57 ` [PATCH v1 4/6] LoongArch: use -mstrict-align by default when building libraries Yang Yujie
@ 2023-08-14  3:57 ` Yang Yujie
  2023-08-14  3:57 ` [PATCH v1 6/6] LoongArch: support loongarch*-elf target Yang Yujie
  2023-08-14  5:38 ` [PATCH v1 1/6] LoongArch: a symmetric multilib subdir layout Xi Ruoyao
  5 siblings, 0 replies; 27+ messages in thread
From: Yang Yujie @ 2023-08-14  3:57 UTC (permalink / raw)
  To: gcc-patches; +Cc: xry111, xuchenghua, panchenghui, chenglulu, Yang Yujie

gcc/ChangeLog:
        * gcc/config/loongarch/t-loongarch: include loongarch-def.h,
        loongarch-tune.h and loongarch-driver.h in OPTIONS_H_EXTRA.

Co-authored-by: Lulu Cheng <chenglulu@loongson.cn>
---
 gcc/config/loongarch/t-loongarch | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/gcc/config/loongarch/t-loongarch b/gcc/config/loongarch/t-loongarch
index 4ca08035bc8..ea633c69f7b 100644
--- a/gcc/config/loongarch/t-loongarch
+++ b/gcc/config/loongarch/t-loongarch
@@ -20,6 +20,9 @@
 LA_MULTIARCH_TRIPLET = $(patsubst LA_MULTIARCH_TRIPLET=%,%,$\
 $(filter LA_MULTIARCH_TRIPLET=%,$(tm_defines)))
 
+OPTIONS_H_EXTRA += $(srcdir)/config/loongarch/loongarch-def.h \
+		   $(srcdir)/config/loongarch/loongarch-tune.h \
+		   $(srcdir)/config/loongarch/loongarch-driver.h
 # String definition header
 LA_STR_H = $(srcdir)/config/loongarch/loongarch-str.h
 
@@ -62,7 +65,7 @@ loongarch-def.o: $(srcdir)/config/loongarch/loongarch-def.c $(LA_STR_H)
 $(srcdir)/config/loongarch/loongarch.opt: s-loongarch-opt ; @true
 s-loongarch-opt: $(srcdir)/config/loongarch/genopts/genstr.sh \
 	$(srcdir)/config/loongarch/genopts/loongarch.opt.in \
-	$(srcdir)/config/loongarch/genopts/loongarch-strings $(LA_STR_H)
+	$(srcdir)/config/loongarch/genopts/loongarch-strings
 	$(SHELL) $(srcdir)/config/loongarch/genopts/genstr.sh opt \
     $(srcdir)/config/loongarch/genopts/loongarch.opt.in \
     > tmp-loongarch.opt
-- 
2.41.0


^ permalink raw reply	[flat|nested] 27+ messages in thread

* [PATCH v1 6/6] LoongArch: support loongarch*-elf target
  2023-08-14  3:57 [PATCH v1 1/6] LoongArch: a symmetric multilib subdir layout Yang Yujie
                   ` (3 preceding siblings ...)
  2023-08-14  3:57 ` [PATCH v1 5/6] LoongArch: export headers for building GCC plugins Yang Yujie
@ 2023-08-14  3:57 ` Yang Yujie
  2023-08-14  5:38 ` [PATCH v1 1/6] LoongArch: a symmetric multilib subdir layout Xi Ruoyao
  5 siblings, 0 replies; 27+ messages in thread
From: Yang Yujie @ 2023-08-14  3:57 UTC (permalink / raw)
  To: gcc-patches; +Cc: xry111, xuchenghua, panchenghui, chenglulu, Yang Yujie

gcc/ChangeLog:

        * config.gcc: add loongarch*-elf target.
        * config/loongarch/elf.h: New file.
        Link against newlib by default.

libgcc/ChangeLog:

        * config.host: add loongarch*-elf target.
---
 gcc/config.gcc             | 21 ++++++++++++---
 gcc/config/loongarch/elf.h | 52 ++++++++++++++++++++++++++++++++++++++
 libgcc/config.host         |  9 +++++--
 3 files changed, 76 insertions(+), 6 deletions(-)
 create mode 100644 gcc/config/loongarch/elf.h

diff --git a/gcc/config.gcc b/gcc/config.gcc
index 9412f73fe35..0661f13ebc8 100644
--- a/gcc/config.gcc
+++ b/gcc/config.gcc
@@ -2491,6 +2491,18 @@ loongarch*-*-linux*)
 	gcc_cv_initfini_array=yes
 	;;
 
+loongarch*-*-elf*)
+	tm_file="elfos.h newlib-stdint.h ${tm_file}"
+	tm_file="${tm_file} loongarch/elf.h loongarch/linux.h"
+	tmake_file="${tmake_file} loongarch/t-linux"
+	gnu_ld=yes
+	gas=yes
+
+	# For .init_array support.  The configure script cannot always
+	# automatically detect that GAS supports it, yet we require it.
+	gcc_cv_initfini_array=yes
+	;;
+
 mips*-*-netbsd*)			# NetBSD/mips, either endian.
 	target_cpu_default="MASK_ABICALLS"
 	tm_file="elfos.h ${tm_file} mips/elf.h ${nbsd_tm_file} mips/netbsd.h"
@@ -4904,16 +4916,16 @@ case "${target}" in
 
 		# Infer ABI from the triplet.
 		case ${target} in
-		loongarch64-*-*-*f64)
+		loongarch64-*f64)
 			abi_pattern="lp64d"
 			;;
-		loongarch64-*-*-*f32)
+		loongarch64-*f32)
 			abi_pattern="lp64f"
 			;;
-		loongarch64-*-*-*sf)
+		loongarch64-*sf)
 			abi_pattern="lp64s"
 			;;
-		loongarch64-*-*-*)
+		loongarch64-*)
 			abi_pattern="lp64[dfs]"
 			abi_default="lp64d"
 			;;
@@ -4930,6 +4942,7 @@ case "${target}" in
 		case ${target} in
 		  *-linux-gnu*)  triplet_os="linux-gnu";;
 		  *-linux-musl*) triplet_os="linux-musl";;
+		  *-elf*)        triplet_os="elf";;
 		  *)
 			  echo "Unsupported target ${target}." 1>&2
 			  exit 1
diff --git a/gcc/config/loongarch/elf.h b/gcc/config/loongarch/elf.h
new file mode 100644
index 00000000000..39e2cbc7b5e
--- /dev/null
+++ b/gcc/config/loongarch/elf.h
@@ -0,0 +1,52 @@
+/* Definitions for LoongArch ELF-based systems.
+   Copyright (C) 1998-2023 Free Software Foundation, Inc.
+
+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/>.  */
+
+/* Define the size of the wide character type.  */
+#undef WCHAR_TYPE
+#define WCHAR_TYPE "int"
+
+#undef WCHAR_TYPE_SIZE
+#define WCHAR_TYPE_SIZE 32
+
+
+/* GNU-specific SPEC definitions.  */
+#define GNU_USER_LINK_EMULATION "elf" ABI_GRLEN_SPEC "loongarch"
+
+#undef GNU_USER_TARGET_LINK_SPEC
+#define GNU_USER_TARGET_LINK_SPEC \
+  "%{shared} -m " GNU_USER_LINK_EMULATION
+
+
+/* Link against Newlib libraries, because the ELF backend assumes Newlib.
+   Handle the circular dependence between libc and libgloss. */
+#undef  LIB_SPEC
+#define LIB_SPEC "--start-group -lc %{!specs=nosys.specs:-lgloss} --end-group"
+
+#undef LINK_SPEC
+#define LINK_SPEC GNU_USER_TARGET_LINK_SPEC
+
+#undef  STARTFILE_SPEC
+#define STARTFILE_SPEC "crt0%O%s crtbegin%O%s"
+
+#undef  ENDFILE_SPEC
+#define ENDFILE_SPEC "crtend%O%s"
+
+#undef SUBTARGET_CC1_SPEC
+#define SUBTARGET_CC1_SPEC "%{profile:-p}"
+
diff --git a/libgcc/config.host b/libgcc/config.host
index c94d69d84b7..6a112a07b14 100644
--- a/libgcc/config.host
+++ b/libgcc/config.host
@@ -136,7 +136,7 @@ hppa*-*-*)
 lm32*-*-*)
 	cpu_type=lm32
 	;;
-loongarch*-*-*)
+loongarch*-*)
 	cpu_type=loongarch
 	tmake_file="loongarch/t-loongarch"
 	if test "${libgcc_cv_loongarch_hard_float}" = yes; then
@@ -944,7 +944,7 @@ lm32-*-uclinux*)
         extra_parts="$extra_parts crtbegin.o crtendS.o crtbeginT.o"
         tmake_file="lm32/t-lm32 lm32/t-uclinux t-libgcc-pic t-softfp-sfdf t-softfp"
 	;;
-loongarch*-*-linux*)
+loongarch*-linux*)
 	extra_parts="$extra_parts crtfastmath.o"
 	tmake_file="${tmake_file} t-crtfm loongarch/t-crtstuff"
 	case ${host} in
@@ -954,6 +954,11 @@ loongarch*-*-linux*)
 	esac
 	md_unwind_header=loongarch/linux-unwind.h
 	;;
+loongarch*-elf*)
+	extra_parts="$extra_parts crtfastmath.o"
+	tmake_file="${tmake_file} t-crtfm loongarch/t-crtstuff"
+	tmake_file="${tmake_file} t-slibgcc-libgcc"
+	;;
 m32r-*-elf*)
 	tmake_file="$tmake_file m32r/t-m32r t-fdpbit"
 	extra_parts="$extra_parts crtinit.o crtfini.o"
-- 
2.41.0


^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v1 4/6] LoongArch: use -mstrict-align by default when building libraries
  2023-08-14  3:57 ` [PATCH v1 4/6] LoongArch: use -mstrict-align by default when building libraries Yang Yujie
@ 2023-08-14  5:18   ` Xi Ruoyao
  0 siblings, 0 replies; 27+ messages in thread
From: Xi Ruoyao @ 2023-08-14  5:18 UTC (permalink / raw)
  To: Yang Yujie, gcc-patches; +Cc: xuchenghua, panchenghui, chenglulu

On Mon, 2023-08-14 at 11:57 +0800, Yang Yujie wrote:
> LoongArch processors may not support memory accesses without natural
> alignments.  Building libraries with -mstrict-align may help with
> toolchain binary compatiblity and performance on these implementations
> (e.g. Loongson 2K1000LA).

I don't think it's a good idea.  You should provide a configuration-time
option (maybe named --with-strict-align) to make -mstrict-align the
default instead, thus both the libraries and the compiled user code will
be suitable for 2K1000.

> With this patch, no significant performance degredation is observed on
> current mainstream LoongArch processors.
> 
> gcc/ChangeLog:
> 
>         * gcc/config/t-linux: add -mstrict-align via self_specs
>         when building GCC libraries.
> ---
>  gcc/config/loongarch/t-linux | 3 +++
>  1 file changed, 3 insertions(+)
> 
> diff --git a/gcc/config/loongarch/t-linux b/gcc/config/loongarch/t-linux
> index 75bb430c555..2a170d600a9 100644
> --- a/gcc/config/loongarch/t-linux
> +++ b/gcc/config/loongarch/t-linux
> @@ -35,6 +35,9 @@ gen_mlib_spec = $(if $(word 2,$1),\
>  # clean up the result of DRIVER_SELF_SPEC to avoid conflict
>  lib_build_self_spec  = %<march=* %<mtune=* %<mcmodel=* %<mfpu=* %<msimd=*
>  
> +# build libraries with -mstrict-align by default
> +lib_build_self_spec += -mstrict-align
> +
>  # append user-specified build options from --with-multilib-list
>  lib_build_self_spec += $(foreach mlib,$(subst $(comma), ,$(TM_MULTILIB_CONFIG)),\
>                         $(call gen_mlib_spec,$(subst /, ,$(mlib))))

-- 
Xi Ruoyao <xry111@xry111.site>
School of Aerospace Science and Technology, Xidian University

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v1 2/6] LoongArch: improved target configuration interface
  2023-08-14  3:57 ` [PATCH v1 2/6] LoongArch: improved target configuration interface Yang Yujie
@ 2023-08-14  5:22   ` Xi Ruoyao
  2023-08-15  1:12     ` Yujie Yang
  2023-08-14  5:29   ` Xi Ruoyao
                     ` (2 subsequent siblings)
  3 siblings, 1 reply; 27+ messages in thread
From: Xi Ruoyao @ 2023-08-14  5:22 UTC (permalink / raw)
  To: Yang Yujie, gcc-patches; +Cc: xuchenghua, panchenghui, chenglulu

On Mon, 2023-08-14 at 11:57 +0800, Yang Yujie wrote:
> The configure script and the GCC driver are updated so that
> it is easier to customize and control GCC builds for targeting
> different LoongArch implementations.
> 
> * Support options for LoongArch SIMD extensions:
>   new configure options --with-simd={none,lsx,lasx};
>   new driver options -m[no]-l[a]sx / -msimd={none,lsx,lasx}.

What's the relationship between -mlasx and -msimd=lasx?  What will
happen if the user specifies -mlasx -msimd=none or -mlasx -msimd=lsx?

-- 
Xi Ruoyao <xry111@xry111.site>
School of Aerospace Science and Technology, Xidian University

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v1 3/6] LoongArch: define preprocessing macros "__loongarch_{arch,tune}"
  2023-08-14  3:57 ` [PATCH v1 3/6] LoongArch: define preprocessing macros "__loongarch_{arch,tune}" Yang Yujie
@ 2023-08-14  5:24   ` Xi Ruoyao
  0 siblings, 0 replies; 27+ messages in thread
From: Xi Ruoyao @ 2023-08-14  5:24 UTC (permalink / raw)
  To: Yang Yujie, gcc-patches; +Cc: xuchenghua, panchenghui, chenglulu

On Mon, 2023-08-14 at 11:57 +0800, Yang Yujie wrote:
> These are exported according to the LoongArch Toolchain Conventions[1]
> as a replacement of the obsolete "_LOONGARCH_{ARCH,TUNE}" macros,
> which are expanded to strings representing the actual architecture
> and microarchitecture of the target.
> 
> [1] currently relased at https://github.com/loongson/LoongArch-Documentation
>     /blob/main/docs/LoongArch-toolchain-conventions-EN.adoc
> 
> gcc/ChangeLog:
> 
>         * gcc/config/loongarch/loongarch-c.cc: Export macros
>         "__loongarch_{arch,tune}" in the preprocessor.

Ok.  I think this can be applied anyway (regardless of other patches).

> ---
>  gcc/config/loongarch/loongarch-c.cc | 3 +++
>  1 file changed, 3 insertions(+)
> 
> diff --git a/gcc/config/loongarch/loongarch-c.cc b/gcc/config/loongarch/loongarch-c.cc
> index 660c68f0e06..7bee037cc4a 100644
> --- a/gcc/config/loongarch/loongarch-c.cc
> +++ b/gcc/config/loongarch/loongarch-c.cc
> @@ -64,6 +64,9 @@ loongarch_cpu_cpp_builtins (cpp_reader *pfile)
>    LARCH_CPP_SET_PROCESSOR ("_LOONGARCH_ARCH", la_target.cpu_arch);
>    LARCH_CPP_SET_PROCESSOR ("_LOONGARCH_TUNE", la_target.cpu_tune);
>  
> +  LARCH_CPP_SET_PROCESSOR ("__loongarch_arch", la_target.cpu_arch);
> +  LARCH_CPP_SET_PROCESSOR ("__loongarch_tune", la_target.cpu_tune);
> +
>    /* Base architecture / ABI.  */
>    if (TARGET_64BIT)
>      {

-- 
Xi Ruoyao <xry111@xry111.site>
School of Aerospace Science and Technology, Xidian University

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v1 2/6] LoongArch: improved target configuration interface
  2023-08-14  3:57 ` [PATCH v1 2/6] LoongArch: improved target configuration interface Yang Yujie
  2023-08-14  5:22   ` Xi Ruoyao
@ 2023-08-14  5:29   ` Xi Ruoyao
  2023-08-14  5:58   ` Xi Ruoyao
  2023-09-06  6:43   ` Richard Sandiford
  3 siblings, 0 replies; 27+ messages in thread
From: Xi Ruoyao @ 2023-08-14  5:29 UTC (permalink / raw)
  To: Yang Yujie, gcc-patches; +Cc: xuchenghua, panchenghui, chenglulu

On Mon, 2023-08-14 at 11:57 +0800, Yang Yujie wrote:
>                 loongarch64)
> -                       tune_pattern="loongarch64|la464"
> -                       tune_default="la464"
> +                       tune_pattern="native|abi-default|loongarch64|la464"

I think we can remove tune_pattern completely.  There is no reason to
limit --with-tune setting based on --with-arch setting.

-- 
Xi Ruoyao <xry111@xry111.site>
School of Aerospace Science and Technology, Xidian University

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v1 1/6] LoongArch: a symmetric multilib subdir layout
  2023-08-14  3:57 [PATCH v1 1/6] LoongArch: a symmetric multilib subdir layout Yang Yujie
                   ` (4 preceding siblings ...)
  2023-08-14  3:57 ` [PATCH v1 6/6] LoongArch: support loongarch*-elf target Yang Yujie
@ 2023-08-14  5:38 ` Xi Ruoyao
  2023-08-14  5:40   ` Xi Ruoyao
  2023-08-14  7:37   ` Yujie Yang
  5 siblings, 2 replies; 27+ messages in thread
From: Xi Ruoyao @ 2023-08-14  5:38 UTC (permalink / raw)
  To: Yang Yujie, gcc-patches; +Cc: xuchenghua, panchenghui, chenglulu

On Mon, 2023-08-14 at 11:57 +0800, Yang Yujie wrote:

> However, for LoongArch, we do not want such a "toplevel" library
> installation since the default ABI may change.  We expect all
> multilib variants of libraries to be installed to their designated
> ABI-specific subdirs (e.g. base/lp64d) of the GCC libdir, so that
> the default ABI can be configured arbitrarily (with --with-abi)
> while the gcc libdir layout stays consistent.  This could be
> helpful for the distribution packaging of GCC libraries.

Have you tested a --disable-multilib configuration?  To me with --
disable-configuration everything should be still in the toplevel
directory, not any sub-directory.

/* snip */

> ChangeLog:
> 
>         * config-ml.in: add loongarch support.  Allow overriding

Use a tab, not 8 white spaces.  Likewise for all patches in the series.

>         toplevel multisubdir.

-- 
Xi Ruoyao <xry111@xry111.site>
School of Aerospace Science and Technology, Xidian University

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v1 1/6] LoongArch: a symmetric multilib subdir layout
  2023-08-14  5:38 ` [PATCH v1 1/6] LoongArch: a symmetric multilib subdir layout Xi Ruoyao
@ 2023-08-14  5:40   ` Xi Ruoyao
  2023-08-14  7:37   ` Yujie Yang
  1 sibling, 0 replies; 27+ messages in thread
From: Xi Ruoyao @ 2023-08-14  5:40 UTC (permalink / raw)
  To: Yang Yujie, gcc-patches; +Cc: xuchenghua, panchenghui, chenglulu

On Mon, 2023-08-14 at 13:38 +0800, Xi Ruoyao wrote:
> 
> > However, for LoongArch, we do not want such a "toplevel" library
> > installation since the default ABI may change.  We expect all
> > multilib variants of libraries to be installed to their designated
> > ABI-specific subdirs (e.g. base/lp64d) of the GCC libdir, so that
> > the default ABI can be configured arbitrarily (with --with-abi)
> > while the gcc libdir layout stays consistent.  This could be
> > helpful for the distribution packaging of GCC libraries.
> 
> Have you tested a --disable-multilib configuration?  To me with --
> disable-configuration everything should be still in the toplevel

I mean --disable-multilib configuration, not "--disable-configuration".

> directory, not any sub-directory.

-- 
Xi Ruoyao <xry111@xry111.site>
School of Aerospace Science and Technology, Xidian University

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v1 2/6] LoongArch: improved target configuration interface
  2023-08-14  3:57 ` [PATCH v1 2/6] LoongArch: improved target configuration interface Yang Yujie
  2023-08-14  5:22   ` Xi Ruoyao
  2023-08-14  5:29   ` Xi Ruoyao
@ 2023-08-14  5:58   ` Xi Ruoyao
  2023-08-14  6:01     ` Xi Ruoyao
  2023-08-14  8:44     ` Yujie Yang
  2023-09-06  6:43   ` Richard Sandiford
  3 siblings, 2 replies; 27+ messages in thread
From: Xi Ruoyao @ 2023-08-14  5:58 UTC (permalink / raw)
  To: Yang Yujie, gcc-patches; +Cc: xuchenghua, panchenghui, chenglulu

On Mon, 2023-08-14 at 11:57 +0800, Yang Yujie wrote:
> * Support options for LoongArch SIMD extensions:
>   new configure options --with-simd={none,lsx,lasx};
>   new driver options -m[no]-l[a]sx / -msimd={none,lsx,lasx}.

I suggest to rename --with-simd= to --with-ext= and accept a comma-
separated ISA extension list, because we have non-SIMD ISA extensions. 
For example, "--with-ext=lasx,lbt" will make -mlasx, -mlsx (implied),
and -mlbt the default.  I prefer "-mlasx" over "-msimd=lasx" because "-
mlasx" is shorter anyway (if there is no real reason to make -mlasx and
-msimd=lasx two different things).

-- 
Xi Ruoyao <xry111@xry111.site>
School of Aerospace Science and Technology, Xidian University

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v1 2/6] LoongArch: improved target configuration interface
  2023-08-14  5:58   ` Xi Ruoyao
@ 2023-08-14  6:01     ` Xi Ruoyao
  2023-08-14  8:44     ` Yujie Yang
  1 sibling, 0 replies; 27+ messages in thread
From: Xi Ruoyao @ 2023-08-14  6:01 UTC (permalink / raw)
  To: Yang Yujie, gcc-patches; +Cc: xuchenghua, panchenghui, chenglulu

On Mon, 2023-08-14 at 13:58 +0800, Xi Ruoyao via Gcc-patches wrote:
> On Mon, 2023-08-14 at 11:57 +0800, Yang Yujie wrote:
> > * Support options for LoongArch SIMD extensions:
> >   new configure options --with-simd={none,lsx,lasx};
> >   new driver options -m[no]-l[a]sx / -msimd={none,lsx,lasx}.
> 
> I suggest to rename --with-simd= to --with-ext= and accept a comma-
> separated ISA extension list, because we have non-SIMD ISA extensions.
> For example, "--with-ext=lasx,lbt" will make -mlasx, -mlsx (implied),
> and -mlbt the default.  I prefer "-mlasx" over "-msimd=lasx" because "-
> mlasx" is shorter anyway (if there is no real reason to make -mlasx and
> -msimd=lasx two different things).

Perhaps just "--with-feature" or "--with-loongarch-feature", then we can
even fold -mstrict-align here, like "--with-feature=lbt,strict-align".


-- 
Xi Ruoyao <xry111@xry111.site>
School of Aerospace Science and Technology, Xidian University

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v1 1/6] LoongArch: a symmetric multilib subdir layout
  2023-08-14  5:38 ` [PATCH v1 1/6] LoongArch: a symmetric multilib subdir layout Xi Ruoyao
  2023-08-14  5:40   ` Xi Ruoyao
@ 2023-08-14  7:37   ` Yujie Yang
  2023-08-14  7:48     ` Xi Ruoyao
  1 sibling, 1 reply; 27+ messages in thread
From: Yujie Yang @ 2023-08-14  7:37 UTC (permalink / raw)
  To: Xi Ruoyao, gcc-patches

On Mon, Aug 14, 2023 at 01:38:40PM +0800, Xi Ruoyao wrote:
> On Mon, 2023-08-14 at 11:57 +0800, Yang Yujie wrote:
> 
> > However, for LoongArch, we do not want such a "toplevel" library
> > installation since the default ABI may change.  We expect all
> > multilib variants of libraries to be installed to their designated
> > ABI-specific subdirs (e.g. base/lp64d) of the GCC libdir, so that
> > the default ABI can be configured arbitrarily (with --with-abi)
> > while the gcc libdir layout stays consistent.  This could be
> > helpful for the distribution packaging of GCC libraries.
> 
> Have you tested a --disable-multilib configuration?  To me with --
> disable-configuration everything should be still in the toplevel
> directory, not any sub-directory.

That's a good point, sorry I missed --disable-multilib here.

However, you don't really need --disable-multilib since
the libraries are only built once in the default ABI configuration
as long as --with-multilib-list does not request anything more than
that.

Maybe we should force-enabling multilib in all cases.


^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v1 1/6] LoongArch: a symmetric multilib subdir layout
  2023-08-14  7:37   ` Yujie Yang
@ 2023-08-14  7:48     ` Xi Ruoyao
  2023-08-14 10:18       ` Yujie Yang
  0 siblings, 1 reply; 27+ messages in thread
From: Xi Ruoyao @ 2023-08-14  7:48 UTC (permalink / raw)
  To: Yujie Yang, gcc-patches

On Mon, 2023-08-14 at 15:37 +0800, Yujie Yang wrote:
> On Mon, Aug 14, 2023 at 01:38:40PM +0800, Xi Ruoyao wrote:
> > On Mon, 2023-08-14 at 11:57 +0800, Yang Yujie wrote:
> > 
> > > However, for LoongArch, we do not want such a "toplevel" library
> > > installation since the default ABI may change.  We expect all
> > > multilib variants of libraries to be installed to their designated
> > > ABI-specific subdirs (e.g. base/lp64d) of the GCC libdir, so that
> > > the default ABI can be configured arbitrarily (with --with-abi)
> > > while the gcc libdir layout stays consistent.  This could be
> > > helpful for the distribution packaging of GCC libraries.
> > 
> > Have you tested a --disable-multilib configuration?  To me with --
> > disable-configuration everything should be still in the toplevel
> > directory, not any sub-directory.
> 
> That's a good point, sorry I missed --disable-multilib here.
> 
> However, you don't really need --disable-multilib since
> the libraries are only built once in the default ABI configuration
> as long as --with-multilib-list does not request anything more than
> that.
> 
> Maybe we should force-enabling multilib in all cases.

I really don't like this.  Why must I always remind my self "hey, this
is LoongArch, there is a different directory layout" when I don't need
multilib at all?

-- 
Xi Ruoyao <xry111@xry111.site>
School of Aerospace Science and Technology, Xidian University

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v1 2/6] LoongArch: improved target configuration interface
  2023-08-14  5:58   ` Xi Ruoyao
  2023-08-14  6:01     ` Xi Ruoyao
@ 2023-08-14  8:44     ` Yujie Yang
  2023-08-14  8:49       ` Xi Ruoyao
  1 sibling, 1 reply; 27+ messages in thread
From: Yujie Yang @ 2023-08-14  8:44 UTC (permalink / raw)
  To: Xi Ruoyao; +Cc: gcc-patches, xuchenghua, panchenghui, chenglulu

On Mon, Aug 14, 2023 at 01:58:24PM +0800, Xi Ruoyao wrote:
> On Mon, 2023-08-14 at 11:57 +0800, Yang Yujie wrote:
> > * Support options for LoongArch SIMD extensions:
> >   new configure options --with-simd={none,lsx,lasx};
> >   new driver options -m[no]-l[a]sx / -msimd={none,lsx,lasx}.
> 
> I suggest to rename --with-simd= to --with-ext= and accept a comma-
> separated ISA extension list, because we have non-SIMD ISA extensions. 
> For example, "--with-ext=lasx,lbt" will make -mlasx, -mlsx (implied),
> and -mlbt the default.  I prefer "-mlasx" over "-msimd=lasx" because "-
> mlasx" is shorter anyway (if there is no real reason to make -mlasx and
> -msimd=lasx two different things).
> 
> -- 
> Xi Ruoyao <xry111@xry111.site>
> School of Aerospace Science and Technology, Xidian University

Thanks for the suggestion, --with-ext seems a good idea.  I will
consider adding it later.

-msimd=lasx and -mlasx are the same if you only use them once, but things
gets complicated if you also want -mno-lsx to cancel the effect of -mlasx.

In short, -msimd= is *necessary* for a correct (and convenient) implementation
of the "legacy" -m[no-]l[a]sx options.  Let's hope I can explain this clearly:

I assume we all want:

 (1) -mlasx -mlsx -> enable LSX and LASX
 (2) -mlasx -mno-lsx -> disable LSX and LASX
 (3) -mno-lsx -mlasx -> enable LSX and LASX

Unless we declare -mlsx / -mlasx as driver deferred, AFAIK there is no other way for
us to know the actual order of appearnce of all -m[no-]l[a]sx options on the command
line.  All we know from GCC's option system would be a final on/off state of "lsx"
and a final on/off state of "lasx".

These states results from independent processing of -m[no-]lsx and -m[no-]lasx options
in the order they appear, respectively.  So we can't distinguish between (2) and (3).

Another seemingly viable approach is to declare three options -mlsx / -mlasx / -mno-lsx
and making them mutually exclusive.  In this way GCC would only consider the last one
appearing on the command line.  But we lost (1) in this case.

So, it seems that GCC is forbidding a compiler option to express a "state change"
rather than a independent configuration state itself.  This makes sense since
"-grecord-gcc-switches" and the LTO objects prefers that a target configuration
can be uniquely expressed in a "tuple of coordinates", rather than a series of
"connected vectors", so that they can be easily compared.

Now what we want is clear:

1. support convenient options like -mlsx / -mlasx (maybe something like
-m32 / -m64 in the future) that express state changes that interferes with
the effect of prior flags with different names.

2. the options passed to the compiler proper has a clear one-one
correspondence to the target configuration.


The implementation: canonicalize everything in the GCC driver, process the "flags"
that express state changes in the order they appear into a group of independent
parameters.  If the parameters they have overlapping semantics, the priority
is hard-coded, like -march and -msimd.

(This is also necessary for multilib since this is where the multilib selection
happens and final ABI needs to be decided before that.)

For this purpose, -msimd= is the canonicalized parameter form of the state
of SIMD extension, and -m[no-]l[a]sx are defined as convenient driver-only
flags.


^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v1 2/6] LoongArch: improved target configuration interface
  2023-08-14  8:44     ` Yujie Yang
@ 2023-08-14  8:49       ` Xi Ruoyao
  2023-08-14  8:57         ` Yujie Yang
  0 siblings, 1 reply; 27+ messages in thread
From: Xi Ruoyao @ 2023-08-14  8:49 UTC (permalink / raw)
  To: Yujie Yang; +Cc: gcc-patches, xuchenghua, panchenghui, chenglulu

On Mon, 2023-08-14 at 16:44 +0800, Yujie Yang wrote:
> I assume we all want:
> 
>  (1) -mlasx -mlsx -> enable LSX and LASX
>  (2) -mlasx -mno-lsx -> disable LSX and LASX
>  (3) -mno-lsx -mlasx -> enable LSX and LASX

Yes.

> Unless we declare -mlsx / -mlasx as driver deferred, AFAIK there is no other way for
> us to know the actual order of appearnce of all -m[no-]l[a]sx options on the command
> line.  All we know from GCC's option system would be a final on/off state of "lsx"
> and a final on/off state of "lasx".

But x86 does this correct;

$ echo __AVX__ + __AVX2__ | LANG= cpp -E -mno-avx -mavx2
# 0 "<stdin>"
# 0 "<built-in>"
# 0 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 0 "<command-line>" 2
# 1 "<stdin>"
1 + 1

so there must be a way to handle this...

-- 
Xi Ruoyao <xry111@xry111.site>
School of Aerospace Science and Technology, Xidian University

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v1 2/6] LoongArch: improved target configuration interface
  2023-08-14  8:49       ` Xi Ruoyao
@ 2023-08-14  8:57         ` Yujie Yang
  2023-08-14  8:58           ` Xi Ruoyao
  0 siblings, 1 reply; 27+ messages in thread
From: Yujie Yang @ 2023-08-14  8:57 UTC (permalink / raw)
  To: Xi Ruoyao; +Cc: gcc-patches, xuchenghua, panchenghui, chenglulu

On Mon, Aug 14, 2023 at 04:49:11PM +0800, Xi Ruoyao wrote:
> On Mon, 2023-08-14 at 16:44 +0800, Yujie Yang wrote:
> > I assume we all want:
> > 
> >  (1) -mlasx -mlsx -> enable LSX and LASX
> >  (2) -mlasx -mno-lsx -> disable LSX and LASX
> >  (3) -mno-lsx -mlasx -> enable LSX and LASX
> 
> Yes.
> 
> > Unless we declare -mlsx / -mlasx as driver deferred, AFAIK there is no other way for
> > us to know the actual order of appearnce of all -m[no-]l[a]sx options on the command
> > line.  All we know from GCC's option system would be a final on/off state of "lsx"
> > and a final on/off state of "lasx".
> 
> But x86 does this correct;
> 
> $ echo __AVX__ + __AVX2__ | LANG= cpp -E -mno-avx -mavx2
> # 0 "<stdin>"
> # 0 "<built-in>"
> # 0 "<command-line>"
> # 1 "/usr/include/stdc-predef.h" 1 3 4
> # 0 "<command-line>" 2
> # 1 "<stdin>"
> 1 + 1
> 
> so there must be a way to handle this...
> 
> -- 
> Xi Ruoyao <xry111@xry111.site>
> School of Aerospace Science and Technology, Xidian University

Emm... What happens if you reverse the order?

$ echo __AVX__ + __AVX2__ | LANG= cpp -E -mavx2 -mno-avx

Anyways, I believe there may be other ways to implement this, but it would
require equally much effort (or even much more) that the current approach.
Especially considering the possiblity of future updates -- we now have a
framework for this sort of things.

Meanwhile you confortably can stay away from -msimd= and use only
-mlsx / -mlasx. So...a matter of style maybe?


^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v1 2/6] LoongArch: improved target configuration interface
  2023-08-14  8:57         ` Yujie Yang
@ 2023-08-14  8:58           ` Xi Ruoyao
  0 siblings, 0 replies; 27+ messages in thread
From: Xi Ruoyao @ 2023-08-14  8:58 UTC (permalink / raw)
  To: Yujie Yang; +Cc: gcc-patches, xuchenghua, panchenghui, chenglulu

On Mon, 2023-08-14 at 16:57 +0800, Yujie Yang wrote:
> On Mon, Aug 14, 2023 at 04:49:11PM +0800, Xi Ruoyao wrote:
> > On Mon, 2023-08-14 at 16:44 +0800, Yujie Yang wrote:
> > > I assume we all want:
> > > 
> > >  (1) -mlasx -mlsx -> enable LSX and LASX
> > >  (2) -mlasx -mno-lsx -> disable LSX and LASX
> > >  (3) -mno-lsx -mlasx -> enable LSX and LASX
> > 
> > Yes.
> > 
> > > Unless we declare -mlsx / -mlasx as driver deferred, AFAIK there is no other way for
> > > us to know the actual order of appearnce of all -m[no-]l[a]sx options on the command
> > > line.  All we know from GCC's option system would be a final on/off state of "lsx"
> > > and a final on/off state of "lasx".
> > 
> > But x86 does this correct;
> > 
> > $ echo __AVX__ + __AVX2__ | LANG= cpp -E -mno-avx -mavx2
> > # 0 "<stdin>"
> > # 0 "<built-in>"
> > # 0 "<command-line>"
> > # 1 "/usr/include/stdc-predef.h" 1 3 4
> > # 0 "<command-line>" 2
> > # 1 "<stdin>"
> > 1 + 1
> > 
> > so there must be a way to handle this...
> > 
> > -- 
> > Xi Ruoyao <xry111@xry111.site>
> > School of Aerospace Science and Technology, Xidian University
> 
> Emm... What happens if you reverse the order?
> 
> $ echo __AVX__ + __AVX2__ | LANG= cpp -E -mavx2 -mno-avx
> 
> Anyways, I believe there may be other ways to implement this, but it would
> require equally much effort (or even much more) that the current approach.
> Especially considering the possiblity of future updates -- we now have a
> framework for this sort of things.
> 
> Meanwhile you confortably can stay away from -msimd= and use only
> -mlsx / -mlasx. So...a matter of style maybe?

I'm OK with that, but we need to document it clearly in invoke.texi.

-- 
Xi Ruoyao <xry111@xry111.site>
School of Aerospace Science and Technology, Xidian University

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v1 1/6] LoongArch: a symmetric multilib subdir layout
  2023-08-14  7:48     ` Xi Ruoyao
@ 2023-08-14 10:18       ` Yujie Yang
  2023-08-14 11:16         ` Xi Ruoyao
  0 siblings, 1 reply; 27+ messages in thread
From: Yujie Yang @ 2023-08-14 10:18 UTC (permalink / raw)
  To: Xi Ruoyao; +Cc: gcc-patches

On Mon, Aug 14, 2023 at 03:48:53PM +0800, Xi Ruoyao wrote:
> On Mon, 2023-08-14 at 15:37 +0800, Yujie Yang wrote:
> > On Mon, Aug 14, 2023 at 01:38:40PM +0800, Xi Ruoyao wrote:
> > > On Mon, 2023-08-14 at 11:57 +0800, Yang Yujie wrote:
> > > 
> > > > However, for LoongArch, we do not want such a "toplevel" library
> > > > installation since the default ABI may change.  We expect all
> > > > multilib variants of libraries to be installed to their designated
> > > > ABI-specific subdirs (e.g. base/lp64d) of the GCC libdir, so that
> > > > the default ABI can be configured arbitrarily (with --with-abi)
> > > > while the gcc libdir layout stays consistent.  This could be
> > > > helpful for the distribution packaging of GCC libraries.
> > > 
> > > Have you tested a --disable-multilib configuration?  To me with --
> > > disable-configuration everything should be still in the toplevel
> > > directory, not any sub-directory.
> > 
> > That's a good point, sorry I missed --disable-multilib here.
> > 
> > However, you don't really need --disable-multilib since
> > the libraries are only built once in the default ABI configuration
> > as long as --with-multilib-list does not request anything more than
> > that.
> > 
> > Maybe we should force-enabling multilib in all cases.
> 
> I really don't like this.  Why must I always remind my self "hey, this
> is LoongArch, there is a different directory layout" when I don't need
> multilib at all?
> 

AFAIK, the two main uses of the multisubdir layout are in the C++
header directory and the GCC libdir (where libgcc.a resides), respectively.
The GCC libdir is fine since they are private to a user's GCC build.
However, the C++ header directory is shared across the system unless
an alternative sysroot is chosen, so the consisentency of the multilib
layout matters.

So theoretically, the toplevel libraries should have the same ABI under
the the target triplet.  However, for many architectures, the
"--with-abi + MULTILIB_DEFAULT" scheme may cause the toplevel to be
configured to have different meanings.

So I think it's also a reasonable approach that we just simply eliminate
the ambiguous toplevel libraries and use a symmetric layout instead.


^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v1 1/6] LoongArch: a symmetric multilib subdir layout
  2023-08-14 10:18       ` Yujie Yang
@ 2023-08-14 11:16         ` Xi Ruoyao
  2023-08-15  1:29           ` Xi Ruoyao
  0 siblings, 1 reply; 27+ messages in thread
From: Xi Ruoyao @ 2023-08-14 11:16 UTC (permalink / raw)
  To: Yujie Yang; +Cc: gcc-patches

On Mon, 2023-08-14 at 18:18 +0800, Yujie Yang wrote:
> On Mon, Aug 14, 2023 at 03:48:53PM +0800, Xi Ruoyao wrote:
> > On Mon, 2023-08-14 at 15:37 +0800, Yujie Yang wrote:
> > > On Mon, Aug 14, 2023 at 01:38:40PM +0800, Xi Ruoyao wrote:
> > > > On Mon, 2023-08-14 at 11:57 +0800, Yang Yujie wrote:
> > > > 
> > > > > However, for LoongArch, we do not want such a "toplevel" library
> > > > > installation since the default ABI may change.  We expect all
> > > > > multilib variants of libraries to be installed to their designated
> > > > > ABI-specific subdirs (e.g. base/lp64d) of the GCC libdir, so that
> > > > > the default ABI can be configured arbitrarily (with --with-abi)
> > > > > while the gcc libdir layout stays consistent.  This could be
> > > > > helpful for the distribution packaging of GCC libraries.
> > > > 
> > > > Have you tested a --disable-multilib configuration?  To me with --
> > > > disable-configuration everything should be still in the toplevel
> > > > directory, not any sub-directory.
> > > 
> > > That's a good point, sorry I missed --disable-multilib here.
> > > 
> > > However, you don't really need --disable-multilib since
> > > the libraries are only built once in the default ABI configuration
> > > as long as --with-multilib-list does not request anything more than
> > > that.
> > > 
> > > Maybe we should force-enabling multilib in all cases.
> > 
> > I really don't like this.  Why must I always remind my self "hey, this
> > is LoongArch, there is a different directory layout" when I don't need
> > multilib at all?
> > 
> 
> AFAIK, the two main uses of the multisubdir layout are in the C++
> header directory and the GCC libdir (where libgcc.a resides), respectively.
> The GCC libdir is fine since they are private to a user's GCC build.
> However, the C++ header directory is shared across the system unless
> an alternative sysroot is chosen, so the consisentency of the multilib
> layout matters.

The C++ header directory should also be considered private to the GCC
build.  AFAIK no distro supports "overwriting a part of the system", so
you cannot just install a custom GCC build and overwrite the system C++
header directory.  For a cross compiler, the C++ header directory is
$prefix/$target_triple/include/c++/$gcc_version/$multi_dir, the C++
header in $sysroot/usr/include/c++ (if it ever exists) will not be used
at all.

> So theoretically, the toplevel libraries should have the same ABI under
> the the target triplet.  However, for many architectures, the
> "--with-abi + MULTILIB_DEFAULT" scheme may cause the toplevel to be
> configured to have different meanings.

https://gcc.gnu.org/PR104085 is an example of the issue caused by the
different meaning.

> So I think it's also a reasonable approach that we just simply eliminate
> the ambiguous toplevel libraries and use a symmetric layout instead.

I don't like the inconsistency among different GCC ports.  If all ports
use the same approach I'll not object.

-- 
Xi Ruoyao <xry111@xry111.site>
School of Aerospace Science and Technology, Xidian University

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v1 2/6] LoongArch: improved target configuration interface
  2023-08-14  5:22   ` Xi Ruoyao
@ 2023-08-15  1:12     ` Yujie Yang
  0 siblings, 0 replies; 27+ messages in thread
From: Yujie Yang @ 2023-08-15  1:12 UTC (permalink / raw)
  To: Xi Ruoyao; +Cc: gcc-patches, xuchenghua, panchenghui, chenglulu

On Mon, Aug 14, 2023 at 01:22:32PM +0800, Xi Ruoyao wrote:
> On Mon, 2023-08-14 at 11:57 +0800, Yang Yujie wrote:
> > The configure script and the GCC driver are updated so that
> > it is easier to customize and control GCC builds for targeting
> > different LoongArch implementations.
> > 
> > * Support options for LoongArch SIMD extensions:
> >   new configure options --with-simd={none,lsx,lasx};
> >   new driver options -m[no]-l[a]sx / -msimd={none,lsx,lasx}.
> 
> What's the relationship between -mlasx and -msimd=lasx?  What will
> happen if the user specifies -mlasx -msimd=none or -mlasx -msimd=lsx?
> 
> -- 
> Xi Ruoyao <xry111@xry111.site>
> School of Aerospace Science and Technology, Xidian University

At this moment we make sure all "flags" (that expresses a config "delta")
are processed after the "parameters", which is documented in the LoongArch
Toolchain Conventions[1].

So if -msimd=* and -m[no-]l[a]sx appear together on the driver command
line, the final configuration would be derived by first applying -msimd=*
and then the sequence of -m[no-]l[a]sx, in the order they appear.

This is similar to the relationship between -msoft-float and -mfpu / -mabi,
where -mfpu / -mabi are applied first, and -msoft-float modifies the existing
target configuration states (FPU, ABI).

[1] currently released at https://github.com/loongson/LoongArch-Documentation
    /blob/main/docs/LoongArch-toolchain-conventions-EN.adoc


^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v1 1/6] LoongArch: a symmetric multilib subdir layout
  2023-08-14 11:16         ` Xi Ruoyao
@ 2023-08-15  1:29           ` Xi Ruoyao
  2023-08-15  2:32             ` Yujie Yang
  0 siblings, 1 reply; 27+ messages in thread
From: Xi Ruoyao @ 2023-08-15  1:29 UTC (permalink / raw)
  To: Yujie Yang; +Cc: gcc-patches

On Mon, 2023-08-14 at 19:16 +0800, Xi Ruoyao wrote:
> On Mon, 2023-08-14 at 18:18 +0800, Yujie Yang wrote:
> > On Mon, Aug 14, 2023 at 03:48:53PM +0800, Xi Ruoyao wrote:
> > > On Mon, 2023-08-14 at 15:37 +0800, Yujie Yang wrote:
> > > > On Mon, Aug 14, 2023 at 01:38:40PM +0800, Xi Ruoyao wrote:
> > > > > On Mon, 2023-08-14 at 11:57 +0800, Yang Yujie wrote:
> > > > > 
> > > > > > However, for LoongArch, we do not want such a "toplevel" library
> > > > > > installation since the default ABI may change.  We expect all
> > > > > > multilib variants of libraries to be installed to their designated
> > > > > > ABI-specific subdirs (e.g. base/lp64d) of the GCC libdir, so that
> > > > > > the default ABI can be configured arbitrarily (with --with-abi)
> > > > > > while the gcc libdir layout stays consistent.  This could be
> > > > > > helpful for the distribution packaging of GCC libraries.
> > > > > 
> > > > > Have you tested a --disable-multilib configuration?  To me with --
> > > > > disable-configuration everything should be still in the toplevel
> > > > > directory, not any sub-directory.
> > > > 
> > > > That's a good point, sorry I missed --disable-multilib here.
> > > > 
> > > > However, you don't really need --disable-multilib since
> > > > the libraries are only built once in the default ABI configuration
> > > > as long as --with-multilib-list does not request anything more than
> > > > that.
> > > > 
> > > > Maybe we should force-enabling multilib in all cases.
> > > 
> > > I really don't like this.  Why must I always remind my self "hey, this
> > > is LoongArch, there is a different directory layout" when I don't need
> > > multilib at all?
> > > 
> > 
> > AFAIK, the two main uses of the multisubdir layout are in the C++
> > header directory and the GCC libdir (where libgcc.a resides), respectively.
> > The GCC libdir is fine since they are private to a user's GCC build.
> > However, the C++ header directory is shared across the system unless
> > an alternative sysroot is chosen, so the consisentency of the multilib
> > layout matters.
> 
> The C++ header directory should also be considered private to the GCC
> build.  AFAIK no distro supports "overwriting a part of the system", so
> you cannot just install a custom GCC build and overwrite the system C++
> header directory.  For a cross compiler, the C++ header directory is
> $prefix/$target_triple/include/c++/$gcc_version/$multi_dir, the C++
> header in $sysroot/usr/include/c++ (if it ever exists) will not be used
> at all.
> 
> > So theoretically, the toplevel libraries should have the same ABI under
> > the the target triplet.  However, for many architectures, the
> > "--with-abi + MULTILIB_DEFAULT" scheme may cause the toplevel to be
> > configured to have different meanings.
> 
> https://gcc.gnu.org/PR104085 is an example of the issue caused by the
> different meaning.
> 
> > So I think it's also a reasonable approach that we just simply eliminate
> > the ambiguous toplevel libraries and use a symmetric layout instead.
> 
> I don't like the inconsistency among different GCC ports.  If all ports
> use the same approach I'll not object.

I came up with another idea. What if we:

1. Keep the "default" ABI libs in the toplevel directory. There is
*always* a default ABI so treating it specially is not really nonsense.
2. Create a symlink for consistency. For example, if --with-abi=lp64d, -
-with-multilib-list=lp64d,lp64s:

 * /usr/lib/gcc/loongarch64-linux-gnu/14.0.0 contains the lp64d
   libraries.
 * /usr/lib/gcc/loongarch64-linux-gnu/14.0.0/lp64s contains the lp64s
   libraries.
 * /usr/lib/gcc/loongarch64-linux-gnu/14.0.0/lp64d is a symlink to "."

Then we can refer to the lp64d libgcc.a with both
/usr/lib/gcc/loongarch64-linux-gnu/14.0.0/lp64d/libgcc.a, and
/usr/lib/gcc/loongarch64-linux-gnu/14.0.0/libgcc.a.

For referring to the default multilib, the non-suffixed
/usr/lib/gcc/loongarch64-linux-gnu/14.0.0 path should be used; for
referring lp64d (no matter what the default is),
/usr/lib/gcc/loongarch64-linux-gnu/14.0.0/lp64d should be used.

The symlink can be created by the GCC building system or manually by the
distro maintainer (or gcc packager).

Thoughts?

-- 
Xi Ruoyao <xry111@xry111.site> School of Aerospace Science and
Technology, Xidian University

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v1 1/6] LoongArch: a symmetric multilib subdir layout
  2023-08-15  1:29           ` Xi Ruoyao
@ 2023-08-15  2:32             ` Yujie Yang
  0 siblings, 0 replies; 27+ messages in thread
From: Yujie Yang @ 2023-08-15  2:32 UTC (permalink / raw)
  To: Xi Ruoyao; +Cc: gcc-patches

> I came up with another idea. What if we:
> 
> 1. Keep the "default" ABI libs in the toplevel directory. There is
> *always* a default ABI so treating it specially is not really nonsense.
> 2. Create a symlink for consistency. For example, if --with-abi=lp64d, -
> -with-multilib-list=lp64d,lp64s:
> 
>  * /usr/lib/gcc/loongarch64-linux-gnu/14.0.0 contains the lp64d
>    libraries.
>  * /usr/lib/gcc/loongarch64-linux-gnu/14.0.0/lp64s contains the lp64s
>    libraries.
>  * /usr/lib/gcc/loongarch64-linux-gnu/14.0.0/lp64d is a symlink to "."
> 
> Then we can refer to the lp64d libgcc.a with both
> /usr/lib/gcc/loongarch64-linux-gnu/14.0.0/lp64d/libgcc.a, and
> /usr/lib/gcc/loongarch64-linux-gnu/14.0.0/libgcc.a.
> 
> For referring to the default multilib, the non-suffixed
> /usr/lib/gcc/loongarch64-linux-gnu/14.0.0 path should be used; for
> referring lp64d (no matter what the default is),
> /usr/lib/gcc/loongarch64-linux-gnu/14.0.0/lp64d should be used.
> 
> The symlink can be created by the GCC building system or manually by the
> distro maintainer (or gcc packager).
> 
> Thoughts?
> 
> -- 
> Xi Ruoyao <xry111@xry111.site> School of Aerospace Science and
> Technology, Xidian University

Yes, this also eliminates the duplicate build.

In this case, the symlink would not really be necessary since the
toplevel directory is searched by the driver for all ABI configurations
anyways.

It is even easier to implement:

1. (gcc/config.gcc) stipulate that
   loongarch64-linux-gnu    == --with-abi=lp64d,
   loongarch64-linux-gnuf64 == --with-abi=lp64d,
   loongarch64-linux-gnuf32 == --with-abi=lp64f,
   loongarch64-linux-gnusf  == --with-abi=lp64s,
   and no customization is allowed.
   (maybe we can simply remove --with-abi?)

2. (config-ml.in) delete the "default" multisubdir from ${multidirs}.
   (which is base/lp64d for --with-abi=lp64d)

No other tweaking in config-ml.in is required.  So this seems to be
canonical.

The only problem is, I understand that triplets are essential to
the GNU build system, but should they always imply the default
ABI to be used when the compiler is invoked without an argument?


^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v1 2/6] LoongArch: improved target configuration interface
  2023-08-14  3:57 ` [PATCH v1 2/6] LoongArch: improved target configuration interface Yang Yujie
                     ` (2 preceding siblings ...)
  2023-08-14  5:58   ` Xi Ruoyao
@ 2023-09-06  6:43   ` Richard Sandiford
  2023-09-06  6:54     ` Yang Yujie
  3 siblings, 1 reply; 27+ messages in thread
From: Richard Sandiford @ 2023-09-06  6:43 UTC (permalink / raw)
  To: Yang Yujie; +Cc: gcc-patches, xry111, xuchenghua, panchenghui, chenglulu

Yang Yujie <yangyujie@loongson.cn> writes:
> @@ -5171,25 +5213,21 @@ case "${target}" in
>  		# ${with_multilib_list} should not contain whitespaces,
>  		# consecutive commas or slashes.
>  		if echo "${with_multilib_list}" \
> -		| grep -E -e "[[:space:]]" -e '[,/][,/]' -e '[,/]$' -e '^[,/]' > /dev/null; then
> +		| grep -E -e "[[:space:]]" -e '[,/][,/]' -e '[,/]$' -e '^[,/]' > /dev/null 2>&1; then
>  			echo "Invalid argument to --with-multilib-list." 1>&2
>  			exit 1
>  		fi
>  
> -		unset component idx elem_abi_base elem_abi_ext elem_tmp
> +		unset component elem_abi_base elem_abi_ext elem_tmp parse_state all_abis
>  		for elem in $(echo "${with_multilib_list}" | tr ',' ' '); do
> -			idx=0
> -			while true; do
> -				idx=$((idx + 1))
> -				component=$(echo "${elem}" | awk -F'/' '{print $'"${idx}"'}')
> -
> -				case ${idx} in
> -				1)
> -					# Component 1: Base ABI type
> +			unset elem_abi_base elem_abi_ext
> +			parse_state="abi-base"
> +
> +			for component in $(echo "${elem}" | tr '/' ' '); do
> +				if test x${parse_state} = x"abi-base"; then
> +					# Base ABI type
>  					case ${component} in
> -					lp64d) elem_tmp="ABI_BASE_LP64D,";;
> -					lp64f) elem_tmp="ABI_BASE_LP64F,";;
> -					lp64s) elem_tmp="ABI_BASE_LP64S,";;
> +					lp64d | lp64f | lp64s) elem_tmp="ABI_BASE_$(tr a-z A-Z <<< ${component}),";;

"<<<" isn't portable shell.  Could you try with:

  echo ${component} | tr ...

instead?

As it stands, this causes a bootstrap failure with non-bash shells
such as dash, even on non-Loongson targets.

(Part of me wishes that we'd just standardise on bash.  But since that
isn't the policy, I sometimes use dash to pick up my own lapses.)

Thanks,
Richard

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v1 2/6] LoongArch: improved target configuration interface
  2023-09-06  6:43   ` Richard Sandiford
@ 2023-09-06  6:54     ` Yang Yujie
  0 siblings, 0 replies; 27+ messages in thread
From: Yang Yujie @ 2023-09-06  6:54 UTC (permalink / raw)
  To: richard.sandiford
  Cc: gcc-patches, xry111, xuchenghua, panchenghui, chenglulu, yangyujie

On Wed, Sep 06, 2023 at 07:43:26AM +0100, Richard Sandiford wrote:
> Yang Yujie <yangyujie@loongson.cn> writes:
> > @@ -5171,25 +5213,21 @@ case "${target}" in
> >  		# ${with_multilib_list} should not contain whitespaces,
> >  		# consecutive commas or slashes.
> >  		if echo "${with_multilib_list}" \
> > -		| grep -E -e "[[:space:]]" -e '[,/][,/]' -e '[,/]$' -e '^[,/]' > /dev/null; then
> > +		| grep -E -e "[[:space:]]" -e '[,/][,/]' -e '[,/]$' -e '^[,/]' > /dev/null 2>&1; then
> >  			echo "Invalid argument to --with-multilib-list." 1>&2
> >  			exit 1
> >  		fi
> >  
> > -		unset component idx elem_abi_base elem_abi_ext elem_tmp
> > +		unset component elem_abi_base elem_abi_ext elem_tmp parse_state all_abis
> >  		for elem in $(echo "${with_multilib_list}" | tr ',' ' '); do
> > -			idx=0
> > -			while true; do
> > -				idx=$((idx + 1))
> > -				component=$(echo "${elem}" | awk -F'/' '{print $'"${idx}"'}')
> > -
> > -				case ${idx} in
> > -				1)
> > -					# Component 1: Base ABI type
> > +			unset elem_abi_base elem_abi_ext
> > +			parse_state="abi-base"
> > +
> > +			for component in $(echo "${elem}" | tr '/' ' '); do
> > +				if test x${parse_state} = x"abi-base"; then
> > +					# Base ABI type
> >  					case ${component} in
> > -					lp64d) elem_tmp="ABI_BASE_LP64D,";;
> > -					lp64f) elem_tmp="ABI_BASE_LP64F,";;
> > -					lp64s) elem_tmp="ABI_BASE_LP64S,";;
> > +					lp64d | lp64f | lp64s) elem_tmp="ABI_BASE_$(tr a-z A-Z <<< ${component}),";;
> 
> "<<<" isn't portable shell.  Could you try with:
> 
>   echo ${component} | tr ...
> 
> instead?
> 
> As it stands, this causes a bootstrap failure with non-bash shells
> such as dash, even on non-Loongson targets.
> 
> (Part of me wishes that we'd just standardise on bash.  But since that
> isn't the policy, I sometimes use dash to pick up my own lapses.)
> 
> Thanks,
> Richard

Sorry, I missed it when cleaning up the patches. :(
Thanks for the review.  Will fix this in a new patch.

Yujie


^ permalink raw reply	[flat|nested] 27+ messages in thread

end of thread, other threads:[~2023-09-06  6:54 UTC | newest]

Thread overview: 27+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-08-14  3:57 [PATCH v1 1/6] LoongArch: a symmetric multilib subdir layout Yang Yujie
2023-08-14  3:57 ` [PATCH v1 2/6] LoongArch: improved target configuration interface Yang Yujie
2023-08-14  5:22   ` Xi Ruoyao
2023-08-15  1:12     ` Yujie Yang
2023-08-14  5:29   ` Xi Ruoyao
2023-08-14  5:58   ` Xi Ruoyao
2023-08-14  6:01     ` Xi Ruoyao
2023-08-14  8:44     ` Yujie Yang
2023-08-14  8:49       ` Xi Ruoyao
2023-08-14  8:57         ` Yujie Yang
2023-08-14  8:58           ` Xi Ruoyao
2023-09-06  6:43   ` Richard Sandiford
2023-09-06  6:54     ` Yang Yujie
2023-08-14  3:57 ` [PATCH v1 3/6] LoongArch: define preprocessing macros "__loongarch_{arch,tune}" Yang Yujie
2023-08-14  5:24   ` Xi Ruoyao
2023-08-14  3:57 ` [PATCH v1 4/6] LoongArch: use -mstrict-align by default when building libraries Yang Yujie
2023-08-14  5:18   ` Xi Ruoyao
2023-08-14  3:57 ` [PATCH v1 5/6] LoongArch: export headers for building GCC plugins Yang Yujie
2023-08-14  3:57 ` [PATCH v1 6/6] LoongArch: support loongarch*-elf target Yang Yujie
2023-08-14  5:38 ` [PATCH v1 1/6] LoongArch: a symmetric multilib subdir layout Xi Ruoyao
2023-08-14  5:40   ` Xi Ruoyao
2023-08-14  7:37   ` Yujie Yang
2023-08-14  7:48     ` Xi Ruoyao
2023-08-14 10:18       ` Yujie Yang
2023-08-14 11:16         ` Xi Ruoyao
2023-08-15  1:29           ` Xi Ruoyao
2023-08-15  2:32             ` Yujie Yang

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).