[PATCH v3 4/5] openmp, fortran: Add support for map iterators in OpenMP target construct (Fortran)

2024-10-04 Thread Kwok Cheung Yeung
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)

2024-10-04 Thread Kwok Cheung Yeung
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

2024-10-04 Thread Tobias Burnus

'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