]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
LoongArch: Implement target pragma.
authorLulu Cheng <chenglulu@loongson.cn>
Tue, 7 Jan 2025 04:00:12 +0000 (12:00 +0800)
committerLulu Cheng <chenglulu@loongson.cn>
Tue, 21 Jan 2025 09:36:41 +0000 (17:36 +0800)
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.

22 files changed:
gcc/config/loongarch/loongarch-protos.h
gcc/config/loongarch/loongarch-target-attr.cc
gcc/config/loongarch/loongarch.cc
gcc/config/loongarch/loongarch.h
gcc/doc/extend.texi
gcc/testsuite/gcc.target/loongarch/arch-func-attr-1.c
gcc/testsuite/gcc.target/loongarch/arch-pragma-attr-1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/loongarch/cmodel-func-attr-1.c
gcc/testsuite/gcc.target/loongarch/cmodel-pragma-attr-1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/loongarch/lasx-func-attr-1.c
gcc/testsuite/gcc.target/loongarch/lasx-pragma-attr-1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/loongarch/lasx-pragma-attr-2.c [new file with mode: 0644]
gcc/testsuite/gcc.target/loongarch/lsx-func-attr-1.c
gcc/testsuite/gcc.target/loongarch/lsx-pragma-attr-1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/loongarch/lsx-pragma-attr-2.c [new file with mode: 0644]
gcc/testsuite/gcc.target/loongarch/pragma-push-pop.c [new file with mode: 0644]
gcc/testsuite/gcc.target/loongarch/strict_align-func-attr-1.c
gcc/testsuite/gcc.target/loongarch/strict_align-func-attr-2.c
gcc/testsuite/gcc.target/loongarch/strict_align-pragma-attr-1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/loongarch/strict_align-pragma-attr-2.c [new file with mode: 0644]
gcc/testsuite/gcc.target/loongarch/vector-func-attr-1.c
gcc/testsuite/gcc.target/loongarch/vector-pragma-attr-1.c [new file with mode: 0644]

index dba52beac00afafe52bc9ed921f52934550067a6..b99f949a004ef25d4befe7f9fe2964e872004f38 100644 (file)
@@ -216,4 +216,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 */
index 6bb1e6b753cb8638fa6dc435a838620c416e8a38..cee7031ca1e76addfa31c8b163eade4fc6620323 100644 (file)
@@ -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;
+}
index ee44d9dd7fa0e1b09d621beaf7cf3d796e9671e6..e9978370e8c956474cc1b5ddded852d4ae1e59af 100644 (file)
@@ -7751,11 +7751,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))
@@ -7808,13 +7814,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
index 4ee01618de1f96a06cb88f9d9f22bec2564d53ac..42a38a44efeb81d617afb918c93ca39dbebfa834 100644 (file)
@@ -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
index c711f017df5cc4d64fc06448d3681b969cbe8853..2764597a479b3412d795a0ea555decf4ecd75009 100644 (file)
@@ -28457,6 +28457,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::
@@ -28509,6 +28510,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
 
index 98cc7e577e324c0cc4d320abb6607f082d43c5f4..b8e51e6d9e1989bf670dd3cae410984337570afe 100644 (file)
@@ -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 (file)
index 0000000..bd918e7
--- /dev/null
@@ -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" } } */
index 119cd0e16468ce41c746819bfd5140adfb66a14b..9f44dc66bfd958a8f24c146e845dd6e83e71b163 100644 (file)
@@ -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 (file)
index 0000000..b522891
--- /dev/null
@@ -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" } } */
index 5dad9821f03cb945910a7069c46a99bdbd2dbf2e..720719e80b8d349cc9721285874441c97a27a089 100644 (file)
@@ -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 (file)
index 0000000..d5bc68f
--- /dev/null
@@ -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 (file)
index 0000000..67e4f71
--- /dev/null
@@ -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" } */
+}
index 3e2c1dc3359793919adf0ed3efb1ec581f31f7c3..3558898d3536651fd1310bcce60203cba66b4c1e 100644 (file)
@@ -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 (file)
index 0000000..c499f18
--- /dev/null
@@ -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 (file)
index 0000000..40314d0
--- /dev/null
@@ -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 (file)
index 0000000..a2bcdcb
--- /dev/null
@@ -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);
+}
index 04893746de8cbc9709233f4a3d1e2ceac1d538a1..c1ed6515ccfc361162c479d578750836bfc5c7d9 100644 (file)
@@ -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)
 {
index 0e81486cd53588d0a03adb242c98abffb9be855e..70bf810037e68608c56620990e994b2fb30d9dd4 100644 (file)
@@ -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 (file)
index 0000000..a95d0b9
--- /dev/null
@@ -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 (file)
index 0000000..93b76c5
--- /dev/null
@@ -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" } } */
index 655ca234be08849c9ae471acf93602c3819b053e..4e00606b1c61b50d3362eb24c2f4620651972902 100644 (file)
@@ -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 (file)
index 0000000..7bbb169
--- /dev/null
@@ -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" } } */