[PATCH v3 4/5] openmp, fortran: Add support for map iterators in OpenMP target construct (Fortran)
This patch adds support for iterators in the map clause of OpenMP target constructs. The parsing and translation of iterators in the front-end works the same way as for the affinity and depend clauses, except for putting the iterator into the OMP_CLAUSE_ITERATOR of the clause. The iterator gimplification needed to be modified slightly to handle Fortran. The difference in how ranges work in loops (i.e. the condition on the upper bound is <=, rather than < as in C/C++) needs to be compensated for when calculating the iteration count and in the iteration loop itself. During Fortran translation of iterators, statements for the side-effects of any translated expressions are placed into BLOCK_SUBBLOCKS of the block containing the iterator variables (this also occurs with the other clauses supporting iterators). However, the previous lowering of iterators into Gimple does not appear to do anything with these statements, which causes issues if anything in the loop body references these side-effects (typically calculation of array boundaries and strides). This appears to be a bug that was simply not triggered by existing testcases. These statements are now gimplified into the innermost loop body. The libgomp runtime was modified to handle GOMP_MAP_STRUCTs in iterators, which can result from the use of derived types (which I used in test cases to implement arrays of pointers). libgomp expects a GOMP_MAP_STRUCT map to be followed immediately by a number of maps corresponding to the fields of the struct, so an iterator GOMP_MAP_STRUCT and its fields need to be expanded in a breadth-first order, rather than the usual depth-first manner (which would result in multiple GOMP_MAP_STRUCTS, followed by multiple instances of the first field, then multiples of the second etc.). The presence of variables in the field offset triggers the unwanted creation of GOMP_MAP_STRUCT_UNORD for variable offsets. The offset tree is now walked over and if it only contains iterator variables, then the offset is treated as constant again (which it is, within the context of each iteration of the iterator).From a24aa032c2e23577d4fbc61df6da79345bae8292 Mon Sep 17 00:00:00 2001 From: Kwok Cheung Yeung Date: Fri, 4 Oct 2024 15:16:29 +0100 Subject: [PATCH 4/5] openmp, fortran: Add support for map iterators in OpenMP target construct (Fortran) This adds support for iterators in map clauses within OpenMP 'target' constructs in Fortran. Some special handling for struct field maps has been added to libgomp in order to handle arrays of derived types. 2024-10-04 Kwok Cheung Yeung gcc/fortran/ * dump-parse-tree.cc (show_omp_namelist): Add iterator support for OMP_LIST_MAP. * openmp.cc (gfc_free_omp_clauses): Free namespace in namelist for OMP_LIST_MAP. (gfc_match_omp_clauses): Parse 'iterator' modifier for 'map' clause. (resolve_omp_clauses): Resolve iterators for OMP_LIST_MAP. * trans-openmp.cc (gfc_trans_omp_clauses): Handle iterators in OMP_LIST_MAP clauses. Add expressions to iter_block rather than block. gcc/ * gimplify.cc (compute_iterator_count): Account for difference in loop boundaries in Fortran. (build_iterator_loop): Change upper boundary condition for Fortran. Insert block statements into innermost loop. (contains_only_iterator_vars_1): New. (contains_only_iterator_vars): New. (extract_base_bit_offset): Add iterator argument. Do not set variable_offset if contains_only_iterator_vars is true. (omp_accumulate_sibling_list): Add iterator argument to extract_base_bit_offset. * omp-low.cc (lower_omp_target): Add sorry if iterators used with deep mapping. * tree-pretty-print.cc (dump_block_node): Ignore BLOCK_SUBBLOCKS containing iterator block statements. gcc/testsuite/ * gfortran.dg/gomp/target-map-iterators-1.f90: New. * gfortran.dg/gomp/target-map-iterators-2.f90: New. * gfortran.dg/gomp/target-map-iterators-3.f90: New. libgomp/ * target.c (kind_to_name): Handle GOMP_MAP_STRUCT and GOMP_MAP_STRUCT_UNORD. (gomp_add_map): New. (gomp_merge_iterator_maps): Expand fields of a struct mapping breadth-first. * testsuite/libgomp.fortran/target-map-iterators-1.f90: New. * testsuite/libgomp.fortran/target-map-iterators-2.f90: New. * testsuite/libgomp.fortran/target-map-iterators-3.f90: New. --- gcc/fortran/dump-parse-tree.cc| 9 +- gcc/fortran/openmp.cc | 35 ++-- gcc/fortran/trans-openmp.cc | 71 gcc/gimplify.cc | 76 ++--- gcc/omp-low.cc| 5 ++ .../gomp/target-map-iterators-1.f90 | 26 ++ .../gomp/target-map-iterators-2.f90 | 27
[PATCH v3 5/5] openmp, fortran: Add support for iterators in OpenMP 'target update' constructs (Fortran)
This patch adds parsing and translation of the 'to' and 'from' clauses for the 'target update' construct in Fortran.From da8ab0cb38d2bc347cf902ec417b0397c28e24e2 Mon Sep 17 00:00:00 2001 From: Kwok Cheung Yeung Date: Fri, 4 Oct 2024 15:16:38 +0100 Subject: [PATCH 5/5] openmp, fortran: Add support for iterators in OpenMP 'target update' constructs (Fortran) This adds Fortran support for iterators in 'to' and 'from' clauses in the 'target update' OpenMP directive. 2024-10-04 Kwok Cheung Yeung gcc/fortran/ * dump-parse-tree.cc (show_omp_namelist): Add iterator support for OMP_LIST_TO and OMP_LIST_FROM. * openmp.cc (gfc_free_omp_clauses): Free namespace for OMP_LIST_TO and OMP_LIST_FROM. (gfc_match_motion_var_list): Parse 'iterator' modifier. (resolve_omp_clauses): Resolve iterators for OMP_LIST_TO and OMP_LIST_FROM. * trans-openmp.cc (gfc_trans_omp_clauses): Handle iterators in OMP_LIST_TO and OMP_LIST_FROM clauses. Add expressions to iter_block rather than block. gcc/testsuite/ * gfortran.dg/gomp/target-update-iterators-1.f90: New. * gfortran.dg/gomp/target-update-iterators-2.f90: New. * gfortran.dg/gomp/target-update-iterators-3.f90: New. libgomp/ * testsuite/libgomp.fortran/target-update-iterators-1.f90: New. * testsuite/libgomp.fortran/target-update-iterators-2.f90: New. * testsuite/libgomp.fortran/target-update-iterators-3.f90: New. --- gcc/fortran/dump-parse-tree.cc| 7 +- gcc/fortran/openmp.cc | 62 +-- gcc/fortran/trans-openmp.cc | 50 ++-- .../gomp/target-update-iterators-1.f90| 25 ++ .../gomp/target-update-iterators-2.f90| 22 ++ .../gomp/target-update-iterators-3.f90| 23 ++ .../target-update-iterators-1.f90 | 68 .../target-update-iterators-2.f90 | 63 +++ .../target-update-iterators-3.f90 | 78 +++ 9 files changed, 386 insertions(+), 12 deletions(-) create mode 100644 gcc/testsuite/gfortran.dg/gomp/target-update-iterators-1.f90 create mode 100644 gcc/testsuite/gfortran.dg/gomp/target-update-iterators-2.f90 create mode 100644 gcc/testsuite/gfortran.dg/gomp/target-update-iterators-3.f90 create mode 100644 libgomp/testsuite/libgomp.fortran/target-update-iterators-1.f90 create mode 100644 libgomp/testsuite/libgomp.fortran/target-update-iterators-2.f90 create mode 100644 libgomp/testsuite/libgomp.fortran/target-update-iterators-3.f90 diff --git a/gcc/fortran/dump-parse-tree.cc b/gcc/fortran/dump-parse-tree.cc index 3ee6ed1ea7f..0a2d546d3fe 100644 --- a/gcc/fortran/dump-parse-tree.cc +++ b/gcc/fortran/dump-parse-tree.cc @@ -1360,7 +1360,8 @@ show_omp_namelist (int list_type, gfc_omp_namelist *n) { gfc_current_ns = ns_curr; if (list_type == OMP_LIST_AFFINITY || list_type == OMP_LIST_DEPEND - || list_type == OMP_LIST_MAP) + || list_type == OMP_LIST_MAP + || list_type == OMP_LIST_TO || list_type == OMP_LIST_FROM) { gfc_current_ns = n->u2.ns ? n->u2.ns : ns_curr; if (n->u2.ns != ns_iter) @@ -1376,6 +1377,10 @@ show_omp_namelist (int list_type, gfc_omp_namelist *n) fputs ("DEPEND (", dumpfile); else if (list_type == OMP_LIST_MAP) fputs ("MAP (", dumpfile); + else if (list_type == OMP_LIST_TO) + fputs ("TO (", dumpfile); + else if (list_type == OMP_LIST_FROM) + fputs ("FROM (", dumpfile); else gcc_unreachable (); } diff --git a/gcc/fortran/openmp.cc b/gcc/fortran/openmp.cc index 3003ba605cf..c765d5814a7 100644 --- a/gcc/fortran/openmp.cc +++ b/gcc/fortran/openmp.cc @@ -194,7 +194,8 @@ gfc_free_omp_clauses (gfc_omp_clauses *c) for (i = 0; i < OMP_LIST_NUM; i++) gfc_free_omp_namelist (c->lists[i], i == OMP_LIST_AFFINITY || i == OMP_LIST_DEPEND - || i == OMP_LIST_MAP, + || i == OMP_LIST_MAP + || i == OMP_LIST_TO || i == OMP_LIST_FROM, i == OMP_LIST_ALLOCATE, i == OMP_LIST_USES_ALLOCATORS, i == OMP_LIST_INIT); @@ -1368,17 +1369,65 @@ gfc_match_motion_var_list (const char *str, gfc_omp_namelist **list, if (m != MATCH_YES) return m; - match m_present = gfc_match (" present : "); + gfc_namespace *ns_iter = NULL, *ns_curr = gfc_current_ns; + int present_modifier = 0, iterator_modifier = 0; + locus present_locus = gfc_current_locus, iterator_locus = gfc_current_locus; - m = gfc_match_omp_variable_list ("", list, false, NULL, h
[Patch] OpenMP: Allocate directive for static vars, clean up
'omp allocate' permits to use a different (specified) allocator and alignment for both stack/automatic and static/saved variables; the latter takes only predefined allocators. Currently, only C and Fortran are support for stack/automatic variables; static variables are rejected before the attached patch. (For them, only predefined allocators are permitted.) * * * I happened to look at the 'allocate' directive recently and, doing so, I stumbled over a couple of issues, which the attached patch addresses (missing diagnostics for corner cases, not updated checks, unhelpful documentation ['allocate' *clause*], ...). Doing so, I wondered whether: Shouldn't we just accept 'omp allocate' for static variables by just honoring the aligning and ignoring the actually requested allocator? - First, we do already the same for actual allocations as not all traits are supported. And for the host this seems to be the most sensible to do in any case. [For some use cases, pointers + allocation in the constructor would be better, but in general, not adding an indirection seems to be better and has fewer corner-case usability issue.] I guess we later want to honor the requested memory for nvptx and/or gcn; at least Nvidia GPUs could make use for constant memory (having advantages for reading the same memory by many threads/broadcasting it). I guess OpenACC 2.7's 'readonly' modifier serves a similar purpose. For now we don't, but the attribute is passed on to the backends, which could make use of them, if desired. ('groupprivate' directive vs. cgroup/thread allocators are similar device-only features.) As mentioned, this patch also fixes a few other issues here and there, see commit log and source code for details. Code comments? Suggestions or remarks? - Before I apply this patch? Tobias PS: I am aware that C++ support is lacking. There is a pending patch that needs to be updated for this patch, probably some bitrotting, and in particular for the review comments, cf. https://gcc.gnu.org/pipermail/gcc-patches/2023-October/633782.html and https://gcc.gnu.org/pipermail/gcc-patches/2023-December/639929.html OpenMP: Allocate directive for static vars, clean up For the 'allocate' directive, remove the sorry for static variables and just keep using normal memory, but honor the requested alignment and set a DECL_ATTRIBUTE in case a target may want to make use of this later on. The documentation is updated accordingly. The C diagnostic to check for predefined allocators in this case failed to accept GCC's ompx_gnu_... allocator, now fixed. (Fortran was already okay; but both now use new common #defined value for checking.) And while Fortran common block variables are still rejected, the check has been improved as before the sorry diagnostic did not work for common blocks in modules. Finally, for 'allocate' clause on the target/task/taskloop directives, there is now a warning for omp_thread_mem_alloc (i.e. predefined allocator with access = thread), which is undefined behavior according to the OpenMP specification. And, last, testing showed that var decl + static_assert sets TREE_USED but does not produce a statement list in C, which did run into an assert in gimplify. This special case is now also handled. gcc/c/ChangeLog: * c-parser.cc (c_parser_omp_allocate): Set alignment for alignof; accept static variables and fix predef allocator check. gcc/fortran/ChangeLog: * openmp.cc (is_predefined_allocator): Use gomp-constants.h consts. * trans-common.cc (translate_common): Reject OpenMP allocate directives. * trans-decl.cc (gfc_finish_var_decl): Handle allocate directive for static variables. (gfc_trans_deferred_vars): Update for the latter. gcc/ChangeLog: * gimplify.cc (gimplify_bind_expr): Fix corner case for OpenMP allocate directive. (gimplify_scan_omp_clauses): Warn if omp_thread_mem_alloc is used as allocator with the target/task/taskloop directive. include/ChangeLog: * gomp-constants.h (GOMP_OMP_PREDEF_ALLOC_MAX, GOMP_OMPX_PREDEF_ALLOC_MIN, GOMP_OMPX_PREDEF_ALLOC_MAX, GOMP_OMP_PREDEF_ALLOC_THREADS): New defines. libgomp/ChangeLog: * allocator.c: Add static asserts for news GOMP_OMP{,X}_PREDEF_ALLOC_{MIN,MAX} range values. * libgomp.texi (OpenMP Impl. Status): Allocate directive for static vars is now supported. Refer to PR for allocate clause. (Memory allocation): Update for static vars; minor word tweaking. gcc/testsuite/ChangeLog: * c-c++-common/gomp/allocate-9.c: Update for removed sorry. * gfortran.dg/gomp/allocate-15.f90: Likewise. * gfortran.dg/gomp/allocate-pinned-1.f90: Likewise. * gfortran.dg/gomp/allocate-4.f90: Likewise; add dg-error for previously missing diagnostic. * c-c++-common/gomp/allocate-18.c: New test. * c-c++-common/gomp/allocate-19.c: New test. * gfortran.dg/gomp/allocate-clause.f90: New test. * gfortran.dg/gomp/allocate-static-2.f90: New test. * gfortran.dg/gomp/allocate-static.f90: New test. gcc/c/c-parser.cc | 29