The target pragmas defined correspond to the target function attributes.
This implementation is derived from AArch64.
gcc/ChangeLog:
* config/loongarch/loongarch-protos.h
(loongarch_reset_previous_fndecl): Add function declaration.
(loongarch_save_restore_target_globals): Likewise.
(loongarch_register_pragmas): Likewise.
* config/loongarch/loongarch-target-attr.cc
(loongarch_option_valid_attribute_p): Optimize the processing
of attributes.
(loongarch_pragma_target_parse): New functions.
(loongarch_register_pragmas): Likewise.
* config/loongarch/loongarch.cc
(loongarch_reset_previous_fndecl): New functions.
(loongarch_set_current_function): When the old_tree is the same
as the new_tree, the rules for using registers, etc.,
are set according to the option values to ensure that the
pragma can be processed correctly.
* config/loongarch/loongarch.h (REGISTER_TARGET_PRAGMAS):
Define macro.
* doc/extend.texi: Supplemental Documentation.
gcc/testsuite/ChangeLog:
* gcc.target/loongarch/arch-func-attr-1.c: Add '#pragma'.
* gcc.target/loongarch/cmodel-func-attr-1.c: Likewise.
* gcc.target/loongarch/lasx-func-attr-1.c: Likewise.
* gcc.target/loongarch/lsx-func-attr-1.c: Likewise.
* gcc.target/loongarch/strict_align-func-attr-1.c: Likewise.
* gcc.target/loongarch/strict_align-func-attr-2.c: Likewise.
* gcc.target/loongarch/vector-func-attr-1.c: Likewise.
* gcc.target/loongarch/arch-pragma-attr-1.c: Likewise.
* gcc.target/loongarch/cmodel-pragma-attr-1.c: New test.
* gcc.target/loongarch/lasx-pragma-attr-1.c: New test.
* gcc.target/loongarch/lasx-pragma-attr-2.c: New test.
* gcc.target/loongarch/lsx-pragma-attr-1.c: New test.
* gcc.target/loongarch/lsx-pragma-attr-2.c: New test.
* gcc.target/loongarch/strict_align-pragma-attr-1.c: New test.
* gcc.target/loongarch/strict_align-pragma-attr-2.c: New test.
* gcc.target/loongarch/vector-pragma-attr-1.c: New test.
* gcc.target/loongarch/pragma-push-pop.c: New test.
---
gcc/config/loongarch/loongarch-protos.h | 3 +
gcc/config/loongarch/loongarch-target-attr.cc | 59 +++++++++++++++++++
gcc/config/loongarch/loongarch.cc | 19 +++---
gcc/config/loongarch/loongarch.h | 2 +
gcc/doc/extend.texi | 13 ++++
.../gcc.target/loongarch/arch-func-attr-1.c | 6 +-
.../gcc.target/loongarch/arch-pragma-attr-1.c | 7 +++
.../gcc.target/loongarch/cmodel-func-attr-1.c | 4 ++
.../loongarch/cmodel-pragma-attr-1.c | 7 +++
.../gcc.target/loongarch/lasx-func-attr-1.c | 4 ++
.../gcc.target/loongarch/lasx-pragma-attr-1.c | 7 +++
.../gcc.target/loongarch/lasx-pragma-attr-2.c | 12 ++++
.../gcc.target/loongarch/lsx-func-attr-1.c | 4 ++
.../gcc.target/loongarch/lsx-pragma-attr-1.c | 7 +++
.../gcc.target/loongarch/lsx-pragma-attr-2.c | 12 ++++
.../gcc.target/loongarch/pragma-push-pop.c | 22 +++++++
.../loongarch/strict_align-func-attr-1.c | 4 ++
.../loongarch/strict_align-func-attr-2.c | 4 ++
.../loongarch/strict_align-pragma-attr-1.c | 7 +++
.../loongarch/strict_align-pragma-attr-2.c | 7 +++
.../gcc.target/loongarch/vector-func-attr-1.c | 4 ++
.../loongarch/vector-pragma-attr-1.c | 7 +++
22 files changed, 213 insertions(+), 8 deletions(-)
create mode 100644 gcc/testsuite/gcc.target/loongarch/arch-pragma-attr-1.c
create mode 100644 gcc/testsuite/gcc.target/loongarch/cmodel-pragma-attr-1.c
create mode 100644 gcc/testsuite/gcc.target/loongarch/lasx-pragma-attr-1.c
create mode 100644 gcc/testsuite/gcc.target/loongarch/lasx-pragma-attr-2.c
create mode 100644 gcc/testsuite/gcc.target/loongarch/lsx-pragma-attr-1.c
create mode 100644 gcc/testsuite/gcc.target/loongarch/lsx-pragma-attr-2.c
create mode 100644 gcc/testsuite/gcc.target/loongarch/pragma-push-pop.c
create mode 100644
gcc/testsuite/gcc.target/loongarch/strict_align-pragma-attr-1.c
create mode 100644
gcc/testsuite/gcc.target/loongarch/strict_align-pragma-attr-2.c
create mode 100644 gcc/testsuite/gcc.target/loongarch/vector-pragma-attr-1.c
diff --git a/gcc/config/loongarch/loongarch-protos.h
b/gcc/config/loongarch/loongarch-protos.h
index 531b0bcb636..967f1633ae6 100644
--- a/gcc/config/loongarch/loongarch-protos.h
+++ b/gcc/config/loongarch/loongarch-protos.h
@@ -214,4 +214,7 @@ extern bool loongarch_explicit_relocs_p (enum
loongarch_symbol_type);
extern bool loongarch_symbol_extreme_p (enum loongarch_symbol_type);
extern bool loongarch_option_valid_attribute_p (tree, tree, tree, int);
extern void loongarch_option_override_internal (struct loongarch_target *,
struct gcc_options *, struct gcc_options *);
+extern void loongarch_reset_previous_fndecl (void);
+extern void loongarch_save_restore_target_globals (tree new_tree);
+extern void loongarch_register_pragmas (void);
#endif /* ! GCC_LOONGARCH_PROTOS_H */
diff --git a/gcc/config/loongarch/loongarch-target-attr.cc
b/gcc/config/loongarch/loongarch-target-attr.cc
index 1fafd4c4466..61d5c85c680 100644
--- a/gcc/config/loongarch/loongarch-target-attr.cc
+++ b/gcc/config/loongarch/loongarch-target-attr.cc
@@ -349,6 +349,16 @@ loongarch_option_valid_attribute_p (tree fndecl, tree,
tree args, int)
tree new_target, new_optimize;
tree existing_target = DECL_FUNCTION_SPECIFIC_TARGET (fndecl);
+ /* If what we're processing is the current pragma string then the
+ target option node is already stored in target_option_current_node
+ by loongarch_pragma_target_parse in loongarch-target-attr.cc.
+ Use that to avoid having to re-parse the string. */
+ if (!existing_target && args == current_target_pragma)
+ {
+ DECL_FUNCTION_SPECIFIC_TARGET (fndecl) = target_option_current_node;
+ return true;
+ }
+
tree func_optimize = DECL_FUNCTION_SPECIFIC_OPTIMIZATION (fndecl);
old_optimize
@@ -411,3 +421,52 @@ loongarch_option_valid_attribute_p (tree fndecl, tree,
tree args, int)
TREE_OPTIMIZATION (old_optimize));
return ret;
}
+
+/* Hook to validate the current #pragma GCC target and set the state, and
+ update the macros based on what was changed. If ARGS is NULL, then
+ POP_TARGET is used to reset the options. */
+
+static bool
+loongarch_pragma_target_parse (tree args, tree pop_target)
+{
+ /* If args is not NULL then process it and setup the target-specific
+ information that it specifies. */
+ if (args)
+ {
+ if (!loongarch_process_target_attr (args, NULL))
+ return false;
+
+ loongarch_option_override_internal (&la_target,
+ &global_options,
+ &global_options_set);
+ }
+
+ /* args is NULL, restore to the state described in pop_target. */
+ else
+ {
+ pop_target = pop_target ? pop_target : target_option_default_node;
+ cl_target_option_restore (&global_options, &global_options_set,
+ TREE_TARGET_OPTION (pop_target));
+ }
+
+ target_option_current_node
+ = build_target_option_node (&global_options, &global_options_set);
+
+ loongarch_reset_previous_fndecl ();
+
+ /* If we're popping or reseting make sure to update the globals so that
+ the optab availability predicates get recomputed. */
+ if (pop_target)
+ loongarch_save_restore_target_globals (pop_target);
+
+ return true;
+}
+
+/* Implement REGISTER_TARGET_PRAGMAS. */
+
+void
+loongarch_register_pragmas (void)
+{
+ /* Update pragma hook to allow parsing #pragma GCC target. */
+ targetm.target_option.pragma_parse = loongarch_pragma_target_parse;
+}
diff --git a/gcc/config/loongarch/loongarch.cc
b/gcc/config/loongarch/loongarch.cc
index f3514073cea..5b73e2a9f85 100644
--- a/gcc/config/loongarch/loongarch.cc
+++ b/gcc/config/loongarch/loongarch.cc
@@ -7677,11 +7677,17 @@ loongarch_option_override_internal (struct
loongarch_target *target,
static GTY(()) tree loongarch_previous_fndecl;
+void
+loongarch_reset_previous_fndecl (void)
+{
+ loongarch_previous_fndecl = NULL;
+}
+
/* Restore or save the TREE_TARGET_GLOBALS from or to new_tree.
Used by loongarch_set_current_function to
make sure optab availability predicates are recomputed when necessary. */
-static void
+void
loongarch_save_restore_target_globals (tree new_tree)
{
if (TREE_TARGET_GLOBALS (new_tree))
@@ -7734,13 +7740,12 @@ loongarch_set_current_function (tree fndecl)
loongarch_previous_fndecl = fndecl;
- if (new_tree == old_tree)
- return;
+ if (new_tree != old_tree)
+ /* According to the settings of the functions attribute and pragma,
+ the options is corrected. */
+ cl_target_option_restore (&global_options, &global_options_set,
+ TREE_TARGET_OPTION (new_tree));
- /* According to the settings of the functions attribute and pragma,
- the options is corrected. */
- cl_target_option_restore (&global_options, &global_options_set,
- TREE_TARGET_OPTION (new_tree));
/* After correcting the value of options, we need to update the
rules for using the hardware registers to ensure that the
diff --git a/gcc/config/loongarch/loongarch.h b/gcc/config/loongarch/loongarch.h
index 4ee01618de1..42a38a44efe 100644
--- a/gcc/config/loongarch/loongarch.h
+++ b/gcc/config/loongarch/loongarch.h
@@ -26,6 +26,8 @@ along with GCC; see the file COPYING3. If not see
#define SWITCHABLE_TARGET 1
+#define REGISTER_TARGET_PRAGMAS() loongarch_register_pragmas ()
+
#define TARGET_SUPPORTS_WIDE_INT 1
/* Macros to silence warnings about numbers being signed in traditional
diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index d896677fd3a..d72fa0764f6 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -28413,6 +28413,7 @@ option is specified. @xref{OpenMP}, and @ref{OpenACC}.
@menu
* AArch64 Pragmas::
* ARM Pragmas::
+* LoongArch Pragmas::
* M32C Pragmas::
* PRU Pragmas::
* RS/6000 and PowerPC Pragmas::
@@ -28465,6 +28466,18 @@ Do not affect the @code{long_call} or
@code{short_call} attributes of
subsequent functions.
@end table
+@node LoongArch Pragmas
+@subsection LoongArch Pragmas
+
+The list of attributes supported by Pragma is the same as that of target
+function attributres. @xref{LoongArch Function Attributes}.
+
+Example:
+
+@smallexample
+#pragma GCC target("strict-align")
+@end smallexample
+
@node M32C Pragmas
@subsection M32C Pragmas
diff --git a/gcc/testsuite/gcc.target/loongarch/arch-func-attr-1.c
b/gcc/testsuite/gcc.target/loongarch/arch-func-attr-1.c
index 98cc7e577e3..b8e51e6d9e1 100644
--- a/gcc/testsuite/gcc.target/loongarch/arch-func-attr-1.c
+++ b/gcc/testsuite/gcc.target/loongarch/arch-func-attr-1.c
@@ -1,10 +1,14 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -march=loongarch64 -mno-lsx" } */
+/* { dg-options "-O2 -march=loongarch64 -mno-lsx -std=gnu11" } */
extern char a[64];
extern char b[64];
+#ifndef TEST_TARGET_PRAGMA
__attribute__ ((target ("arch=la64v1.1")))
+#else
+#pragma GCC target ("arch=la64v1.1")
+#endif
void
test (void)
{
diff --git a/gcc/testsuite/gcc.target/loongarch/arch-pragma-attr-1.c
b/gcc/testsuite/gcc.target/loongarch/arch-pragma-attr-1.c
new file mode 100644
index 00000000000..bd918e70926
--- /dev/null
+++ b/gcc/testsuite/gcc.target/loongarch/arch-pragma-attr-1.c
@@ -0,0 +1,7 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=loongarch64 -mno-lsx -std=gnu11" } */
+
+#define TEST_TARGET_PRAGMA 1
+#include "./arch-func-attr-1.c"
+
+/* { dg-final { scan-assembler "vld" } } */
diff --git a/gcc/testsuite/gcc.target/loongarch/cmodel-func-attr-1.c
b/gcc/testsuite/gcc.target/loongarch/cmodel-func-attr-1.c
index 119cd0e1646..9f44dc66bfd 100644
--- a/gcc/testsuite/gcc.target/loongarch/cmodel-func-attr-1.c
+++ b/gcc/testsuite/gcc.target/loongarch/cmodel-func-attr-1.c
@@ -4,7 +4,11 @@
extern char a[8];
extern char b[8];
+#ifndef TEST_TARGET_PRAGMA
__attribute__ ((target ("cmodel=extreme")))
+#else
+#pragma GCC target ("cmodel=extreme")
+#endif
void
test (void)
{
diff --git a/gcc/testsuite/gcc.target/loongarch/cmodel-pragma-attr-1.c
b/gcc/testsuite/gcc.target/loongarch/cmodel-pragma-attr-1.c
new file mode 100644
index 00000000000..b522891487c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/loongarch/cmodel-pragma-attr-1.c
@@ -0,0 +1,7 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mcmodel=normal -mexplicit-relocs=none" } */
+
+#define TEST_TARGET_PRAGMA 1
+#include "./cmodel-func-attr-1.c"
+
+/* { dg-final { scan-assembler "la.global\t\\\$r\[0-9\]+,\\\$r\[0-9\]+,a" } }
*/
diff --git a/gcc/testsuite/gcc.target/loongarch/lasx-func-attr-1.c
b/gcc/testsuite/gcc.target/loongarch/lasx-func-attr-1.c
index 5dad9821f03..720719e80b8 100644
--- a/gcc/testsuite/gcc.target/loongarch/lasx-func-attr-1.c
+++ b/gcc/testsuite/gcc.target/loongarch/lasx-func-attr-1.c
@@ -4,7 +4,11 @@
typedef int v8i32 __attribute__ ((vector_size(32), aligned(32)));
extern v8i32 a, b, c;
+#ifndef TEST_TARGET_PRAGMA
__attribute__ ((target ("lasx")))
+#else
+#pragma GCC target ("lasx")
+#endif
void
test (void)
{
diff --git a/gcc/testsuite/gcc.target/loongarch/lasx-pragma-attr-1.c
b/gcc/testsuite/gcc.target/loongarch/lasx-pragma-attr-1.c
new file mode 100644
index 00000000000..d5bc68f1cb8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/loongarch/lasx-pragma-attr-1.c
@@ -0,0 +1,7 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mno-lsx" } */
+
+#define TEST_TARGET_PRAGMA 1
+#include "./lasx-func-attr-1.c"
+
+/* { dg-final { scan-assembler "xvadd.w" } } */
diff --git a/gcc/testsuite/gcc.target/loongarch/lasx-pragma-attr-2.c
b/gcc/testsuite/gcc.target/loongarch/lasx-pragma-attr-2.c
new file mode 100644
index 00000000000..67e4f7179fa
--- /dev/null
+++ b/gcc/testsuite/gcc.target/loongarch/lasx-pragma-attr-2.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mlasx" } */
+
+typedef int v8i32 __attribute__ ((vector_size(32), aligned(32)));
+extern v8i32 a, b, c;
+
+#pragma GCC target ("no-lasx")
+void
+test (void)
+{
+ a = __builtin_lasx_xvadd_w (b, c); /* { dg-error "built-in function
'__builtin_lasx_xvadd_w' is not enabled" } */
+}
diff --git a/gcc/testsuite/gcc.target/loongarch/lsx-func-attr-1.c
b/gcc/testsuite/gcc.target/loongarch/lsx-func-attr-1.c
index 3e2c1dc3359..3558898d353 100644
--- a/gcc/testsuite/gcc.target/loongarch/lsx-func-attr-1.c
+++ b/gcc/testsuite/gcc.target/loongarch/lsx-func-attr-1.c
@@ -4,7 +4,11 @@
typedef int v4i32 __attribute__ ((vector_size(16), aligned(16)));
extern v4i32 a, b, c;
+#ifndef TEST_TARGET_PRAGMA
__attribute__ ((target ("lsx")))
+#else
+#pragma GCC target ("lsx")
+#endif
void
test (void)
{
diff --git a/gcc/testsuite/gcc.target/loongarch/lsx-pragma-attr-1.c
b/gcc/testsuite/gcc.target/loongarch/lsx-pragma-attr-1.c
new file mode 100644
index 00000000000..c499f18fc42
--- /dev/null
+++ b/gcc/testsuite/gcc.target/loongarch/lsx-pragma-attr-1.c
@@ -0,0 +1,7 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mno-lsx" } */
+
+#define TEST_TARGET_PRAGMA 1
+#include "./lsx-func-attr-1.c"
+
+/* { dg-final { scan-assembler "vadd.w" } } */
diff --git a/gcc/testsuite/gcc.target/loongarch/lsx-pragma-attr-2.c
b/gcc/testsuite/gcc.target/loongarch/lsx-pragma-attr-2.c
new file mode 100644
index 00000000000..40314d026eb
--- /dev/null
+++ b/gcc/testsuite/gcc.target/loongarch/lsx-pragma-attr-2.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mlsx" } */
+
+typedef int v4i32 __attribute__ ((vector_size(16), aligned(16)));
+extern v4i32 a, b, c;
+
+#pragma GCC target ("no-lsx")
+void
+test (void)
+{
+ a = __builtin_lsx_vadd_w (b, c); /* { dg-error "built-in function
'__builtin_lsx_vadd_w' is not enabled" } */
+}
diff --git a/gcc/testsuite/gcc.target/loongarch/pragma-push-pop.c
b/gcc/testsuite/gcc.target/loongarch/pragma-push-pop.c
new file mode 100644
index 00000000000..a2bcdcb10d5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/loongarch/pragma-push-pop.c
@@ -0,0 +1,22 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mlasx" } */
+/* { dg-final { scan-assembler-not "xvadd\\\.w" } } */
+/* { dg-final { scan-assembler "xvsll\\\.w" } } */
+
+#include <lasxintrin.h>
+
+extern v8i32 a, b, c;
+#pragma GCC push_options
+#pragma GCC target ("no-lasx")
+void
+test (void)
+{
+ a = b + c;
+}
+#pragma GCC pop_options
+
+void
+test1 (void)
+{
+ c = __builtin_lasx_xvsll_w (a, b);
+}
diff --git a/gcc/testsuite/gcc.target/loongarch/strict_align-func-attr-1.c
b/gcc/testsuite/gcc.target/loongarch/strict_align-func-attr-1.c
index 04893746de8..c1ed6515ccf 100644
--- a/gcc/testsuite/gcc.target/loongarch/strict_align-func-attr-1.c
+++ b/gcc/testsuite/gcc.target/loongarch/strict_align-func-attr-1.c
@@ -3,7 +3,11 @@
extern char a[8];
extern char b[8];
+#ifndef TEST_TARGET_PRAGMA
__attribute__ ((target ("no-strict-align")))
+#else
+#pragma GCC target ("no-strict-align")
+#endif
void
test (void)
{
diff --git a/gcc/testsuite/gcc.target/loongarch/strict_align-func-attr-2.c
b/gcc/testsuite/gcc.target/loongarch/strict_align-func-attr-2.c
index 0e81486cd53..70bf810037e 100644
--- a/gcc/testsuite/gcc.target/loongarch/strict_align-func-attr-2.c
+++ b/gcc/testsuite/gcc.target/loongarch/strict_align-func-attr-2.c
@@ -3,7 +3,11 @@
extern char a[8];
extern char b[8];
+#ifndef TEST_TARGET_PRAGMA
__attribute__ ((target ("strict-align")))
+#else
+#pragma GCC target ("strict-align")
+#endif
void
test (void)
{
diff --git a/gcc/testsuite/gcc.target/loongarch/strict_align-pragma-attr-1.c
b/gcc/testsuite/gcc.target/loongarch/strict_align-pragma-attr-1.c
new file mode 100644
index 00000000000..a95d0b97282
--- /dev/null
+++ b/gcc/testsuite/gcc.target/loongarch/strict_align-pragma-attr-1.c
@@ -0,0 +1,7 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mstrict-align" } */
+
+#define TEST_TARGET_PRAGMA 1
+#include "./strict_align-func-attr-1.c"
+
+/* { dg-final { scan-assembler-not "ld.bu" } } */
diff --git a/gcc/testsuite/gcc.target/loongarch/strict_align-pragma-attr-2.c
b/gcc/testsuite/gcc.target/loongarch/strict_align-pragma-attr-2.c
new file mode 100644
index 00000000000..93b76c59b6c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/loongarch/strict_align-pragma-attr-2.c
@@ -0,0 +1,7 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mno-strict-align" } */
+
+#define TEST_TARGET_PRAGMA 1
+#include "./strict_align-func-attr-2.c"
+
+/* { dg-final { scan-assembler-not "ld.w" } } */
diff --git a/gcc/testsuite/gcc.target/loongarch/vector-func-attr-1.c
b/gcc/testsuite/gcc.target/loongarch/vector-func-attr-1.c
index 655ca234be0..4e00606b1c6 100644
--- a/gcc/testsuite/gcc.target/loongarch/vector-func-attr-1.c
+++ b/gcc/testsuite/gcc.target/loongarch/vector-func-attr-1.c
@@ -4,7 +4,11 @@
typedef int v4i32 __attribute__ ((vector_size(16), aligned(16)));
extern v4i32 a, b, c;
+#ifndef TEST_TARGET_PRAGMA
__attribute__ ((target ("no-lasx")))
+#else
+#pragma GCC target ("no-lasx")
+#endif
void
test (void)
{
diff --git a/gcc/testsuite/gcc.target/loongarch/vector-pragma-attr-1.c
b/gcc/testsuite/gcc.target/loongarch/vector-pragma-attr-1.c
new file mode 100644
index 00000000000..7bbb1690113
--- /dev/null
+++ b/gcc/testsuite/gcc.target/loongarch/vector-pragma-attr-1.c
@@ -0,0 +1,7 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mlsx" } */
+
+#define TEST_TARGET_PRAGMA 1
+#include "./vector-func-attr-1.c"
+
+/* { dg-final { scan-assembler "vadd.w" } } */
--
2.34.1