Re: [Patch, fortran] PR37336 (Finalization) - [F03] Finish derived-type finalization

2022-02-18 Thread Paul Richard Thomas via Fortran
Hi Harald and Thomas,

Thank you for your contributions to understanding the interpretation by
different vendors of the F2018 requirements for finalization. While it does
appear to be rather chaotic, the differences are down to a small number of
"features" of each compiler.

Before describing my interpretation of the behaviour of the offerings from
other vendors, I should remark briefly about where I am with gfortran. I
now have a patch that handles derived types correctly according to F2018
7.5.6.2 and 7.5.6.3, modulo the ambiguous requirement for the handling of
parent components that I will come to when discussing ifort. I have a patch
ready to fix this, should Intel's interpretation be correct. I have not
moved on to class finalization yet because there are memory leaks connected
with finalization of function results that I have yet to pin down. Also,
finalization of function results within array and structure constructors is
yet to come. Once I have it all working, I will break up the patch into a
number of stages to make it more digestible for review. However, just in
case I fall under the proverbial bus, I have attached the patch for
reference.

Turning to the results from the other vendors:

Cray: Seemingly, the only difference in interpretation concerns the
finalization of structure constructors. 7.5.6.3 paragraphs 5 and 6 only
mention function results. Having scoured the standard for guidance, I have
only found Note 7.57: "name(...) ...snip... is interpreted as a structure
constructor only if it cannot be interpreted as a generic function
reference." From this, I take it that a structure constructor is distinct
from a function reference and, since not mentioned in 7.5.6.3, the result
should not be finalized.

nagfor 7.1: The NAG offering seems to be a bit inconsistent in the
finalization of function results. It is missing in assignment 4 and suffers
a surfeit in assignment 5. The two extras in assignment 5 seem to be
mangled. As far as I can tell, these are problems of implementation rather
than interpretation.

ifort: In all the versions tested, assignment 1 generates, contrary to the
standard, a finalization of an unallocated allocated 'var'. The other
difference from gfortran with the patch applied is in the finalization of
the parent component in the finalization of arrays of extended types. ifort
makes use of the scalar finalizer, whereas all the other compilers use the
array finalizer. In fairness to the folk at Intel, I think that there is an
ambiguity in 7.5.6.2 -

"(2) All finalizable components that appear in the type definition are
finalized in a processor-dependent order. If the entity being finalized is
an array, each finalizable component of each element of that entity is
finalized separately.
(3) If the entity is of extended type and the parent type is finalizable,
the parent component is finalized."

The separate mention of the parent component in (3) rather than in (2)
saying, "..each finalizable component, including the parent component,..."
implies that it is in some way different. I think that an interpretation
request is in order.

I will be unavailable to do any gfortran work for two weeks now but will
complete this work then.

Best regards and thanks again.

Paul


On Thu, 17 Feb 2022 at 21:23, Thomas Koenig  wrote:

> Hi Paul,
>
> > I have gone back to the start and have gone through finalizable derived
> > type assignments with the F2018 in hand. I have had a dreadful time with
> > direct by reference function calls and still am struggling with
> assignment
> > number 6 in the attached. I would be very grateful if you would run this
> > testcase for the other brands.
>
> This is the output of nagfor 7.1, no idea how correct this is.
>
> Best regards
>
> Thomas
>
>   At start of program: final_count =0
>   ***
>
>   1st assignment: No finalization because MyType unallocated.
>   After 1st assignment(var not allocated): final_count =0(0)
>   ***
>
>   2nd assignment: MyType(=simple(1,MyType) finalized before assignment
>   finalize simple - Mytype2%ind =1
>   After 2nd assignment(var allocated): final_count =1(1)
>   ***
>
>   3rd assignment: MyTypeArray(%ind = [41 42]) finalized before assignment
>
>   finalize simple(:) - MyTypeArray%ind=   42  43
>   After 3rd assignment(array var allocated): final_count =1(1)
>   ***
>
>   Deallocation generates final call with self = simple (21, ThyType)
>   4th assignment: MyTypeArray finalized before assignment
>   Mtype finalized before assignment with self = simple (11, MyType)
>   Function result finalized after assignment with self = simple (99,
> MyType)
>
>   finalize simple - ThyType%ind =   21
>   finalize simple - MyType%ind =   11
>   After 4th 

[PATCH 0/8] OpenMP 5.0: C++ "declare mapper" support (plus struct rework, etc.)

2022-02-18 Thread Julian Brown
Hi,

This patch contains rebased/slightly bug-fixed versions of the patches
previously posted in the series:

https://gcc.gnu.org/pipermail/gcc-patches/2021-November/585439.html

plus a new implementation of "declare mapper" support for C++. This
can't be committed now, but posting now so others (mostly Jakub?) have
a chance to look at it and comment on the general approach, etc..

Further commentary on individual patches.

Thanks,

Julian

Julian Brown (8):
  OpenMP 5.0: Clause ordering for OpenMP 5.0 (topological sorting by
base pointer)
  Remove omp_target_reorder_clauses
  OpenMP/OpenACC struct sibling list gimplification extension and rework
  OpenMP: Add inspector class to unify mapped address analysis
  OpenMP: lvalue parsing for map clauses (C++)
  OpenMP: lvalue parsing for map clauses (C)
  Use OMP_ARRAY_SECTION instead of TREE_LIST in C++ FE
  OpenMP 5.0 "declare mapper" support for C++

 gcc/c-family/c-common.h   |   45 +
 gcc/c-family/c-omp.cc |  227 ++
 gcc/c/c-parser.cc |  150 +-
 gcc/c/c-tree.h|1 +
 gcc/c/c-typeck.cc |  251 +-
 gcc/cp/cp-gimplify.cc |6 +
 gcc/cp/cp-objcp-common.h  |2 +
 gcc/cp/cp-tree.h  |   10 +
 gcc/cp/decl.cc|   18 +-
 gcc/cp/error.cc   |9 +
 gcc/cp/mangle.cc  |5 +-
 gcc/cp/name-lookup.cc |3 +-
 gcc/cp/parser.cc  |  520 ++-
 gcc/cp/parser.h   |3 +
 gcc/cp/pt.cc  |  144 +-
 gcc/cp/semantics.cc   |  863 +++--
 gcc/fortran/parse.cc  |3 +
 gcc/fortran/trans-openmp.cc   |   20 +-
 gcc/gimplify.cc   | 2822 -
 gcc/langhooks-def.h   |3 +
 gcc/langhooks.cc  |9 +
 gcc/langhooks.h   |4 +
 gcc/omp-general.h |   52 +
 gcc/omp-low.cc|   23 +-
 gcc/testsuite/c-c++-common/gomp/map-1.c   |3 +-
 gcc/testsuite/c-c++-common/gomp/map-6.c   |   12 +-
 gcc/testsuite/g++.dg/goacc/member-array-acc.C |   13 +
 gcc/testsuite/g++.dg/gomp/declare-mapper-1.C  |   58 +
 gcc/testsuite/g++.dg/gomp/declare-mapper-2.C  |   30 +
 gcc/testsuite/g++.dg/gomp/declare-mapper-3.C  |   27 +
 gcc/testsuite/g++.dg/gomp/declare-mapper-4.C  |   74 +
 gcc/testsuite/g++.dg/gomp/ind-base-3.C|   38 +
 gcc/testsuite/g++.dg/gomp/map-assignment-1.C  |   12 +
 gcc/testsuite/g++.dg/gomp/map-inc-1.C |   10 +
 gcc/testsuite/g++.dg/gomp/map-lvalue-ref-1.C  |   19 +
 gcc/testsuite/g++.dg/gomp/map-ptrmem-1.C  |   36 +
 gcc/testsuite/g++.dg/gomp/map-ptrmem-2.C  |   39 +
 .../g++.dg/gomp/map-static-cast-lvalue-1.C|   17 +
 gcc/testsuite/g++.dg/gomp/map-ternary-1.C |   20 +
 gcc/testsuite/g++.dg/gomp/member-array-2.C|   86 +
 gcc/testsuite/g++.dg/gomp/member-array-omp.C  |   13 +
 gcc/testsuite/g++.dg/gomp/pr67522.C   |2 +-
 gcc/testsuite/g++.dg/gomp/target-3.C  |4 +-
 gcc/testsuite/g++.dg/gomp/target-lambda-1.C   |6 +-
 gcc/testsuite/g++.dg/gomp/target-this-2.C |2 +-
 gcc/testsuite/g++.dg/gomp/target-this-3.C |4 +-
 gcc/testsuite/g++.dg/gomp/target-this-4.C |4 +-
 .../g++.dg/gomp/unmappable-component-1.C  |   21 +
 gcc/tree-core.h   |4 +
 gcc/tree-pretty-print.cc  |   56 +
 gcc/tree.cc   |2 +
 gcc/tree.def  |   10 +
 gcc/tree.h|   21 +
 include/gomp-constants.h  |8 +-
 libgomp/testsuite/libgomp.c++/baseptrs-3.C|  275 ++
 libgomp/testsuite/libgomp.c++/class-array-1.C |   59 +
 .../testsuite/libgomp.c++/declare-mapper-1.C  |   87 +
 .../testsuite/libgomp.c++/declare-mapper-2.C  |   55 +
 .../testsuite/libgomp.c++/declare-mapper-3.C  |   63 +
 .../testsuite/libgomp.c++/declare-mapper-4.C  |   63 +
 .../testsuite/libgomp.c++/declare-mapper-5.C  |   52 +
 .../testsuite/libgomp.c++/declare-mapper-6.C  |   37 +
 .../testsuite/libgomp.c++/declare-mapper-7.C  |   48 +
 .../testsuite/libgomp.c++/declare-mapper-8.C  |   61 +
 libgomp/testsuite/libgomp.c++/ind-base-1.C|  162 +
 libgomp/testsuite/libgomp.c++/ind-base-2.C|   49 +
 libgomp/testsuite/libgomp.c++/map-comma-1.C   |   15 +
 .../testsuite/libgomp.c++/map-rvalue-ref-1.C  |   22 +
 .../testsuite/libgomp.c++/member-array-1.C|   89 +
 libgomp/testsuite/libgomp.c++/struct-ref-1.C  |   97 +
 .../libgomp.c-c++-common/baseptrs-1.c |   50 +
 .../libgomp.c-c++-common/baseptrs-2.c |   70 +
 .../libgo

[PATCH 1/8] OpenMP 5.0: Clause ordering for OpenMP 5.0 (topological sorting by base pointer)

2022-02-18 Thread Julian Brown
This patch reimplements the omp_target_reorder_clauses function in
anticipation of supporting "deeper" struct mappings (that is, with
several structure dereference operators, or similar).

The idea is that in place of the (possibly quadratic) algorithm in
omp_target_reorder_clauses that greedily moves clauses containing
addresses that are subexpressions of other addresses before those other
addresses, we employ a topological sort algorithm to calculate a proper
order for map clauses. This should run in linear time, and hopefully
handles degenerate cases where multiple "levels" of indirect accesses
are present on a given directive.

The new method also takes care to keep clause groups together, addressing
the concerns raised in:

  https://gcc.gnu.org/pipermail/gcc-patches/2021-May/570501.html

To figure out if some given clause depends on a base pointer in another
clause, we strip off the outer layers of the address expression, and check
(via a tree_operand_hash hash table we have built) if the result is a
"base pointer" as defined in OpenMP 5.0 (1.2.6 Data Terminology). There
are some subtleties involved, however:

 - We must treat MEM_REF with zero offset the same as INDIRECT_REF.
   This should probably be fixed in the front ends instead so we always
   use a canonical form (probably INDIRECT_REF). The following patch
   shows one instance of the problem, but there may be others:

   https://gcc.gnu.org/pipermail/gcc-patches/2021-May/571382.html

 - Mapping a whole struct implies mapping each of that struct's
   elements, which may be base pointers. Because those base pointers
   aren't necessarily explicitly referenced in the directive in question,
   we treat the whole-struct mapping as a dependency instead.

This version of the patch has been moved to the front of the patch queue,
thus isn't dependent on any of the following struct-rework patches.

Tested with offloading to NVPTX and bootstrapped. OK (for stage 1)?

Thanks,

Julian

2022-02-18  Julian Brown  

gcc/
* gimplify.c (is_or_contains_p, omp_target_reorder_clauses): Delete
functions.
(omp_tsort_mark): Add enum.
(omp_mapping_group): Add struct.
(debug_mapping_group, omp_get_base_pointer, omp_get_attachment,
omp_group_last, omp_gather_mapping_groups, omp_group_base,
omp_index_mapping_groups, omp_containing_struct,
omp_tsort_mapping_groups_1, omp_tsort_mapping_groups,
omp_segregate_mapping_groups, omp_reorder_mapping_groups): New
functions.
(gimplify_scan_omp_clauses): Call above functions instead of
omp_target_reorder_clauses, unless we've seen an error.
* omp-low.c (scan_sharing_clauses): Avoid strict test if we haven't
sorted mapping groups.

gcc/testsuite/
* g++.dg/gomp/target-lambda-1.C: Adjust expected output.
* g++.dg/gomp/target-this-3.C: Likewise.
* g++.dg/gomp/target-this-4.C: Likewise.
---
 gcc/gimplify.cc | 785 +++-
 gcc/omp-low.cc  |   7 +-
 gcc/testsuite/g++.dg/gomp/target-lambda-1.C |   7 +-
 gcc/testsuite/g++.dg/gomp/target-this-3.C   |   4 +-
 gcc/testsuite/g++.dg/gomp/target-this-4.C   |   4 +-
 5 files changed, 793 insertions(+), 14 deletions(-)

diff --git a/gcc/gimplify.cc b/gcc/gimplify.cc
index 875b115d02d..968cbd263f5 100644
--- a/gcc/gimplify.cc
+++ b/gcc/gimplify.cc
@@ -8738,6 +8738,7 @@ extract_base_bit_offset (tree base, tree *base_ref, 
poly_int64 *bitposp,
   return base;
 }
 
+#if 0
 /* Returns true if EXPR is or contains (as a sub-component) BASE_PTR.  */
 
 static bool
@@ -8761,6 +8762,7 @@ is_or_contains_p (tree expr, tree base_ptr)
   return operand_equal_p (expr, base_ptr);
 }
 
+
 /* Implement OpenMP 5.x map ordering rules for target directives. There are
several rules, and with some level of ambiguity, hopefully we can at least
collect the complexity here in one place.  */
@@ -8940,6 +8942,761 @@ omp_target_reorder_clauses (tree *list_p)
}
   }
 }
+#endif
+
+
+enum omp_tsort_mark {
+  UNVISITED,
+  TEMPORARY,
+  PERMANENT
+};
+
+struct omp_mapping_group {
+  tree *grp_start;
+  tree grp_end;
+  omp_tsort_mark mark;
+  struct omp_mapping_group *sibling;
+  struct omp_mapping_group *next;
+};
+
+__attribute__((used)) static void
+debug_mapping_group (omp_mapping_group *grp)
+{
+  tree tmp = OMP_CLAUSE_CHAIN (grp->grp_end);
+  OMP_CLAUSE_CHAIN (grp->grp_end) = NULL;
+  debug_generic_expr (*grp->grp_start);
+  OMP_CLAUSE_CHAIN (grp->grp_end) = tmp;
+}
+
+/* Return the OpenMP "base pointer" of an expression EXPR, or NULL if there
+   isn't one.  This needs improvement.  */
+
+static tree
+omp_get_base_pointer (tree expr)
+{
+  while (TREE_CODE (expr) == ARRAY_REF)
+expr = TREE_OPERAND (expr, 0);
+
+  while (TREE_CODE (expr) == COMPONENT_REF
+&& (DECL_P (TREE_OPERAND (expr, 0))
+|| (TREE_CODE (TREE_OPERAND (expr, 0)) == COMPONENT_REF)
+|| TREE_CODE (

[PATCH 2/8] Remove omp_target_reorder_clauses

2022-02-18 Thread Julian Brown
This patch has been split out from the previous one to avoid a
confusingly-interleaved diff.  The two patches should probably be
committed squashed together.

2021-10-01  Julian Brown  

gcc/
* gimplify.c (is_or_contains_p, omp_target_reorder_clauses): Delete.
---
 gcc/gimplify.cc | 207 
 1 file changed, 207 deletions(-)

diff --git a/gcc/gimplify.cc b/gcc/gimplify.cc
index 968cbd263f5..b667012a118 100644
--- a/gcc/gimplify.cc
+++ b/gcc/gimplify.cc
@@ -8738,213 +8738,6 @@ extract_base_bit_offset (tree base, tree *base_ref, 
poly_int64 *bitposp,
   return base;
 }
 
-#if 0
-/* Returns true if EXPR is or contains (as a sub-component) BASE_PTR.  */
-
-static bool
-is_or_contains_p (tree expr, tree base_ptr)
-{
-  if ((TREE_CODE (expr) == INDIRECT_REF && TREE_CODE (base_ptr) == MEM_REF)
-  || (TREE_CODE (expr) == MEM_REF && TREE_CODE (base_ptr) == INDIRECT_REF))
-return operand_equal_p (TREE_OPERAND (expr, 0),
-   TREE_OPERAND (base_ptr, 0));
-  while (!operand_equal_p (expr, base_ptr))
-{
-  if (TREE_CODE (base_ptr) == COMPOUND_EXPR)
-   base_ptr = TREE_OPERAND (base_ptr, 1);
-  if (TREE_CODE (base_ptr) == COMPONENT_REF
- || TREE_CODE (base_ptr) == POINTER_PLUS_EXPR
- || TREE_CODE (base_ptr) == SAVE_EXPR)
-   base_ptr = TREE_OPERAND (base_ptr, 0);
-  else
-   break;
-}
-  return operand_equal_p (expr, base_ptr);
-}
-
-
-/* Implement OpenMP 5.x map ordering rules for target directives. There are
-   several rules, and with some level of ambiguity, hopefully we can at least
-   collect the complexity here in one place.  */
-
-static void
-omp_target_reorder_clauses (tree *list_p)
-{
-  /* Collect refs to alloc/release/delete maps.  */
-  auto_vec ard;
-  tree *cp = list_p;
-  while (*cp != NULL_TREE)
-if (OMP_CLAUSE_CODE (*cp) == OMP_CLAUSE_MAP
-   && (OMP_CLAUSE_MAP_KIND (*cp) == GOMP_MAP_ALLOC
-   || OMP_CLAUSE_MAP_KIND (*cp) == GOMP_MAP_RELEASE
-   || OMP_CLAUSE_MAP_KIND (*cp) == GOMP_MAP_DELETE))
-  {
-   /* Unlink cp and push to ard.  */
-   tree c = *cp;
-   tree nc = OMP_CLAUSE_CHAIN (c);
-   *cp = nc;
-   ard.safe_push (c);
-
-   /* Any associated pointer type maps should also move along.  */
-   while (*cp != NULL_TREE
-  && OMP_CLAUSE_CODE (*cp) == OMP_CLAUSE_MAP
-  && (OMP_CLAUSE_MAP_KIND (*cp) == GOMP_MAP_FIRSTPRIVATE_REFERENCE
-  || OMP_CLAUSE_MAP_KIND (*cp) == GOMP_MAP_FIRSTPRIVATE_POINTER
-  || OMP_CLAUSE_MAP_KIND (*cp) == GOMP_MAP_ATTACH_DETACH
-  || OMP_CLAUSE_MAP_KIND (*cp) == GOMP_MAP_POINTER
-  || OMP_CLAUSE_MAP_KIND (*cp) == GOMP_MAP_ALWAYS_POINTER
-  || OMP_CLAUSE_MAP_KIND (*cp) == GOMP_MAP_TO_PSET))
- {
-   c = *cp;
-   nc = OMP_CLAUSE_CHAIN (c);
-   *cp = nc;
-   ard.safe_push (c);
- }
-  }
-else
-  cp = &OMP_CLAUSE_CHAIN (*cp);
-
-  /* Link alloc/release/delete maps to the end of list.  */
-  for (unsigned int i = 0; i < ard.length (); i++)
-{
-  *cp = ard[i];
-  cp = &OMP_CLAUSE_CHAIN (ard[i]);
-}
-  *cp = NULL_TREE;
-
-  /* OpenMP 5.0 requires that pointer variables are mapped before
- its use as a base-pointer.  */
-  auto_vec atf;
-  for (tree *cp = list_p; *cp; cp = &OMP_CLAUSE_CHAIN (*cp))
-if (OMP_CLAUSE_CODE (*cp) == OMP_CLAUSE_MAP)
-  {
-   /* Collect alloc, to, from, to/from clause tree pointers.  */
-   gomp_map_kind k = OMP_CLAUSE_MAP_KIND (*cp);
-   if (k == GOMP_MAP_ALLOC
-   || k == GOMP_MAP_TO
-   || k == GOMP_MAP_FROM
-   || k == GOMP_MAP_TOFROM
-   || k == GOMP_MAP_ALWAYS_TO
-   || k == GOMP_MAP_ALWAYS_FROM
-   || k == GOMP_MAP_ALWAYS_TOFROM)
- atf.safe_push (cp);
-  }
-
-  for (unsigned int i = 0; i < atf.length (); i++)
-if (atf[i])
-  {
-   tree *cp = atf[i];
-   tree decl = OMP_CLAUSE_DECL (*cp);
-   if (TREE_CODE (decl) == INDIRECT_REF || TREE_CODE (decl) == MEM_REF)
- {
-   tree base_ptr = TREE_OPERAND (decl, 0);
-   STRIP_TYPE_NOPS (base_ptr);
-   for (unsigned int j = i + 1; j < atf.length (); j++)
- if (atf[j])
-   {
- tree *cp2 = atf[j];
- tree decl2 = OMP_CLAUSE_DECL (*cp2);
-
- decl2 = OMP_CLAUSE_DECL (*cp2);
- if (is_or_contains_p (decl2, base_ptr))
-   {
- /* Move *cp2 to before *cp.  */
- tree c = *cp2;
- *cp2 = OMP_CLAUSE_CHAIN (c);
- OMP_CLAUSE_CHAIN (c) = *cp;
- *cp = c;
-
- if (*cp2 != NULL_TREE
- && OMP_CLAUSE_CODE (*cp2) == OMP_CLAUSE_MAP
- && OMP_CLAUSE_MAP_KIND (*cp2) == 
GOMP_MAP_

[PATCH 3/8] OpenMP/OpenACC struct sibling list gimplification extension and rework

2022-02-18 Thread Julian Brown
This patch is a combination of several previously-posted patches,
rebased and squashed together, and with a couple of additional bugfixes:

"Rewrite GOMP_MAP_ATTACH_DETACH mappings unconditionally"
https://gcc.gnu.org/pipermail/gcc-patches/2021-November/585440.html

"OpenMP/OpenACC: Move array_ref/indirect_ref handling code out of
extract_base_bit_offset"
https://gcc.gnu.org/pipermail/gcc-patches/2021-November/585441.html

"OpenACC/OpenMP: Refactor struct lowering in gimplify.c"
https://gcc.gnu.org/pipermail/gcc-patches/2021-November/585442.html

"OpenACC: Rework indirect struct handling in gimplify.c"
https://gcc.gnu.org/pipermail/gcc-patches/2021-November/585443.html

"Remove base_ind/base_ref handling from extract_base_bit_offset"
https://gcc.gnu.org/pipermail/gcc-patches/2021-November/585445.html

"OpenMP/OpenACC: Hoist struct sibling list handling in gimplification"
https://gcc.gnu.org/pipermail/gcc-patches/2021-November/585448.html

"OpenMP: Allow array ref components for C & C++"
https://gcc.gnu.org/pipermail/gcc-patches/2021-November/585449.html

"OpenMP: Fix non-zero attach/detach bias for struct dereferences"
https://gcc.gnu.org/pipermail/gcc-patches/2021-November/585451.html

"OpenMP: Handle reference-typed struct members"
https://gcc.gnu.org/pipermail/gcc-patches/2021-November/585453.html

"OpenACC: Make deep-copy-arrayofstruct.c a libgomp/runtime test"
https://gcc.gnu.org/pipermail/gcc-patches/2021-November/585452.html

This resulting patch thus contains all the struct gimplification changes
(and associated fixes) previously posted: the hope was that this would
reduce the amount of churn to be reviewed, although maybe this patch does
too much at once. The changes as a whole are all relating to increasing
the variety of supported expressions in OpenMP and OpenACC map clauses,
though.

2022-02-18  Julian Brown  

gcc/c-family/
* c-common.h (c_omp_decompose_attachable_address): Add prototype.
* c-omp.cc (c_omp_decompose_attachable_address): New function.

gcc/c/
* c-typeck.cc (handle_omp_array_sections): Handle attach/detach for
struct dereferences with non-zero bias.
(c_finish_omp_clauses): Allow ARRAY_REF components.

gcc/cp/
* semantics.cc (handle_omp_array_section): Handle attach/detach for
struct dereferences with non-zero bias.
(finish_omp_clauses): Allow ARRAY_REF components.  Handle
reference-typed members.

gcc/fortran/
* trans-openmp.cc (gfc_trans_omp_clauses): Don't create
GOMP_MAP_TO_PSET mappings for class metadata, nor GOMP_MAP_POINTER
mappings for POINTER_TYPE_P decls.

gcc/
* gimplify.c (gimplify_omp_var_data): Remove GOVD_MAP_HAS_ATTACHMENTS.
(insert_struct_comp_map): Refactor function into...
(build_struct_comp_nodes): This new function.  Remove list handling
and improve self-documentation.
(extract_base_bit_offset): Remove BASE_REF, OFFSETP parameters.  Move
code to strip outer parts of address out of function, but strip no-op
conversions.
(omp_mapping_group): Add DELETED field for use during reindexing.
(strip_components_and_deref, strip_indirections): New functions.
(omp_group_last, omp_group_base): Add GOMP_MAP_STRUCT handling.
(omp_gather_mapping_groups): Initialise DELETED field for new groups.
(omp_index_mapping_groups): Notice DELETED groups when (re)indexing.
(insert_node_after, move_node_after, move_nodes_after,
move_concat_nodes_after): New helper functions.
(accumulate_sibling_list): New function to build up GOMP_MAP_STRUCT
node groups for sibling lists. Outlined from gimplify_scan_omp_clauses.
(omp_build_struct_sibling_lists): New function.
(gimplify_scan_omp_clauses): Remove struct_map_to_clause,
struct_seen_clause, struct_deref_set.  Call
omp_build_struct_sibling_lists as pre-pass instead of handling sibling
lists in the function's main processing loop.
(gimplify_adjust_omp_clauses_1): Remove GOVD_MAP_HAS_ATTACHMENTS
handling, unused now.
* omp-low.cc (scan_sharing_clauses): Handle pointer-type indirect
struct references, and references to pointers to structs also.

gcc/testsuite/
* g++.dg/goacc/member-array-acc.C: New test.
* g++.dg/gomp/member-array-omp.C: New test.
* g++.dg/gomp/target-3.C: Update expected output.
* g++.dg/gomp/target-lambda-1.C: Likewise.
* g++.dg/gomp/target-this-2.C: Likewise.
* c-c++-common/goacc/deep-copy-arrayofstruct.c: Move test from here.

libgomp/
* testsuite/libgomp.c-c++-common/baseptrs-1.c: Add test.
* testsuite/libgomp.c-c++-common/baseptrs-2.c: Add test.
* testsuite/libgomp.c++/baseptrs-3.C: Add test.
* testsuite/libgomp.oacc-c-c++-common/deep-copy-15.c: New test.
* testsuite/libgomp.oacc-c-c++-common/deep-copy-16.c: New test.
* testsuite/libgom

[PATCH 4/8] OpenMP: Add inspector class to unify mapped address analysis

2022-02-18 Thread Julian Brown
Several places in the C and C++ front-ends dig through OpenMP addresses
from "map" clauses (etc.) in order to determine whether they are component
accesses that need "attach" operations, check duplicate mapping clauses,
and so on.  When we're extending support for more kinds of lvalues in
map clauses, it seems helpful to bring these all into one place in order
to keep all the analyses in sync, and to make it easier to reason about
which kinds of expressions are supported.

This patch introduces an "address inspector" class for that purpose,
and adjusts the C and C++ front-ends to use it.

2021-11-15  Julian Brown  

gcc/c-family/
* c-common.h (c_omp_address_inspector): New class.
* c-omp.c (c_omp_address_inspector::init,
c_omp_address_inspector::analyze_components,
c_omp_address_inspector::map_supported_p,
c_omp_address_inspector::mappable_type): New methods.

gcc/c/
* c-typeck.c (handle_omp_array_sections_1,
c_finish_omp_clauses): Use c_omp_address_inspector class.

gcc/cp/
* semantics.c (cp_omp_address_inspector): New class, derived from
c_omp_address_inspector.
(handle_omp_array_sections_1): Use cp_omp_address_inspector class to
analyze OpenMP map clause expressions.  Support POINTER_PLUS_EXPR.
(finish_omp_clauses): Likewise.  Support some additional kinds of
lvalues in map clauses.

gcc/testsuite/
* g++.dg/gomp/unmappable-component-1.C: New test.

Make map_supported_p strip nops

lvalue thing, generic part
---
 gcc/c-family/c-common.h   |  44 +++
 gcc/c-family/c-omp.cc | 150 +++
 gcc/c/c-typeck.cc | 199 +++---
 gcc/cp/semantics.cc   | 253 ++
 .../g++.dg/gomp/unmappable-component-1.C  |  21 ++
 libgomp/testsuite/libgomp.c++/class-array-1.C |  59 
 6 files changed, 400 insertions(+), 326 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/gomp/unmappable-component-1.C
 create mode 100644 libgomp/testsuite/libgomp.c++/class-array-1.C

diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index d00838a57f0..af8dc6c4e4f 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -1254,6 +1254,50 @@ extern const char *c_omp_map_clause_name (tree, bool);
 extern void c_omp_adjust_map_clauses (tree, bool);
 extern tree c_omp_decompose_attachable_address (tree t, tree *virtbase);
 
+class c_omp_address_inspector
+{
+  tree clause;
+  tree orig;
+  tree deref_toplevel;
+  tree outer_virtual_base;
+  tree root_term;
+  bool component_access;
+  bool indirections;
+  int map_supported;
+
+protected:
+  virtual bool reference_ref_p (tree) { return false; }
+  virtual bool processing_template_decl_p () { return false; }
+  virtual bool mappable_type (tree t);
+  virtual void emit_unmappable_type_notes (tree) { }
+
+public:
+  c_omp_address_inspector (tree c, tree t)
+: clause (c), orig (t), deref_toplevel (NULL_TREE),
+  outer_virtual_base (NULL_TREE), root_term (NULL_TREE),
+  component_access (false), indirections (false), map_supported (-1)
+  { }
+
+  ~c_omp_address_inspector () {}
+
+  virtual void init ();
+
+  tree analyze_components (bool);
+
+  tree get_deref_toplevel () { return deref_toplevel; }
+  tree get_outer_virtual_base () { return outer_virtual_base; }
+  tree get_root_term () { gcc_assert (root_term); return root_term; }
+  bool component_access_p () { return component_access; }
+
+  bool indir_component_ref_p ()
+{
+  gcc_assert (!component_access || root_term != NULL_TREE);
+  return component_access && indirections;
+}
+
+  bool map_supported_p ();
+};
+
 enum c_omp_directive_kind {
   C_OMP_DIR_STANDALONE,
   C_OMP_DIR_CONSTRUCT,
diff --git a/gcc/c-family/c-omp.cc b/gcc/c-family/c-omp.cc
index 0e76eb4392e..e3270f781b0 100644
--- a/gcc/c-family/c-omp.cc
+++ b/gcc/c-family/c-omp.cc
@@ -3113,6 +3113,156 @@ c_omp_adjust_map_clauses (tree clauses, bool is_target)
 }
 }
 
+/* This could just be done in the constructor, but we need to call the
+   subclass's version of reference_ref_p, etc.  */
+
+void
+c_omp_address_inspector::init ()
+{
+  tree t = orig;
+
+  gcc_assert (TREE_CODE (t) != ARRAY_REF);
+
+  /* We may have a reference-typed component access at the outermost level
+ that has had convert_from_reference called on it.  Look through that
+ access.  */
+  if (reference_ref_p (t)
+  && TREE_CODE (TREE_OPERAND (t, 0)) == COMPONENT_REF)
+{
+  t = TREE_OPERAND (t, 0);
+  deref_toplevel = t;
+}
+  else
+deref_toplevel = t;
+
+  /* Strip off expression nodes that may enclose a COMPONENT_REF.  Look through
+ references, but not indirections through pointers.  */
+  while (1)
+{
+  if (TREE_CODE (t) == COMPOUND_EXPR)
+   {
+ t = TREE_OPERAND (t, 1);
+ STRIP_NOPS (t);
+   }
+  else if (TREE_CODE (t) == POINTER_PLUS_EXPR
+ 

[PATCH 5/8] OpenMP: lvalue parsing for map clauses (C++)

2022-02-18 Thread Julian Brown
This patch changes parsing for OpenMP map clauses in C++ to use the
generic expression parser, hence adds support for parsing general
lvalues (as required by OpenMP 5.0+).  So far only a few new types of
expression are actually supported throughout compilation (including
everything in the testsuite of course, and newly-added tests), and we
attempt to reject unsupported expressions in order to avoid surprises
for the user.

This version of the patch relaxes the check for supported map expressions
to include LVALUE_EXPR, which makes pointer-to-member mappings
stop "accidentally" failing the check.  However such mappings don't
actually work yet, so they have been explicitly disallowed elsewhere.
Supporting pointer-to-member mappings can probably be done most easily
by mapping the whole of the containing struct, and mapping the offsets as
firstprivate or similar.  That's a little fiddly to get working though,
and isn't unambiguously the right thing to do, so that might need more
thought.

2022-02-18  Julian Brown  

gcc/c-family/
* c-omp.cc (c_omp_decompose_attachable_address): Handle more types of
expressions.

gcc/cp/
* error.cc (dump_expr): Handle OMP_ARRAY_SECTION.
* parser.cc (cp_parser_new): Initialize parser->omp_array_section_p.
(cp_parser_postfix_open_square_expression): Support OMP_ARRAY_SECTION
parsing.
(cp_parser_omp_var_list_no_open): Remove ALLOW_DEREF parameter, add
MAP_LVALUE in its place.  Supported generalised lvalue parsing for map
clauses.
(cp_parser_omp_var_list): Remove ALLOW_DEREF parameter, add MAP_LVALUE.
Pass to cp_parser_omp_var_list_no_open.
(cp_parser_oacc_data_clause, cp_parser_omp_all_clauses): Update calls
to cp_parser_omp_var_list.
* parser.h (cp_parser): Add omp_array_section_p field.
* semantics.cc (handle_omp_array_sections_1): Handle more types of map
expression.
(handle_omp_array_section): Handle non-DECL_P attachment points.
(finish_omp_clauses): Check for supported types of expression.

gcc/
* gimplify.cc (accumulate_sibling_list): Handle reference-typed
component accesses.  Fix support for non-DECL_P struct bases.
(omp_ptrmem_p): New function.
(omp_build_struct_sibling_lists): Support length-two group for
synthesized inner struct mapping.  Explicitly disallow pointers to
members.
* tree-pretty-print.c (dump_generic_node): Support OMP_ARRAY_SECTION.
* tree.def (OMP_ARRAY_SECTION): New tree code.

gcc/testsuite/
* c-c++-common/gomp/map-6.c: Update expected output.
* g++.dg/gomp/pr67522.C: Likewise.
* g++.dg/gomp/ind-base-3.C: New test.
* g++.dg/gomp/map-assignment-1.C: New test.
* g++.dg/gomp/map-inc-1.C: New test.
* g++.dg/gomp/map-lvalue-ref-1.C: New test.
* g++.dg/gomp/map-ptrmem-1.C: New test.
* g++.dg/gomp/map-ptrmem-2.C: New test.
* g++.dg/gomp/map-static-cast-lvalue-1.C: New test.
* g++.dg/gomp/map-ternary-1.C: New test.
* g++.dg/gomp/member-array-2.C: New test.

libgomp/
* testsuite/libgomp.c++/ind-base-1.C: New test.
* testsuite/libgomp.c++/ind-base-2.C: New test.
* testsuite/libgomp.c++/map-comma-1.C: New test.
* testsuite/libgomp.c++/map-rvalue-ref-1.C: New test.
* testsuite/libgomp.c++/member-array-1.C: New test.
* testsuite/libgomp.c++/struct-ref-1.C: New test.
---
 gcc/c-family/c-omp.cc |  25 ++-
 gcc/cp/error.cc   |   9 +
 gcc/cp/parser.cc  | 141 +--
 gcc/cp/parser.h   |   3 +
 gcc/cp/semantics.cc   |  55 +-
 gcc/gimplify.cc   |  71 +++-
 gcc/testsuite/c-c++-common/gomp/map-6.c   |   4 +-
 gcc/testsuite/g++.dg/gomp/ind-base-3.C|  38 
 gcc/testsuite/g++.dg/gomp/map-assignment-1.C  |  12 ++
 gcc/testsuite/g++.dg/gomp/map-inc-1.C |  10 ++
 gcc/testsuite/g++.dg/gomp/map-lvalue-ref-1.C  |  19 ++
 gcc/testsuite/g++.dg/gomp/map-ptrmem-1.C  |  36 
 gcc/testsuite/g++.dg/gomp/map-ptrmem-2.C  |  39 +
 .../g++.dg/gomp/map-static-cast-lvalue-1.C|  17 ++
 gcc/testsuite/g++.dg/gomp/map-ternary-1.C |  20 +++
 gcc/testsuite/g++.dg/gomp/member-array-2.C|  86 ++
 gcc/testsuite/g++.dg/gomp/pr67522.C   |   2 +-
 gcc/tree-pretty-print.cc  |  14 ++
 gcc/tree.def  |   3 +
 libgomp/testsuite/libgomp.c++/ind-base-1.C| 162 ++
 libgomp/testsuite/libgomp.c++/ind-base-2.C|  49 ++
 libgomp/testsuite/libgomp.c++/map-comma-1.C   |  15 ++
 .../testsuite/libgomp.c++/map-rvalue-ref-1.C  |  22 +++
 .../testsuite/libgomp.c++/member-array-1.C|  89 ++
 libgomp/testsuite/libgomp.c++/struct-ref-1.C  |  97 +++
 25 files 

[PATCH 7/8] Use OMP_ARRAY_SECTION instead of TREE_LIST in C++ FE

2022-02-18 Thread Julian Brown
This patch changes the representation of OMP array sections in the
C++ front end to use the new OMP_ARRAY_SECTION tree code instead of a
TREE_LIST.  This is important for "declare mapper" support, because the
array section representation may stick around longer (in "declare mapper"
definitions), and special-case handling TREE_LIST becomes necessary in
more places, which starts to become unwieldy.

2022-02-18  Julian Brown  

gcc/c-family/
* c-omp.cc (c_omp_split_clauses): Support OMP_ARRAY_SECTION.

gcc/cp/
* parser.cc (cp_parser_omp_var_list_no_open): Use OMP_ARRAY_SECTION
code instead of TREE_LIST to represent OpenMP array sections.
* pt.cc (tsubst_copy, tsubst_omp_clause_decl, tsubst_copy_and_build):
Add OMP_ARRAY_SECTION support.
* semantics.cc (handle_omp_array_sections_1, handle_omp_array_sections,
cp_oacc_check_attachments, finish_omp_clauses): Use OMP_ARRAY_SECTION
instead of TREE_LIST where appropriate.
* gimplify.cc (gimplify_expr): Ensure OMP_ARRAY_SECTION has been
processed out before gimplification.
---
 gcc/c-family/c-omp.cc | 14 +++
 gcc/cp/parser.cc  | 15 
 gcc/cp/pt.cc  | 52 
 gcc/cp/semantics.cc   | 56 ++-
 gcc/gimplify.cc   |  3 +++
 5 files changed, 109 insertions(+), 31 deletions(-)

diff --git a/gcc/c-family/c-omp.cc b/gcc/c-family/c-omp.cc
index ad34f817029..3f5f9637213 100644
--- a/gcc/c-family/c-omp.cc
+++ b/gcc/c-family/c-omp.cc
@@ -2662,6 +2662,9 @@ c_omp_split_clauses (location_t loc, enum tree_code code,
}
  else if (TREE_CODE (OMP_CLAUSE_DECL (c)) == TREE_LIST)
{
+ /* TODO: This can go away once we transition all uses of
+TREE_LIST for representing OMP array sections to
+OMP_ARRAY_SECTION.  */
  tree t;
  for (t = OMP_CLAUSE_DECL (c);
   TREE_CODE (t) == TREE_LIST; t = TREE_CHAIN (t))
@@ -2670,6 +2673,17 @@ c_omp_split_clauses (location_t loc, enum tree_code code,
bitmap_clear_bit (&allocate_head, DECL_UID (t));
  break;
}
+ else if (TREE_CODE (OMP_CLAUSE_DECL (c)) == OMP_ARRAY_SECTION)
+   {
+ tree t;
+ for (t = OMP_CLAUSE_DECL (c);
+  TREE_CODE (t) == OMP_ARRAY_SECTION;
+  t = TREE_OPERAND (t, 0))
+   ;
+ if (DECL_P (t))
+   bitmap_clear_bit (&allocate_head, DECL_UID (t));
+ break;
+   }
  /* FALLTHRU */
case OMP_CLAUSE_PRIVATE:
case OMP_CLAUSE_FIRSTPRIVATE:
diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index efb65543e11..8d5ae9c44d0 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -36639,11 +36639,14 @@ cp_parser_omp_var_list_no_open (cp_parser *parser, 
enum omp_clause_code kind,
decl = TREE_OPERAND (decl, 0);
 
  for (int i = dims.length () - 1; i >= 0; i--)
-   decl = tree_cons (dims[i].low_bound, dims[i].length, decl);
+   decl = build3_loc (input_location, OMP_ARRAY_SECTION,
+  TREE_TYPE (decl), decl, dims[i].low_bound,
+  dims[i].length);
}
  else if (TREE_CODE (decl) == INDIRECT_REF)
{
  bool ref_p = REFERENCE_REF_P (decl);
+ tree type = TREE_TYPE (decl);
 
  /* Turn *foo into the representation previously used for
 foo[0].  */
@@ -36653,7 +36656,8 @@ cp_parser_omp_var_list_no_open (cp_parser *parser, enum 
omp_clause_code kind,
  /* ...but don't add the [0:1] representation for references
 (because they have special handling elsewhere).  */
  if (!ref_p)
-   decl = tree_cons (integer_zero_node, integer_one_node, decl);
+   decl = build3_loc (input_location, OMP_ARRAY_SECTION, type,
+  decl, integer_zero_node, integer_one_node);
}
  else if (TREE_CODE (decl) == ARRAY_REF)
{
@@ -36662,7 +3,8 @@ cp_parser_omp_var_list_no_open (cp_parser *parser, enum 
omp_clause_code kind,
  decl = TREE_OPERAND (decl, 0);
  STRIP_NOPS (decl);
 
- decl = tree_cons (idx, integer_one_node, decl);
+ decl = build3_loc (input_location, OMP_ARRAY_SECTION,
+TREE_TYPE (decl), decl, idx, integer_one_node);
}
  else if (TREE_CODE (decl) == NON_LVALUE_EXPR
   || CONVERT_EXPR_P (decl))
@@ -36837,7 +36842,9 @@ cp_parser_omp_var_list_no_open (cp_parser 

[PATCH 6/8] OpenMP: lvalue parsing for map clauses (C)

2022-02-18 Thread Julian Brown
This patch adds support for parsing general lvalues for OpenMP "map"
clauses to the C front-end, similar to the previous patch for C++.

This version of the patch fixes several omissions regarding non-DECL_P
root terms in map clauses (i.e. "*foo" in "(*foo)->ptr->arr[:N]") --
similar to the cp/semantics.c changes in the previous patch -- and adds
a couple of new tests.

2021-11-24  Julian Brown  

gcc/c/
* c-parser.c (c_parser_postfix_expression_after_primary): Add support
for OpenMP array section parsing.
(c_parser_omp_variable_list): Change ALLOW_DEREF parameter to
MAP_LVALUE.  Support parsing of general lvalues in "map" clauses.
(c_parser_omp_var_list_parens): Change ALLOW_DEREF parameter to
MAP_LVALUE.  Update call to c_parser_omp_variable_list.
(c_parser_oacc_data_clause, c_parser_omp_clause_to,
c_parser_omp_clause_from): Update calls to
c_parser_omp_var_list_parens.
* c-tree.h (c_omp_array_section_p): Add extern declaration.
* c-typeck.c (c_omp_array_section_p): Add flag.
(mark_exp_read): Support OMP_ARRAY_SECTION.
(handle_omp_array_sections_1): Handle more kinds of expressions.
(handle_omp_array_sections): Handle non-DECL_P attachment points.
(c_finish_omp_clauses): Check for supported expression types.  Support
non-DECL_P root term for map clauses.

gcc/testsuite/
* c-c++-common/gomp/map-1.c: Adjust expected output.
* c-c++-common/gomp/map-6.c: Likewise.

libgomp/
* testsuite/libgomp.c-c++-common/ind-base-4.c: New test.
* testsuite/libgomp.c-c++-common/unary-ptr-1.c: New test.
---
 gcc/c/c-parser.cc | 150 +++---
 gcc/c/c-tree.h|   1 +
 gcc/c/c-typeck.cc |  45 +-
 gcc/testsuite/c-c++-common/gomp/map-1.c   |   3 +-
 gcc/testsuite/c-c++-common/gomp/map-6.c   |   2 +
 .../libgomp.c-c++-common/ind-base-4.c |  50 ++
 .../libgomp.c-c++-common/unary-ptr-1.c|  16 ++
 7 files changed, 243 insertions(+), 24 deletions(-)
 create mode 100644 libgomp/testsuite/libgomp.c-c++-common/ind-base-4.c
 create mode 100644 libgomp/testsuite/libgomp.c-c++-common/unary-ptr-1.c

diff --git a/gcc/c/c-parser.cc b/gcc/c/c-parser.cc
index e9086c58524..cc590e56e75 100644
--- a/gcc/c/c-parser.cc
+++ b/gcc/c/c-parser.cc
@@ -10486,7 +10486,7 @@ c_parser_postfix_expression_after_primary (c_parser 
*parser,
   struct c_expr expr)
 {
   struct c_expr orig_expr;
-  tree ident, idx;
+  tree ident, idx, len;
   location_t sizeof_arg_loc[3], comp_loc;
   tree sizeof_arg[3];
   unsigned int literal_zero_mask;
@@ -10505,15 +10505,44 @@ c_parser_postfix_expression_after_primary (c_parser 
*parser,
case CPP_OPEN_SQUARE:
  /* Array reference.  */
  c_parser_consume_token (parser);
- idx = c_parser_expression (parser).value;
- c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE,
-"expected %<]%>");
- start = expr.get_start ();
- finish = parser->tokens_buf[0].location;
- expr.value = build_array_ref (op_loc, expr.value, idx);
- set_c_expr_source_range (&expr, start, finish);
- expr.original_code = ERROR_MARK;
- expr.original_type = NULL;
+ idx = len = NULL_TREE;
+ if (!c_omp_array_section_p
+ || c_parser_next_token_is_not (parser, CPP_COLON))
+   idx = c_parser_expression (parser).value;
+
+ if (c_omp_array_section_p
+ && c_parser_next_token_is (parser, CPP_COLON))
+   {
+ c_parser_consume_token (parser);
+ if (c_parser_next_token_is_not (parser, CPP_CLOSE_SQUARE))
+   len = c_parser_expression (parser).value;
+
+ c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE,
+"expected %<]%>");
+
+/* NOTE: We are reusing using the type of the whole array as the
+   type of the array section here, which isn't necessarily
+   entirely correct.  Might need revisiting.  */
+ start = expr.get_start ();
+ finish = parser->tokens_buf[0].location;
+ expr.value = build3_loc (op_loc, OMP_ARRAY_SECTION,
+  TREE_TYPE (expr.value), expr.value,
+  idx, len);
+ set_c_expr_source_range (&expr, start, finish);
+ expr.original_code = ERROR_MARK;
+ expr.original_type = NULL;
+   }
+ else
+   {
+ c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE,
+"expected %<]%>");
+ start = expr.get_start ();
+ finish = parser->tokens_buf[0].location;
+ expr.value = build_array_ref (op_loc, expr.value, i

[PATCH 8/8] OpenMP 5.0 "declare mapper" support for C++

2022-02-18 Thread Julian Brown
This patch implements OpenMP 5.0 "declare mapper" support for C++ --
except for arrays of structs with mappers, which are TBD. I've taken cues
from the existing "declare reduction" support where appropriate, though
obviously the details of implementation differ somewhat (in particular,
"declare mappers" must survive longer, until gimplification time).

Both named and unnamed (default) mappers are supported, and both
explicitly-mapped structures and implicitly-mapped struct-typed variables
used within an offload region are supported. For the latter, we need a
way to communicate to the middle end which mapper (visible, in-scope) is
the right one to use -- for that, we scan the target body in the front
end for uses of structure (etc.) types, and create artificial "mapper
binding" clauses to associate types with visible mappers. (It doesn't
matter too much if we create these mapper bindings a bit over-eagerly,
since they will only be used if needed later during gimplification.)

Another difficulty concerns the order in which an OpenMP offload region
body's clauses are processed relative to its body: in order to add
clauses for instantiated mappers, we need to have processed the body
already in order to find which variables have been used, but at present
the region's clauses are processed strictly before the body. So, this
patch adds a second clause-processing step after gimplification of the
body in order to add clauses resulting from instantiated mappers.

(C and Fortran FE support are TBD.)

Tested (alongside previous patches) with offloading to NVPTX, and
bootstrapped.  Any comments on this general approach?  Thoughts on
handling arrays of custom-mapped structs?  OK (for stage 1)?

Thanks,

Julian

2022-02-18  Julian Brown  

gcc/cp/
* cp-gimplify.cc (cxx_omp_finish_mapper_clauses): New function.
* cp-objcp-common.h (LANG_HOOKS_OMP_FINISH_MAPPER_CLAUSES): Add new
langhook.
* cp-tree.h (lang_decl_fn): Add omp_declare_mapper_p field.
(DECL_OMP_DECLARE_MAPPER_P): New function.
(omp_mapper_id, cp_check_omp_declare_mapper, omp_instantiate_mappers,
cxx_omp_finish_mapper_clauses): Add prototypes.
* decl.cc (duplicate_decls): Support DECL_OMP_DECLARE_MAPPER_P
functions.
(finish_function): Likewise.
* mangle.cc (decl_mangling_context): Likewise.
* name-lookup.cc (set_decl_context_in_fn): Likewise.
* parser.cc (cp_parser_class_specifier_1): Likewise.
(cp_parser_omp_declare_mapper, cp_parser_omp_declare_mapper_maplist):
New functions.
(cp_parser_late_parsing_for_member): Support DECL_OMP_DECLARE_MAPPER_P
functions.
(cp_parser_omp_clause_map): Add KIND parameter.  Support "mapper"
modifier.
(cp_parser_omp_all_clauses): Add KIND argument to
cp_parser_omp_clause_map call.
(cp_parser_omp_target): Call omp_instantiate_mappers before
finish_omp_clauses.
(cp_parser_omp_declare): Add "declare mapper" support.
* pt.cc (instantiate_class_template_1, tsubst_function_decl): Support
DECL_OMP_DECLARE_MAPPER_P functions.
(tsubst_omp_clauses): Call omp_instantiate_mappers before
finish_omp_clauses, for target regions.
(tsubst_expr): Support DECL_OMP_DECLARE_MAPPER_P functions.
(tsubst_omp_udm): New function.
(instantiate_body): Support DECL_OMP_DECLARE_MAPPER_P functions.
* semantics.cc (gimplify.h): Include.
(expand_or_defer_fn_1): Support DECL_OMP_DECLARE_MAPPER_P functions.
(omp_mapper_id, omp_mapper_lookup, omp_extract_mapper_directive,
cp_check_omp_declare_mapper): New functions.
(remap_mapper_decl_info): New struct.
(remap_mapper_decl_1, omp_instantiate_mapper, omp_instantiate_mappers):
New functions.
(finish_omp_clauses): Delete GOMP_MAP_PUSH_MAPPER_NAME and
GOMP_MAP_POP_MAPPER_NAME artificial clauses.
(mapper_list): New struct.
(find_nested_mappers): New function.
(omp_target_walk_data): Add MAPPERS field.
(finish_omp_target_clauses_r): Scan for uses of struct/union/class type
variables.
(finish_omp_target_clauses): Create artificial mapper binding clauses
for used structs/unions/classes in offload region.

gcc/fortran/
* parse.cc (tree.h, fold-const.h, tree-hash-traits.h): Add includes
(for additions to omp-general.h).

gcc/
* gimplify.cc (gimplify_omp_ctx): Add IMPLICIT_MAPPERS field.
(new_omp_context): Initialise IMPLICIT_MAPPERS hash map.
(delete_omp_context): Delete IMPLICIT_MAPPERS hash map.
(instantiate_mapper_info, remap_mapper_decl_info): New structs.
(remap_mapper_decl_1, omp_instantiate_mapper, handled_struct_p,
omp_instantiate_implicit_mappers, new_omp_context_for_scan): New
functions.
(gimplify_scan_omp_clauses): Add optional USE_MAPPERS parameter.
Instantia

[PATCH] Add a restriction on allocate clause (OpenMP 5.0)

2022-02-18 Thread Hafiz Abid Qadeer
An allocate clause in target region must specify an allocator
unless the compilation unit has requires construct with
dynamic_allocators clause.  Current implementation of the allocate
clause did not check for this restriction. This patch fills that
gap.

gcc/ChangeLog:

* omp-low.cc (omp_maybe_offloaded_ctx): New prototype.
(scan_sharing_clauses):  Check a restriction on allocate clause.

gcc/testsuite/ChangeLog:

* c-c++-common/gomp/allocate-2.c: Add tests.
* c-c++-common/gomp/allocate-8.c: New test.
* gfortran.dg/gomp/allocate-3.f90: Add tests.
* gcc.dg/gomp/pr104517.c: Update.
---
 gcc/omp-low.cc| 10 ++
 gcc/testsuite/c-c++-common/gomp/allocate-2.c  | 15 +++
 gcc/testsuite/c-c++-common/gomp/allocate-8.c  | 18 ++
 gcc/testsuite/gcc.dg/gomp/pr104517.c  | 18 ++
 gcc/testsuite/gfortran.dg/gomp/allocate-3.f90 | 14 ++
 5 files changed, 67 insertions(+), 8 deletions(-)
 create mode 100644 gcc/testsuite/c-c++-common/gomp/allocate-8.c

diff --git a/gcc/omp-low.cc b/gcc/omp-low.cc
index 77176efe715..658cb3de7d6 100644
--- a/gcc/omp-low.cc
+++ b/gcc/omp-low.cc
@@ -195,6 +195,7 @@ static vec task_cpyfns;
 
 static void scan_omp (gimple_seq *, omp_context *);
 static tree scan_omp_1_op (tree *, int *, void *);
+static bool omp_maybe_offloaded_ctx (omp_context *ctx);
 
 #define WALK_SUBSTMTS  \
 case GIMPLE_BIND: \
@@ -1169,6 +1170,15 @@ scan_sharing_clauses (tree clauses, omp_context *ctx)
|| !integer_onep (OMP_CLAUSE_ALLOCATE_ALLOCATOR (c))
|| OMP_CLAUSE_ALLOCATE_ALIGN (c) != NULL_TREE))
   {
+   /* The allocate clauses that appear on a target construct or on
+  constructs in a target region must specify an allocator expression
+  unless a requires directive with the dynamic_allocators clause
+  is present in the same compilation unit.  */
+   if (OMP_CLAUSE_ALLOCATE_ALLOCATOR (c) == NULL_TREE
+   && ((omp_requires_mask & OMP_REQUIRES_DYNAMIC_ALLOCATORS) == 0)
+   && omp_maybe_offloaded_ctx (ctx))
+ error_at (OMP_CLAUSE_LOCATION (c), "% clause must"
+   " specify an allocator here");
if (ctx->allocate_map == NULL)
  ctx->allocate_map = new hash_map;
tree val = integer_zero_node;
diff --git a/gcc/testsuite/c-c++-common/gomp/allocate-2.c 
b/gcc/testsuite/c-c++-common/gomp/allocate-2.c
index cc77efc8ffe..6bb4a8af2e7 100644
--- a/gcc/testsuite/c-c++-common/gomp/allocate-2.c
+++ b/gcc/testsuite/c-c++-common/gomp/allocate-2.c
@@ -43,3 +43,18 @@ foo (int x, int z)
   #pragma omp parallel private (x) allocate (0 : x)/* { dg-error 
"'allocate' clause allocator expression has type 'int' rather than 
'omp_allocator_handle_t'" } */
   bar (x, &x, 0);
 }
+
+void
+foo1 ()
+{
+  int a = 10;
+#pragma omp target
+  {
+#pragma omp parallel private (a) allocate(a) // { dg-error "'allocate' 
clause must specify an allocator here" }
+a = 20;
+  }
+#pragma omp target private(a) allocate(a) // { dg-error "'allocate' clause 
must specify an allocator here" }
+  {
+a = 30;
+  }
+}
diff --git a/gcc/testsuite/c-c++-common/gomp/allocate-8.c 
b/gcc/testsuite/c-c++-common/gomp/allocate-8.c
new file mode 100644
index 000..bacefafc6fc
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/allocate-8.c
@@ -0,0 +1,18 @@
+#pragma omp requires dynamic_allocators
+void
+foo ()
+{
+  int a = 10;
+#pragma omp parallel private (a) allocate(a)
+  a = 20;
+#pragma omp target
+  {
+#pragma omp parallel private (a) allocate(a)
+a = 30;
+  }
+#pragma omp target private(a) allocate(a)
+  {
+a = 40;
+  }
+}
+
diff --git a/gcc/testsuite/gcc.dg/gomp/pr104517.c 
b/gcc/testsuite/gcc.dg/gomp/pr104517.c
index efb3175beb3..7e3bd1a1d1e 100644
--- a/gcc/testsuite/gcc.dg/gomp/pr104517.c
+++ b/gcc/testsuite/gcc.dg/gomp/pr104517.c
@@ -2,11 +2,13 @@
 /* { dg-do compile } */
 /* { dg-options "-O1 -fcompare-debug -fopenmp -fno-tree-ter -save-temps" } */
 
-enum {
-  omp_default_mem_alloc,
-  omp_large_cap_mem_alloc,
-  omp_const_mem_alloc,
-  omp_high_bw_mem_alloc
+typedef enum omp_allocator_handle_t
+{
+  omp_null_allocator = 0,
+  omp_default_mem_alloc = 1,
+  omp_large_cap_mem_alloc = 2,
+  omp_const_mem_alloc = 3,
+  omp_high_bw_mem_alloc = 4,
 } omp_allocator_handle_t;
 
 int t, bar_nte, bar_tl, bar_i3, bar_dd;
@@ -23,7 +25,7 @@ bar (int *idp, int s, int nth, int g, int nta, int fi, int 
pp, int *q,
   int p = 0, i2 = 0, i1 = 0, m = 0, d = 0;
 
 #pragma omp target parallel for   \
-  device(p) firstprivate (f) allocate (f) in_reduction(+:r2)
+  device(p) firstprivate (f) allocate (omp_default_mem_alloc:f) 
in_reduction(+:r2)
   for (int i = 0; i < 4; i++)
 ll++;
 
@@ -31,8 +33,8 @@ bar (int *idp, int s, int nth, int g, int nta, int fi, int 
pp, int *q,
   device(d) map (m) \
   if