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.
Change-Id: Ie1643cbe93c278adadf85484eccd21289c320225
---
.../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(-)
create mode 100644 gcc/config/loongarch/loongarch-evol-attr.def
create mode 100644 gcc/testsuite/gcc.target/loongarch/pragma-la64V1_1-2.c
create mode 100644 gcc/testsuite/gcc.target/loongarch/pragma-la64V1_1.c
diff --git a/gcc/config/loongarch/genopts/gen-evolution.awk
b/gcc/config/loongarch/genopts/gen-evolution.awk
index 507063bd50d..3e27a3f92bd 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 97517da40f4..fc11a70b4bf 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 00000000000..a5137b2390e
--- /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 922aa0483b5..f7e7d403c22 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 b7dbb4befc5..462ad5129dd 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 882c0820a6e..fdcb17bfb82 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -4836,6 +4836,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 00000000000..1a6ca4ef6f7
--- /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 00000000000..6165d95493b
--- /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
--
2.34.1