]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
RISC-V: Pragma target [PR115325].
authorRobin Dapp <rdapp@ventanamicro.com>
Fri, 5 Dec 2025 09:55:18 +0000 (10:55 +0100)
committerRobin Dapp <rdapp@ventanamicro.com>
Tue, 9 Dec 2025 08:36:03 +0000 (09:36 +0100)
This implements #pragma GCC target () for riscv.

All the functionality was already there so we only need to wrap existing
functions.

PR target/115325

gcc/ChangeLog:

* config/riscv/riscv-c.cc (riscv_pragma_target_parse): New
function.
(riscv_register_pragmas): Register riscv_pragma_target_parse.
* config/riscv/riscv-protos.h (riscv_process_target_attr_for_pragma):
Declare.
(riscv_reset_previous_fndecl): Ditto.
* config/riscv/riscv-target-attr.cc (riscv_process_target_attr_for_pragma):
New function.
* config/riscv/riscv.cc (riscv_reset_previous_fndecl): Reset.
(riscv_option_save): New function.
(riscv_option_print): Ditto.
(riscv_get_interrupt_type): Adjust docs.
(TARGET_OPTION_SAVE): Implement.
(TARGET_OPTION_PRINT): Ditto.
* doc/extend.texi: Document that riscv can do target pragams.

gcc/testsuite/ChangeLog:

* gcc.target/riscv/pragma-target-1.c: New test.
* gcc.target/riscv/pragma-target-2.c: New test.

gcc/config/riscv/riscv-c.cc
gcc/config/riscv/riscv-protos.h
gcc/config/riscv/riscv-target-attr.cc
gcc/config/riscv/riscv.cc
gcc/doc/extend.texi
gcc/testsuite/gcc.target/riscv/pragma-target-1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/riscv/pragma-target-2.c [new file with mode: 0644]

index 4fc05281782458495103aa923b235b0898ac3431..24537d547cfd25e962f38b6d43036afbc7b6df39 100644 (file)
@@ -213,6 +213,49 @@ riscv_pragma_intrinsic (cpp_reader *)
     error ("unknown %<#pragma riscv intrinsic%> option %qs", name);
 }
 
+/* Implement TARGETM.TARGET_OPTION.PRAGMA_PARSE.  */
+
+static bool
+riscv_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 (!riscv_process_target_attr_for_pragma (args))
+       return false;
+
+      riscv_override_options_internal (&global_options);
+    }
+  /* 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);
+
+  riscv_reset_previous_fndecl ();
+
+  /* For the definitions, ensure all newly defined macros are considered
+     as used for -Wunused-macros.  There is no point warning about the
+     compiler predefined macros.  */
+  cpp_options *cpp_opts = cpp_get_options (parse_in);
+  unsigned char saved_warn_unused_macros = cpp_opts->warn_unused_macros;
+  cpp_opts->warn_unused_macros = 0;
+
+  cpp_force_token_locations (parse_in, BUILTINS_LOCATION);
+  riscv_cpu_cpp_builtins (parse_in);
+  cpp_stop_forcing_token_locations (parse_in);
+
+  cpp_opts->warn_unused_macros = saved_warn_unused_macros;
+
+  return true;
+}
+
 /* Implement TARGET_CHECK_BUILTIN_CALL.  */
 static bool
 riscv_check_builtin_call (location_t loc, vec<location_t> arg_loc, tree fndecl,
@@ -272,5 +315,6 @@ riscv_register_pragmas (void)
 {
   targetm.resolve_overloaded_builtin = riscv_resolve_overloaded_builtin;
   targetm.check_builtin_call = riscv_check_builtin_call;
+  targetm.target_option.pragma_parse = riscv_pragma_target_parse;
   c_register_pragma ("riscv", "intrinsic", riscv_pragma_intrinsic);
 }
index 817f2d7be4ab6e20870aa365681803c6078511f1..abf9df77891fa8c7675f00fe59d62fb140853eb6 100644 (file)
@@ -849,12 +849,15 @@ riscv_option_valid_attribute_p (tree, tree, tree, int);
 extern bool
 riscv_option_valid_version_attribute_p (tree, tree, tree, int);
 extern bool
+riscv_process_target_attr_for_pragma (tree);
+extern bool
 riscv_process_target_version_attr (tree, location_t *);
 extern bool
 riscv_process_target_version_str (string_slice, location_t *);
 extern void
 riscv_override_options_internal (struct gcc_options *);
 extern void riscv_option_override (void);
+extern void riscv_reset_previous_fndecl (void);
 extern rtx riscv_prefetch_cookie (rtx, rtx);
 extern bool riscv_prefetch_offset_address_p (rtx, machine_mode);
 
index 94f0a296e305cd39e0dc45ce37aa975bf5061cc1..e6ea073acc14c148dcc458f8dd3fcd88bbad277c 100644 (file)
@@ -489,6 +489,17 @@ riscv_option_valid_attribute_p (tree fndecl, tree, tree args, int)
   return ret;
 }
 
+/* Public wrapper for pragma processing.
+   Parse ARGS (a TREE_LIST of target attributes) and update global_options.
+   This is used by #pragma GCC target.  */
+
+bool
+riscv_process_target_attr_for_pragma (tree args)
+{
+  location_t loc = UNKNOWN_LOCATION;
+  return riscv_process_target_attr (args, &loc, riscv_target_attrs);
+}
+
 /* Parse the tree in ARGS that contains the target_version attribute
    information and update the global target options space.  If LOC is nonnull,
    report diagnostics against *LOC, otherwise remain silent.  */
index 7b6a29d9f89642e0d2bc70116ab4f7a9b4b2d29e..223344a2533afdb7bb0676786324783f816c6067 100644 (file)
@@ -12462,6 +12462,39 @@ riscv_option_restore (struct gcc_options *opts,
 
 static GTY (()) tree riscv_previous_fndecl;
 
+/* Reset the previous function declaration.  */
+
+void
+riscv_reset_previous_fndecl (void)
+{
+  riscv_previous_fndecl = NULL;
+}
+
+/* Implement TARGET_OPTION_SAVE.  */
+
+static void
+riscv_option_save (struct cl_target_option *ptr,
+                  struct gcc_options *opts,
+                  struct gcc_options * /* opts_set */)
+{
+  ptr->x_riscv_arch_string = opts->x_riscv_arch_string;
+  ptr->x_riscv_tune_string = opts->x_riscv_tune_string;
+  ptr->x_riscv_cpu_string = opts->x_riscv_cpu_string;
+}
+
+/* Implement TARGET_OPTION_PRINT.  */
+
+static void
+riscv_option_print (FILE *file, int indent, struct cl_target_option *ptr)
+{
+  fprintf (file, "%*sarch = %s\n", indent, "",
+          ptr->x_riscv_arch_string ? ptr->x_riscv_arch_string : "default");
+  fprintf (file, "%*stune = %s\n", indent, "",
+          ptr->x_riscv_tune_string ? ptr->x_riscv_tune_string : "default");
+  if (ptr->x_riscv_cpu_string)
+    fprintf (file, "%*scpu = %s\n", indent, "", ptr->x_riscv_cpu_string);
+}
+
 /* Implement TARGET_CONDITIONAL_REGISTER_USAGE.  */
 
 static void
@@ -12798,7 +12831,7 @@ riscv_get_interrupt_type (tree decl)
 /* Implement `TARGET_SET_CURRENT_FUNCTION'.  Unpack the codegen decisions
    like tuning and ISA features from the DECL_FUNCTION_SPECIFIC_TARGET
    of the function, if such exists.  This function may be called multiple
-   times on a single function so use aarch64_previous_fndecl to avoid
+   times on a single function so use riscv_previous_fndecl to avoid
    setting up identical state.  */
 
 /* Sanity checking for above function attributes.  */
@@ -16309,9 +16342,15 @@ riscv_prefetch_offset_address_p (rtx x, machine_mode mode)
 #undef TARGET_OPTION_OVERRIDE
 #define TARGET_OPTION_OVERRIDE riscv_option_override
 
+#undef TARGET_OPTION_SAVE
+#define TARGET_OPTION_SAVE riscv_option_save
+
 #undef TARGET_OPTION_RESTORE
 #define TARGET_OPTION_RESTORE riscv_option_restore
 
+#undef TARGET_OPTION_PRINT
+#define TARGET_OPTION_PRINT riscv_option_print
+
 #undef TARGET_OPTION_VALID_ATTRIBUTE_P
 #define TARGET_OPTION_VALID_ATTRIBUTE_P riscv_option_valid_attribute_p
 
index 11f6b02db366e59b483b76725d2849fc03185bdd..916452a932d72be303c32640d5df8f58fb801f9f 100644 (file)
@@ -10722,7 +10722,7 @@ for more information about the @code{target} attribute and the attribute
 syntax.
 
 The @code{#pragma GCC target} pragma is presently implemented for
-x86, ARM, AArch64, PowerPC, and S/390 targets only.
+x86, ARM, AArch64, PowerPC, RISC-V, and S/390 targets only.
 
 @cindex pragma GCC optimize
 @item #pragma GCC optimize (@var{string}, @dots{})
diff --git a/gcc/testsuite/gcc.target/riscv/pragma-target-1.c b/gcc/testsuite/gcc.target/riscv/pragma-target-1.c
new file mode 100644 (file)
index 0000000..d1a0600
--- /dev/null
@@ -0,0 +1,59 @@
+/* Test for #pragma GCC target and push/pop options support in RISC-V */
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gc -mabi=lp64d -O2" } */
+
+/* Default compilation options - no vector */
+void default_func(void) {
+#ifdef __riscv_vector
+  __builtin_abort();  /* Should not have vector by default */
+#endif
+}
+
+/* Change target to enable vector */
+#pragma GCC push_options
+#pragma GCC target("arch=rv64gcv")
+void vector_func(void) {
+#ifndef __riscv_vector
+  __builtin_abort();  /* Should have vector here */
+#endif
+}
+#pragma GCC pop_options
+
+/* Back to default - no vector */
+void after_pop_func(void) {
+#ifdef __riscv_vector
+  __builtin_abort();  /* Should not have vector after pop */
+#endif
+}
+
+/* Test multiple push/pop levels */
+#pragma GCC push_options
+#pragma GCC target("arch=rv64gc")
+void base_func(void) {
+#ifdef __riscv_vector
+  __builtin_abort();  /* Should not have vector */
+#endif
+}
+
+#pragma GCC push_options
+#pragma GCC target("arch=rv64gcv")
+void nested_vector_func(void) {
+#ifndef __riscv_vector
+  __builtin_abort();  /* Should have vector here */
+#endif
+}
+#pragma GCC pop_options
+
+void after_nested_pop_func(void) {
+#ifdef __riscv_vector
+  __builtin_abort();  /* Should not have vector after nested pop */
+#endif
+}
+#pragma GCC pop_options
+
+/* Final function should be back to original default */
+void final_func(void) {
+#ifdef __riscv_vector
+  __builtin_abort();  /* Should not have vector */
+#endif
+}
diff --git a/gcc/testsuite/gcc.target/riscv/pragma-target-2.c b/gcc/testsuite/gcc.target/riscv/pragma-target-2.c
new file mode 100644 (file)
index 0000000..077bcdd
--- /dev/null
@@ -0,0 +1,26 @@
+/* Test for #pragma GCC target with tune parameter */
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gc -mabi=lp64d -mtune=rocket -O2" } */
+
+void default_tune(void) {
+  /* Default tune is rocket */
+}
+
+#pragma GCC push_options
+#pragma GCC target("tune=sifive-7-series")
+void sifive_tune(void) {
+  /* Tune should be sifive-7-series */
+}
+#pragma GCC pop_options
+
+void back_to_rocket(void) {
+  /* Tune should be back to rocket */
+}
+
+#pragma GCC target("arch=rv64gcv;tune=generic")
+void combined_options(void) {
+#ifndef __riscv_vector
+  __builtin_abort();  /* Should have vector */
+#endif
+  /* Tune should be generic */
+}