aboutsummaryrefslogtreecommitdiff
path: root/gcc/omp-general.cc
diff options
context:
space:
mode:
authorSandra Loosemore <sandra@codesourcery.com>2023-08-24 17:35:00 +0000
committerSandra Loosemore <sandra@codesourcery.com>2023-08-25 19:42:50 +0000
commit143151ac2013c22e471dd674d02c7dec0798d3bd (patch)
treeb958fa3c3789eccc89afb62055e3f2d94e522a98 /gcc/omp-general.cc
parenta62c8324e7e31ae6614f549bdf9d8a653233f8fc (diff)
downloadgcc-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.cc134
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"