diff options
author | Sandra Loosemore <sandra@codesourcery.com> | 2023-08-24 17:35:00 +0000 |
---|---|---|
committer | Sandra Loosemore <sandra@codesourcery.com> | 2023-08-25 19:42:50 +0000 |
commit | 143151ac2013c22e471dd674d02c7dec0798d3bd (patch) | |
tree | b958fa3c3789eccc89afb62055e3f2d94e522a98 /gcc/omp-general.cc | |
parent | a62c8324e7e31ae6614f549bdf9d8a653233f8fc (diff) | |
download | gcc-143151ac2013c22e471dd674d02c7dec0798d3bd.zip gcc-143151ac2013c22e471dd674d02c7dec0798d3bd.tar.gz gcc-143151ac2013c22e471dd674d02c7dec0798d3bd.tar.bz2 |
OpenMP: C front end support for imperfectly-nested loops
OpenMP 5.0 removed the restriction that multiple collapsed loops must
be perfectly nested, allowing "intervening code" (including nested
BLOCKs) before or after each nested loop. In GCC this code is moved
into the inner loop body by the respective front ends.
This patch changes the C front end to use recursive descent parsing
on nested loops within an "omp for" construct, rather than an iterative
approach, in order to preserve proper nesting of compound statements.
New common C/C++ testcases are in a separate patch.
gcc/c-family/ChangeLog
* c-common.h (c_omp_check_loop_binding_exprs): Declare.
* c-omp.cc: Include tree-iterator.h.
(find_binding_in_body): New.
(check_loop_binding_expr_r): New.
(LOCATION_OR): New.
(check_looop_binding_expr): New.
(c_omp_check_loop_binding_exprs): New.
gcc/c/ChangeLog
* c-parser.cc (struct c_parser): Add omp_for_parse_state field.
(struct omp_for_parse_data): New.
(check_omp_intervening_code): New.
(add_structured_block_stmt): New.
(c_parser_compound_statement_nostart): Recognize intervening code,
nested loops, and other things that need special handling in
OpenMP loop constructs.
(c_parser_while_statement): Error on loop in intervening code.
(c_parser_do_statement): Likewise.
(c_parser_for_statement): Likewise.
(c_parser_postfix_expression_after_primary): Error on calls to
the OpenMP runtime in intervening code.
(c_parser_pragma): Error on OpenMP pragmas in intervening code.
(c_parser_omp_loop_nest): New.
(c_parser_omp_for_loop): Rewrite to use recursive descent, calling
c_parser_omp_loop_nest to do the heavy lifting.
gcc/ChangeLog
* omp-api.h: New.
* omp-general.cc (omp_runtime_api_procname): New.
(omp_runtime_api_call): Moved here from omp-low.cc, and make
non-static.
* omp-general.h: Include omp-api.h.
* omp-low.cc (omp_runtime_api_call): Delete this copy.
gcc/testsuite/ChangeLog
* c-c++-common/goacc/collapse-1.c: Update for new C error behavior.
* c-c++-common/goacc/tile-2.c: Likewise.
* gcc.dg/gomp/collapse-1.c: Likewise.
Diffstat (limited to 'gcc/omp-general.cc')
-rw-r--r-- | gcc/omp-general.cc | 134 |
1 files changed, 134 insertions, 0 deletions
diff --git a/gcc/omp-general.cc b/gcc/omp-general.cc index eefdcb5..1e31014 100644 --- a/gcc/omp-general.cc +++ b/gcc/omp-general.cc @@ -3013,4 +3013,138 @@ omp_build_component_ref (tree obj, tree field) return ret; } +/* Return true if NAME is the name of an omp_* runtime API call. */ +bool +omp_runtime_api_procname (const char *name) +{ + if (!startswith (name, "omp_")) + return false; + + static const char *omp_runtime_apis[] = + { + /* This array has 3 sections. First omp_* calls that don't + have any suffixes. */ + "aligned_alloc", + "aligned_calloc", + "alloc", + "calloc", + "free", + "get_mapped_ptr", + "realloc", + "target_alloc", + "target_associate_ptr", + "target_disassociate_ptr", + "target_free", + "target_is_accessible", + "target_is_present", + "target_memcpy", + "target_memcpy_async", + "target_memcpy_rect", + "target_memcpy_rect_async", + NULL, + /* Now omp_* calls that are available as omp_* and omp_*_; however, the + DECL_NAME is always omp_* without tailing underscore. */ + "capture_affinity", + "destroy_allocator", + "destroy_lock", + "destroy_nest_lock", + "display_affinity", + "fulfill_event", + "get_active_level", + "get_affinity_format", + "get_cancellation", + "get_default_allocator", + "get_default_device", + "get_device_num", + "get_dynamic", + "get_initial_device", + "get_level", + "get_max_active_levels", + "get_max_task_priority", + "get_max_teams", + "get_max_threads", + "get_nested", + "get_num_devices", + "get_num_places", + "get_num_procs", + "get_num_teams", + "get_num_threads", + "get_partition_num_places", + "get_place_num", + "get_proc_bind", + "get_supported_active_levels", + "get_team_num", + "get_teams_thread_limit", + "get_thread_limit", + "get_thread_num", + "get_wtick", + "get_wtime", + "in_explicit_task", + "in_final", + "in_parallel", + "init_lock", + "init_nest_lock", + "is_initial_device", + "pause_resource", + "pause_resource_all", + "set_affinity_format", + "set_default_allocator", + "set_lock", + "set_nest_lock", + "test_lock", + "test_nest_lock", + "unset_lock", + "unset_nest_lock", + NULL, + /* And finally calls available as omp_*, omp_*_ and omp_*_8_; however, + as DECL_NAME only omp_* and omp_*_8 appear. */ + "display_env", + "get_ancestor_thread_num", + "init_allocator", + "get_partition_place_nums", + "get_place_num_procs", + "get_place_proc_ids", + "get_schedule", + "get_team_size", + "set_default_device", + "set_dynamic", + "set_max_active_levels", + "set_nested", + "set_num_teams", + "set_num_threads", + "set_schedule", + "set_teams_thread_limit" + }; + + int mode = 0; + for (unsigned i = 0; i < ARRAY_SIZE (omp_runtime_apis); i++) + { + if (omp_runtime_apis[i] == NULL) + { + mode++; + continue; + } + size_t len = strlen (omp_runtime_apis[i]); + if (strncmp (name + 4, omp_runtime_apis[i], len) == 0 + && (name[4 + len] == '\0' + || (mode > 1 && strcmp (name + 4 + len, "_8") == 0))) + return true; + } + return false; +} + +/* Return true if FNDECL is an omp_* runtime API call. */ + +bool +omp_runtime_api_call (const_tree fndecl) +{ + tree declname = DECL_NAME (fndecl); + if (!declname + || (DECL_CONTEXT (fndecl) != NULL_TREE + && TREE_CODE (DECL_CONTEXT (fndecl)) != TRANSLATION_UNIT_DECL) + || !TREE_PUBLIC (fndecl)) + return false; + return omp_runtime_api_procname (IDENTIFIER_POINTER (declname)); +} + #include "gt-omp-general.h" |