]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
LoongArch: improved target configuration interface
authorYang Yujie <yangyujie@loongson.cn>
Wed, 23 Aug 2023 07:16:21 +0000 (15:16 +0800)
committerLulu Cheng <chenglulu@loongson.cn>
Tue, 5 Sep 2023 03:47:55 +0000 (11:47 +0800)
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.

20 files changed:
config-ml.in
gcc/config.gcc
gcc/config/loongarch/genopts/loongarch-strings
gcc/config/loongarch/genopts/loongarch.opt.in
gcc/config/loongarch/la464.md
gcc/config/loongarch/loongarch-c.cc
gcc/config/loongarch/loongarch-cpu.cc
gcc/config/loongarch/loongarch-cpu.h
gcc/config/loongarch/loongarch-def.c
gcc/config/loongarch/loongarch-def.h
gcc/config/loongarch/loongarch-driver.cc
gcc/config/loongarch/loongarch-driver.h
gcc/config/loongarch/loongarch-opts.cc
gcc/config/loongarch/loongarch-opts.h
gcc/config/loongarch/loongarch-str.h
gcc/config/loongarch/loongarch.cc
gcc/config/loongarch/loongarch.opt
gcc/config/loongarch/t-linux
gcc/doc/install.texi
gcc/doc/invoke.texi

index 68854a4f16c2bfcd48a8d721d4c28f0a602148cf..ad0db07817182a0badc28ca38097489c7ab96777 100644 (file)
@@ -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
index 0ba1a7f494cc3835b757d4615af55b8c5fc6fa4c..543b0ba076ba08c0fc2eea1ceb999ab74f38f101 100644 (file)
@@ -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"
                ;;
 
index a40998ead975a2133deb7ec0385d7b171147e825..adecaec3eda5e72acd910d1b46c2df3c9fb98e36 100644 (file)
@@ -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
index 4b9b4ac273e91bc650326f84c63ed08e715b102a..f3567b279358dede0d8a08424fce1fda03726d9f 100644 (file)
 ; <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
index 541040fdfa864a01d33cfc93ef05d8097f66d491..3b4d14f0b3cb3e4a29b19a10af3b21687d38ecfe 100644 (file)
 ;; 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")
index 6ffbf74831613f63cb3b7f8e89edc2b41132b2ea..f5a966a1d1c7b7a8b93f5536bc7af4fe710220bb 100644 (file)
@@ -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");
+    }
+
   /* Add support for FLOAT128_TYPE on the LoongArch architecture.  */
   builtin_define ("__FLOAT128_TYPE__");
 
index 34905f3de30e1ec6cbb4587f186a6530f201827f..7a2866f60f98c5f78825b036c8ad23312db4bef5 100644 (file)
@@ -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;
+    }
 }
index 57ad8456ffa76733a91ffa99d35e3c131b74cf44..28618f3cf6cb07cca3382850da4349f80e36fadc 100644 (file)
@@ -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);
 
index 6729c857f7c4b75c23f1f5d53ca42aba3c835c22..e744ee01d6d76422fdc0a8ff54ecb04a2664cca2 100644 (file)
@@ -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
+      },
   },
 };
index fb8bb88eb52ff7d3f50a03e97750839e01055703..769efcb70fb8949e1c82218e4e62c1b3f53b2804 100644 (file)
@@ -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[];
index 11ce082417f980bc0a328bf7e733f9e51303d81f..bafd27e67a5f7f4c646dfb8143881a33b0436c59 100644 (file)
@@ -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]);
 
index ba8817a4621cc9056a0d67a8293de94ab722bdc8..b39b96dec3659eea4f72e3206228b6963fb387b5 100644 (file)
@@ -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 \
index a52e25236ea04cd93d7445496625f462c0dce883..e5921189a06426101b066880a250661b32219fb3 100644 (file)
@@ -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;
+}
index b1ff54426e42e19b457f8d7ee282474f2b5354ea..7a58dabdea85b31381633d6c1da582881197850c 100644 (file)
@@ -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 */
index af2e82a321f020e770d2b03f7aa23e878b27aa45..a3e0510493bd62c82b52797a8577535c66c4e731 100644 (file)
@@ -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"
index 28f771bb0755dcee8dba4c2eeead91b3719dacae..c823725361a27939e8907a423e9d3b77d3dd4c98 100644 (file)
@@ -2555,7 +2555,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,
@@ -2597,7 +2597,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:
@@ -6064,8 +6064,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;
 }
@@ -6076,8 +6076,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;
 }
@@ -6254,17 +6254,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;
@@ -6273,33 +6310,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
@@ -6307,12 +6324,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");
@@ -6382,7 +6393,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.  */
index 68018ade73f039968360aa8920a4f60b2c264d50..8be2b0bcb4f9a04d178f2e865dcf4cc5e394d8d5 100644 (file)
 ; <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
index e40da179203a0435eb4b91a64e43d5c47e5d5681..9997596d722a0ba0af10d91f250507c3c0cef381 100644 (file)
@@ -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)
index e099cd0b56803caa6615e955ff6a37f6c5f37a60..bbc58cb60caf109b5e5bb817e3c657fa193191cb 100644 (file)
@@ -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
index 02de0f657e858f37085b68626ad8c07f3cb263e5..435fb2fba992abbb0057f3b737bc712246ea1739 100644 (file)
@@ -1030,7 +1030,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
@@ -25997,6 +25998,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
@@ -26015,6 +26031,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.
@@ -26115,6 +26144,7 @@ kernels, executables linked with @option{-static} or @option{-static-pie}.
 @option{-fpic}.
 @end table
 
+
 @node M32C Options
 @subsection M32C Options
 @cindex M32C options