Projects
home:lf14:branches:Mega:23.09
gcc
_service:tar_scm:LoongArch-improved-target-conf...
Sign Up
Log In
Username
Password
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File _service:tar_scm:LoongArch-improved-target-configuration-interface.patch of Package gcc
From b980a32eabcbd34e8f8e6a245dbba1898256555e Mon Sep 17 00:00:00 2001 From: Yang Yujie <yangyujie@loongson.cn> Date: Wed, 23 Aug 2023 15:16:21 +0800 Subject: [PATCH 058/124] LoongArch: improved target configuration interface 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. Signed-off-by: Peng Fan <fanpeng@loongson.cn> Signed-off-by: ticat_fp <fanpeng@loongson.cn> --- config-ml.in | 10 + gcc/config.gcc | 379 ++++++++++-------- .../loongarch/genopts/loongarch-strings | 8 +- gcc/config/loongarch/genopts/loongarch.opt.in | 62 +-- gcc/config/loongarch/la464.md | 32 +- gcc/config/loongarch/loongarch-c.cc | 19 +- gcc/config/loongarch/loongarch-cpu.cc | 263 +++++++----- gcc/config/loongarch/loongarch-cpu.h | 3 +- gcc/config/loongarch/loongarch-def.c | 67 ++-- gcc/config/loongarch/loongarch-def.h | 57 +-- gcc/config/loongarch/loongarch-driver.cc | 208 +++++----- gcc/config/loongarch/loongarch-driver.h | 40 +- gcc/config/loongarch/loongarch-opts.cc | 372 ++++++++++++----- gcc/config/loongarch/loongarch-opts.h | 59 +-- gcc/config/loongarch/loongarch-str.h | 7 +- gcc/config/loongarch/loongarch.cc | 87 ++-- gcc/config/loongarch/loongarch.opt | 60 ++- gcc/config/loongarch/t-linux | 32 +- gcc/doc/install.texi | 52 ++- 19 files changed, 1136 insertions(+), 681 deletions(-) diff --git a/config-ml.in b/config-ml.in index 68854a4f1..ad0db0781 100644 --- a/config-ml.in +++ b/config-ml.in @@ -301,6 +301,16 @@ arm-*-*) done fi ;; +loongarch*-*) + old_multidirs="${multidirs}" + multidirs="" + for x in ${old_multidirs}; do + case "$x" in + `${CC-gcc} --print-multi-directory`) : ;; + *) multidirs="${multidirs} ${x}" ;; + esac + done + ;; m68*-*-*) if [ x$enable_softfloat = xno ] then diff --git a/gcc/config.gcc b/gcc/config.gcc index 5c378c698..62525c296 100644 --- a/gcc/config.gcc +++ b/gcc/config.gcc @@ -4965,43 +4965,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";; @@ -5010,42 +5013,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. @@ -5059,73 +5044,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" ;; @@ -5138,7 +5091,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 @@ -5157,7 +5110,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 @@ -5178,7 +5131,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 @@ -5186,32 +5139,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 @@ -5223,13 +5163,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 @@ -5245,25 +5225,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 @@ -5272,57 +5248,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 @@ -5783,34 +5813,37 @@ case ${target} in # Let --with- flags initialize the enum variables from loongarch.opt. # See macro definitions from loongarch-opts.h and loongarch-cpu.h. - case ${with_arch} in - native) tm_defines="${tm_defines} DEFAULT_CPU_ARCH=CPU_NATIVE" ;; - la464) tm_defines="${tm_defines} DEFAULT_CPU_ARCH=CPU_LA464" ;; - loongarch64) tm_defines="${tm_defines} DEFAULT_CPU_ARCH=CPU_LOONGARCH64" ;; - esac - case ${with_tune} in - native) tm_defines="${tm_defines} DEFAULT_CPU_TUNE=CPU_NATIVE" ;; - la464) tm_defines="${tm_defines} DEFAULT_CPU_TUNE=CPU_LA464" ;; - loongarch64) tm_defines="${tm_defines} DEFAULT_CPU_TUNE=CPU_LOONGARCH64" ;; - esac + # Architecture + tm_defines="${tm_defines} DEFAULT_CPU_ARCH=CPU_$(echo ${with_arch} | tr a-z- A-Z_)" - case ${with_abi} in - lp64d) tm_defines="${tm_defines} DEFAULT_ABI_BASE=ABI_BASE_LP64D" ;; - lp64f) tm_defines="${tm_defines} DEFAULT_ABI_BASE=ABI_BASE_LP64F" ;; - lp64s) tm_defines="${tm_defines} DEFAULT_ABI_BASE=ABI_BASE_LP64S" ;; - esac + # Base ABI type + tm_defines="${tm_defines} DEFAULT_ABI_BASE=ABI_BASE_$(echo ${abi_base} | tr a-z- A-Z_)" - case ${with_abiext} in + # ABI Extension + case ${abi_ext} in base) tm_defines="${tm_defines} DEFAULT_ABI_EXT=ABI_EXT_BASE" ;; esac + # Microarchitecture + if test x${with_tune} != x; then + tm_defines="${tm_defines} DEFAULT_CPU_TUNE=CPU_$(echo ${with_tune} | tr a-z- A-Z_)" + fi + + # FPU adjustment case ${with_fpu} in - none) tm_defines="$tm_defines DEFAULT_ISA_EXT_FPU=ISA_EXT_NOFPU" ;; + none) tm_defines="$tm_defines DEFAULT_ISA_EXT_FPU=ISA_EXT_NONE" ;; 32) tm_defines="$tm_defines DEFAULT_ISA_EXT_FPU=ISA_EXT_FPU32" ;; 64) tm_defines="$tm_defines DEFAULT_ISA_EXT_FPU=ISA_EXT_FPU64" ;; esac + # SIMD extensions + case ${with_simd} in + none) tm_defines="$tm_defines DEFAULT_ISA_EXT_SIMD=ISA_EXT_NONE" ;; + lsx) tm_defines="$tm_defines DEFAULT_ISA_EXT_SIMD=ISA_EXT_SIMD_LSX" ;; + lasx) tm_defines="$tm_defines DEFAULT_ISA_EXT_SIMD=ISA_EXT_SIMD_LASX" ;; + esac + tmake_file="loongarch/t-loongarch $tmake_file" ;; diff --git a/gcc/config/loongarch/genopts/loongarch-strings b/gcc/config/loongarch/genopts/loongarch-strings index 44ebb7ab1..21245f52a 100644 --- a/gcc/config/loongarch/genopts/loongarch-strings +++ b/gcc/config/loongarch/genopts/loongarch-strings @@ -23,6 +23,7 @@ OPTSTR_ARCH arch OPTSTR_TUNE tune STR_CPU_NATIVE native +STR_CPU_ABI_DEFAULT abi-default STR_CPU_LOONGARCH64 loongarch64 STR_CPU_LA464 la464 @@ -31,7 +32,7 @@ STR_ISA_BASE_LA64V100 la64 # -mfpu OPTSTR_ISA_EXT_FPU fpu -STR_ISA_EXT_NOFPU none +STR_NONE none STR_ISA_EXT_FPU0 0 STR_ISA_EXT_FPU32 32 STR_ISA_EXT_FPU64 64 @@ -40,6 +41,11 @@ OPTSTR_SOFT_FLOAT soft-float OPTSTR_SINGLE_FLOAT single-float OPTSTR_DOUBLE_FLOAT double-float +# SIMD extensions +OPTSTR_ISA_EXT_SIMD simd +STR_ISA_EXT_LSX lsx +STR_ISA_EXT_LASX lasx + # -mabi= OPTSTR_ABI_BASE abi STR_ABI_BASE_LP64D lp64d diff --git a/gcc/config/loongarch/genopts/loongarch.opt.in b/gcc/config/loongarch/genopts/loongarch.opt.in index e10618777..c6e337d05 100644 --- a/gcc/config/loongarch/genopts/loongarch.opt.in +++ b/gcc/config/loongarch/genopts/loongarch.opt.in @@ -17,22 +17,12 @@ ; <http://www.gnu.org/licenses/>. ; -; Variables (macros) that should be exported by loongarch.opt: -; la_opt_switches, -; la_opt_abi_base, la_opt_abi_ext, -; la_opt_cpu_arch, la_opt_cpu_tune, -; la_opt_fpu, -; la_cmodel. - HeaderInclude config/loongarch/loongarch-opts.h HeaderInclude config/loongarch/loongarch-str.h -Variable -HOST_WIDE_INT la_opt_switches = 0 - ; ISA related options ;; Base ISA Enum @@ -42,14 +32,13 @@ Basic ISAs of LoongArch: EnumValue Enum(isa_base) String(@@STR_ISA_BASE_LA64V100@@) Value(ISA_BASE_LA64V100) - ;; ISA extensions / adjustments Enum Name(isa_ext_fpu) Type(int) FPU types of LoongArch: EnumValue -Enum(isa_ext_fpu) String(@@STR_ISA_EXT_NOFPU@@) Value(ISA_EXT_NOFPU) +Enum(isa_ext_fpu) String(@@STR_NONE@@) Value(ISA_EXT_NONE) EnumValue Enum(isa_ext_fpu) String(@@STR_ISA_EXT_FPU32@@) Value(ISA_EXT_FPU32) @@ -58,24 +47,48 @@ EnumValue Enum(isa_ext_fpu) String(@@STR_ISA_EXT_FPU64@@) Value(ISA_EXT_FPU64) m@@OPTSTR_ISA_EXT_FPU@@= -Target RejectNegative Joined ToLower Enum(isa_ext_fpu) Var(la_opt_fpu) Init(M_OPTION_NOT_SEEN) +Target RejectNegative Joined ToLower Enum(isa_ext_fpu) Var(la_opt_fpu) Init(M_OPT_UNSET) -m@@OPTSTR_ISA_EXT_FPU@@=FPU Generate code for the given FPU. m@@OPTSTR_ISA_EXT_FPU@@=@@STR_ISA_EXT_FPU0@@ -Target RejectNegative Alias(m@@OPTSTR_ISA_EXT_FPU@@=,@@STR_ISA_EXT_NOFPU@@) +Target RejectNegative Alias(m@@OPTSTR_ISA_EXT_FPU@@=,@@STR_NONE@@) m@@OPTSTR_SOFT_FLOAT@@ -Target Driver RejectNegative Var(la_opt_switches) Mask(FORCE_SOFTF) Negative(m@@OPTSTR_SINGLE_FLOAT@@) +Target Driver Defer Var(la_deferred_options) RejectNegative Negative(m@@OPTSTR_SINGLE_FLOAT@@) Prevent the use of all hardware floating-point instructions. m@@OPTSTR_SINGLE_FLOAT@@ -Target Driver RejectNegative Var(la_opt_switches) Mask(FORCE_F32) Negative(m@@OPTSTR_DOUBLE_FLOAT@@) +Target Driver Defer Var(la_deferred_options) RejectNegative Negative(m@@OPTSTR_DOUBLE_FLOAT@@) Restrict the use of hardware floating-point instructions to 32-bit operations. m@@OPTSTR_DOUBLE_FLOAT@@ -Target Driver RejectNegative Var(la_opt_switches) Mask(FORCE_F64) Negative(m@@OPTSTR_SOFT_FLOAT@@) +Target Driver Defer Var(la_deferred_options) RejectNegative Negative(m@@OPTSTR_SOFT_FLOAT@@) Allow hardware floating-point instructions to cover both 32-bit and 64-bit operations. +Enum +Name(isa_ext_simd) Type(int) +SIMD extension levels of LoongArch: + +EnumValue +Enum(isa_ext_simd) String(@@STR_NONE@@) Value(ISA_EXT_NONE) + +EnumValue +Enum(isa_ext_simd) String(@@STR_ISA_EXT_LSX@@) Value(ISA_EXT_SIMD_LSX) + +EnumValue +Enum(isa_ext_simd) String(@@STR_ISA_EXT_LASX@@) Value(ISA_EXT_SIMD_LASX) + +m@@OPTSTR_ISA_EXT_SIMD@@= +Target RejectNegative Joined ToLower Enum(isa_ext_simd) Var(la_opt_simd) Init(M_OPT_UNSET) +-m@@OPTSTR_ISA_EXT_SIMD@@=SIMD Generate code for the given SIMD extension. + +m@@STR_ISA_EXT_LSX@@ +Target Driver Defer Var(la_deferred_options) +Enable LoongArch SIMD Extension (LSX, 128-bit). + +m@@STR_ISA_EXT_LASX@@ +Target Driver Defer Var(la_deferred_options) +Enable LoongArch Advanced SIMD Extension (LASX, 256-bit). ;; Base target models (implies ISA & tune parameters) Enum @@ -85,6 +98,9 @@ LoongArch CPU types: EnumValue Enum(cpu_type) String(@@STR_CPU_NATIVE@@) Value(CPU_NATIVE) +EnumValue +Enum(cpu_type) String(@@STR_CPU_ABI_DEFAULT@@) Value(CPU_ABI_DEFAULT) + EnumValue Enum(cpu_type) String(@@STR_CPU_LOONGARCH64@@) Value(CPU_LOONGARCH64) @@ -92,11 +108,11 @@ EnumValue Enum(cpu_type) String(@@STR_CPU_LA464@@) Value(CPU_LA464) m@@OPTSTR_ARCH@@= -Target RejectNegative Joined Enum(cpu_type) Var(la_opt_cpu_arch) Init(M_OPTION_NOT_SEEN) +Target RejectNegative Joined Enum(cpu_type) Var(la_opt_cpu_arch) Init(M_OPT_UNSET) -m@@OPTSTR_ARCH@@=PROCESSOR Generate code for the given PROCESSOR ISA. m@@OPTSTR_TUNE@@= -Target RejectNegative Joined Enum(cpu_type) Var(la_opt_cpu_tune) Init(M_OPTION_NOT_SEEN) +Target RejectNegative Joined Enum(cpu_type) Var(la_opt_cpu_tune) Init(M_OPT_UNSET) -m@@OPTSTR_TUNE@@=PROCESSOR Generate optimized code for PROCESSOR. @@ -118,13 +134,13 @@ EnumValue Enum(abi_base) String(@@STR_ABI_BASE_LP64S@@) Value(ABI_BASE_LP64S) m@@OPTSTR_ABI_BASE@@= -Target RejectNegative Joined ToLower Enum(abi_base) Var(la_opt_abi_base) Init(M_OPTION_NOT_SEEN) +Target RejectNegative Joined ToLower Enum(abi_base) Var(la_opt_abi_base) Init(M_OPT_UNSET) -m@@OPTSTR_ABI_BASE@@=BASEABI Generate code that conforms to the given BASEABI. + ;; ABI Extension Variable -int la_opt_abi_ext = M_OPTION_NOT_SEEN - +int la_opt_abi_ext = M_OPT_UNSET mbranch-cost= Target RejectNegative Joined UInteger Var(loongarch_branch_cost) @@ -182,7 +198,7 @@ EnumValue Enum(cmodel) String(@@STR_CMODEL_EXTREME@@) Value(CMODEL_EXTREME) mcmodel= -Target RejectNegative Joined Enum(cmodel) Var(la_opt_cmodel) Init(CMODEL_NORMAL) +Target RejectNegative Joined Enum(cmodel) Var(la_opt_cmodel) Init(M_OPT_UNSET) Specify the code model. mdirect-extern-access diff --git a/gcc/config/loongarch/la464.md b/gcc/config/loongarch/la464.md index 0ae177610..89d61bf58 100644 --- a/gcc/config/loongarch/la464.md +++ b/gcc/config/loongarch/la464.md @@ -43,88 +43,88 @@ ;; Describe instruction reservations. (define_insn_reservation "la464_arith" 1 - (and (match_test "TARGET_TUNE_LA464") + (and (match_test "TARGET_uARCH_LA464") (eq_attr "type" "arith,clz,const,logical, move,nop,shift,signext,slt")) "la464_alu1 | la464_alu2") (define_insn_reservation "la464_branch" 1 - (and (match_test "TARGET_TUNE_LA464") + (and (match_test "TARGET_uARCH_LA464") (eq_attr "type" "branch,jump,call,condmove,trap")) "la464_alu1 | la464_alu2") (define_insn_reservation "la464_imul" 7 - (and (match_test "TARGET_TUNE_LA464") + (and (match_test "TARGET_uARCH_LA464") (eq_attr "type" "imul")) "la464_alu1 | la464_alu2") (define_insn_reservation "la464_idiv_si" 12 - (and (match_test "TARGET_TUNE_LA464") + (and (match_test "TARGET_uARCH_LA464") (and (eq_attr "type" "idiv") (eq_attr "mode" "SI"))) "la464_alu1 | la464_alu2") (define_insn_reservation "la464_idiv_di" 25 - (and (match_test "TARGET_TUNE_LA464") + (and (match_test "TARGET_uARCH_LA464") (and (eq_attr "type" "idiv") (eq_attr "mode" "DI"))) "la464_alu1 | la464_alu2") (define_insn_reservation "la464_load" 4 - (and (match_test "TARGET_TUNE_LA464") + (and (match_test "TARGET_uARCH_LA464") (eq_attr "type" "load")) "la464_mem1 | la464_mem2") (define_insn_reservation "la464_gpr_fp" 16 - (and (match_test "TARGET_TUNE_LA464") + (and (match_test "TARGET_uARCH_LA464") (eq_attr "type" "mftg,mgtf")) "la464_mem1") (define_insn_reservation "la464_fpload" 4 - (and (match_test "TARGET_TUNE_LA464") + (and (match_test "TARGET_uARCH_LA464") (eq_attr "type" "fpload")) "la464_mem1 | la464_mem2") (define_insn_reservation "la464_prefetch" 0 - (and (match_test "TARGET_TUNE_LA464") + (and (match_test "TARGET_uARCH_LA464") (eq_attr "type" "prefetch,prefetchx")) "la464_mem1 | la464_mem2") (define_insn_reservation "la464_store" 0 - (and (match_test "TARGET_TUNE_LA464") + (and (match_test "TARGET_uARCH_LA464") (eq_attr "type" "store,fpstore,fpidxstore")) "la464_mem1 | la464_mem2") (define_insn_reservation "la464_fadd" 4 - (and (match_test "TARGET_TUNE_LA464") + (and (match_test "TARGET_uARCH_LA464") (eq_attr "type" "fadd,fmul,fmadd")) "la464_falu1 | la464_falu2") (define_insn_reservation "la464_fcmp" 2 - (and (match_test "TARGET_TUNE_LA464") + (and (match_test "TARGET_uARCH_LA464") (eq_attr "type" "fabs,fcmp,fmove,fneg")) "la464_falu1 | la464_falu2") (define_insn_reservation "la464_fcvt" 4 - (and (match_test "TARGET_TUNE_LA464") + (and (match_test "TARGET_uARCH_LA464") (eq_attr "type" "fcvt")) "la464_falu1 | la464_falu2") (define_insn_reservation "la464_fdiv_sf" 12 - (and (match_test "TARGET_TUNE_LA464") + (and (match_test "TARGET_uARCH_LA464") (and (eq_attr "type" "fdiv,frdiv,fsqrt,frsqrt") (eq_attr "mode" "SF"))) "la464_falu1 | la464_falu2") (define_insn_reservation "la464_fdiv_df" 19 - (and (match_test "TARGET_TUNE_LA464") + (and (match_test "TARGET_uARCH_LA464") (and (eq_attr "type" "fdiv,frdiv,fsqrt,frsqrt") (eq_attr "mode" "DF"))) "la464_falu1 | la464_falu2") ;; Force single-dispatch for unknown or multi. (define_insn_reservation "la464_unknown" 1 - (and (match_test "TARGET_TUNE_LA464") + (and (match_test "TARGET_uARCH_LA464") (eq_attr "type" "unknown,multi,atomic,syncloop")) "la464_alu1 + la464_alu2 + la464_falu1 + la464_falu2 + la464_mem1 + la464_mem2") diff --git a/gcc/config/loongarch/loongarch-c.cc b/gcc/config/loongarch/loongarch-c.cc index f779a7355..2cf84eec7 100644 --- a/gcc/config/loongarch/loongarch-c.cc +++ b/gcc/config/loongarch/loongarch-c.cc @@ -61,8 +61,8 @@ loongarch_cpu_cpp_builtins (cpp_reader *pfile) builtin_assert ("cpu=loongarch"); builtin_define ("__loongarch__"); - LARCH_CPP_SET_PROCESSOR ("_LOONGARCH_ARCH", LARCH_ACTUAL_ARCH); - LARCH_CPP_SET_PROCESSOR ("_LOONGARCH_TUNE", LARCH_ACTUAL_TUNE); + LARCH_CPP_SET_PROCESSOR ("_LOONGARCH_ARCH", la_target.cpu_arch); + LARCH_CPP_SET_PROCESSOR ("_LOONGARCH_TUNE", la_target.cpu_tune); /* Base architecture / ABI. */ if (TARGET_64BIT) @@ -99,6 +99,21 @@ loongarch_cpu_cpp_builtins (cpp_reader *pfile) else builtin_define ("__loongarch_frlen=0"); + if (ISA_HAS_LSX) + { + builtin_define ("__loongarch_simd"); + builtin_define ("__loongarch_sx"); + + if (!ISA_HAS_LASX) + builtin_define ("__loongarch_simd_width=128"); + } + + if (ISA_HAS_LASX) + { + builtin_define ("__loongarch_asx"); + builtin_define ("__loongarch_simd_width=256"); + } + /* Add support for FLOAT128_TYPE on the LoongArch architecture. */ builtin_define ("__FLOAT128_TYPE__"); diff --git a/gcc/config/loongarch/loongarch-cpu.cc b/gcc/config/loongarch/loongarch-cpu.cc index a886dd932..ea05526d7 100644 --- a/gcc/config/loongarch/loongarch-cpu.cc +++ b/gcc/config/loongarch/loongarch-cpu.cc @@ -26,6 +26,7 @@ along with GCC; see the file COPYING3. If not see #include "tm.h" #include "diagnostic-core.h" +#include "loongarch-def.h" #include "loongarch-opts.h" #include "loongarch-cpu.h" #include "loongarch-str.h" @@ -80,127 +81,191 @@ get_native_prid_str (void) } /* Fill property tables for CPU_NATIVE. */ -unsigned int -fill_native_cpu_config (int p_arch_native, int p_tune_native) +void +fill_native_cpu_config (struct loongarch_target *tgt) { - int ret_cpu_type; + int arch_native_p = tgt->cpu_arch == CPU_NATIVE; + int tune_native_p = tgt->cpu_tune == CPU_NATIVE; + int native_cpu_type = CPU_NATIVE; /* Nothing needs to be done unless "-march/tune=native" is given or implied. */ - if (!(p_arch_native || p_tune_native)) - return CPU_NATIVE; + if (!arch_native_p && !tune_native_p) + return; /* Fill cpucfg_cache with the "cpucfg" instruction. */ cache_cpucfg (); - - /* Fill: loongarch_cpu_default_isa[CPU_NATIVE].base - With: base architecture (ARCH) - At: cpucfg_words[1][1:0] */ - - #define NATIVE_BASE_ISA (loongarch_cpu_default_isa[CPU_NATIVE].base) - switch (cpucfg_cache[1] & 0x3) - { - case 0x02: - NATIVE_BASE_ISA = ISA_BASE_LA64V100; - break; - - default: - if (p_arch_native) - fatal_error (UNKNOWN_LOCATION, - "unknown base architecture %<0x%x%>, %qs failed", - (unsigned int) (cpucfg_cache[1] & 0x3), - "-m" OPTSTR_ARCH "=" STR_CPU_NATIVE); - } - - /* Fill: loongarch_cpu_default_isa[CPU_NATIVE].fpu - With: FPU type (FP, FP_SP, FP_DP) - At: cpucfg_words[2][2:0] */ - - #define NATIVE_FPU (loongarch_cpu_default_isa[CPU_NATIVE].fpu) - switch (cpucfg_cache[2] & 0x7) - { - case 0x07: - NATIVE_FPU = ISA_EXT_FPU64; - break; - - case 0x03: - NATIVE_FPU = ISA_EXT_FPU32; - break; - - case 0x00: - NATIVE_FPU = ISA_EXT_NOFPU; - break; - - default: - if (p_arch_native) - fatal_error (UNKNOWN_LOCATION, - "unknown FPU type %<0x%x%>, %qs failed", - (unsigned int) (cpucfg_cache[2] & 0x7), - "-m" OPTSTR_ARCH "=" STR_CPU_NATIVE); - } - - /* Fill: loongarch_cpu_cache[CPU_NATIVE] - With: cache size info - At: cpucfg_words[16:20][31:0] */ - - int l1d_present = 0, l1u_present = 0; - int l2d_present = 0; - uint32_t l1_szword, l2_szword; - - l1u_present |= cpucfg_cache[16] & 3; /* bit[1:0]: unified l1 cache */ - l1d_present |= cpucfg_cache[16] & 4; /* bit[2:2]: l1 dcache */ - l1_szword = l1d_present ? 18 : (l1u_present ? 17 : 0); - l1_szword = l1_szword ? cpucfg_cache[l1_szword]: 0; - - l2d_present |= cpucfg_cache[16] & 24; /* bit[4:3]: unified l2 cache */ - l2d_present |= cpucfg_cache[16] & 128; /* bit[7:7]: l2 dcache */ - l2_szword = l2d_present ? cpucfg_cache[19]: 0; - - loongarch_cpu_cache[CPU_NATIVE].l1d_line_size - = 1 << ((l1_szword & 0x7f000000) >> 24); /* bit[30:24]: log2(linesize) */ - - loongarch_cpu_cache[CPU_NATIVE].l1d_size - = (1 << ((l1_szword & 0x00ff0000) >> 16)) /* bit[23:16]: log2(idx) */ - * ((l1_szword & 0x0000ffff) + 1) /* bit[15:0]: sets - 1 */ - * (1 << ((l1_szword & 0x7f000000) >> 24)) /* bit[30:24]: log2(linesize) */ - >> 10; /* in kilobytes */ - - loongarch_cpu_cache[CPU_NATIVE].l2d_size - = (1 << ((l2_szword & 0x00ff0000) >> 16)) /* bit[23:16]: log2(idx) */ - * ((l2_szword & 0x0000ffff) + 1) /* bit[15:0]: sets - 1 */ - * (1 << ((l2_szword & 0x7f000000) >> 24)) /* bit[30:24]: log2(linesize) */ - >> 10; /* in kilobytes */ - - /* Fill: ret_cpu_type + /* Fill: tgt->cpu_arch | tgt->cpu_tune With: processor ID (PRID) At: cpucfg_words[0][31:0] */ switch (cpucfg_cache[0] & 0x00ffff00) { case 0x0014c000: /* LA464 */ - ret_cpu_type = CPU_LA464; + native_cpu_type = CPU_LA464; break; default: - /* Unknown PRID. This is generally harmless as long as - the properties above can be obtained via "cpucfg". */ - if (p_tune_native) + /* Unknown PRID. */ + if (tune_native_p) inform (UNKNOWN_LOCATION, "unknown processor ID %<0x%x%>, " "some tuning parameters will fall back to default", cpucfg_cache[0]); break; } - /* Properties that cannot be looked up directly using cpucfg. */ - loongarch_cpu_issue_rate[CPU_NATIVE] - = loongarch_cpu_issue_rate[ret_cpu_type]; - - loongarch_cpu_multipass_dfa_lookahead[CPU_NATIVE] - = loongarch_cpu_multipass_dfa_lookahead[ret_cpu_type]; - - loongarch_cpu_rtx_cost_data[CPU_NATIVE] - = loongarch_cpu_rtx_cost_data[ret_cpu_type]; + /* if -march=native */ + if (arch_native_p) + { + int tmp; + tgt->cpu_arch = native_cpu_type; + + /* Fill: loongarch_cpu_default_isa[tgt->cpu_arch].base + With: base architecture (ARCH) + At: cpucfg_words[1][1:0] */ + + #define PRESET_ARCH (loongarch_cpu_default_isa[tgt->cpu_arch].base) + switch (cpucfg_cache[1] & 0x3) + { + case 0x02: + tmp = ISA_BASE_LA64V100; + break; + + default: + fatal_error (UNKNOWN_LOCATION, + "unknown native base architecture %<0x%x%>, " + "%qs failed", (unsigned int) (cpucfg_cache[1] & 0x3), + "-m" OPTSTR_ARCH "=" STR_CPU_NATIVE); + } + + /* Check consistency with PRID presets. */ + if (native_cpu_type != CPU_NATIVE && tmp != PRESET_ARCH) + warning (0, "base architecture %qs differs from PRID preset %qs", + loongarch_isa_base_strings[tmp], + loongarch_isa_base_strings[PRESET_ARCH]); + + /* Use the native value anyways. */ + PRESET_ARCH = tmp; + + /* Fill: loongarch_cpu_default_isa[tgt->cpu_arch].fpu + With: FPU type (FP, FP_SP, FP_DP) + At: cpucfg_words[2][2:0] */ + + #define PRESET_FPU (loongarch_cpu_default_isa[tgt->cpu_arch].fpu) + switch (cpucfg_cache[2] & 0x7) + { + case 0x07: + tmp = ISA_EXT_FPU64; + break; + + case 0x03: + tmp = ISA_EXT_FPU32; + break; + + case 0x00: + tmp = ISA_EXT_NONE; + break; + + default: + fatal_error (UNKNOWN_LOCATION, + "unknown native FPU type %<0x%x%>, %qs failed", + (unsigned int) (cpucfg_cache[2] & 0x7), + "-m" OPTSTR_ARCH "=" STR_CPU_NATIVE); + } + + /* Check consistency with PRID presets. */ + if (native_cpu_type != CPU_NATIVE && tmp != PRESET_FPU) + warning (0, "floating-point unit %qs differs from PRID preset %qs", + loongarch_isa_ext_strings[tmp], + loongarch_isa_ext_strings[PRESET_FPU]); + + /* Use the native value anyways. */ + PRESET_FPU = tmp; + + + /* Fill: loongarch_cpu_default_isa[CPU_NATIVE].simd + With: SIMD extension type (LSX, LASX) + At: cpucfg_words[2][7:6] */ + + #define PRESET_SIMD (loongarch_cpu_default_isa[tgt->cpu_arch].simd) + switch (cpucfg_cache[2] & 0xc0) + { + case 0xc0: + tmp = ISA_EXT_SIMD_LASX; + break; + + case 0x40: + tmp = ISA_EXT_SIMD_LSX; + break; + + case 0x80: + tmp = 0; + warning (0, "unknown SIMD extension " + "(%qs disabled while %qs is enabled), disabling SIMD", + loongarch_isa_ext_strings[ISA_EXT_SIMD_LSX], + loongarch_isa_ext_strings[ISA_EXT_SIMD_LASX]); + break; + + case 0x00: + tmp = 0; + break; + } + + /* Check consistency with PRID presets. */ + + /* + if (native_cpu_type != CPU_NATIVE && tmp != PRESET_SIMD) + warning (0, "SIMD extension %qs differs from PRID preset %qs", + loongarch_isa_ext_strings[tmp], + loongarch_isa_ext_strings[PRESET_SIMD]); + */ + + /* Use the native value anyways. */ + PRESET_SIMD = tmp; + } - return ret_cpu_type; + if (tune_native_p) + { + tgt->cpu_tune = native_cpu_type; + + /* Fill: loongarch_cpu_cache[tgt->cpu_tune] + With: cache size info + At: cpucfg_words[16:20][31:0] */ + + #define PRESET_CACHE (loongarch_cpu_cache[tgt->cpu_tune]) + struct loongarch_cache native_cache; + int l1d_present = 0, l1u_present = 0; + int l2d_present = 0; + uint32_t l1_szword, l2_szword; + + l1u_present |= cpucfg_cache[16] & 3; /* bit[1:0]: unified l1 */ + l1d_present |= cpucfg_cache[16] & 4; /* bit[2:2]: l1d */ + l1_szword = l1d_present ? 18 : (l1u_present ? 17 : 0); + l1_szword = l1_szword ? cpucfg_cache[l1_szword]: 0; + + l2d_present |= cpucfg_cache[16] & 24; /* bit[4:3]: unified l2 */ + l2d_present |= cpucfg_cache[16] & 128; /* bit[7:7]: l2d */ + l2_szword = l2d_present ? cpucfg_cache[19]: 0; + + native_cache.l1d_line_size + = 1 << ((l1_szword & 0x7f000000) >> 24); /* bit[30:24]: log2(line) */ + + native_cache.l1d_size + = (1 << ((l1_szword & 0x00ff0000) >> 16)) /* bit[23:16]: log2(idx) */ + * ((l1_szword & 0x0000ffff) + 1) /* bit[15:0]: sets - 1 */ + * (1 << ((l1_szword & 0x7f000000) >> 24)) /* bit[30:24]: log2(line) */ + >> 10; /* in kibibytes */ + + native_cache.l2d_size + = (1 << ((l2_szword & 0x00ff0000) >> 16)) /* bit[23:16]: log2(idx) */ + * ((l2_szword & 0x0000ffff) + 1) /* bit[15:0]: sets - 1 */ + * (1 << ((l2_szword & 0x7f000000) >> 24)) /* bit[30:24]: log2(linesz) */ + >> 10; /* in kibibytes */ + + /* Use the native value anyways. */ + PRESET_CACHE.l1d_line_size = native_cache.l1d_line_size; + PRESET_CACHE.l1d_size = native_cache.l1d_size; + PRESET_CACHE.l2d_size = native_cache.l2d_size; + } } diff --git a/gcc/config/loongarch/loongarch-cpu.h b/gcc/config/loongarch/loongarch-cpu.h index 93d656f70..eacb38774 100644 --- a/gcc/config/loongarch/loongarch-cpu.h +++ b/gcc/config/loongarch/loongarch-cpu.h @@ -21,9 +21,10 @@ along with GCC; see the file COPYING3. If not see #define LOONGARCH_CPU_H #include "system.h" +#include "loongarch-def.h" void cache_cpucfg (void); -unsigned int fill_native_cpu_config (int p_arch_native, int p_tune_native); +void fill_native_cpu_config (struct loongarch_target *tgt); uint32_t get_native_prid (void); const char* get_native_prid_str (void); diff --git a/gcc/config/loongarch/loongarch-def.c b/gcc/config/loongarch/loongarch-def.c index 74d422ce0..d29d5f001 100644 --- a/gcc/config/loongarch/loongarch-def.c +++ b/gcc/config/loongarch/loongarch-def.c @@ -21,25 +21,11 @@ along with GCC; see the file COPYING3. If not see #include "loongarch-def.h" #include "loongarch-str.h" -/* Default RTX cost initializer. */ -#define COSTS_N_INSNS(N) ((N) * 4) -#define DEFAULT_COSTS \ - .fp_add = COSTS_N_INSNS (1), \ - .fp_mult_sf = COSTS_N_INSNS (2), \ - .fp_mult_df = COSTS_N_INSNS (4), \ - .fp_div_sf = COSTS_N_INSNS (6), \ - .fp_div_df = COSTS_N_INSNS (8), \ - .int_mult_si = COSTS_N_INSNS (1), \ - .int_mult_di = COSTS_N_INSNS (1), \ - .int_div_si = COSTS_N_INSNS (4), \ - .int_div_di = COSTS_N_INSNS (6), \ - .branch_cost = 2, \ - .memory_latency = 4 - /* CPU property tables. */ const char* loongarch_cpu_strings[N_TUNE_TYPES] = { [CPU_NATIVE] = STR_CPU_NATIVE, + [CPU_ABI_DEFAULT] = STR_CPU_ABI_DEFAULT, [CPU_LOONGARCH64] = STR_CPU_LOONGARCH64, [CPU_LA464] = STR_CPU_LA464, }; @@ -49,10 +35,12 @@ loongarch_cpu_default_isa[N_ARCH_TYPES] = { [CPU_LOONGARCH64] = { .base = ISA_BASE_LA64V100, .fpu = ISA_EXT_FPU64, + .simd = 0, }, [CPU_LA464] = { .base = ISA_BASE_LA64V100, .fpu = ISA_EXT_FPU64, + .simd = ISA_EXT_SIMD_LASX, }, }; @@ -84,6 +72,22 @@ loongarch_cpu_align[N_TUNE_TYPES] = { }, }; + +/* Default RTX cost initializer. */ +#define COSTS_N_INSNS(N) ((N) * 4) +#define DEFAULT_COSTS \ + .fp_add = COSTS_N_INSNS (1), \ + .fp_mult_sf = COSTS_N_INSNS (2), \ + .fp_mult_df = COSTS_N_INSNS (4), \ + .fp_div_sf = COSTS_N_INSNS (6), \ + .fp_div_df = COSTS_N_INSNS (8), \ + .int_mult_si = COSTS_N_INSNS (1), \ + .int_mult_di = COSTS_N_INSNS (1), \ + .int_div_si = COSTS_N_INSNS (4), \ + .int_div_di = COSTS_N_INSNS (6), \ + .branch_cost = 2, \ + .memory_latency = 4 + /* The following properties cannot be looked up directly using "cpucfg". So it is necessary to provide a default value for "unknown native" tune targets (i.e. -mtune=native while PRID does not correspond to @@ -103,7 +107,7 @@ loongarch_cpu_rtx_cost_data[N_TUNE_TYPES] = { }; /* RTX costs to use when optimizing for size. */ -extern const struct loongarch_rtx_cost_data +const struct loongarch_rtx_cost_data loongarch_rtx_cost_optimize_size = { .fp_add = 4, .fp_mult_sf = 4, @@ -144,9 +148,11 @@ loongarch_isa_base_strings[N_ISA_BASE_TYPES] = { const char* loongarch_isa_ext_strings[N_ISA_EXT_TYPES] = { - [ISA_EXT_FPU64] = STR_ISA_EXT_FPU64, + [ISA_EXT_NONE] = STR_NONE, [ISA_EXT_FPU32] = STR_ISA_EXT_FPU32, - [ISA_EXT_NOFPU] = STR_ISA_EXT_NOFPU, + [ISA_EXT_FPU64] = STR_ISA_EXT_FPU64, + [ISA_EXT_SIMD_LSX] = STR_ISA_EXT_LSX, + [ISA_EXT_SIMD_LASX] = STR_ISA_EXT_LASX, }; const char* @@ -171,24 +177,29 @@ loongarch_cmodel_strings[] = { [CMODEL_EXTREME] = STR_CMODEL_EXTREME, }; -const char* -loongarch_switch_strings[] = { - [SW_SOFT_FLOAT] = OPTSTR_SOFT_FLOAT, - [SW_SINGLE_FLOAT] = OPTSTR_SINGLE_FLOAT, - [SW_DOUBLE_FLOAT] = OPTSTR_DOUBLE_FLOAT, -}; - /* ABI-related definitions. */ const struct loongarch_isa abi_minimal_isa[N_ABI_BASE_TYPES][N_ABI_EXT_TYPES] = { [ABI_BASE_LP64D] = { - [ABI_EXT_BASE] = {.base = ISA_BASE_LA64V100, .fpu = ISA_EXT_FPU64}, + [ABI_EXT_BASE] = { + .base = ISA_BASE_LA64V100, + .fpu = ISA_EXT_FPU64, + .simd = 0 + }, }, [ABI_BASE_LP64F] = { - [ABI_EXT_BASE] = {.base = ISA_BASE_LA64V100, .fpu = ISA_EXT_FPU32}, + [ABI_EXT_BASE] = { + .base = ISA_BASE_LA64V100, + .fpu = ISA_EXT_FPU32, + .simd = 0 + }, }, [ABI_BASE_LP64S] = { - [ABI_EXT_BASE] = {.base = ISA_BASE_LA64V100, .fpu = ISA_EXT_NOFPU}, + [ABI_EXT_BASE] = { + .base = ISA_BASE_LA64V100, + .fpu = ISA_EXT_NONE, + .simd = 0 + }, }, }; diff --git a/gcc/config/loongarch/loongarch-def.h b/gcc/config/loongarch/loongarch-def.h index eb87a79a5..0aee7dc19 100644 --- a/gcc/config/loongarch/loongarch-def.h +++ b/gcc/config/loongarch/loongarch-def.h @@ -59,11 +59,13 @@ extern const char* loongarch_isa_base_strings[]; /* enum isa_ext_* */ extern const char* loongarch_isa_ext_strings[]; -#define ISA_EXT_NOFPU 0 +#define ISA_EXT_NONE 0 #define ISA_EXT_FPU32 1 #define ISA_EXT_FPU64 2 #define N_ISA_EXT_FPU_TYPES 3 -#define N_ISA_EXT_TYPES 3 +#define ISA_EXT_SIMD_LSX 3 +#define ISA_EXT_SIMD_LASX 4 +#define N_ISA_EXT_TYPES 5 /* enum abi_base */ extern const char* loongarch_abi_base_strings[]; @@ -72,6 +74,16 @@ extern const char* loongarch_abi_base_strings[]; #define ABI_BASE_LP64S 2 #define N_ABI_BASE_TYPES 3 +#define TO_LP64_ABI_BASE(C) (C) + +#define ABI_FPU_64(abi_base) \ + (abi_base == ABI_BASE_LP64D) +#define ABI_FPU_32(abi_base) \ + (abi_base == ABI_BASE_LP64F) +#define ABI_FPU_NONE(abi_base) \ + (abi_base == ABI_BASE_LP64S) + + /* enum abi_ext */ extern const char* loongarch_abi_ext_strings[]; #define ABI_EXT_BASE 0 @@ -87,55 +99,44 @@ extern const char* loongarch_cmodel_strings[]; #define CMODEL_EXTREME 5 #define N_CMODEL_TYPES 6 -/* enum switches */ -/* The "SW_" codes represent command-line switches (options that - accept no parameters). Definition for other switches that affects - the target ISA / ABI configuration will also be appended here - in the future. */ - -extern const char* loongarch_switch_strings[]; -#define SW_SOFT_FLOAT 0 -#define SW_SINGLE_FLOAT 1 -#define SW_DOUBLE_FLOAT 2 -#define N_SWITCH_TYPES 3 - /* The common default value for variables whose assignments are triggered by command-line options. */ -#define M_OPTION_NOT_SEEN -1 -#define M_OPT_ABSENT(opt_enum) ((opt_enum) == M_OPTION_NOT_SEEN) +#define M_OPT_UNSET -1 +#define M_OPT_ABSENT(opt_enum) ((opt_enum) == M_OPT_UNSET) /* Internal representation of the target. */ struct loongarch_isa { - unsigned char base; /* ISA_BASE_ */ - unsigned char fpu; /* ISA_EXT_FPU_ */ + int base; /* ISA_BASE_ */ + int fpu; /* ISA_EXT_FPU_ */ + int simd; /* ISA_EXT_SIMD_ */ }; struct loongarch_abi { - unsigned char base; /* ABI_BASE_ */ - unsigned char ext; /* ABI_EXT_ */ + int base; /* ABI_BASE_ */ + int ext; /* ABI_EXT_ */ }; struct loongarch_target { struct loongarch_isa isa; struct loongarch_abi abi; - unsigned char cpu_arch; /* CPU_ */ - unsigned char cpu_tune; /* same */ - unsigned char cpu_native; /* same */ - unsigned char cmodel; /* CMODEL_ */ + int cpu_arch; /* CPU_ */ + int cpu_tune; /* same */ + int cmodel; /* CMODEL_ */ }; /* CPU properties. */ /* index */ #define CPU_NATIVE 0 -#define CPU_LOONGARCH64 1 -#define CPU_LA464 2 -#define N_ARCH_TYPES 3 -#define N_TUNE_TYPES 3 +#define CPU_ABI_DEFAULT 1 +#define CPU_LOONGARCH64 2 +#define CPU_LA464 3 +#define N_ARCH_TYPES 4 +#define N_TUNE_TYPES 4 /* parallel tables. */ extern const char* loongarch_cpu_strings[]; diff --git a/gcc/config/loongarch/loongarch-driver.cc b/gcc/config/loongarch/loongarch-driver.cc index 0adcc923b..b3626984d 100644 --- a/gcc/config/loongarch/loongarch-driver.cc +++ b/gcc/config/loongarch/loongarch-driver.cc @@ -26,122 +26,137 @@ along with GCC; see the file COPYING3. If not see #include "tm.h" #include "obstack.h" #include "diagnostic-core.h" +#include "opts.h" #include "loongarch-opts.h" #include "loongarch-driver.h" -static int - opt_arch_driver = M_OPTION_NOT_SEEN, - opt_tune_driver = M_OPTION_NOT_SEEN, - opt_fpu_driver = M_OPTION_NOT_SEEN, - opt_abi_base_driver = M_OPTION_NOT_SEEN, - opt_abi_ext_driver = M_OPTION_NOT_SEEN, - opt_cmodel_driver = M_OPTION_NOT_SEEN; - -int opt_switches = 0; - /* This flag is set to 1 if we believe that the user might be avoiding linking (implicitly) against something from the startfile search paths. */ static int no_link = 0; -#define LARCH_DRIVER_SET_M_FLAG(OPTS_ARRAY, N_OPTS, FLAG, STR) \ - for (int i = 0; i < (N_OPTS); i++) \ - { \ - if ((OPTS_ARRAY)[i] != 0) \ - if (strcmp ((STR), (OPTS_ARRAY)[i]) == 0) \ - (FLAG) = i; \ - } - /* Use the public obstack from the gcc driver (defined in gcc.c). This is for allocating space for the returned string. */ extern struct obstack opts_obstack; -#define APPEND_LTR(S) \ - obstack_grow (&opts_obstack, (const void*) (S), \ - sizeof ((S)) / sizeof (char) -1) - -#define APPEND_VAL(S) \ - obstack_grow (&opts_obstack, (const void*) (S), strlen ((S))) +const char* +la_driver_init (int argc ATTRIBUTE_UNUSED, const char **argv ATTRIBUTE_UNUSED) +{ + /* Initialize all fields of la_target to -1 */ + loongarch_init_target (&la_target, M_OPT_UNSET, M_OPT_UNSET, M_OPT_UNSET, + M_OPT_UNSET, M_OPT_UNSET, M_OPT_UNSET, M_OPT_UNSET); + return ""; +} +const char* +driver_set_no_link (int argc ATTRIBUTE_UNUSED, + const char **argv ATTRIBUTE_UNUSED) +{ + no_link = 1; + return ""; +} const char* -driver_set_m_flag (int argc, const char **argv) +driver_set_m_parm (int argc, const char **argv) { - int parm_off = 0; + gcc_assert (argc == 2); + +#define LARCH_DRIVER_PARSE_PARM(OPT_IDX, NAME, OPTSTR_LIST, \ + OPT_IDX_LO, OPT_IDX_HI) \ + if (strcmp (argv[0], OPTSTR_##NAME) == 0) \ + for (int i = (OPT_IDX_LO); i < (OPT_IDX_HI); i++) \ + { \ + if ((OPTSTR_LIST)[i] != 0) \ + if (strcmp (argv[1], (OPTSTR_LIST)[i]) == 0) \ + { \ + (OPT_IDX) = i; \ + return 0; \ + } \ + } - if (argc != 1) - return "%eset_m_flag requires exactly 1 argument."; + LARCH_DRIVER_PARSE_PARM (la_target.abi.base, ABI_BASE, \ + loongarch_abi_base_strings, 0, N_ABI_BASE_TYPES) -#undef PARM -#define PARM (argv[0] + parm_off) + LARCH_DRIVER_PARSE_PARM (la_target.isa.fpu, ISA_EXT_FPU, \ + loongarch_isa_ext_strings, 0, N_ISA_EXT_FPU_TYPES) -/* Note: sizeof (OPTSTR_##NAME) equals the length of "<option>=". */ -#undef MATCH_OPT -#define MATCH_OPT(NAME) \ - (strncmp (argv[0], OPTSTR_##NAME "=", \ - (parm_off = sizeof (OPTSTR_##NAME))) == 0) + LARCH_DRIVER_PARSE_PARM (la_target.isa.simd, ISA_EXT_SIMD, \ + loongarch_isa_ext_strings, 0, N_ISA_EXT_TYPES) - if (strcmp (argv[0], "no_link") == 0) - { - no_link = 1; - } - else if (MATCH_OPT (ABI_BASE)) - { - LARCH_DRIVER_SET_M_FLAG ( - loongarch_abi_base_strings, N_ABI_BASE_TYPES, - opt_abi_base_driver, PARM) - } - else if (MATCH_OPT (ISA_EXT_FPU)) - { - LARCH_DRIVER_SET_M_FLAG (loongarch_isa_ext_strings, N_ISA_EXT_FPU_TYPES, - opt_fpu_driver, PARM) - } - else if (MATCH_OPT (ARCH)) - { - LARCH_DRIVER_SET_M_FLAG (loongarch_cpu_strings, N_ARCH_TYPES, - opt_arch_driver, PARM) - } - else if (MATCH_OPT (TUNE)) - { - LARCH_DRIVER_SET_M_FLAG (loongarch_cpu_strings, N_TUNE_TYPES, - opt_tune_driver, PARM) - } - else if (MATCH_OPT (CMODEL)) - { - LARCH_DRIVER_SET_M_FLAG (loongarch_cmodel_strings, N_CMODEL_TYPES, - opt_cmodel_driver, PARM) - } - else /* switches */ - { - int switch_idx = M_OPTION_NOT_SEEN; + LARCH_DRIVER_PARSE_PARM (la_target.cpu_arch, ARCH, \ + loongarch_cpu_strings, 0, N_ARCH_TYPES) - LARCH_DRIVER_SET_M_FLAG (loongarch_switch_strings, N_SWITCH_TYPES, - switch_idx, argv[0]) + LARCH_DRIVER_PARSE_PARM (la_target.cpu_tune, TUNE, \ + loongarch_cpu_strings, 0, N_TUNE_TYPES) - if (switch_idx != M_OPTION_NOT_SEEN) - opt_switches |= loongarch_switch_mask[switch_idx]; - } - return ""; + LARCH_DRIVER_PARSE_PARM (la_target.cmodel, CMODEL, \ + loongarch_cmodel_strings, 0, N_CMODEL_TYPES) + + gcc_unreachable (); +} + +static void +driver_record_deferred_opts (struct loongarch_flags *flags) +{ + unsigned int i; + cl_deferred_option *opt; + vec<cl_deferred_option> *v = (vec<cl_deferred_option> *) la_deferred_options; + + gcc_assert (flags); + + /* Initialize flags */ + flags->flt = M_OPT_UNSET; + flags->flt_str = NULL; + flags->sx[0] = flags->sx[1] = 0; + + int sx_flag_idx = 0; + + if (v) + FOR_EACH_VEC_ELT (*v, i, opt) + { + switch (opt->opt_index) + { + case OPT_mlsx: + flags->sx[sx_flag_idx++] = ISA_EXT_SIMD_LSX + * (opt->value ? 1 : -1); + break; + + case OPT_mlasx: + flags->sx[sx_flag_idx++] = ISA_EXT_SIMD_LASX + * (opt->value ? 1 : -1); + break; + + case OPT_msoft_float: + flags->flt = ISA_EXT_NONE; + flags->flt_str = OPTSTR_SOFT_FLOAT; + break; + + case OPT_msingle_float: + flags->flt = ISA_EXT_FPU32; + flags->flt_str = OPTSTR_SINGLE_FLOAT; + break; + + case OPT_mdouble_float: + flags->flt = ISA_EXT_FPU64; + flags->flt_str = OPTSTR_DOUBLE_FLOAT; + break; + + default: + gcc_unreachable (); + } + gcc_assert (sx_flag_idx <= 2); + } } const char* -driver_get_normalized_m_opts (int argc, const char **argv) +driver_get_normalized_m_opts (int argc, const char **argv ATTRIBUTE_UNUSED) { if (argc != 0) - { - (void) argv; /* To make compiler shut up about unused argument. */ - return " %eget_normalized_m_opts requires no argument.\n"; - } + return " %eget_normalized_m_opts requires no argument.\n"; - loongarch_config_target (& la_target, - opt_switches, - opt_arch_driver, - opt_tune_driver, - opt_fpu_driver, - opt_abi_base_driver, - opt_abi_ext_driver, - opt_cmodel_driver, - !no_link /* follow_multilib_list */); + struct loongarch_flags flags; + driver_record_deferred_opts (&flags); + loongarch_config_target (&la_target, &flags, !no_link); /* Output normalized option strings. */ obstack_blank (&opts_obstack, 0); @@ -160,11 +175,15 @@ driver_get_normalized_m_opts (int argc, const char **argv) APPEND_LTR (" %<m" OPTSTR_##NAME "=* " \ " -m" OPTSTR_##NAME "=") - for (int i = 0; i < N_SWITCH_TYPES; i++) - { - APPEND_LTR (" %<m"); - APPEND_VAL (loongarch_switch_strings[i]); - } +#undef CLEAR_FLAG +#define CLEAR_FLAG(NAME) \ + APPEND_LTR (" %<m" NAME " %<mno-" NAME) + + CLEAR_FLAG (STR_ISA_EXT_LSX); + CLEAR_FLAG (STR_ISA_EXT_LASX); + CLEAR_FLAG (OPTSTR_SOFT_FLOAT); + CLEAR_FLAG (OPTSTR_SINGLE_FLOAT); + CLEAR_FLAG (OPTSTR_DOUBLE_FLOAT); APPEND_OPT (ABI_BASE); APPEND_VAL (loongarch_abi_base_strings[la_target.abi.base]); @@ -175,6 +194,9 @@ driver_get_normalized_m_opts (int argc, const char **argv) APPEND_OPT (ISA_EXT_FPU); APPEND_VAL (loongarch_isa_ext_strings[la_target.isa.fpu]); + APPEND_OPT (ISA_EXT_SIMD); + APPEND_VAL (loongarch_isa_ext_strings[la_target.isa.simd]); + APPEND_OPT (CMODEL); APPEND_VAL (loongarch_cmodel_strings[la_target.cmodel]); diff --git a/gcc/config/loongarch/loongarch-driver.h b/gcc/config/loongarch/loongarch-driver.h index 2e4a7a9c8..6cfe0efb5 100644 --- a/gcc/config/loongarch/loongarch-driver.h +++ b/gcc/config/loongarch/loongarch-driver.h @@ -24,33 +24,37 @@ along with GCC; see the file COPYING3. If not see #include "loongarch-str.h" extern const char* -driver_set_m_flag (int argc, const char **argv); +la_driver_init (int argc, const char **argv); + +extern const char* +driver_set_m_parm (int argc, const char **argv); + +extern const char* +driver_set_no_link (int argc, const char **argv); extern const char* driver_get_normalized_m_opts (int argc, const char **argv); #define EXTRA_SPEC_FUNCTIONS \ - { "set_m_flag", driver_set_m_flag }, \ + { "driver_init", la_driver_init }, \ + { "set_m_parm", driver_set_m_parm }, \ + { "set_no_link", driver_set_no_link }, \ { "get_normalized_m_opts", driver_get_normalized_m_opts }, /* Pre-process ABI-related options. */ #define LA_SET_PARM_SPEC(NAME) \ - " %{m" OPTSTR_##NAME "=*: %:set_m_flag(" OPTSTR_##NAME "=%*)}" \ - -#define LA_SET_FLAG_SPEC(NAME) \ - " %{m" OPTSTR_##NAME ": %:set_m_flag(" OPTSTR_##NAME ")}" \ - -#define DRIVER_HANDLE_MACHINE_OPTIONS \ - " %{c|S|E|nostdlib: %:set_m_flag(no_link)}" \ - " %{nostartfiles: %{nodefaultlibs: %:set_m_flag(no_link)}}" \ - LA_SET_PARM_SPEC (ABI_BASE) \ - LA_SET_PARM_SPEC (ARCH) \ - LA_SET_PARM_SPEC (TUNE) \ - LA_SET_PARM_SPEC (ISA_EXT_FPU) \ - LA_SET_PARM_SPEC (CMODEL) \ - LA_SET_FLAG_SPEC (SOFT_FLOAT) \ - LA_SET_FLAG_SPEC (SINGLE_FLOAT) \ - LA_SET_FLAG_SPEC (DOUBLE_FLOAT) \ + " %{m" OPTSTR_##NAME "=*: %:set_m_parm(" OPTSTR_##NAME " %*)}" \ + +#define DRIVER_HANDLE_MACHINE_OPTIONS \ + " %:driver_init()" \ + " %{c|S|E|nostdlib: %:set_no_link()}" \ + " %{nostartfiles: %{nodefaultlibs: %:set_no_link()}}" \ + LA_SET_PARM_SPEC (ABI_BASE) \ + LA_SET_PARM_SPEC (ARCH) \ + LA_SET_PARM_SPEC (TUNE) \ + LA_SET_PARM_SPEC (ISA_EXT_FPU) \ + LA_SET_PARM_SPEC (ISA_EXT_SIMD) \ + LA_SET_PARM_SPEC (CMODEL) \ " %:get_normalized_m_opts()" #define DRIVER_SELF_SPECS \ diff --git a/gcc/config/loongarch/loongarch-opts.cc b/gcc/config/loongarch/loongarch-opts.cc index e13eafb58..200702b0e 100644 --- a/gcc/config/loongarch/loongarch-opts.cc +++ b/gcc/config/loongarch/loongarch-opts.cc @@ -26,9 +26,11 @@ along with GCC; see the file COPYING3. If not see #include "tm.h" #include "obstack.h" #include "diagnostic-core.h" + #include "loongarch-cpu.h" #include "loongarch-opts.h" #include "loongarch-str.h" +#include "loongarch-def.h" struct loongarch_target la_target; @@ -76,16 +78,6 @@ init_enabled_abi_types () #endif } -/* Switch masks. */ -#undef M -#define M(NAME) OPTION_MASK_##NAME -const int loongarch_switch_mask[N_SWITCH_TYPES] = { - /* SW_SOFT_FLOAT */ M(FORCE_SOFTF), - /* SW_SINGLE_FLOAT */ M(FORCE_F32), - /* SW_DOUBLE_FLOAT */ M(FORCE_F64), -}; -#undef M - /* String processing. */ static struct obstack msg_obstack; #define APPEND_STRING(STR) obstack_grow (&msg_obstack, STR, strlen(STR)); @@ -104,9 +96,10 @@ static int isa_fpu_compat_p (const struct loongarch_isa *set1, const struct loongarch_isa *set2); static int abi_compat_p (const struct loongarch_isa *isa, struct loongarch_abi abi); -static int abi_default_cpu_arch (struct loongarch_abi abi); +static int abi_default_cpu_arch (struct loongarch_abi abi, + struct loongarch_isa *isa); -/* Checking configure-time defaults. */ +/* Mandatory configure-time defaults. */ #ifndef DEFAULT_ABI_BASE #error missing definition of DEFAULT_ABI_BASE in ${tm_defines}. #endif @@ -119,21 +112,57 @@ static int abi_default_cpu_arch (struct loongarch_abi abi); #error missing definition of DEFAULT_CPU_ARCH in ${tm_defines}. #endif -#ifndef DEFAULT_ISA_EXT_FPU -#error missing definition of DEFAULT_ISA_EXT_FPU in ${tm_defines}. +/* Optional configure-time defaults. */ +#ifdef DEFAULT_CPU_TUNE +static int with_default_tune = 1; +#else +#define DEFAULT_CPU_TUNE -1 +static int with_default_tune = 0; +#endif + +#ifdef DEFAULT_ISA_EXT_FPU +static int with_default_fpu = 1; +#else +#define DEFAULT_ISA_EXT_FPU -1 +static int with_default_fpu = 0; +#endif + +#ifdef DEFAULT_ISA_EXT_SIMD +static int with_default_simd = 1; +#else +#define DEFAULT_ISA_EXT_SIMD -1 +static int with_default_simd = 0; #endif -/* Handle combinations of -m machine option values + +/* Initialize loongarch_target from separate option variables. */ + +void +loongarch_init_target (struct loongarch_target *target, + int cpu_arch, int cpu_tune, int fpu, int simd, + int abi_base, int abi_ext, int cmodel) +{ + if (!target) + return; + target->cpu_arch = cpu_arch; + target->cpu_tune = cpu_tune; + target->isa.fpu = fpu; + target->isa.simd = simd; + target->abi.base = abi_base; + target->abi.ext = abi_ext; + target->cmodel = cmodel; +} + + +/* Handle combinations of -m parameters (see loongarch.opt and loongarch-opts.h). */ + void loongarch_config_target (struct loongarch_target *target, - HOST_WIDE_INT opt_switches, - int opt_arch, int opt_tune, int opt_fpu, - int opt_abi_base, int opt_abi_ext, - int opt_cmodel, int follow_multilib_list) + struct loongarch_flags *flags, + int follow_multilib_list_p) { struct loongarch_target t; - if (!target) return; @@ -142,67 +171,63 @@ loongarch_config_target (struct loongarch_target *target, obstack_init (&msg_obstack); struct { - int arch, tune, fpu, abi_base, abi_ext, cmodel; + int arch, tune, fpu, simd, abi_base, abi_ext, cmodel, abi_flt; } constrained = { - M_OPT_ABSENT(opt_arch) ? 0 : 1, - M_OPT_ABSENT(opt_tune) ? 0 : 1, - M_OPT_ABSENT(opt_fpu) ? 0 : 1, - M_OPT_ABSENT(opt_abi_base) ? 0 : 1, - M_OPT_ABSENT(opt_abi_ext) ? 0 : 1, - M_OPT_ABSENT(opt_cmodel) ? 0 : 1, + M_OPT_ABSENT (target->cpu_arch) ? 0 : 1, + M_OPT_ABSENT (target->cpu_tune) ? 0 : 1, + M_OPT_ABSENT (target->isa.fpu) ? 0 : 1, + M_OPT_ABSENT (target->isa.simd) ? 0 : 1, + M_OPT_ABSENT (target->abi.base) ? 0 : 1, + M_OPT_ABSENT (target->abi.ext) ? 0 : 1, + M_OPT_ABSENT (target->cmodel) ? 0 : 1, + M_OPT_ABSENT (target->abi.base) ? 0 : 1, }; -#define on(NAME) ((loongarch_switch_mask[(SW_##NAME)] & opt_switches) \ - && (on_switch = (SW_##NAME), 1)) - int on_switch; - /* 1. Target ABI */ - t.abi.base = constrained.abi_base ? opt_abi_base : DEFAULT_ABI_BASE; + if (constrained.abi_base) + t.abi.base = target->abi.base; + else + t.abi.base = DEFAULT_ABI_BASE; - t.abi.ext = constrained.abi_ext ? opt_abi_ext : DEFAULT_ABI_EXT; + t.abi.ext = constrained.abi_ext ? target->abi.ext : DEFAULT_ABI_EXT; - /* Extra switch handling. */ - if (on (SOFT_FLOAT) || on (SINGLE_FLOAT) || on (DOUBLE_FLOAT)) + /* Process -m*-float flags */ + if (flags && !M_OPT_ABSENT (flags->flt)) { - switch (on_switch) - { - case SW_SOFT_FLOAT: - opt_fpu = ISA_EXT_NOFPU; - break; - - case SW_SINGLE_FLOAT: - opt_fpu = ISA_EXT_FPU32; - break; - - case SW_DOUBLE_FLOAT: - opt_fpu = ISA_EXT_FPU64; - break; + /* Modifying the original "target" here makes it easier to write the + t.isa.fpu assignment below, because otherwise there would be three + levels of precedence (-m*-float / -mfpu / -march) to be handled + (now the first two are merged). */ - default: - gcc_unreachable(); - } + target->isa.fpu = flags->flt; constrained.fpu = 1; /* The target ISA is not ready yet, but (isa_required (t.abi) + forced fpu) is enough for computing the forced base ABI. */ - struct loongarch_isa default_isa = isa_required (t.abi); - struct loongarch_isa force_isa = default_isa; - struct loongarch_abi force_abi = t.abi; - force_isa.fpu = opt_fpu; + + struct loongarch_isa force_isa = isa_required (t.abi); + force_isa.fpu = flags->flt; + + struct loongarch_abi force_abi; force_abi.base = isa_default_abi (&force_isa).base; - if (constrained.abi_base && (t.abi.base != force_abi.base)) - inform (UNKNOWN_LOCATION, - "%<-m%s%> overrides %<-m%s=%s%>, adjusting ABI to %qs", - loongarch_switch_strings[on_switch], - OPTSTR_ABI_BASE, loongarch_abi_base_strings[t.abi.base], - abi_str (force_abi)); + if (constrained.abi_base && constrained.abi_flt + && (t.abi.base != force_abi.base)) + { + force_abi.ext = t.abi.ext; + inform (UNKNOWN_LOCATION, + "%<-m%s%> overrides %<-m%s=%s%>, adjusting ABI to %qs", + flags->flt_str, OPTSTR_ABI_BASE, + loongarch_abi_base_strings[t.abi.base], + abi_str (force_abi)); + } t.abi.base = force_abi.base; + constrained.abi_flt = 1; } #ifdef LA_DISABLE_MULTILIB - if (follow_multilib_list) + if (follow_multilib_list_p) if (t.abi.base != DEFAULT_ABI_BASE || t.abi.ext != DEFAULT_ABI_EXT) { static const struct loongarch_abi default_abi @@ -214,18 +239,22 @@ loongarch_config_target (struct loongarch_target *target, #endif /* 2. Target CPU */ - t.cpu_arch = constrained.arch ? opt_arch : DEFAULT_CPU_ARCH; + t.cpu_arch = constrained.arch ? target->cpu_arch : DEFAULT_CPU_ARCH; + + /* If cpu_tune is not set using neither -mtune nor --with-tune, + the current cpu_arch is used as its default. */ + t.cpu_tune = constrained.tune ? target->cpu_tune + : (constrained.arch ? target->cpu_arch : + (with_default_tune ? DEFAULT_CPU_TUNE : DEFAULT_CPU_ARCH)); - t.cpu_tune = constrained.tune ? opt_tune - : (constrained.arch ? DEFAULT_CPU_ARCH : DEFAULT_CPU_TUNE); + /* Handle -march/tune=native */ #ifdef __loongarch__ /* For native compilers, gather local CPU information and fill the "CPU_NATIVE" index of arrays defined in loongarch-cpu.c. */ - t.cpu_native = fill_native_cpu_config (t.cpu_arch == CPU_NATIVE, - t.cpu_tune == CPU_NATIVE); + fill_native_cpu_config (&t); #else if (t.cpu_arch == CPU_NATIVE) @@ -239,17 +268,130 @@ loongarch_config_target (struct loongarch_target *target, "-m" OPTSTR_TUNE "=" STR_CPU_NATIVE); #endif - /* 3. Target ISA */ + /* Handle -march/tune=abi-default */ + if (t.cpu_tune == CPU_ABI_DEFAULT) + t.cpu_tune = abi_default_cpu_arch (t.abi, NULL); + + if (t.cpu_arch == CPU_ABI_DEFAULT) + { + t.cpu_arch = abi_default_cpu_arch (t.abi, &(t.isa)); + loongarch_cpu_default_isa[t.cpu_arch] = t.isa; + } + + /* 3. Target base ISA */ config_target_isa: /* Get default ISA from "-march" or its default value. */ - t.isa = loongarch_cpu_default_isa[LARCH_ACTUAL_ARCH]; + t.isa = loongarch_cpu_default_isa[t.cpu_arch]; /* Apply incremental changes. */ /* "-march=native" overrides the default FPU type. */ - t.isa.fpu = constrained.fpu ? opt_fpu : - ((t.cpu_arch == CPU_NATIVE && constrained.arch) ? - t.isa.fpu : DEFAULT_ISA_EXT_FPU); + + t.isa.fpu = constrained.fpu ? target->isa.fpu : + (constrained.arch ? t.isa.fpu : + (with_default_fpu ? DEFAULT_ISA_EXT_FPU : t.isa.fpu)); + + int simd_base = (constrained.arch ? t.isa.simd : + (with_default_simd ? DEFAULT_ISA_EXT_SIMD : t.isa.simd)); + + t.isa.simd = constrained.simd ? target->isa.simd : simd_base; + + /* If fallback_lsx is set, using -mno-lasx would cause + a fall-back to -msimd=lsx instead of -msimd=none. */ + + int fallback_lsx = 0; + if (t.isa.simd == ISA_EXT_SIMD_LSX || simd_base != ISA_EXT_NONE) + fallback_lsx = 1; + + /* apply -m[no-]lsx and -m[no-]lasx flags */ + if (flags) + for (int i = 0; i < 2; i++) + { + switch (SX_FLAG_TYPE (flags->sx[i])) + { + case ISA_EXT_SIMD_LSX: + constrained.simd = 1; + + if (flags->sx[i] > 0) + fallback_lsx = 1; + + if (flags->sx[i] > 0 && t.isa.simd != ISA_EXT_SIMD_LASX) + t.isa.simd = ISA_EXT_SIMD_LSX; + else if (flags->sx[i] < 0) + t.isa.simd = ISA_EXT_NONE; + break; + + case ISA_EXT_SIMD_LASX: + constrained.simd = 1; + /* If -mlsx or simd=lsx (msimd or march-default) was not + involved, do not fall back to simd=lsx. */ + if (flags->sx[i] < 0 && t.isa.simd == ISA_EXT_SIMD_LASX) + t.isa.simd = fallback_lsx ? ISA_EXT_SIMD_LSX : ISA_EXT_NONE; + else if (flags->sx[i] > 0) + t.isa.simd = ISA_EXT_SIMD_LASX; + break; + + case 0: + break; + + default: + gcc_unreachable (); + } + } + + /* All SIMD extensions imply a 64-bit FPU: + - silently adjust t.isa.fpu to "fpu64" if it is unconstrained. + - warn if -msingle-float / -msoft-float is on, + then disable SIMD extensions (done in driver) + - abort if -mfpu=0 / -mfpu=32 is forced. */ + + if (t.isa.simd != ISA_EXT_NONE && t.isa.fpu != ISA_EXT_FPU64) + { + if (!constrained.fpu) + { + /* As long as the arch-default "t.isa.simd" is set to non-zero + for an element "t" in loongarch_cpu_default_isa, "t.isa.fpu" + should be set to "ISA_EXT_FPU64" accordingly. Thus reaching + here must be the result of forcing -mlsx/-mlasx explicitly. */ + gcc_assert (constrained.simd); + + inform (UNKNOWN_LOCATION, + "enabing %qs promotes %<%s%s%> to %<%s%s%>", + loongarch_isa_ext_strings[t.isa.simd], + OPTSTR_ISA_EXT_FPU, loongarch_isa_ext_strings[t.isa.fpu], + OPTSTR_ISA_EXT_FPU, loongarch_isa_ext_strings[ISA_EXT_FPU64]); + + t.isa.fpu = ISA_EXT_FPU64; + } + else if (flags && (flags->flt == ISA_EXT_NONE + || flags->flt == ISA_EXT_FPU32)) + { + if (constrained.simd) + inform (UNKNOWN_LOCATION, + "%qs is disabled by %<-m%s%>, because it requires %<%s%s%>", + loongarch_isa_ext_strings[t.isa.simd], flags->flt_str, + OPTSTR_ISA_EXT_FPU, + loongarch_isa_ext_strings[ISA_EXT_FPU64]); + + t.isa.simd = ISA_EXT_NONE; + } + else + { + /* -mfpu=0 / -mfpu=32 is set. */ + if (constrained.simd) + fatal_error (UNKNOWN_LOCATION, + "%<-m%s=%s%> conflicts with %qs, " + "which requires %<%s%s%>", + OPTSTR_ISA_EXT_FPU, + loongarch_isa_ext_strings[t.isa.fpu], + loongarch_isa_ext_strings[t.isa.simd], + OPTSTR_ISA_EXT_FPU, + loongarch_isa_ext_strings[ISA_EXT_FPU64]); + + /* Same as above. */ + t.isa.simd = ISA_EXT_NONE; + } + } /* 4. ABI-ISA compatibility */ @@ -272,7 +414,7 @@ config_target_isa: { /* Base architecture can only be implied by -march, so we adjust that first if it is not constrained. */ - int fallback_arch = abi_default_cpu_arch (t.abi); + int fallback_arch = abi_default_cpu_arch (t.abi, NULL); if (t.cpu_arch == CPU_NATIVE) warning (0, "your native CPU architecture (%qs) " @@ -319,7 +461,7 @@ fatal: if (abi_tmp.base != t.abi.base || abi_tmp.ext != t.abi.ext) { /* This flag is only set in the GCC driver. */ - if (follow_multilib_list) + if (follow_multilib_list_p) { /* Continue falling back until we find a feasible ABI type @@ -360,7 +502,7 @@ fatal: fallback: t.abi = abi_tmp; } - else if (follow_multilib_list) + else if (follow_multilib_list_p) { if (!is_multilib_enabled (t.abi)) { @@ -375,7 +517,7 @@ fallback: /* 5. Target code model */ - t.cmodel = constrained.cmodel ? opt_cmodel : CMODEL_NORMAL; + t.cmodel = constrained.cmodel ? target->cmodel : CMODEL_NORMAL; switch (t.cmodel) { @@ -419,7 +561,7 @@ isa_default_abi (const struct loongarch_isa *isa) abi.base = ABI_BASE_LP64F; break; - case ISA_EXT_NOFPU: + case ISA_EXT_NONE: if (isa->base == ISA_BASE_LA64V100) abi.base = ABI_BASE_LP64S; break; @@ -459,7 +601,7 @@ isa_fpu_compat_p (const struct loongarch_isa *set1, case ISA_EXT_FPU32: return set1->fpu == ISA_EXT_FPU32 || set1->fpu == ISA_EXT_FPU64; - case ISA_EXT_NOFPU: + case ISA_EXT_NONE: return 1; default: @@ -483,16 +625,22 @@ abi_compat_p (const struct loongarch_isa *isa, struct loongarch_abi abi) /* The behavior of this function should be consistent with config.gcc. */ static inline int -abi_default_cpu_arch (struct loongarch_abi abi) +abi_default_cpu_arch (struct loongarch_abi abi, + struct loongarch_isa *isa) { - switch (abi.base) - { - case ABI_BASE_LP64D: - case ABI_BASE_LP64F: - case ABI_BASE_LP64S: - if (abi.ext == ABI_EXT_BASE) + static struct loongarch_isa tmp; + if (!isa) + isa = &tmp; + + if (abi.ext == ABI_EXT_BASE) + switch (abi.base) + { + case ABI_BASE_LP64D: + case ABI_BASE_LP64F: + case ABI_BASE_LP64S: + *isa = isa_required (abi); return CPU_LOONGARCH64; - } + } gcc_unreachable (); } @@ -521,7 +669,7 @@ isa_str (const struct loongarch_isa *isa, char separator) APPEND_STRING (loongarch_isa_base_strings[isa->base]) APPEND1 (separator) - if (isa->fpu == ISA_EXT_NOFPU) + if (isa->fpu == ISA_EXT_NONE) { APPEND_STRING ("no" OPTSTR_ISA_EXT_FPU) } @@ -530,6 +678,18 @@ isa_str (const struct loongarch_isa *isa, char separator) APPEND_STRING (OPTSTR_ISA_EXT_FPU) APPEND_STRING (loongarch_isa_ext_strings[isa->fpu]) } + + switch (isa->simd) + { + case ISA_EXT_SIMD_LSX: + case ISA_EXT_SIMD_LASX: + APPEND1 (separator); + APPEND_STRING (loongarch_isa_ext_strings[isa->simd]); + break; + + default: + gcc_assert (isa->simd == 0); + } APPEND1 ('\0') /* Add more here. */ @@ -542,18 +702,12 @@ arch_str (const struct loongarch_target *target) { if (target->cpu_arch == CPU_NATIVE) { - if (target->cpu_native == CPU_NATIVE) - { - /* Describe a native CPU with unknown PRID. */ - const char* isa_string = isa_str (&target->isa, ','); - APPEND_STRING ("PRID: 0x") - APPEND_STRING (get_native_prid_str ()) - APPEND_STRING (", ISA features: ") - APPEND_STRING (isa_string) - APPEND1 ('\0') - } - else - APPEND_STRING (loongarch_cpu_strings[target->cpu_native]); + /* Describe a native CPU with unknown PRID. */ + const char* isa_string = isa_str (&target->isa, ','); + APPEND_STRING ("PRID: 0x") + APPEND_STRING (get_native_prid_str ()) + APPEND_STRING (", ISA features: ") + APPEND_STRING (isa_string) } else APPEND_STRING (loongarch_cpu_strings[target->cpu_arch]); @@ -594,3 +748,23 @@ multilib_enabled_abi_list () return XOBFINISH (&msg_obstack, const char *); } + +/* option status feedback for "gcc --help=target -Q" */ +void +loongarch_update_gcc_opt_status (struct loongarch_target *target, + struct gcc_options *opts, + struct gcc_options *opts_set) +{ + (void) opts_set; + + /* status of -mabi */ + opts->x_la_opt_abi_base = target->abi.base; + + /* status of -march and -mtune */ + opts->x_la_opt_cpu_arch = target->cpu_arch; + opts->x_la_opt_cpu_tune = target->cpu_tune; + + /* status of -mfpu */ + opts->x_la_opt_fpu = target->isa.fpu; + opts->x_la_opt_simd = target->isa.simd; +} diff --git a/gcc/config/loongarch/loongarch-opts.h b/gcc/config/loongarch/loongarch-opts.h index 3523a4cf7..e3f9b6f99 100644 --- a/gcc/config/loongarch/loongarch-opts.h +++ b/gcc/config/loongarch/loongarch-opts.h @@ -21,24 +21,39 @@ along with GCC; see the file COPYING3. If not see #ifndef LOONGARCH_OPTS_H #define LOONGARCH_OPTS_H +#include "loongarch-def.h" /* Target configuration */ extern struct loongarch_target la_target; -/* Switch masks */ -extern const int loongarch_switch_mask[]; - -#include "loongarch-def.h" +/* Flag status */ +struct loongarch_flags { + int flt; const char* flt_str; +#define SX_FLAG_TYPE(x) ((x) < 0 ? -(x) : (x)) + int sx[2]; +}; #if !defined(IN_LIBGCC2) && !defined(IN_TARGET_LIBS) && !defined(IN_RTS) + +/* Initialize loongarch_target from separate option variables. */ +void +loongarch_init_target (struct loongarch_target *target, + int cpu_arch, int cpu_tune, int fpu, int simd, + int abi_base, int abi_ext, int cmodel); + + /* Handler for "-m" option combinations, shared by the driver and the compiler proper. */ void loongarch_config_target (struct loongarch_target *target, - HOST_WIDE_INT opt_switches, - int opt_arch, int opt_tune, int opt_fpu, - int opt_abi_base, int opt_abi_ext, - int opt_cmodel, int follow_multilib_list); + struct loongarch_flags *flags, + int follow_multilib_list_p); + +/* option status feedback for "gcc --help=target -Q" */ +void +loongarch_update_gcc_opt_status (struct loongarch_target *target, + struct gcc_options *opts, + struct gcc_options *opts_set); #endif @@ -50,11 +65,11 @@ loongarch_config_target (struct loongarch_target *target, #define TARGET_CMODEL_LARGE (la_target.cmodel == CMODEL_LARGE) #define TARGET_CMODEL_EXTREME (la_target.cmodel == CMODEL_EXTREME) -#define TARGET_HARD_FLOAT (la_target.isa.fpu != ISA_EXT_NOFPU) +#define TARGET_HARD_FLOAT (la_target.isa.fpu != ISA_EXT_NONE) #define TARGET_HARD_FLOAT_ABI (la_target.abi.base == ABI_BASE_LP64D \ || la_target.abi.base == ABI_BASE_LP64F) -#define TARGET_SOFT_FLOAT (la_target.isa.fpu == ISA_EXT_NOFPU) +#define TARGET_SOFT_FLOAT (la_target.isa.fpu == ISA_EXT_NONE) #define TARGET_SOFT_FLOAT_ABI (la_target.abi.base == ABI_BASE_LP64S) #define TARGET_SINGLE_FLOAT (la_target.isa.fpu == ISA_EXT_FPU32) #define TARGET_SINGLE_FLOAT_ABI (la_target.abi.base == ABI_BASE_LP64F) @@ -66,30 +81,16 @@ loongarch_config_target (struct loongarch_target *target, || la_target.abi.base == ABI_BASE_LP64F \ || la_target.abi.base == ABI_BASE_LP64S) -#define TARGET_ARCH_NATIVE (la_target.cpu_arch == CPU_NATIVE) -#define LARCH_ACTUAL_ARCH (TARGET_ARCH_NATIVE \ - ? (la_target.cpu_native < N_ARCH_TYPES \ - ? (la_target.cpu_native) : (CPU_NATIVE)) \ - : (la_target.cpu_arch)) +#define ISA_HAS_LSX (la_target.isa.simd == ISA_EXT_SIMD_LSX \ + || la_target.isa.simd == ISA_EXT_SIMD_LASX) +#define ISA_HAS_LASX (la_target.isa.simd == ISA_EXT_SIMD_LASX) -#define TARGET_TUNE_NATIVE (la_target.cpu_tune == CPU_NATIVE) -#define LARCH_ACTUAL_TUNE (TARGET_TUNE_NATIVE \ - ? (la_target.cpu_native < N_TUNE_TYPES \ - ? (la_target.cpu_native) : (CPU_NATIVE)) \ - : (la_target.cpu_tune)) -#define TARGET_ARCH_LOONGARCH64 (LARCH_ACTUAL_ARCH == CPU_LOONGARCH64) -#define TARGET_ARCH_LA464 (LARCH_ACTUAL_ARCH == CPU_LA464) - -#define TARGET_TUNE_LOONGARCH64 (LARCH_ACTUAL_TUNE == CPU_LOONGARCH64) -#define TARGET_TUNE_LA464 (LARCH_ACTUAL_TUNE == CPU_LA464) +/* TARGET_ macros for use in *.md template conditionals */ +#define TARGET_uARCH_LA464 (la_target.cpu_tune == CPU_LA464) /* Note: optimize_size may vary across functions, while -m[no]-memcpy imposes a global constraint. */ #define TARGET_DO_OPTIMIZE_BLOCK_MOVE_P loongarch_do_optimize_block_move_p() -#ifndef HAVE_AS_EXPLICIT_RELOCS -#define HAVE_AS_EXPLICIT_RELOCS 0 -#endif - #endif /* LOONGARCH_OPTS_H */ diff --git a/gcc/config/loongarch/loongarch-str.h b/gcc/config/loongarch/loongarch-str.h index 9f1b0989c..6b12754a3 100644 --- a/gcc/config/loongarch/loongarch-str.h +++ b/gcc/config/loongarch/loongarch-str.h @@ -27,13 +27,14 @@ along with GCC; see the file COPYING3. If not see #define OPTSTR_TUNE "tune" #define STR_CPU_NATIVE "native" +#define STR_CPU_ABI_DEFAULT "abi-default" #define STR_CPU_LOONGARCH64 "loongarch64" #define STR_CPU_LA464 "la464" #define STR_ISA_BASE_LA64V100 "la64" #define OPTSTR_ISA_EXT_FPU "fpu" -#define STR_ISA_EXT_NOFPU "none" +#define STR_NONE "none" #define STR_ISA_EXT_FPU0 "0" #define STR_ISA_EXT_FPU32 "32" #define STR_ISA_EXT_FPU64 "64" @@ -42,6 +43,10 @@ along with GCC; see the file COPYING3. If not see #define OPTSTR_SINGLE_FLOAT "single-float" #define OPTSTR_DOUBLE_FLOAT "double-float" +#define OPTSTR_ISA_EXT_SIMD "simd" +#define STR_ISA_EXT_LSX "lsx" +#define STR_ISA_EXT_LASX "lasx" + #define OPTSTR_ABI_BASE "abi" #define STR_ABI_BASE_LP64D "lp64d" #define STR_ABI_BASE_LP64F "lp64f" diff --git a/gcc/config/loongarch/loongarch.cc b/gcc/config/loongarch/loongarch.cc index 41d344b82..bd774d4a9 100644 --- a/gcc/config/loongarch/loongarch.cc +++ b/gcc/config/loongarch/loongarch.cc @@ -2551,7 +2551,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, @@ -2593,7 +2593,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: @@ -6060,8 +6060,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; } @@ -6072,8 +6072,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; } @@ -6250,17 +6250,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; @@ -6269,33 +6306,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 @@ -6303,12 +6320,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"); @@ -6378,7 +6389,7 @@ loongarch_option_override_internal (struct gcc_options *opts) static void loongarch_option_override (void) { - loongarch_option_override_internal (&global_options); + loongarch_option_override_internal (&global_options, &global_options_set); } /* Implement TARGET_CONDITIONAL_REGISTER_USAGE. */ diff --git a/gcc/config/loongarch/loongarch.opt b/gcc/config/loongarch/loongarch.opt index 96c811c85..f96d32769 100644 --- a/gcc/config/loongarch/loongarch.opt +++ b/gcc/config/loongarch/loongarch.opt @@ -24,22 +24,12 @@ ; <http://www.gnu.org/licenses/>. ; -; Variables (macros) that should be exported by loongarch.opt: -; la_opt_switches, -; la_opt_abi_base, la_opt_abi_ext, -; la_opt_cpu_arch, la_opt_cpu_tune, -; la_opt_fpu, -; la_cmodel. - HeaderInclude config/loongarch/loongarch-opts.h HeaderInclude config/loongarch/loongarch-str.h -Variable -HOST_WIDE_INT la_opt_switches = 0 - ; ISA related options ;; Base ISA Enum @@ -49,14 +39,13 @@ Basic ISAs of LoongArch: EnumValue Enum(isa_base) String(la64) Value(ISA_BASE_LA64V100) - ;; ISA extensions / adjustments Enum Name(isa_ext_fpu) Type(int) FPU types of LoongArch: EnumValue -Enum(isa_ext_fpu) String(none) Value(ISA_EXT_NOFPU) +Enum(isa_ext_fpu) String(none) Value(ISA_EXT_NONE) EnumValue Enum(isa_ext_fpu) String(32) Value(ISA_EXT_FPU32) @@ -65,24 +54,48 @@ EnumValue Enum(isa_ext_fpu) String(64) Value(ISA_EXT_FPU64) mfpu= -Target RejectNegative Joined ToLower Enum(isa_ext_fpu) Var(la_opt_fpu) Init(M_OPTION_NOT_SEEN) +Target RejectNegative Joined ToLower Enum(isa_ext_fpu) Var(la_opt_fpu) Init(M_OPT_UNSET) -mfpu=FPU Generate code for the given FPU. mfpu=0 Target RejectNegative Alias(mfpu=,none) msoft-float -Target Driver RejectNegative Var(la_opt_switches) Mask(FORCE_SOFTF) Negative(msingle-float) +Target Driver Defer Var(la_deferred_options) RejectNegative Negative(msingle-float) Prevent the use of all hardware floating-point instructions. msingle-float -Target Driver RejectNegative Var(la_opt_switches) Mask(FORCE_F32) Negative(mdouble-float) +Target Driver Defer Var(la_deferred_options) RejectNegative Negative(mdouble-float) Restrict the use of hardware floating-point instructions to 32-bit operations. mdouble-float -Target Driver RejectNegative Var(la_opt_switches) Mask(FORCE_F64) Negative(msoft-float) +Target Driver Defer Var(la_deferred_options) RejectNegative Negative(msoft-float) Allow hardware floating-point instructions to cover both 32-bit and 64-bit operations. +Enum +Name(isa_ext_simd) Type(int) +SIMD extension levels of LoongArch: + +EnumValue +Enum(isa_ext_simd) String(none) Value(ISA_EXT_NONE) + +EnumValue +Enum(isa_ext_simd) String(lsx) Value(ISA_EXT_SIMD_LSX) + +EnumValue +Enum(isa_ext_simd) String(lasx) Value(ISA_EXT_SIMD_LASX) + +msimd= +Target RejectNegative Joined ToLower Enum(isa_ext_simd) Var(la_opt_simd) Init(M_OPT_UNSET) +-msimd=SIMD Generate code for the given SIMD extension. + +mlsx +Target Driver Defer Var(la_deferred_options) +Enable LoongArch SIMD Extension (LSX, 128-bit). + +mlasx +Target Driver Defer Var(la_deferred_options) +Enable LoongArch Advanced SIMD Extension (LASX, 256-bit). ;; Base target models (implies ISA & tune parameters) Enum @@ -92,6 +105,9 @@ LoongArch CPU types: EnumValue Enum(cpu_type) String(native) Value(CPU_NATIVE) +EnumValue +Enum(cpu_type) String(abi-default) Value(CPU_ABI_DEFAULT) + EnumValue Enum(cpu_type) String(loongarch64) Value(CPU_LOONGARCH64) @@ -99,11 +115,11 @@ EnumValue Enum(cpu_type) String(la464) Value(CPU_LA464) march= -Target RejectNegative Joined Enum(cpu_type) Var(la_opt_cpu_arch) Init(M_OPTION_NOT_SEEN) +Target RejectNegative Joined Enum(cpu_type) Var(la_opt_cpu_arch) Init(M_OPT_UNSET) -march=PROCESSOR Generate code for the given PROCESSOR ISA. mtune= -Target RejectNegative Joined Enum(cpu_type) Var(la_opt_cpu_tune) Init(M_OPTION_NOT_SEEN) +Target RejectNegative Joined Enum(cpu_type) Var(la_opt_cpu_tune) Init(M_OPT_UNSET) -mtune=PROCESSOR Generate optimized code for PROCESSOR. @@ -125,13 +141,13 @@ EnumValue Enum(abi_base) String(lp64s) Value(ABI_BASE_LP64S) mabi= -Target RejectNegative Joined ToLower Enum(abi_base) Var(la_opt_abi_base) Init(M_OPTION_NOT_SEEN) +Target RejectNegative Joined ToLower Enum(abi_base) Var(la_opt_abi_base) Init(M_OPT_UNSET) -mabi=BASEABI Generate code that conforms to the given BASEABI. + ;; ABI Extension Variable -int la_opt_abi_ext = M_OPTION_NOT_SEEN - +int la_opt_abi_ext = M_OPT_UNSET mbranch-cost= Target RejectNegative Joined UInteger Var(loongarch_branch_cost) @@ -189,7 +205,7 @@ EnumValue Enum(cmodel) String(extreme) Value(CMODEL_EXTREME) mcmodel= -Target RejectNegative Joined Enum(cmodel) Var(la_opt_cmodel) Init(CMODEL_NORMAL) +Target RejectNegative Joined Enum(cmodel) Var(la_opt_cmodel) Init(M_OPT_UNSET) Specify the code model. mdirect-extern-access diff --git a/gcc/config/loongarch/t-linux b/gcc/config/loongarch/t-linux index 136b27d0a..62a870b66 100644 --- a/gcc/config/loongarch/t-linux +++ b/gcc/config/loongarch/t-linux @@ -23,7 +23,37 @@ MULTILIB_DIRNAMES = base/lp64d base/lp64f base/lp64s # The GCC driver always gets all abi-related options on the command line. # (see loongarch-driver.c:driver_get_normalized_m_opts) comma=, -MULTILIB_REQUIRED = $(subst $(comma), ,$(TM_MULTILIB_CONFIG)) +MULTILIB_REQUIRED = $(foreach mlib,$(subst $(comma), ,$(TM_MULTILIB_CONFIG)),\ + $(firstword $(subst /, ,$(mlib)))) + +SPECS = specs.install + +# temporary self_spec when building libraries (e.g. libgcc) +gen_mlib_spec = $(if $(word 2,$1),\ + %{$(firstword $1):$(patsubst %,-%,$(wordlist 2,$(words $1),$1))}) + +# clean up the result of DRIVER_SELF_SPEC to avoid conflict +lib_build_self_spec = %<march=* %<mtune=* %<mcmodel=* %<mfpu=* %<msimd=* + +# append user-specified build options from --with-multilib-list +lib_build_self_spec += $(foreach mlib,\ + $(subst $(comma), ,$(TM_MULTILIB_CONFIG)),\ + $(call gen_mlib_spec,$(subst /, ,$(mlib)))) + +specs: specs.install + sed '/^*self_spec:$$/{ n;s/^$$/$(lib_build_self_spec)/g; }' $< > $@ + +# Do some preparation before regression tests: +# remove lib-build-specs / make symlinks for the toplevel multilib variant + +LA_DEFAULT_MULTISUBDIR = $(shell $(GCC_FOR_TARGET) --print-multi-dir) +.PHONY: remove-lib-specs +check check-host check-target $(CHECK_TARGETS) $(lang_checks): remove-lib-specs +remove-lib-specs: + -mv -f specs.install specs 2>/dev/null + -mv $(LA_DEFAULT_MULTISUBDIR)/* ./ + -mkdir -p ../$(target_noncanonical)/`dirname $(LA_DEFAULT_MULTISUBDIR)` + -$(LN_S) .. ../$(target_noncanonical)/$(LA_DEFAULT_MULTISUBDIR) # Multiarch ifneq ($(call if_multiarch,yes),yes) diff --git a/gcc/doc/install.texi b/gcc/doc/install.texi index 19d073256..1fc5f0bfa 100644 --- a/gcc/doc/install.texi +++ b/gcc/doc/install.texi @@ -1173,7 +1173,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. @@ -1263,12 +1263,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 @@ -1319,6 +1340,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 @@ -1468,6 +1502,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 @@ -4489,8 +4524,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 -- 2.33.0
Locations
Projects
Search
Status Monitor
Help
Open Build Service
OBS Manuals
API Documentation
OBS Portal
Reporting a Bug
Contact
Mailing List
Forums
Chat (IRC)
Twitter
Open Build Service (OBS)
is an
openSUSE project
.
浙ICP备2022010568号-2