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

Reply via email to