From: Robin Dapp Date: Fri, 5 Dec 2025 09:55:18 +0000 (+0100) Subject: RISC-V: Pragma target [PR115325]. X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c139a4c91829373e77dedf8bb62f9e4361fc56ab;p=thirdparty%2Fgcc.git RISC-V: Pragma target [PR115325]. 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. --- diff --git a/gcc/config/riscv/riscv-c.cc b/gcc/config/riscv/riscv-c.cc index 4fc05281782..24537d547cf 100644 --- a/gcc/config/riscv/riscv-c.cc +++ b/gcc/config/riscv/riscv-c.cc @@ -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 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); } diff --git a/gcc/config/riscv/riscv-protos.h b/gcc/config/riscv/riscv-protos.h index 817f2d7be4a..abf9df77891 100644 --- a/gcc/config/riscv/riscv-protos.h +++ b/gcc/config/riscv/riscv-protos.h @@ -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); diff --git a/gcc/config/riscv/riscv-target-attr.cc b/gcc/config/riscv/riscv-target-attr.cc index 94f0a296e30..e6ea073acc1 100644 --- a/gcc/config/riscv/riscv-target-attr.cc +++ b/gcc/config/riscv/riscv-target-attr.cc @@ -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. */ diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc index 7b6a29d9f89..223344a2533 100644 --- a/gcc/config/riscv/riscv.cc +++ b/gcc/config/riscv/riscv.cc @@ -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 diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi index 11f6b02db36..916452a932d 100644 --- a/gcc/doc/extend.texi +++ b/gcc/doc/extend.texi @@ -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 index 00000000000..d1a06001557 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/pragma-target-1.c @@ -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 index 00000000000..077bcdd280c --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/pragma-target-2.c @@ -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 */ +}