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, "\\.")
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 ""
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()
}
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
;;
--- /dev/null
+/* 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)
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;
{
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;
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;
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 ();
}
}
decoded.value = !invert;
loongarch_handle_option (&global_options, &global_options_set,
- &decoded, input_location);
+ &decoded, input_location,
+ p_attr->opt_mask);
break;
}
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);
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:
$(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) $@
$ 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
--- /dev/null
+/* { 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
--- /dev/null
+/* { 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