public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH v3 0/4] LoongArch: target configuration interface update
@ 2023-08-31 12:48 Yang Yujie
  2023-08-31 12:48 ` [PATCH v3 1/4] LoongArch: improved target configuration interface Yang Yujie
                   ` (4 more replies)
  0 siblings, 5 replies; 21+ messages in thread
From: Yang Yujie @ 2023-08-31 12:48 UTC (permalink / raw)
  To: gcc-patches
  Cc: xuchenghua, chenglulu, panchenghui, joseph, xry111, Yang Yujie

This is an update of
https://gcc.gnu.org/pipermail/gcc-patches/2023-August/628772.html

Changes since the last patchset:

1. Fix texinfo format of the install.texi document.
2. Add documentation for --with-strict-align-lib.

v1 -> v2:
1. Add new configure option --with-strict-align-lib to control
   whether -mstrict-align should be used when building libraries.
   This facilitates building toolchains targeting both LA264
   (Loongson 2k1000la) and non-LA264 cores.

2. Define preprocessing macros  __loongarch_sx / __loongarch_asx
   / __loongarch_simd_width that indicates the enabled SIMD
   extensions.

3. Keep the current non-symmetric multidir layout, but do not build
   duplicate multilib variants with the same ABI option.  Make
   --with-abi= obsolete to ensure a consistent directory layout.
   (ABI type of the "toplevel" libraries can be inferred from the
    target triplet)

4. Using "-mno-lasx" do not cause a fallback to "-msimd=none" as
   long as the -march= architecture or the default --with-simd=
   setting has LSX support.

Yang Yujie (4):
  LoongArch: improved target configuration interface
  LoongArch: define preprocessing macros "__loongarch_{arch,tune}"
  LoongArch: add new configure option --with-strict-align-lib
  LoongArch: support loongarch*-elf target

 config-ml.in                                  |  10 +
 gcc/config.gcc                                | 408 ++++++++++--------
 gcc/config/loongarch/elf.h                    |  52 +++
 .../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           |  22 +-
 gcc/config/loongarch/loongarch-cpu.cc         | 263 ++++++-----
 gcc/config/loongarch/loongarch-cpu.h          |   3 +-
 gcc/config/loongarch/loongarch-def.c          |  67 +--
 gcc/config/loongarch/loongarch-def.h          |  57 +--
 gcc/config/loongarch/loongarch-driver.cc      | 208 +++++----
 gcc/config/loongarch/loongarch-driver.h       |  40 +-
 gcc/config/loongarch/loongarch-opts.cc        | 372 +++++++++++-----
 gcc/config/loongarch/loongarch-opts.h         |  59 +--
 gcc/config/loongarch/loongarch-str.h          |   7 +-
 gcc/config/loongarch/loongarch.cc             |  87 ++--
 gcc/config/loongarch/loongarch.opt            |  60 ++-
 gcc/config/loongarch/t-linux                  |  32 +-
 gcc/doc/install.texi                          |  56 ++-
 gcc/doc/invoke.texi                           |  32 +-
 libgcc/config.host                            |   9 +-
 22 files changed, 1261 insertions(+), 685 deletions(-)
 create mode 100644 gcc/config/loongarch/elf.h

-- 
2.36.0


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

* [PATCH v3 1/4] LoongArch: improved target configuration interface
  2023-08-31 12:48 [PATCH v3 0/4] LoongArch: target configuration interface update Yang Yujie
@ 2023-08-31 12:48 ` Yang Yujie
  2023-09-05 11:51   ` Xi Ruoyao
  2023-09-05 13:31   ` Xi Ruoyao
  2023-08-31 12:48 ` [PATCH v3 2/4] LoongArch: define preprocessing macros "__loongarch_{arch,tune}" Yang Yujie
                   ` (3 subsequent siblings)
  4 siblings, 2 replies; 21+ messages in thread
From: Yang Yujie @ 2023-08-31 12:48 UTC (permalink / raw)
  To: gcc-patches
  Cc: xuchenghua, chenglulu, panchenghui, joseph, xry111, 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.

* Make --with-abi obsolete, since it might cause different default ABI
  under the same target triplet, which is undesirable.  The default ABI
  is now purely decided by the target triplet.

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

* 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:
     1. lp64d/base ABI (built with "-march=la464 -mno-strict-align -msimd=lsx")
     2. lp64s/base 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.

ChangeLog:

	* config-ml.in: Do not build the multilib library variant
	that is duplicate with the toplevel one.

gcc/ChangeLog:

	* config.gcc: Make --with-abi= obsolete, decide the default ABI
	with target triplet.  Allow specifying multilib library build
	options with --with-multilib-list and --with-multilib-default.
	* config/loongarch/t-linux: Likewise.
	* config/loongarch/genopts/loongarch-strings: Likewise.
	* config/loongarch/loongarch-str.h: Likewise.
	* doc/install.texi: Likewise.
	* config/loongarch/genopts/loongarch.opt.in: Introduce
	-m[no-]l[a]sx options.  Only process -m*-float and
	-m[no-]l[a]sx in the GCC driver.
	* config/loongarch/loongarch.opt: Likewise.
	* config/loongarch/la464.md: Likewise.
	* config/loongarch/loongarch-c.cc: Likewise.
	* config/loongarch/loongarch-cpu.cc: Likewise.
	* config/loongarch/loongarch-cpu.h: Likewise.
	* config/loongarch/loongarch-def.c: Likewise.
	* config/loongarch/loongarch-def.h: Likewise.
	* config/loongarch/loongarch-driver.cc: Likewise.
	* config/loongarch/loongarch-driver.h: Likewise.
	* config/loongarch/loongarch-opts.cc: Likewise.
	* config/loongarch/loongarch-opts.h: Likewise.
	* config/loongarch/loongarch.cc: Likewise.
	* doc/invoke.texi: Likewise.
---
 config-ml.in                                  |  10 +
 gcc/config.gcc                                | 379 ++++++++++--------
 .../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           |  19 +-
 gcc/config/loongarch/loongarch-cpu.cc         | 263 +++++++-----
 gcc/config/loongarch/loongarch-cpu.h          |   3 +-
 gcc/config/loongarch/loongarch-def.c          |  67 ++--
 gcc/config/loongarch/loongarch-def.h          |  57 +--
 gcc/config/loongarch/loongarch-driver.cc      | 208 +++++-----
 gcc/config/loongarch/loongarch-driver.h       |  40 +-
 gcc/config/loongarch/loongarch-opts.cc        | 372 ++++++++++++-----
 gcc/config/loongarch/loongarch-opts.h         |  59 +--
 gcc/config/loongarch/loongarch-str.h          |   7 +-
 gcc/config/loongarch/loongarch.cc             |  87 ++--
 gcc/config/loongarch/loongarch.opt            |  60 ++-
 gcc/config/loongarch/t-linux                  |  32 +-
 gcc/doc/install.texi                          |  52 ++-
 gcc/doc/invoke.texi                           |  32 +-
 20 files changed, 1167 insertions(+), 682 deletions(-)

diff --git a/config-ml.in b/config-ml.in
index 68854a4f16c..ad0db078171 100644
--- a/config-ml.in
+++ b/config-ml.in
@@ -301,6 +301,16 @@ arm-*-*)
 	  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
+	;;
 m68*-*-*)
 	if [ x$enable_softfloat = xno ]
 	then
diff --git a/gcc/config.gcc b/gcc/config.gcc
index 415e0e1ebc5..4fae672a3b7 100644
--- a/gcc/config.gcc
+++ b/gcc/config.gcc
@@ -4891,43 +4891,46 @@ case "${target}" in
 		esac
 		;;
 
-	loongarch*-*-*)
-		supported_defaults="abi arch tune fpu"
+	loongarch*-*)
+		supported_defaults="abi arch tune fpu simd multilib-default"
 
 		# Local variables
 		unset \
-			abi_pattern      abi_default    \
-			abiext_pattern   abiext_default \
-			arch_pattern     arch_default   \
-			fpu_pattern      fpu_default    \
-			tune_pattern     tune_default   \
-			triplet_os       triplet_abi
+			abi_base	abi_ext \
+			arch_pattern	arch_default \
+			fpu_pattern	fpu_default \
+			triplet_os	triplet_abi \
+			strict_align_opt
+
+		# --with-abi is now obsolete, emit a warning if given.
+		case ${with_abi} in
+		"") ;;
+		*)
+			echo "warning: --with-abi= is now obsolete," \
+			"the default ABI is derived from your target" \
+			"triplet ${target}" 1>&2
+			;;
+		esac
 
 		# Infer ABI from the triplet.
 		case ${target} in
-		loongarch64-*-*-*f64)
-			abi_pattern="lp64d"
-			;;
-		loongarch64-*-*-*f32)
-			abi_pattern="lp64f"
-			;;
-		loongarch64-*-*-*sf)
-			abi_pattern="lp64s"
-			;;
-		loongarch64-*-*-*)
-			abi_pattern="lp64[dfs]"
-			abi_default="lp64d"
-			;;
+		loongarch64-*f64) abi_base="lp64d"; abi_ext="base" ;;
+		loongarch64-*f32) abi_base="lp64f"; abi_ext="base" ;;
+		loongarch64-*sf)  abi_base="lp64s"; abi_ext="base" ;;
+		loongarch64-*)    abi_base="lp64d"; abi_ext="base" ;;
 		*)
 			echo "Unsupported target ${target}." 1>&2
 			exit 1
 			;;
 		esac
 
-		abiext_pattern="*"
-		abiext_default="base"
-
 		# Get the canonical triplet (multiarch specifier).
+		case ${abi_base},${abi_ext} in
+		lp64d,base) triplet_abi="";;
+		lp64f,base) triplet_abi="f32";;
+		lp64s,base) triplet_abi="sf";;
+		esac
+
 		case ${target} in
 		  *-linux-gnu*)  triplet_os="linux-gnu";;
 		  *-linux-musl*) triplet_os="linux-musl";;
@@ -4936,42 +4939,24 @@ case "${target}" in
 			  exit 1
 			  ;;
 		esac
+		la_canonical_triplet="loongarch64-${triplet_os}${triplet_abi}"
+
 
 		# 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
 			;;
 		esac
 
-		case ${with_abi} in
-		"" | lp64d | lp64f | lp64s) ;; # OK, append here.
-		*)
-			echo "Unsupported ABI given in --with-abi=$with_abi" 1>&2
-			exit 1
-			;;
-		esac
-
-		case ${with_abiext} in
-		"" | base) ;; # OK, append here.
-		*)
-			echo "Unsupported ABI extention type $with_abiext" 1>&2
-			exit 1
-			;;
-		esac
 
 		case ${with_fpu} in
 		"" | none | 32 | 64) ;; # OK, append here.
@@ -4985,73 +4970,41 @@ case "${target}" in
 			;;
 		esac
 
-
-		# Set default value for with_abi.
-		case ${with_abi} in
-		"")
-			if test x${abi_default} != x; then
-				with_abi=${abi_default}
-			else
-				with_abi=${abi_pattern}
-			fi
-			;;
-
-		*)
-			if echo "${with_abi}" | grep -E "^${abi_pattern}$" > /dev/null; then
-				: # OK
-			else
-				echo "Incompatible options:" \
-				"--with-abi=${with_abi} and --target=${target}." 1>&2
+		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
-			fi
-			;;
-		esac
-
-		case ${with_abi} in
-		  "lp64d") triplet_abi="";;
-		  "lp64f") triplet_abi="f32";;
-		  "lp64s") triplet_abi="sf";;
-		esac
-		la_canonical_triplet="loongarch64-${triplet_os}${triplet_abi}"
-
-		# Set default value for with_abiext (internal)
-		case ${with_abiext} in
-		"")
-			if test x${abiext_default} != x; then
-				with_abiext=${abiext_default}
-			else
-				with_abiext=${abiext_pattern}
-			fi
+				;;
+			esac
 			;;
 
 		*)
-			if echo "${with_abiext}" | grep -E "^${abiext_pattern}$" > /dev/null; then
-				: # OK
-			else
-				echo "The ABI extension type \"${with_abiext}\"" \
-				"is incompatible with --target=${target}." 1>&2
-				exit 1
-			fi
-
+			echo "Unknown SIMD extension in --with-simd=$with_simd" 1>&2
+			exit 1
 			;;
 		esac
 
 		# Infer ISA-related default options from the ABI: pass 1
-		case ${with_abi}/${with_abiext} in
+		case ${abi_base}/${abi_ext} 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
+			echo "Unsupported ABI type ${abi_base}/${abi_ext}." 1>&2
 			exit 1
 			;;
 		esac
 
 		# Infer ISA-related default options from the ABI: pass 2
-		case ${with_abi}/${with_abiext} in
+		case ${abi_base}/${abi_ext} in
 		lp64d/base)
 			fpu_pattern="64"
 			;;
@@ -5064,7 +5017,7 @@ case "${target}" in
 			fpu_default="none"
 			;;
 		*)
-			echo "Unsupported ABI type ${with_abi}/${with_abiext}." 1>&2
+			echo "Unsupported ABI type ${abi_base}/${abi_ext}." 1>&2
 			exit 1
 			;;
 		esac
@@ -5083,7 +5036,7 @@ case "${target}" in
 			if echo "${with_arch}" | grep -E "^${arch_pattern}$" > /dev/null; then
 				: # OK
 			else
-				echo "${with_abi}/${with_abiext} ABI cannot be implemented with" \
+				echo "${abi_base}/${abi_ext} ABI cannot be implemented with" \
 				"--with-arch=${with_arch}." 1>&2
 				exit 1
 			fi
@@ -5104,7 +5057,7 @@ case "${target}" in
 			if echo "${with_fpu}" | grep -E "^${fpu_pattern}$" > /dev/null; then
 				: # OK
 			else
-				echo "${with_abi}/${with_abiext} ABI cannot be implemented with" \
+				echo "${abi_base}/${abi_ext} ABI cannot be implemented with" \
 				"--with-fpu=${with_fpu}." 1>&2
 				exit 1
 			fi
@@ -5112,32 +5065,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,13 +5089,53 @@ 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 \
 		   || test x"${with_multilib_list}" = xdefault \
 		   || test x"${enable_multilib}" != xyes; then
 
-			with_multilib_list="${with_abi}/${with_abiext}"
+			with_multilib_list="${abi_base}/${abi_ext}"
 		fi
 
 		# Check if the configured default ABI combination is included in
@@ -5171,25 +5151,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,57 +5174,111 @@ 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
 
-			if test x${elem_abi_base} = x${with_abi} \
-			&& test x${elem_abi_ext} = x${with_abiext}; then
+			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${abi_base} \
+			&& test x${elem_abi_ext} = x${abi_ext}; 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
-			if test x${with_abiext} = xbase; then
-				with_abiext=""
+			if test x${abi_ext} = xbase; then
+				abi_ext=""
 			else
-				with_abiext="/${with_abiext}"
+				abi_ext="/${abi_ext}"
 			fi
 
-			echo "Default ABI combination (${with_abi}${with_abiext})" \
+			echo "Default ABI combination (${abi_base}${abi_ext})" \
 			"not found in --with-multilib-list." 1>&2
 			exit 1
 		fi
@@ -5739,34 +5769,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 ${abi_base} | tr a-z- A-Z_)"
 
-		case ${with_abiext} in
+		# ABI Extension
+		case ${abi_ext} 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..adecaec3eda 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 @@ (define_cpu_unit "la464_falu2" "la464_a_falu")
 ;; 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..7e3b57ff9b1 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)
@@ -99,6 +99,21 @@ loongarch_cpu_cpp_builtins (cpp_reader *pfile)
   else
     builtin_define ("__loongarch_frlen=0");
 
+  if (ISA_HAS_LSX)
+    {
+      builtin_define ("__loongarch_simd");
+      builtin_define ("__loongarch_sx");
+
+      if (!ISA_HAS_LASX)
+	builtin_define ("__loongarch_simd_width=128");
+    }
+
+  if (ISA_HAS_LASX)
+    {
+      builtin_define ("__loongarch_asx");
+      builtin_define ("__loongarch_simd_width=256");
+    }
+
   /* Native Data Sizes.  */
   builtin_define_with_int_value ("_LOONGARCH_SZINT", INT_TYPE_SIZE);
   builtin_define_with_int_value ("_LOONGARCH_SZLONG", LONG_TYPE_SIZE);
diff --git a/gcc/config/loongarch/loongarch-cpu.cc b/gcc/config/loongarch/loongarch-cpu.cc
index 34905f3de30..7a2866f60f9 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,191 @@ 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:
+	    tmp = 0;
+	    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]);
+	    break;
+
+	  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..e744ee01d6d 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,29 @@ 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..bafd27e67a5 100644
--- a/gcc/config/loongarch/loongarch-driver.cc
+++ b/gcc/config/loongarch/loongarch-driver.cc
@@ -26,122 +26,137 @@ 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 ATTRIBUTE_UNUSED,
+		    const char **argv ATTRIBUTE_UNUSED)
+{
+  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);
 
   /* Output normalized option strings.  */
   obstack_blank (&opts_obstack, 0);
@@ -160,11 +175,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 +194,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..e5921189a06 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,10 @@ 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 +112,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 +171,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 +239,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 +268,130 @@ 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));
+
+  int simd_base = (constrained.arch ? t.isa.simd :
+    (with_default_simd ? DEFAULT_ISA_EXT_SIMD : t.isa.simd));
+
+  t.isa.simd = constrained.simd ? target->isa.simd : simd_base;
+
+  /* If fallback_lsx is set, using -mno-lasx would cause
+     a fall-back to -msimd=lsx instead of -msimd=none.  */
+
+  int fallback_lsx = 0;
+  if (t.isa.simd == ISA_EXT_SIMD_LSX || simd_base != ISA_EXT_NONE)
+    fallback_lsx = 1;
+
+  /* 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)
+	      fallback_lsx = 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 -mlsx or simd=lsx (msimd or march-default) was not
+	       involved, do not fall back to simd=lsx.  */
+	    if (flags->sx[i] < 0 && t.isa.simd == ISA_EXT_SIMD_LASX)
+	      t.isa.simd = fallback_lsx ? ISA_EXT_SIMD_LSX : ISA_EXT_NONE;
+	    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 +414,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 +461,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 +502,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 +517,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 +561,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 +601,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 +625,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 +669,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 +678,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 +702,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 +748,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..7a58dabdea8 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
 
 
@@ -50,11 +65,11 @@ loongarch_config_target (struct loongarch_target *target,
 #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..9997596d722 100644
--- a/gcc/config/loongarch/t-linux
+++ b/gcc/config/loongarch/t-linux
@@ -23,7 +23,37 @@ 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; }' $< > $@
+
+# Do some preparation before regression tests:
+# remove lib-build-specs / make symlinks for the toplevel multilib variant
+
+LA_DEFAULT_MULTISUBDIR = $(shell $(GCC_FOR_TARGET) --print-multi-dir)
+.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
+	-mv $(LA_DEFAULT_MULTISUBDIR)/* ./
+	-mkdir -p ../$(target_noncanonical)/`dirname $(LA_DEFAULT_MULTISUBDIR)`
+	-$(LN_S) .. ../$(target_noncanonical)/$(LA_DEFAULT_MULTISUBDIR)
 
 # Multiarch
 ifneq ($(call if_multiarch,yes),yes)
diff --git a/gcc/doc/install.texi b/gcc/doc/install.texi
index e099cd0b568..bbc58cb60ca 100644
--- a/gcc/doc/install.texi
+++ b/gcc/doc/install.texi
@@ -1236,7 +1236,7 @@ sysv, aix.
 @itemx --without-multilib-list
 Specify what multilibs to build.  @var{list} is a comma separated list of
 values, possibly consisting of a single value.  Currently only implemented
-for aarch64*-*-*, arm*-*-*, loongarch64-*-*, riscv*-*-*, sh*-*-* and
+for aarch64*-*-*, arm*-*-*, loongarch*-*-*, riscv*-*-*, sh*-*-* and
 x86-64-*-linux*.  The accepted values and meaning for each target is given
 below.
 
@@ -1326,12 +1326,33 @@ 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{[/@var{arch}][/@var{option}/@dots{}]} may follow immediately
+after the ABI identifier to customize the compiler options for building the
+given set of libraries.  @var{arch} denotes the architecture name recognized
+by the @option{-march=@var{arch}} compiler option, which acts as a basic target
+ISA configuration that can be adjusted using the subsequent @var{option}
+suffixes, where each @var{option} is a compiler option without a leading dash
+('-').
+
+If no such suffix is present for a given multilib variant, the
+configured value of @option{--with-multilib-default} is appended as a default
+suffix.  If @option{--with-multilib-default} is not given, the default build
+option @option{-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 @var{arch},
+which means using the architecture configured with
+@option{--with-arch=@var{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 only the default variant of the libraries are built,
+where the default ABI is implied by the configured target triplet.
 
 @item riscv*-*-*
 @var{list} is a single ABI name.  The target architecture must be either
@@ -1382,6 +1403,19 @@ 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{[/@var{arch}][/@var{option}/@dots{}]}, where @var{arch} is an
+architecture name recognized by @option{-march=@var{arch}} compiler option,
+and subsequent @var{option} suffixes are compiler options minus a leading
+dash ('-').
+
+Multiple @var{option}s may appear consecutively while @var{arch} may only
+appear in the beginning or be omitted (which means @option{-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 +1565,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
@@ -4505,8 +4540,7 @@ Uses @code{lp64s/base} ABI by default.
 @end table
 
 @item loongarch64-linux-gnu
-Same as @code{loongarch64-linux-gnuf64}, but may be used with
-@option{--with-abi=*} to configure the default ABI type.
+Same as @code{loongarch64-linux-gnuf64} for legacy support.
 @end table
 
 More information about LoongArch can be found at
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 10f3466052f..2f01baff3e7 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,21 @@ operations.
 Prevent the use of hardware floating-point instructions.
 @end table
 
+@opindex msimd
+@item -msimd=@var{simd-type}
+Enable generation of LoongArch SIMD instructions for vectorization
+and via builtin functions.  The value can be one of:
+@table @samp
+@item lasx
+Enable generating instructions from the 256-bit LoongArch Advanced
+SIMD Extension (LASX) and the 128-bit LoongArch SIMD Extension (LSX).
+@item lsx
+Enable generating instructions from the 128-bit LoongArch SIMD
+Extension (LSX).
+@item none
+No LoongArch SIMD instruction may be generated.
+@end table
+
 @opindex msoft-float
 @item -msoft-float
 Force @option{-mfpu=none} and prevents the use of floating-point
@@ -25988,6 +26004,19 @@ 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 ml[a]sx
+@item -mlasx
+@itemx -mno-lasx
+@item -mlsx
+@itemx -mno-lsx
+Incrementally adjust the scope of the SIMD extensions (none / LSX / LASX)
+that can be used by the compiler for code generation.  Enabling LASX with
+@option{mlasx} automatically enables LSX, and diabling LSX with @option{mno-lsx}
+automatically disables LASX.  These driver-only options act upon the final
+@option{msimd} configuration state and make incremental chagnes in the order
+they appear on the GCC driver's command line, deriving the final / canonicalized
+@option{msimd} option that is passed to the compiler proper.
+
 @opindex mbranch-cost
 @item -mbranch-cost=@var{n}
 Set the cost of branches to roughly @var{n} instructions.
@@ -26088,6 +26117,7 @@ kernels, executables linked with @option{-static} or @option{-static-pie}.
 @option{-fpic}.
 @end table
 
+
 @node M32C Options
 @subsection M32C Options
 @cindex M32C options
-- 
2.36.0


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

* [PATCH v3 2/4] LoongArch: define preprocessing macros "__loongarch_{arch,tune}"
  2023-08-31 12:48 [PATCH v3 0/4] LoongArch: target configuration interface update Yang Yujie
  2023-08-31 12:48 ` [PATCH v3 1/4] LoongArch: improved target configuration interface Yang Yujie
@ 2023-08-31 12:48 ` Yang Yujie
  2023-08-31 12:48 ` [PATCH v3 3/4] LoongArch: add new configure option --with-strict-align-lib Yang Yujie
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 21+ messages in thread
From: Yang Yujie @ 2023-08-31 12:48 UTC (permalink / raw)
  To: gcc-patches
  Cc: xuchenghua, chenglulu, panchenghui, joseph, xry111, 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:

	* 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 7e3b57ff9b1..ec047e3822a 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.36.0


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

* [PATCH v3 3/4] LoongArch: add new configure option --with-strict-align-lib
  2023-08-31 12:48 [PATCH v3 0/4] LoongArch: target configuration interface update Yang Yujie
  2023-08-31 12:48 ` [PATCH v3 1/4] LoongArch: improved target configuration interface Yang Yujie
  2023-08-31 12:48 ` [PATCH v3 2/4] LoongArch: define preprocessing macros "__loongarch_{arch,tune}" Yang Yujie
@ 2023-08-31 12:48 ` Yang Yujie
  2023-08-31 12:48 ` [PATCH v3 4/4] LoongArch: support loongarch*-elf target Yang Yujie
  2023-09-05  4:40 ` Re:[pushed] [PATCH v3 0/4] LoongArch: target configuration interface update chenglulu
  4 siblings, 0 replies; 21+ messages in thread
From: Yang Yujie @ 2023-08-31 12:48 UTC (permalink / raw)
  To: gcc-patches
  Cc: xuchenghua, chenglulu, panchenghui, joseph, xry111, 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).

No significant performance degredation is observed on current mainstream
LoongArch processors when the option is enabled.

gcc/ChangeLog:

	* config.gcc: use -mstrict-align for building libraries
	if --with-strict-align-lib is given.
	* doc/install.texi: likewise.
---
 gcc/config.gcc       | 16 +++++++++++++++-
 gcc/doc/install.texi |  4 ++++
 2 files changed, 19 insertions(+), 1 deletion(-)

diff --git a/gcc/config.gcc b/gcc/config.gcc
index 4fae672a3b7..ed70fa63268 100644
--- a/gcc/config.gcc
+++ b/gcc/config.gcc
@@ -4892,7 +4892,7 @@ case "${target}" in
 		;;
 
 	loongarch*-*)
-		supported_defaults="abi arch tune fpu simd multilib-default"
+		supported_defaults="abi arch tune fpu simd multilib-default strict-align-lib"
 
 		# Local variables
 		unset \
@@ -5089,6 +5089,17 @@ case "${target}" in
 			;;
 		esac
 
+		# Build libraries with -mstrict-align if --with-strict-align-lib is given.
+		case ${with_strict_align_lib} in
+		yes) strict_align_opt="/mstrict-align" ;;
+		""|no)  ;;
+		*)
+			echo "Unknown option: --with-strict-align-lib=${with_strict_align_lib}" 1>&2
+			exit 1
+			;;
+		esac
+
+
 		# Handle --with-multilib-default
 		if echo "${with_multilib_default}" \
 		| grep -E -e '[[:space:]]' -e '//' -e '/$' -e '^/' > /dev/null 2>&1; then
@@ -5250,6 +5261,9 @@ case "${target}" in
 					;;
 			esac
 
+			# Use mstrict-align for building libraries if --with-strict-align-lib is given.
+			loongarch_multilib_list_make="${loongarch_multilib_list_make}${strict_align_opt}"
+
 			# 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
diff --git a/gcc/doc/install.texi b/gcc/doc/install.texi
index bbc58cb60ca..31f2234640f 100644
--- a/gcc/doc/install.texi
+++ b/gcc/doc/install.texi
@@ -1416,6 +1416,10 @@ Multiple @var{option}s may appear consecutively while @var{arch} may only
 appear in the beginning or be omitted (which means @option{-march=abi-default}
 is applied when building the libraries).
 
+@item --with-strict-align-lib
+On LoongArch targets, build all enabled multilibs with @option{-mstrict-align}
+(Not enabled by default).
+
 @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
-- 
2.36.0


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

* [PATCH v3 4/4] LoongArch: support loongarch*-elf target
  2023-08-31 12:48 [PATCH v3 0/4] LoongArch: target configuration interface update Yang Yujie
                   ` (2 preceding siblings ...)
  2023-08-31 12:48 ` [PATCH v3 3/4] LoongArch: add new configure option --with-strict-align-lib Yang Yujie
@ 2023-08-31 12:48 ` Yang Yujie
  2023-09-05  4:40 ` Re:[pushed] [PATCH v3 0/4] LoongArch: target configuration interface update chenglulu
  4 siblings, 0 replies; 21+ messages in thread
From: Yang Yujie @ 2023-08-31 12:48 UTC (permalink / raw)
  To: gcc-patches
  Cc: xuchenghua, chenglulu, panchenghui, joseph, xry111, 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             | 15 ++++++++++-
 gcc/config/loongarch/elf.h | 52 ++++++++++++++++++++++++++++++++++++++
 libgcc/config.host         |  9 +++++--
 3 files changed, 73 insertions(+), 3 deletions(-)
 create mode 100644 gcc/config/loongarch/elf.h

diff --git a/gcc/config.gcc b/gcc/config.gcc
index ed70fa63268..b77e1fd5278 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"
@@ -4932,8 +4944,9 @@ case "${target}" in
 		esac
 
 		case ${target} in
-		  *-linux-gnu*)  triplet_os="linux-gnu";;
+		  *-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..6f84222e4e1
--- /dev/null
+++ b/gcc/config/loongarch/elf.h
@@ -0,0 +1,52 @@
+/* Definitions for LoongArch ELF-based systems.
+   Copyright (C) 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.36.0


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

* Re:[pushed] [PATCH v3 0/4] LoongArch: target configuration interface update
  2023-08-31 12:48 [PATCH v3 0/4] LoongArch: target configuration interface update Yang Yujie
                   ` (3 preceding siblings ...)
  2023-08-31 12:48 ` [PATCH v3 4/4] LoongArch: support loongarch*-elf target Yang Yujie
@ 2023-09-05  4:40 ` chenglulu
  4 siblings, 0 replies; 21+ messages in thread
From: chenglulu @ 2023-09-05  4:40 UTC (permalink / raw)
  To: Yang Yujie, gcc-patches; +Cc: xuchenghua, panchenghui, joseph, xry111

Pushed to r14-3665.

在 2023/8/31 下午8:48, Yang Yujie 写道:
> This is an update of
> https://gcc.gnu.org/pipermail/gcc-patches/2023-August/628772.html
>
> Changes since the last patchset:
>
> 1. Fix texinfo format of the install.texi document.
> 2. Add documentation for --with-strict-align-lib.
>
> v1 -> v2:
> 1. Add new configure option --with-strict-align-lib to control
>     whether -mstrict-align should be used when building libraries.
>     This facilitates building toolchains targeting both LA264
>     (Loongson 2k1000la) and non-LA264 cores.
>
> 2. Define preprocessing macros  __loongarch_sx / __loongarch_asx
>     / __loongarch_simd_width that indicates the enabled SIMD
>     extensions.
>
> 3. Keep the current non-symmetric multidir layout, but do not build
>     duplicate multilib variants with the same ABI option.  Make
>     --with-abi= obsolete to ensure a consistent directory layout.
>     (ABI type of the "toplevel" libraries can be inferred from the
>      target triplet)
>
> 4. Using "-mno-lasx" do not cause a fallback to "-msimd=none" as
>     long as the -march= architecture or the default --with-simd=
>     setting has LSX support.
>
> Yang Yujie (4):
>    LoongArch: improved target configuration interface
>    LoongArch: define preprocessing macros "__loongarch_{arch,tune}"
>    LoongArch: add new configure option --with-strict-align-lib
>    LoongArch: support loongarch*-elf target
>
>   config-ml.in                                  |  10 +
>   gcc/config.gcc                                | 408 ++++++++++--------
>   gcc/config/loongarch/elf.h                    |  52 +++
>   .../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           |  22 +-
>   gcc/config/loongarch/loongarch-cpu.cc         | 263 ++++++-----
>   gcc/config/loongarch/loongarch-cpu.h          |   3 +-
>   gcc/config/loongarch/loongarch-def.c          |  67 +--
>   gcc/config/loongarch/loongarch-def.h          |  57 +--
>   gcc/config/loongarch/loongarch-driver.cc      | 208 +++++----
>   gcc/config/loongarch/loongarch-driver.h       |  40 +-
>   gcc/config/loongarch/loongarch-opts.cc        | 372 +++++++++++-----
>   gcc/config/loongarch/loongarch-opts.h         |  59 +--
>   gcc/config/loongarch/loongarch-str.h          |   7 +-
>   gcc/config/loongarch/loongarch.cc             |  87 ++--
>   gcc/config/loongarch/loongarch.opt            |  60 ++-
>   gcc/config/loongarch/t-linux                  |  32 +-
>   gcc/doc/install.texi                          |  56 ++-
>   gcc/doc/invoke.texi                           |  32 +-
>   libgcc/config.host                            |   9 +-
>   22 files changed, 1261 insertions(+), 685 deletions(-)
>   create mode 100644 gcc/config/loongarch/elf.h
>


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

* Re: [PATCH v3 1/4] LoongArch: improved target configuration interface
  2023-08-31 12:48 ` [PATCH v3 1/4] LoongArch: improved target configuration interface Yang Yujie
@ 2023-09-05 11:51   ` Xi Ruoyao
  2023-09-05 12:01     ` chenglulu
  2023-09-05 13:31   ` Xi Ruoyao
  1 sibling, 1 reply; 21+ messages in thread
From: Xi Ruoyao @ 2023-09-05 11:51 UTC (permalink / raw)
  To: Yang Yujie, gcc-patches; +Cc: xuchenghua, chenglulu, panchenghui, joseph

On Thu, 2023-08-31 at 20:48 +0800, Yang Yujie wrote:
>  /* 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
> -

This causes a build failure with older assembler:

options.cc:3040:3: error: 'HAVE_AS_EXPLICIT_RELOCS' was not declared in this scope; did you mean 'TARGET_EXPLICIT_RELOCS'?
 3040 |   HAVE_AS_EXPLICIT_RELOCS, /* TARGET_EXPLICIT_RELOCS */
      |   ^~~~~~~~~~~~~~~~~~~~~~~
      |   TARGET_EXPLICIT_RELOCS

Why this is removed?  If this is an unintentionally change I'll add it
back.

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

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

* Re: [PATCH v3 1/4] LoongArch: improved target configuration interface
  2023-09-05 11:51   ` Xi Ruoyao
@ 2023-09-05 12:01     ` chenglulu
  2023-09-05 12:17       ` Xi Ruoyao
  0 siblings, 1 reply; 21+ messages in thread
From: chenglulu @ 2023-09-05 12:01 UTC (permalink / raw)
  To: Xi Ruoyao, Yang Yujie, gcc-patches; +Cc: xuchenghua, panchenghui, joseph


在 2023/9/5 下午7:51, Xi Ruoyao 写道:
> On Thu, 2023-08-31 at 20:48 +0800, Yang Yujie wrote:
>>   /* 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
>> -
> This causes a build failure with older assembler:
>
> options.cc:3040:3: error: 'HAVE_AS_EXPLICIT_RELOCS' was not declared in this scope; did you mean 'TARGET_EXPLICIT_RELOCS'?
>   3040 |   HAVE_AS_EXPLICIT_RELOCS, /* TARGET_EXPLICIT_RELOCS */
>        |   ^~~~~~~~~~~~~~~~~~~~~~~
>        |   TARGET_EXPLICIT_RELOCS
>
> Why this is removed?  If this is an unintentionally change I'll add it
> back.
>
Sorry, this was deleted accidentally.

Thanks!



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

* Re: [PATCH v3 1/4] LoongArch: improved target configuration interface
  2023-09-05 12:01     ` chenglulu
@ 2023-09-05 12:17       ` Xi Ruoyao
  2023-09-05 12:26         ` chenglulu
  0 siblings, 1 reply; 21+ messages in thread
From: Xi Ruoyao @ 2023-09-05 12:17 UTC (permalink / raw)
  To: chenglulu, Yang Yujie, gcc-patches; +Cc: xuchenghua, panchenghui, joseph

On Tue, 2023-09-05 at 20:01 +0800, chenglulu wrote:
> 
> 在 2023/9/5 下午7:51, Xi Ruoyao 写道:
> > On Thu, 2023-08-31 at 20:48 +0800, Yang Yujie wrote:
> > >   /* 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
> > > -
> > This causes a build failure with older assembler:
> > 
> > options.cc:3040:3: error: 'HAVE_AS_EXPLICIT_RELOCS' was not declared in this scope; did you mean 'TARGET_EXPLICIT_RELOCS'?
> >   3040 |   HAVE_AS_EXPLICIT_RELOCS, /* TARGET_EXPLICIT_RELOCS */
> >        |   ^~~~~~~~~~~~~~~~~~~~~~~
> >        |   TARGET_EXPLICIT_RELOCS
> > 
> > Why this is removed?  If this is an unintentionally change I'll add it
> > back.
> > 
> Sorry, this was deleted accidentally.
> 
> Thanks!

Added the 3 lines back at r14-3706.

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

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

* Re: [PATCH v3 1/4] LoongArch: improved target configuration interface
  2023-09-05 12:17       ` Xi Ruoyao
@ 2023-09-05 12:26         ` chenglulu
  0 siblings, 0 replies; 21+ messages in thread
From: chenglulu @ 2023-09-05 12:26 UTC (permalink / raw)
  To: Xi Ruoyao, Yang Yujie, gcc-patches; +Cc: xuchenghua, panchenghui, joseph


在 2023/9/5 下午8:17, Xi Ruoyao 写道:
> On Tue, 2023-09-05 at 20:01 +0800, chenglulu wrote:
>> 在 2023/9/5 下午7:51, Xi Ruoyao 写道:
>>> On Thu, 2023-08-31 at 20:48 +0800, Yang Yujie wrote:
>>>>    /* 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
>>>> -
>>> This causes a build failure with older assembler:
>>>
>>> options.cc:3040:3: error: 'HAVE_AS_EXPLICIT_RELOCS' was not declared in this scope; did you mean 'TARGET_EXPLICIT_RELOCS'?
>>>    3040 |   HAVE_AS_EXPLICIT_RELOCS, /* TARGET_EXPLICIT_RELOCS */
>>>         |   ^~~~~~~~~~~~~~~~~~~~~~~
>>>         |   TARGET_EXPLICIT_RELOCS
>>>
>>> Why this is removed?  If this is an unintentionally change I'll add it
>>> back.
>>>
>> Sorry, this was deleted accidentally.
>>
>> Thanks!
> Added the 3 lines back at r14-3706.
>
Ok. Thanks!


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

* Re: [PATCH v3 1/4] LoongArch: improved target configuration interface
  2023-08-31 12:48 ` [PATCH v3 1/4] LoongArch: improved target configuration interface Yang Yujie
  2023-09-05 11:51   ` Xi Ruoyao
@ 2023-09-05 13:31   ` Xi Ruoyao
  2023-09-06  1:04     ` Yang Yujie
  1 sibling, 1 reply; 21+ messages in thread
From: Xi Ruoyao @ 2023-09-05 13:31 UTC (permalink / raw)
  To: Yang Yujie, gcc-patches; +Cc: xuchenghua, chenglulu, panchenghui, joseph

On Thu, 2023-08-31 at 20:48 +0800, Yang Yujie wrote:
> * Support options for LoongArch SIMD extensions:
>   new configure options --with-simd={none,lsx,lasx};
>   new compiler option -msimd={none,lsx,lasx};
>   new driver options -m[no]-l[a]sx.

Hmm... In my build (a cross compiler configured with ../gcc/configure --
target=loongarch64-linux-gnu --with-system-zlib) I have:

$ cat lasx.c
int x __attribute__((vector_size(32)));
int y __attribute__((vector_size(32)));
void test(void) { x += y; }
$ gcc/cc1 lasx.c -msimd=lasx -o- -nostdinc -mexplicit-relocs -O2

... ...

	pcalau12i	$r12,%pc_hi20(.LANCHOR0)
	addi.d	$r12,$r12,%pc_lo12(.LANCHOR0)
	xvld	$xr0,$r12,0
	xvld	$xr1,$r12,32
	xvadd.w	$xr0,$xr0,$xr1
	xvst	$xr0,$r12,0
	jr	$r1

... ...

This seems perfectly fine.  But:

$ gcc/xgcc -B gcc lasx.c -mlasx -o- -nostdinc -mexplicit-relocs -O2 -S

... ...

test:
.LFB0 = .
	pcalau12i	$r12,%pc_hi20(.LANCHOR0)
	addi.d	$r12,$r12,%pc_lo12(.LANCHOR0)
	addi.d	$r3,$r3,-16
.LCFI0 = .
	st.d	$r23,$r3,8
.LCFI1 = .
	ldptr.w	$r7,$r12,0
	ldptr.w	$r23,$r12,32
	ldptr.w	$r6,$r12,8

... ... (no SIMD instructions)

Is this a bug in the driver or I missed something?

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

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

* Re: [PATCH v3 1/4] LoongArch: improved target configuration interface
  2023-09-05 13:31   ` Xi Ruoyao
@ 2023-09-06  1:04     ` Yang Yujie
  2023-09-07  8:49       ` Xi Ruoyao
  0 siblings, 1 reply; 21+ messages in thread
From: Yang Yujie @ 2023-09-06  1:04 UTC (permalink / raw)
  To: Xi Ruoyao
  Cc: Yang Yujie, gcc-patches, xuchenghua, chenglulu, panchenghui, joseph

On Tue, Sep 05, 2023 at 09:31:56PM +0800, Xi Ruoyao wrote:
> On Thu, 2023-08-31 at 20:48 +0800, Yang Yujie wrote:
> > * Support options for LoongArch SIMD extensions:
> >   new configure options --with-simd={none,lsx,lasx};
> >   new compiler option -msimd={none,lsx,lasx};
> >   new driver options -m[no]-l[a]sx.
> 
> Hmm... In my build (a cross compiler configured with ../gcc/configure --
> target=loongarch64-linux-gnu --with-system-zlib) I have:
> 
> $ cat lasx.c
> int x __attribute__((vector_size(32)));
> int y __attribute__((vector_size(32)));
> void test(void) { x += y; }
> $ gcc/cc1 lasx.c -msimd=lasx -o- -nostdinc -mexplicit-relocs -O2
> 
> ... ...
> 
> 	pcalau12i	$r12,%pc_hi20(.LANCHOR0)
> 	addi.d	$r12,$r12,%pc_lo12(.LANCHOR0)
> 	xvld	$xr0,$r12,0
> 	xvld	$xr1,$r12,32
> 	xvadd.w	$xr0,$xr0,$xr1
> 	xvst	$xr0,$r12,0
> 	jr	$r1
> 
> ... ...
> 
> This seems perfectly fine.  But:
> 
> $ gcc/xgcc -B gcc lasx.c -mlasx -o- -nostdinc -mexplicit-relocs -O2 -S
> 
> ... ...
> 
> test:
> .LFB0 = .
> 	pcalau12i	$r12,%pc_hi20(.LANCHOR0)
> 	addi.d	$r12,$r12,%pc_lo12(.LANCHOR0)
> 	addi.d	$r3,$r3,-16
> .LCFI0 = .
> 	st.d	$r23,$r3,8
> .LCFI1 = .
> 	ldptr.w	$r7,$r12,0
> 	ldptr.w	$r23,$r12,32
> 	ldptr.w	$r6,$r12,8
> 
> ... ... (no SIMD instructions)
> 
> Is this a bug in the driver or I missed something?
> 
> -- 
> Xi Ruoyao <xry111@xry111.site>
> School of Aerospace Science and Technology, Xidian University

Maybe you can try deleting gcc/specs first.

It contains a modified version of self_specs that is used for building
the libraries, which purges all user-specified "-m" options.
This file is automatically restored prior to "make check*".

Yujie


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

* Re: [PATCH v3 1/4] LoongArch: improved target configuration interface
  2023-09-06  1:04     ` Yang Yujie
@ 2023-09-07  8:49       ` Xi Ruoyao
  2023-09-07  9:31         ` Yang Yujie
  0 siblings, 1 reply; 21+ messages in thread
From: Xi Ruoyao @ 2023-09-07  8:49 UTC (permalink / raw)
  To: Yang Yujie; +Cc: gcc-patches, xuchenghua, chenglulu, panchenghui, joseph

On Wed, 2023-09-06 at 09:04 +0800, Yang Yujie wrote:
> On Tue, Sep 05, 2023 at 09:31:56PM +0800, Xi Ruoyao wrote:
> > On Thu, 2023-08-31 at 20:48 +0800, Yang Yujie wrote:
> > > * Support options for LoongArch SIMD extensions:
> > >   new configure options --with-simd={none,lsx,lasx};
> > >   new compiler option -msimd={none,lsx,lasx};
> > >   new driver options -m[no]-l[a]sx.
> > 
> > Hmm... In my build (a cross compiler configured with
> > ../gcc/configure --
> > target=loongarch64-linux-gnu --with-system-zlib) I have:
> > 
> > $ cat lasx.c
> > int x __attribute__((vector_size(32)));
> > int y __attribute__((vector_size(32)));
> > void test(void) { x += y; }
> > $ gcc/cc1 lasx.c -msimd=lasx -o- -nostdinc -mexplicit-relocs -O2
> > 
> > ... ...
> > 
> >         pcalau12i       $r12,%pc_hi20(.LANCHOR0)
> >         addi.d  $r12,$r12,%pc_lo12(.LANCHOR0)
> >         xvld    $xr0,$r12,0
> >         xvld    $xr1,$r12,32
> >         xvadd.w $xr0,$xr0,$xr1
> >         xvst    $xr0,$r12,0
> >         jr      $r1
> > 
> > ... ...
> > 
> > This seems perfectly fine.  But:
> > 
> > $ gcc/xgcc -B gcc lasx.c -mlasx -o- -nostdinc -mexplicit-relocs -O2
> > -S
> > 
> > ... ...
> > 
> > test:
> > .LFB0 = .
> >         pcalau12i       $r12,%pc_hi20(.LANCHOR0)
> >         addi.d  $r12,$r12,%pc_lo12(.LANCHOR0)
> >         addi.d  $r3,$r3,-16
> > .LCFI0 = .
> >         st.d    $r23,$r3,8
> > .LCFI1 = .
> >         ldptr.w $r7,$r12,0
> >         ldptr.w $r23,$r12,32
> >         ldptr.w $r6,$r12,8
> > 
> > ... ... (no SIMD instructions)
> > 
> > Is this a bug in the driver or I missed something?
> > 
> > -- 
> > Xi Ruoyao <xry111@xry111.site>
> > School of Aerospace Science and Technology, Xidian University
> 
> Maybe you can try deleting gcc/specs first.
> 
> It contains a modified version of self_specs that is used for building
> the libraries, which purges all user-specified "-m" options.
> This file is automatically restored prior to "make check*".

This is bad.  It makes BOOT_CFLAGS=-mlasx or CFLAGS_FOR_TARGET=-mlasx
silently ignored so we cannot test a LSX/LASX or vectorizer change with
them.

Why do we need to purge all user-specified -m options here?

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

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

* Re: [PATCH v3 1/4] LoongArch: improved target configuration interface
  2023-09-07  8:49       ` Xi Ruoyao
@ 2023-09-07  9:31         ` Yang Yujie
  2023-09-07  9:47           ` Xi Ruoyao
  0 siblings, 1 reply; 21+ messages in thread
From: Yang Yujie @ 2023-09-07  9:31 UTC (permalink / raw)
  To: Xi Ruoyao
  Cc: Yang Yujie, gcc-patches, xuchenghua, chenglulu, panchenghui, joseph

> This is bad.  It makes BOOT_CFLAGS=-mlasx or CFLAGS_FOR_TARGET=-mlasx
> silently ignored so we cannot test a LSX/LASX or vectorizer change with
> them.
>
> Why do we need to purge all user-specified -m options here?

Yes, that is an issue that I haven't considered.

The purge rules (self_specs) exist to clean up the driver-generated
canonical option tuple.  These options are generated before to the
injection of library-building options from --with-multilib-{list,default}.
They are dependent on the default GCC settings and may not be safely
overriden by any injected individual options, so we choose to start
over with a purge.

Working on a patch now, Thanks!

Yujie


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

* Re: [PATCH v3 1/4] LoongArch: improved target configuration interface
  2023-09-07  9:31         ` Yang Yujie
@ 2023-09-07  9:47           ` Xi Ruoyao
  2023-09-07  9:49             ` Xi Ruoyao
  2023-09-07 11:54             ` Yang Yujie
  0 siblings, 2 replies; 21+ messages in thread
From: Xi Ruoyao @ 2023-09-07  9:47 UTC (permalink / raw)
  To: Yang Yujie; +Cc: gcc-patches, xuchenghua, chenglulu, panchenghui, joseph

On Thu, 2023-09-07 at 17:31 +0800, Yang Yujie wrote:
> > This is bad.  It makes BOOT_CFLAGS=-mlasx or CFLAGS_FOR_TARGET=-mlasx
> > silently ignored so we cannot test a LSX/LASX or vectorizer change with
> > them.
> > 
> > Why do we need to purge all user-specified -m options here?
> 
> Yes, that is an issue that I haven't considered.
> 
> The purge rules (self_specs) exist to clean up the driver-generated
> canonical option tuple.  These options are generated before to the
> injection of library-building options from --with-multilib-{list,default}.
> They are dependent on the default GCC settings and may not be safely
> overriden by any injected individual options, so we choose to start
> over with a purge.
> 
> Working on a patch now, Thanks!

I've made some local experiment too, I think we can add a "-mbuild-
multilib" option which does nothing but in the hacked spec we can wrap
the line in %{mbuild-multilib:...}:

%{mbuild-multilib:%<march=* %<mtune=* %<mcmodel=* %<mfpu=* %<msimd=*   %{mabi=lp64d:-march=la464 -mno-strict-align -msimd=lsx}   %{mabi=lp64s:-march=abi-default -mfpu=32}}

Then we can use -mbuild-multilib -mabi=lp64d for non-default multilibs
(or all multilibs unless --disable-multilib?).  In the document we can
just document mbuild-multilib as "internal use only".


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

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

* Re: [PATCH v3 1/4] LoongArch: improved target configuration interface
  2023-09-07  9:47           ` Xi Ruoyao
@ 2023-09-07  9:49             ` Xi Ruoyao
  2023-09-07 11:54             ` Yang Yujie
  1 sibling, 0 replies; 21+ messages in thread
From: Xi Ruoyao @ 2023-09-07  9:49 UTC (permalink / raw)
  To: Yang Yujie; +Cc: gcc-patches, xuchenghua, chenglulu, panchenghui, joseph

On Thu, 2023-09-07 at 17:47 +0800, Xi Ruoyao wrote:

/* snip */

> I've made some local experiment too, I think we can add a "-mbuild-
> multilib" option which does nothing but in the hacked spec we can wrap
> the line in %{mbuild-multilib:...}:
> 
> %{mbuild-multilib:%<march=* %<mtune=* %<mcmodel=* %<mfpu=* %<msimd=*  
> %{mabi=lp64d:-march=la464 -mno-strict-align -msimd=lsx}  
> %{mabi=lp64s:-march=abi-default -mfpu=32}}
> 
> Then we can use -mbuild-multilib -mabi=lp64d for non-default multilibs
                                   ^^^^^^^^^^^^ typo, should be removed

> (or all multilibs unless --disable-multilib?).  In the document we can
> just document mbuild-multilib as "internal use only".

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

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

* Re: [PATCH v3 1/4] LoongArch: improved target configuration interface
  2023-09-07  9:47           ` Xi Ruoyao
  2023-09-07  9:49             ` Xi Ruoyao
@ 2023-09-07 11:54             ` Yang Yujie
  2023-09-09  2:46               ` Yang Yujie
  1 sibling, 1 reply; 21+ messages in thread
From: Yang Yujie @ 2023-09-07 11:54 UTC (permalink / raw)
  To: Xi Ruoyao
  Cc: Yang Yujie, gcc-patches, xuchenghua, chenglulu, panchenghui, joseph

On Thu, Sep 07, 2023 at 05:47:36PM +0800, Xi Ruoyao wrote:
> On Thu, 2023-09-07 at 17:31 +0800, Yang Yujie wrote:
> > > This is bad.  It makes BOOT_CFLAGS=-mlasx or CFLAGS_FOR_TARGET=-mlasx
> > > silently ignored so we cannot test a LSX/LASX or vectorizer change with
> > > them.
> > > 
> > > Why do we need to purge all user-specified -m options here?
> > 
> > Yes, that is an issue that I haven't considered.
> > 
> > The purge rules (self_specs) exist to clean up the driver-generated
> > canonical option tuple.  These options are generated before to the
> > injection of library-building options from --with-multilib-{list,default}.
> > They are dependent on the default GCC settings and may not be safely
> > overriden by any injected individual options, so we choose to start
> > over with a purge.
> > 
> > Working on a patch now, Thanks!
> 
> I've made some local experiment too, I think we can add a "-mbuild-
> multilib" option which does nothing but in the hacked spec we can wrap
> the line in %{mbuild-multilib:...}:
> 
> %{mbuild-multilib:%<march=* %<mtune=* %<mcmodel=* %<mfpu=* %<msimd=*   %{mabi=lp64d:-march=la464 -mno-strict-align -msimd=lsx}   %{mabi=lp64s:-march=abi-default -mfpu=32}}
> 
> Then we can use -mbuild-multilib -mabi=lp64d for non-default multilibs
> (or all multilibs unless --disable-multilib?).  In the document we can
> just document mbuild-multilib as "internal use only".
> 
> 
> -- 
> Xi Ruoyao <xry111@xry111.site>
> School of Aerospace Science and Technology, Xidian University


My idea is to move these options out of self_spec by defining a new spec
rule $(early_self_spec), so that they get processed by the driver before
the canonicalization.

This also solves the problem that one cannot use -m[no-]lsx/-m[no-]lasx
in --with-multilib-list (because they are driver-only options that are
only recognized during the canonicalization).


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

* Re: [PATCH v3 1/4] LoongArch: improved target configuration interface
  2023-09-07 11:54             ` Yang Yujie
@ 2023-09-09  2:46               ` Yang Yujie
  2023-09-09  5:56                 ` Xi Ruoyao
  0 siblings, 1 reply; 21+ messages in thread
From: Yang Yujie @ 2023-09-09  2:46 UTC (permalink / raw)
  To: Xi Ruoyao; +Cc: gcc-patches, xuchenghua, chenglulu, panchenghui, joseph

On Thu, Sep 07, 2023 at 07:54:41PM +0800, Yang Yujie wrote:
> On Thu, Sep 07, 2023 at 05:47:36PM +0800, Xi Ruoyao wrote:
> > On Thu, 2023-09-07 at 17:31 +0800, Yang Yujie wrote:
> > > > This is bad.  It makes BOOT_CFLAGS=-mlasx or CFLAGS_FOR_TARGET=-mlasx
> > > > silently ignored so we cannot test a LSX/LASX or vectorizer change with
> > > > them.
> > > > 
> > > > Why do we need to purge all user-specified -m options here?
> > > 
> > > Yes, that is an issue that I haven't considered.
> > > 
> > > The purge rules (self_specs) exist to clean up the driver-generated
> > > canonical option tuple.  These options are generated before to the
> > > injection of library-building options from --with-multilib-{list,default}.
> > > They are dependent on the default GCC settings and may not be safely
> > > overriden by any injected individual options, so we choose to start
> > > over with a purge.
> > > 
> > > Working on a patch now, Thanks!
> > 
> > I've made some local experiment too, I think we can add a "-mbuild-
> > multilib" option which does nothing but in the hacked spec we can wrap
> > the line in %{mbuild-multilib:...}:
> > 
> > %{mbuild-multilib:%<march=* %<mtune=* %<mcmodel=* %<mfpu=* %<msimd=*   %{mabi=lp64d:-march=la464 -mno-strict-align -msimd=lsx}   %{mabi=lp64s:-march=abi-default -mfpu=32}}
> > 
> > Then we can use -mbuild-multilib -mabi=lp64d for non-default multilibs
> > (or all multilibs unless --disable-multilib?).  In the document we can
> > just document mbuild-multilib as "internal use only".
> > 
> > 
> > -- 
> > Xi Ruoyao <xry111@xry111.site>
> > School of Aerospace Science and Technology, Xidian University
> 
> 
> My idea is to move these options out of self_spec by defining a new spec
> rule $(early_self_spec), so that they get processed by the driver before
> the canonicalization.
> 
> This also solves the problem that one cannot use -m[no-]lsx/-m[no-]lasx
> in --with-multilib-list (because they are driver-only options that are
> only recognized during the canonicalization).

Some updates on this issue -- With some experiments, I think that the most
practical way to solve this completely might still involve a symmetric
multilib build (where the toplevels are not built and installed).  Because
as you proposed, we need to inject an option like "-mbuild-multilib" (maybe
"-fmultiflags" for this purpose) somewhere to distinguish bootstrapping from
building libraries, but overriding the spec seems to always affect both cases.

The next option I can think of would be MULTILIB_EXTRA_OPTS, where -fmultiflags
fit in nicely.  However, these options won't reach the toplevel builds, and
tweaking config-ml.in for getting it there would be quite tedious and perhaps
unreliable:

--------
diff --git a/config-ml.in b/config-ml.in
index ad0db078171..ce7f07b94a7 100644
--- a/config-ml.in
+++ b/config-ml.in
@@ -228,6 +228,9 @@ for i in `${CC-gcc} --print-multi-lib 2>/dev/null`; do
   fi
 done
 
+# Do not apply MULTILIB_EXTRA_OPTS to the toplevel by default.
+ml_toplevel_apply_extra_opts=no
+
 # Target libraries are configured for the host they run on, so we check
 # $host here, not $target.
 
@@ -577,6 +580,19 @@ cat >>Multi.tem <<\EOF
        fi
 EOF
 
+# Apply MULTILIB_EXTRA_OPTS to the toplevel build.
+if [ "${ml_toplevel_apply_extra_opts}" = yes ]; then
+cat >>Multi.tem <<\EOF
+
+$(foreach i,$(shell $(CC) --print-multi-lib), \
+$(if $(i:.;%=),,$(eval ml_extra_opts := $(subst @, -,$(i:.;%=%)))))
+
+$(foreach ml_flags, CFLAGS CCASFLAGS CXXFLAGS FCFLAGS FFLAGS \
+    ADAFLAGS GOCFLAGS GDCFLAGS CXXFLAGS LIBCFLAGS LIBCXXFLAGS \
+    LDFLAGS MLTIFLAGS, $(eval override $(ml_flags) += $(ml_extra_opts)))
+EOF
+fi
+
 cat ${Makefile} Multi.tem > Makefile.tem
 rm -f ${Makefile} Multi.tem
 mv Makefile.tem ${Makefile}
--------

Though this patch works, at least the following additional tweaks has to
be done to the toplevel to maintain a correct build / regtest / install
workflow:

- the C++ headers' install path (fixed temporarily && not very elegant)
- the fortran header path before regtests

Compared to patching for each library individually, I'd rather choose something
less painful -- not building the toplevel could save the most effort because all
the facilities are guaranteed to be present for all multilib variants.

As for the layout change of lib/gcc/<arch>/<version> directory after applying
the symmetric multilib patch, I believe the inconvenience caused would be minimal,
since multisubdir within that directory is private to each gcc instance.  If someone
really has a script that depend on libgcc's path, I would suggest using
--print-multi-dir and --print-file-name=libgcc.a, for you cannot assume the
behavior of the GCC driver without knowing which spec file it is loading anyways.

(We'd still be keeping --with-abi=* obsolete.  That's a good idea, thanks.)

Yujie


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

* Re: [PATCH v3 1/4] LoongArch: improved target configuration interface
  2023-09-09  2:46               ` Yang Yujie
@ 2023-09-09  5:56                 ` Xi Ruoyao
  2023-09-09  6:26                   ` Yang Yujie
  0 siblings, 1 reply; 21+ messages in thread
From: Xi Ruoyao @ 2023-09-09  5:56 UTC (permalink / raw)
  To: Yang Yujie; +Cc: gcc-patches, xuchenghua, chenglulu, panchenghui, joseph

On Sat, 2023-09-09 at 10:46 +0800, Yang Yujie wrote:
> The next option I can think of would be MULTILIB_EXTRA_OPTS, where -fmultiflags
> fit in nicely.  However, these options won't reach the toplevel builds, and
> tweaking config-ml.in for getting it there would be quite tedious and perhaps
> unreliable:

I don't think the spec tweak should affect toplevel (or default, if you
hate the concept of toplevel) library build.

When I build GCC for a specific machine I usually use:

OPT="-O3 -march=native -pipe ..."
make {STAGE1,BOOT}_CFLAGS="$OPT" {C,CXX}FLAGS_FOR_TARGET="$OPT -g"

If the spec tweak affects the toplevel library build it will eat -march=
etc. in {C,CXX}FLAGS_FOR_TARGET silently, and I don't want this.

Or at least it should not affect --disable-multilib (IMO with --disable-
multilib the spec hack should be disabled completely).  Note that for --
enable-multilib we may use --with-default-multilib=lp64d/march=native,
but (1) this is hard to remember (2) this is not usable with --disable-
multilib.

--disable-multilib *should just work*.  Why should a non-multilib user
be punished by the cost of supporting the complex multilib
configuration, esp. today most LoongArch users don't need multilib at
all?

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

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

* Re: [PATCH v3 1/4] LoongArch: improved target configuration interface
  2023-09-09  5:56                 ` Xi Ruoyao
@ 2023-09-09  6:26                   ` Yang Yujie
  2023-09-09  6:56                     ` Xi Ruoyao
  0 siblings, 1 reply; 21+ messages in thread
From: Yang Yujie @ 2023-09-09  6:26 UTC (permalink / raw)
  To: Xi Ruoyao; +Cc: gcc-patches, xuchenghua, chenglulu, panchenghui, joseph

On Sat, Sep 09, 2023 at 01:56:57PM +0800, Xi Ruoyao wrote:
> On Sat, 2023-09-09 at 10:46 +0800, Yang Yujie wrote:
> > The next option I can think of would be MULTILIB_EXTRA_OPTS, where -fmultiflags
> > fit in nicely.  However, these options won't reach the toplevel builds, and
> > tweaking config-ml.in for getting it there would be quite tedious and perhaps
> > unreliable:
> 
> I don't think the spec tweak should affect toplevel (or default, if you
> hate the concept of toplevel) library build.
>
> When I build GCC for a specific machine I usually use:
> 
> OPT="-O3 -march=native -pipe ..."
> make {STAGE1,BOOT}_CFLAGS="$OPT" {C,CXX}FLAGS_FOR_TARGET="$OPT -g"
> 
> If the spec tweak affects the toplevel library build it will eat -march=
> etc. in {C,CXX}FLAGS_FOR_TARGET silently, and I don't want this.

Sorry I didn't make this clear -- Yes, I am removing the spec tweak
*completely*, because I agree it should not affect bootstrapping /
toplevel builds / --disable-multilib builds. 

This is achieved by defining MULTILIB_EXTRA_OPTS as -fmultiflags,
which triggers the multilib build options in driver spec rules
-- so nothing happens to the bootstrapping and --disable-multilib
builds.

What I'm explaining is, MULTILIB_EXTRA_OPTS won't be nicely received
by the toplevel (which is exactly the purpose), so in this solution,
multilib-enabled builds still have to exclude the toplevel.  This means
I will have to bring back (at least part of) my v1 patch:

https://gcc.gnu.org/pipermail/gcc-patches/2023-August/627275.html

I remember you were against it because you think non-multilib users
would be punished because the libdir layout changes (no toplevel).
However this directory should be (mostly) private to each gcc instance,
so I don't see real consequences to this unless you have a build script
that relieas on the path of libgcc.a / startfile, which can still (and
should) be revised using $(gcc --print-multi-dir).
 
> --disable-multilib *should just work*.  Why should a non-multilib user
> be punished by the cost of supporting the complex multilib
> configuration, esp. today most LoongArch users don't need multilib at
> all?

It should *just work*.  I am testing the new patch and will deliver it
as soon as all the test passes.


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

* Re: [PATCH v3 1/4] LoongArch: improved target configuration interface
  2023-09-09  6:26                   ` Yang Yujie
@ 2023-09-09  6:56                     ` Xi Ruoyao
  0 siblings, 0 replies; 21+ messages in thread
From: Xi Ruoyao @ 2023-09-09  6:56 UTC (permalink / raw)
  To: Yang Yujie; +Cc: gcc-patches, xuchenghua, chenglulu, panchenghui, joseph

On Sat, 2023-09-09 at 14:26 +0800, Yang Yujie wrote:
> I remember you were against it because you think non-multilib users
> would be punished because the libdir layout changes (no toplevel).
> However this directory should be (mostly) private to each gcc instance,
> so I don't see real consequences to this unless you have a build script
> that relieas on the path of libgcc.a / startfile, which can still (and
> should) be revised using $(gcc --print-multi-dir).

I guess I can live with it.

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

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

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

Thread overview: 21+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-08-31 12:48 [PATCH v3 0/4] LoongArch: target configuration interface update Yang Yujie
2023-08-31 12:48 ` [PATCH v3 1/4] LoongArch: improved target configuration interface Yang Yujie
2023-09-05 11:51   ` Xi Ruoyao
2023-09-05 12:01     ` chenglulu
2023-09-05 12:17       ` Xi Ruoyao
2023-09-05 12:26         ` chenglulu
2023-09-05 13:31   ` Xi Ruoyao
2023-09-06  1:04     ` Yang Yujie
2023-09-07  8:49       ` Xi Ruoyao
2023-09-07  9:31         ` Yang Yujie
2023-09-07  9:47           ` Xi Ruoyao
2023-09-07  9:49             ` Xi Ruoyao
2023-09-07 11:54             ` Yang Yujie
2023-09-09  2:46               ` Yang Yujie
2023-09-09  5:56                 ` Xi Ruoyao
2023-09-09  6:26                   ` Yang Yujie
2023-09-09  6:56                     ` Xi Ruoyao
2023-08-31 12:48 ` [PATCH v3 2/4] LoongArch: define preprocessing macros "__loongarch_{arch,tune}" Yang Yujie
2023-08-31 12:48 ` [PATCH v3 3/4] LoongArch: add new configure option --with-strict-align-lib Yang Yujie
2023-08-31 12:48 ` [PATCH v3 4/4] LoongArch: support loongarch*-elf target Yang Yujie
2023-09-05  4:40 ` Re:[pushed] [PATCH v3 0/4] LoongArch: target configuration interface update chenglulu

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).