https://gcc.gnu.org/g:009e32e6aa9771835368b8483490d468a5065e6e
commit r16-5149-g009e32e6aa9771835368b8483490d468a5065e6e Author: Lulu Cheng <[email protected]> Date: Fri Sep 19 14:51:34 2025 +0800 LoongArch: Support la64v1.1 evolution features in the target pragma and attribute. Supported options: -mfrecipe -mdiv32 -mlam-bh -mlamcas -mscq -mld-seq-sa. gcc/ChangeLog: * config/loongarch/genopts/gen-evolution.awk: Output the info needed for handling evolution features when parsing the target pragma and attribute. * config/loongarch/genopts/genstr.sh: Add support for generating *.def files. * config/loongarch/loongarch-target-attr.cc (struct loongarch_attribute_info): Add structure member record option mask. (LARCH_ATTR_MASK): New macro. (LARCH_ATTR_ENUM): Likewise. (LARCH_ATTR_BOOL): Likewise. (loongarch_handle_option): Support for new options. (loongarch_process_one_target_attr): Added support for the la64v1.1 extended instruction set. * config/loongarch/t-loongarch: Generate loongarch-evol-attr.def. * doc/extend.texi: Add new attribute description information. * config/loongarch/loongarch-evol-attr.def: Generate. gcc/testsuite/ChangeLog: * gcc.target/loongarch/pragma-la64V1_1.c: New test. * gcc.target/loongarch/pragma-la64V1_1-2.c: New test. Diff: --- gcc/config/loongarch/genopts/gen-evolution.awk | 35 ++++++- gcc/config/loongarch/genopts/genstr.sh | 3 + gcc/config/loongarch/loongarch-evol-attr.def | 32 ++++++ gcc/config/loongarch/loongarch-target-attr.cc | 112 +++++++++++++++------ gcc/config/loongarch/t-loongarch | 3 + gcc/doc/extend.texi | 44 ++++++++ .../gcc.target/loongarch/pragma-la64V1_1-2.c | 68 +++++++++++++ .../gcc.target/loongarch/pragma-la64V1_1.c | 87 ++++++++++++++++ 8 files changed, 348 insertions(+), 36 deletions(-) diff --git a/gcc/config/loongarch/genopts/gen-evolution.awk b/gcc/config/loongarch/genopts/gen-evolution.awk index 507063bd50df..3e27a3f92bd3 100644 --- a/gcc/config/loongarch/genopts/gen-evolution.awk +++ b/gcc/config/loongarch/genopts/gen-evolution.awk @@ -34,6 +34,7 @@ BEGIN { cpucfg_word[NR] = $1 cpucfg_bit_in_word[NR] = $2 name[NR] = $3 + orig_name[NR] = $3 gsub("-", "_", name[NR]) name_capitalized[NR] = toupper(name[NR]) split($4, isa_ver, "\\.") @@ -47,8 +48,12 @@ BEGIN { function copyright_header(from_year,to_year) { - print " Copyright (C) " from_year "-" to_year \ - " Free Software Foundation, Inc." + if (to_year == "") + print " Copyright (C) " from_year \ + " Free Software Foundation, Inc." + else + print " Copyright (C) " from_year "-" to_year \ + " Free Software Foundation, Inc." print "" print "This file is part of GCC." print "" @@ -233,9 +238,31 @@ function gen_full_source() print "};" } +function gen_full_def() +{ + print "/* Generated automatically by \"genstr\" from \"isa-evolution.in\"." + print " Please do not edit this file directly." + print "" + + copyright_header(2025) + + print "*/" + print "" + + print "#ifndef LARCH_ATTR_BOOL" + print "#define LARCH_ATTR_BOOL" + print "#endif" + print "" + for (i = 1; i <= NR; i++) + printf (" LARCH_ATTR_BOOL (\"%s\", OPT_m%s, OPTION_MASK_ISA_%s)\n", + orig_name[i], name[i], name_capitalized[i]) +} + END { - if (header_p) + if (header_p == 1) gen_full_header() - else + else if (header_p == 0) gen_full_source() + else if (header_p == 2) + gen_full_def() } diff --git a/gcc/config/loongarch/genopts/genstr.sh b/gcc/config/loongarch/genopts/genstr.sh index 97517da40f49..fc11a70b4bf1 100755 --- a/gcc/config/loongarch/genopts/genstr.sh +++ b/gcc/config/loongarch/genopts/genstr.sh @@ -125,6 +125,9 @@ main() { evolution_c) awk -v header_p=0 -f gen-evolution.awk isa-evolution.in ;; + evolution_def) + awk -v header_p=2 -f gen-evolution.awk isa-evolution.in + ;; header) gen_defines ;; diff --git a/gcc/config/loongarch/loongarch-evol-attr.def b/gcc/config/loongarch/loongarch-evol-attr.def new file mode 100644 index 000000000000..a5137b2390ea --- /dev/null +++ b/gcc/config/loongarch/loongarch-evol-attr.def @@ -0,0 +1,32 @@ +/* Generated automatically by "genstr" from "isa-evolution.in". + Please do not edit this file directly. + + Copyright (C) 2025 Free Software Foundation, Inc. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 3, or (at your option) +any later version. + +GCC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING3. If not see +<http://www.gnu.org/licenses/>. +*/ + +#ifndef LARCH_ATTR_BOOL +#define LARCH_ATTR_BOOL +#endif + + LARCH_ATTR_BOOL ("frecipe", OPT_mfrecipe, OPTION_MASK_ISA_FRECIPE) + LARCH_ATTR_BOOL ("div32", OPT_mdiv32, OPTION_MASK_ISA_DIV32) + LARCH_ATTR_BOOL ("lam-bh", OPT_mlam_bh, OPTION_MASK_ISA_LAM_BH) + LARCH_ATTR_BOOL ("lamcas", OPT_mlamcas, OPTION_MASK_ISA_LAMCAS) + LARCH_ATTR_BOOL ("scq", OPT_mscq, OPTION_MASK_ISA_SCQ) + LARCH_ATTR_BOOL ("ld-seq-sa", OPT_mld_seq_sa, OPTION_MASK_ISA_LD_SEQ_SA) diff --git a/gcc/config/loongarch/loongarch-target-attr.cc b/gcc/config/loongarch/loongarch-target-attr.cc index 922aa0483b57..f7e7d403c222 100644 --- a/gcc/config/loongarch/loongarch-target-attr.cc +++ b/gcc/config/loongarch/loongarch-target-attr.cc @@ -52,28 +52,59 @@ enum loongarch_attr_opt_type struct loongarch_attribute_info { const char *name; + unsigned int opt_mask; enum loongarch_attr_opt_type attr_type; - bool allow_neg; enum opt_code opt_num; + bool allow_neg; }; + +/* Construct a loongarch_attributes from the given arguments. + + OPTS is the name of the compilation option after the "-m" string. + + OPTNUM is the opt_code corresponding to the compilation option. + + OPTMASK is the mask corresponding to the mutation option. If the + compilation option does not have a corresponding mask, pass 0. + */ +#define LARCH_ATTR_MASK(OPTS, OPTNUM, OPTMASK) \ + { \ + OPTS, OPTMASK, loongarch_attr_mask, OPTNUM, true \ + }, + +#define LARCH_ATTR_ENUM(OPTS, OPTNUM, OPTMASK) \ + { \ + OPTS, OPTMASK, loongarch_attr_enum, OPTNUM, false \ + }, + +#define LARCH_ATTR_BOOL(OPTS, OPTNUM, OPTMASK) \ + { \ + OPTS, OPTMASK, loongarch_attr_bool, OPTNUM, true \ + }, + /* The target attributes that we support. */ static const struct loongarch_attribute_info loongarch_attributes[] = { - { "strict-align", loongarch_attr_mask, true, OPT_mstrict_align }, - { "cmodel", loongarch_attr_enum, false, OPT_mcmodel_ }, - { "arch", loongarch_attr_enum, false, OPT_march_ }, - { "tune", loongarch_attr_enum, false, OPT_mtune_ }, - { "lsx", loongarch_attr_bool, true, OPT_mlsx }, - { "lasx", loongarch_attr_bool, true, OPT_mlasx }, - { NULL, loongarch_attr_bool, false, OPT____ } + LARCH_ATTR_MASK ("strict-align", OPT_mstrict_align, MASK_STRICT_ALIGN) + LARCH_ATTR_ENUM ("cmodel", OPT_mcmodel_, 0) + LARCH_ATTR_ENUM ("arch", OPT_march_, 0) + LARCH_ATTR_ENUM ("tune", OPT_mtune_, 0) + LARCH_ATTR_BOOL ("lsx", OPT_mlsx, 0) + LARCH_ATTR_BOOL ("lasx", OPT_mlasx, 0) +#include "loongarch-evol-attr.def" + { NULL, 0, loongarch_attr_bool, OPT____, false } }; +#undef LARCH_ATTR_MASK +#undef LARCH_ATTR_ENUM +#undef LARCH_ATTR_BOOL -bool +static void loongarch_handle_option (struct gcc_options *opts, struct gcc_options *opts_set ATTRIBUTE_UNUSED, const struct cl_decoded_option *decoded, - location_t loc ATTRIBUTE_UNUSED) + location_t loc ATTRIBUTE_UNUSED, + unsigned int opt_mask ATTRIBUTE_UNUSED) { size_t code = decoded->opt_index; int val = decoded->value; @@ -82,14 +113,14 @@ loongarch_handle_option (struct gcc_options *opts, { case OPT_mstrict_align: if (val) - opts->x_target_flags |= MASK_STRICT_ALIGN; + opts->x_target_flags |= opt_mask; else - opts->x_target_flags &= ~MASK_STRICT_ALIGN; - return true; + opts->x_target_flags &= ~opt_mask; + break; case OPT_mcmodel_: opts->x_la_opt_cmodel = val; - return true; + break; case OPT_march_: opts->x_la_opt_cpu_arch = val; @@ -100,7 +131,7 @@ loongarch_handle_option (struct gcc_options *opts, opts->x_la_opt_simd = M_OPT_UNSET; opts->x_la_opt_fpu = M_OPT_UNSET; opts->x_la_isa_evolution = 0; - return true; + break; case OPT_mtune_: opts->x_la_opt_cpu_tune = val; @@ -111,21 +142,10 @@ loongarch_handle_option (struct gcc_options *opts, opts->x_str_align_functions = NULL; opts->x_str_align_loops = NULL; opts->x_str_align_jumps = NULL; - return true; - - case OPT_mlsx: - opts->x_la_opt_simd = val ? (la_opt_simd == ISA_EXT_SIMD_LASX - ? ISA_EXT_SIMD_LASX : ISA_EXT_SIMD_LSX) : ISA_EXT_NONE; - return true; - - case OPT_mlasx: - opts->x_la_opt_simd = val ? ISA_EXT_SIMD_LASX - : (la_opt_simd == ISA_EXT_SIMD_LASX || la_opt_simd == ISA_EXT_SIMD_LSX - ? ISA_EXT_SIMD_LSX : ISA_EXT_NONE); - return true; + break; default: - return true; + gcc_unreachable (); } } @@ -196,7 +216,8 @@ loongarch_process_one_target_attr (char *arg_str, location_t loc) decoded.value = !invert; loongarch_handle_option (&global_options, &global_options_set, - &decoded, input_location); + &decoded, input_location, + p_attr->opt_mask); break; } @@ -222,7 +243,8 @@ loongarch_process_one_target_attr (char *arg_str, location_t loc) if (valid) loongarch_handle_option (&global_options, &global_options_set, - &decoded, input_location); + &decoded, input_location, + p_attr->opt_mask); else error_at (loc, "pragma or attribute %<target(\"%s=%s\")%> is " "not valid", str_to_check, arg); @@ -236,8 +258,34 @@ loongarch_process_one_target_attr (char *arg_str, location_t loc) generate_option (p_attr->opt_num, NULL, !invert, CL_TARGET, &decoded); - loongarch_handle_option (&global_options, &global_options_set, - &decoded, input_location); + switch (decoded.opt_index) + { + case OPT_mlsx: + global_options.x_la_opt_simd + = decoded.value + ? (la_opt_simd == ISA_EXT_SIMD_LASX + ? ISA_EXT_SIMD_LASX : ISA_EXT_SIMD_LSX) + : ISA_EXT_NONE; + break; + + case OPT_mlasx: + global_options.x_la_opt_simd + = decoded.value + ? ISA_EXT_SIMD_LASX + : (la_opt_simd == ISA_EXT_SIMD_LASX + || la_opt_simd == ISA_EXT_SIMD_LSX + ? ISA_EXT_SIMD_LSX : ISA_EXT_NONE); + break; + + default: + { + if (decoded.value) + global_options.x_la_isa_evolution |= p_attr->opt_mask; + else + global_options.x_la_isa_evolution &= ~p_attr->opt_mask; + global_options_set.x_la_isa_evolution |= p_attr->opt_mask; + } + } break; } default: diff --git a/gcc/config/loongarch/t-loongarch b/gcc/config/loongarch/t-loongarch index b7dbb4befc53..462ad5129dd9 100644 --- a/gcc/config/loongarch/t-loongarch +++ b/gcc/config/loongarch/t-loongarch @@ -103,8 +103,11 @@ s-loongarch-evolution: $(srcdir)/config/loongarch/genopts/genstr.sh \ $(srcdir)/config/loongarch/genopts/gen-evolution.awk $(SHELL) $< evolution_h > tmp-isa-evo.h $(SHELL) $< evolution_c > tmp-isa-evo.cc + $(SHELL) $< evolution_def > tmp-isa-evo.def $(SHELL) $(srcdir)/../move-if-change tmp-isa-evo.h \ $(srcdir)/config/loongarch/loongarch-evolution.h $(SHELL) $(srcdir)/../move-if-change tmp-isa-evo.cc \ $(srcdir)/config/loongarch/loongarch-evolution.cc + $(SHELL) $(srcdir)/../move-if-change tmp-isa-evo.def \ + $(srcdir)/config/loongarch/loongarch-evol-attr.def $(STAMP) $@ diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi index 616e05ebbd2c..403e09ac9c03 100644 --- a/gcc/doc/extend.texi +++ b/gcc/doc/extend.texi @@ -4897,6 +4897,50 @@ But the following method cannot perform 128-bit vectorization. $ gcc test.c -o test.s -O2 -mlasx -mno-lasx @end smallexample +@cindex @code{recipe} function attribute, LoongArch +@item recipe +@itemx no-recipe +@code{recipe} indicates that frecipe.@{s/d@} and frsqrt.@{s/d@}instruction generation +is allowed (not allowed) when compiling the function. The behavior is same as for +the command-line option +@option{-mrecipe} and @option{-mno-recipe}. + +@cindex @code{div32} function attribute, LoongArch +@item div32 +@itemx no-div32 +@code{div32} determines whether div.w[u] and mod.w[u] instructions on 64-bit machines +are evaluated based only on the lower 32 bits of the input registers. +@option{-mdiv32} and @option{-mno-div32}. + +@cindex @code{lam-bh} function attribute, LoongArch +@item lam-bh +@itemx no-lam-bh +@code{lam-bh} indicates that am@{swap/add@}[_db].@{b/h@} instruction generation +is allowed (not allowed) when compiling the function. The behavior is same as for +the command-line option +@option{-mlam-bh} and @option{-mno-lam-bh}. + +@cindex @code{lamcas} function attribute, LoongArch +@item lamcas +@itemx no-lamcas +@code{lamcas} indicates that amcas[_db].@{b/h/w/d@} instruction generation +is allowed (not allowed) when compiling the function. The behavior is same as for +the command-line option +@option{-mlamcas} and @option{-mno-lamcas}. + +@cindex @code{scq} function attribute, LoongArch +@item scq +@itemx no-scq +@code{scq} indicates that sc.q instruction generation is allowed (not allowed) when +compiling the function. The behavior is same as for the command-line option +@option{-mscq} and @option{-mno-scq}. + +@cindex @code{ld-seq-sa} function attribute, LoongArch +@item ld-seq-sa +@itemx no-ld-seq-sa +@code{ld-seq-sa} indicates that whether need load-load barries (dbar 0x700) +@option{-mld-seq-sa} and @option{-mno-ld-seq-sa}. + @end table @node M32C Function Attributes diff --git a/gcc/testsuite/gcc.target/loongarch/pragma-la64V1_1-2.c b/gcc/testsuite/gcc.target/loongarch/pragma-la64V1_1-2.c new file mode 100644 index 000000000000..1a6ca4ef6f7f --- /dev/null +++ b/gcc/testsuite/gcc.target/loongarch/pragma-la64V1_1-2.c @@ -0,0 +1,68 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -march=loongarch64 -std=gnu11 -march=la64v1.1" } */ + +#pragma GCC push_options +#pragma GCC target ("no-frecipe") +float +frecipe (float src) +{ +#ifdef __loongarch_frecipe +#error "Should't define __loongarch_frecipe" +#endif +} +#pragma GCC pop_options + +#pragma GCC push_options +#pragma GCC target ("no-div32") +int +div32 (unsigned long int a, unsigned long int b) +{ +#ifdef __loongarch_div32 +#error "Shouldn't define __loongarch_div32" +#endif +} +#pragma GCC pop_options + +#pragma GCC push_options +#pragma GCC target ("no-lam-bh") +short +lam_bh (short *ptr, short val) +{ +#ifdef __loongarch_lam_bh +#error "Shouldn't define __loongarch_lam_bh" +#endif +} +#pragma GCC pop_options + +#pragma GCC push_options +#pragma GCC target ("no-lamcas") +void +lamcas (int *ptr, int *exp, int des) +{ +#ifdef __loongarch_lamcas +#error "Shouldn't define __loongarch_lamcas" +#endif +} +#pragma GCC pop_options + +#pragma GCC push_options +#pragma GCC target ("no-scq") +void +scq (int *ptr, int *exp, int des) +{ +#ifdef __loongarch_scq +#error "Shouldn't define __loongarch_scq" +#endif +} +#pragma GCC pop_options + +#pragma GCC push_options +#pragma GCC target ("no-ld-seq-sa") +void +ld_seq_sa (int *ptr, int *exp, int des) +{ +#ifdef __loongarch_ld_seq_sa +#error "Shouldn't define __loongarch_ld_seq_sa" +#endif +} +#pragma GCC pop_options diff --git a/gcc/testsuite/gcc.target/loongarch/pragma-la64V1_1.c b/gcc/testsuite/gcc.target/loongarch/pragma-la64V1_1.c new file mode 100644 index 000000000000..6165d95493bf --- /dev/null +++ b/gcc/testsuite/gcc.target/loongarch/pragma-la64V1_1.c @@ -0,0 +1,87 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -march=loongarch64 -std=gnu11" } */ +/* { dg-final { check-function-bodies "**" "" } } */ + + +/* +** frecipe: +** frecipe.s \$f0,\$f0 +** jr \$r1 +*/ +#pragma GCC push_options +#pragma GCC target ("frecipe") +float +frecipe (float src) +{ +#ifndef __loongarch_frecipe +#error "Not define __loongarch_frecipe" +#endif + return __builtin_loongarch_frecipe_s (src); +} +#pragma GCC pop_options + + +/* +** div32: +** div.w \$r4,\$r4,\$r5 +** jr \$r1 +*/ +#pragma GCC push_options +#pragma GCC target ("div32") +int +div32 (unsigned long int a, unsigned long int b) +{ +#ifndef __loongarch_div32 +#error "Not define __loongarch_div32" +#endif + return (int)a / (int)b; +} +#pragma GCC pop_options + +#pragma GCC push_options +#pragma GCC target ("lam-bh") +short +lam_bh (short *ptr, short val) +{ +#ifndef __loongarch_lam_bh +#error "Not define __loongarch_lam_bh" +#endif + return __atomic_fetch_add (ptr, val, __ATOMIC_RELAXED); +} +#pragma GCC pop_options +/* { dg-final { scan-assembler "lam_bh:.*amadd.h.*lam_bh" } } */ + +#pragma GCC push_options +#pragma GCC target ("lamcas") +void +lamcas (int *ptr, int *exp, int des) +{ +#ifndef __loongarch_lamcas +#error "Not define __loongarch_lamcas" +#endif + __atomic_compare_exchange_n (ptr, exp, des, 0, __ATOMIC_ACQ_REL, __ATOMIC_RELAXED); +} +#pragma GCC pop_options +/* { dg-final { scan-assembler "lamcas:.*amcas_db.w.*lamcas" } } */ + +#pragma GCC push_options +#pragma GCC target ("scq") +void +scq (int *ptr, int *exp, int des) +{ +#ifndef __loongarch_scq +#error "Not define __loongarch_scq" +#endif +} +#pragma GCC pop_options + +#pragma GCC push_options +#pragma GCC target ("ld-seq-sa") +void +ld_seq_sa (int *ptr, int *exp, int des) +{ +#ifndef __loongarch_ld_seq_sa +#error "Not define __loongarch_ld_seq_sa" +#endif +} +#pragma GCC pop_options
