Re: [PATCH v7 5/5] OpenMP/OpenACC: Reorganise OMP map clause handling in gimplify.cc

2023-12-21 Thread Tobias Burnus

Hi Julian,

On 20.12.23 22:29, Julian Brown wrote:

Thanks for review! Here's a new version of the patch which hopefully
addresses this round of comments.


Thanks for the patch. LGTM now.

Tobias


On Tue, 19 Dec 2023 16:41:54 +0100
Tobias Burnus  wrote:


On 16.12.23 14:25, Julian Brown wrote:

--- a/gcc/gimplify.cc
+++ b/gcc/gimplify.cc
@@ -10107,6 +10114,20 @@ omp_segregate_mapping_groups
(omp_mapping_group *inlist) ard_tail = >next;
 break;

+ case GOMP_MAP_PRESENT_ALLOC:
+   *pa_tail = w;
+   w->next = NULL;
+   pa_tail = >next;
+   break;
+
+ case GOMP_MAP_PRESENT_FROM:
+ case GOMP_MAP_PRESENT_TO:
+ case GOMP_MAP_PRESENT_TOFROM:
+   *ptf_tail = w;
+   w->next = NULL;
+   ptf_tail = >next;
+   break;
+

First, I note that GOMP_MAP_PRESENT_ALLOC and
GOMP_MAP_PRESENT_{FROM,TO,TOFROM} are semantically identical: If the
variable is not present, error termination will happen - otherwise, if
present, no data movement will happen. Hence, they will be changed to
GOMP_MAP_FORCE_PRESENT in gimplify_adjust_omp_clauses.

That's also the reason that the old code handled all of them
identical.

However, besides a plain 'present', there is also 'always' +
'present'. Those are different as after a normal 'present' check
(abort if not present), the data copying will happen:
GOMP_MAP_ALWAYS_PRESENT_TO, GOMP_MAP_ALWAYS_PRESENT_FROM,
GOMP_MAP_ALWAYS_PRESENT_TOFROM.

(Note that: always + present + alloc = GOMP_MAP_PRESENT_ALLOC (w/o
'always') as already done in the FE.)

Thus, all 'case' from your patch should go to a single group (possibly
adding a comment about it). The question is what to do with the
'present,always' case. I think leaving them under 'default:' is fine,
but I might have missed something.

I've made this change (i.e.: grouping all "GOMP_MAP_PRESENT_*" nodes
together), and in fact that restores the dump output for the
gfortran.dg/gomp/map-12.f90 that needed to be adjusted for the previous
version of the patch (so that hunk has now disappeared).


   default:
 *tf_tail = w;
 w->next = NULL;
@@ -10118,8 +10139,10 @@ omp_segregate_mapping_groups
(omp_mapping_group *inlist)

* * *

@@ -11922,119 +11945,30 @@ gimplify_scan_omp_clauses (tree *list_p,
gimple_seq *pre_p, break;
 }

-  if (code == OMP_TARGET
-  || code == OMP_TARGET_DATA
-  || code == OMP_TARGET_ENTER_DATA
-  || code == OMP_TARGET_EXIT_DATA)
-{
-  vec *groups;
-  groups = omp_gather_mapping_groups (list_p);
-  if (groups)
- {
-   hash_map
*grpmap;
-   grpmap = omp_index_mapping_groups (groups);
+  vec *groups = omp_gather_mapping_groups
(list_p);
+  hash_map *grpmap =
NULL;
+  unsigned grpnum = 0;
+  tree *grp_start_p = NULL, grp_end = NULL_TREE;

...


-  else if (region_type & ORT_ACC)
-{

I wonder whether you should not better call
'omp_gather_mapping_groups' only for the 'code == OMP_TARGET...' and
for ORT_ACC (or some subset of OACC *), given that this function is
also called bygimplify_omp_parallel, gimplify_omp_task,
gimplify_omp_for, ...

This avoids some memory allocation and list_p walking, i.e. it is not
too bad - but also not really needed for task, parallel, for, ...

I've made that change -- OpenACC uses OMP_CLAUSE_MAP in quite a wide
range of directives, but the new version of the patch lists them
individually anyway, rather than using a catch-all for ORT_ACC regions.
That seems OK, I think.


@@ -14008,26 +13926,73 @@ gimplify_adjust_omp_clauses (gimple_seq
*pre_p, gimple_seq body, tree *list_p, default:
 break;
   }
-   if (code == OMP_TARGET_EXIT_DATA
-   && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ALWAYS_POINTER)
+   switch (code)
   {
+ case OMP_TARGET:
+   break;
+ case OACC_DATA:
+   if (TREE_CODE (TREE_TYPE (decl)) != ARRAY_TYPE)
+ break;
+   goto check_firstprivate;
+ case OACC_ENTER_DATA:
+ case OACC_EXIT_DATA:
+ case OMP_TARGET_DATA:
+ case OMP_TARGET_ENTER_DATA:
+ case OMP_TARGET_EXIT_DATA:
+ case OACC_HOST_DATA:
+ check_firstprivate:
+   if (OMP_CLAUSE_MAP_KIND (c) ==
GOMP_MAP_FIRSTPRIVATE_POINTER

I think it looks nicer if the OACC_HOST is before OMP_* such that all
OACC_* are together. (In the old code, oacc_enter/exit was treated
differently than OMP_* and OACC_HOST_DATA; your order is a leftover
from that code movement/change.)

I've fixed this bit -- which actually doesn't need the goto any more
either, so that's now a fallthrough instead.


+ flags = GOVD_MAP | GOVD_EXPLICIT;
+ if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ALWAYS_TO
+ || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ALWAYS_TOFROM)
+   flags |= GOVD_MAP_ALWAYS_TO;

I know that the code has only been moved, but I wonder whether that
should also include GOMP_MAP_ALWAYS_PRESENT_{TO,TOFROM} as condition.

I've added it (caveat: without any tests).


Re: [PATCH v7 5/5] OpenMP/OpenACC: Reorganise OMP map clause handling in gimplify.cc

2023-12-20 Thread Julian Brown
Hi Tobias,

Thanks for review! Here's a new version of the patch which hopefully
addresses this round of comments.

On Tue, 19 Dec 2023 16:41:54 +0100
Tobias Burnus  wrote:

> On 16.12.23 14:25, Julian Brown wrote:
> > --- a/gcc/gimplify.cc
> > +++ b/gcc/gimplify.cc
> > @@ -10107,6 +10114,20 @@ omp_segregate_mapping_groups
> > (omp_mapping_group *inlist) ard_tail = >next;
> > break;
> >
> > + case GOMP_MAP_PRESENT_ALLOC:
> > +   *pa_tail = w;
> > +   w->next = NULL;
> > +   pa_tail = >next;
> > +   break;
> > +
> > + case GOMP_MAP_PRESENT_FROM:
> > + case GOMP_MAP_PRESENT_TO:
> > + case GOMP_MAP_PRESENT_TOFROM:
> > +   *ptf_tail = w;
> > +   w->next = NULL;
> > +   ptf_tail = >next;
> > +   break;
> > +  
> 
> First, I note that GOMP_MAP_PRESENT_ALLOC and
> GOMP_MAP_PRESENT_{FROM,TO,TOFROM} are semantically identical: If the
> variable is not present, error termination will happen - otherwise, if
> present, no data movement will happen. Hence, they will be changed to
> GOMP_MAP_FORCE_PRESENT in gimplify_adjust_omp_clauses.
> 
> That's also the reason that the old code handled all of them
> identical.
> 
> However, besides a plain 'present', there is also 'always' +
> 'present'. Those are different as after a normal 'present' check
> (abort if not present), the data copying will happen:
> GOMP_MAP_ALWAYS_PRESENT_TO, GOMP_MAP_ALWAYS_PRESENT_FROM,
> GOMP_MAP_ALWAYS_PRESENT_TOFROM.
> 
> (Note that: always + present + alloc = GOMP_MAP_PRESENT_ALLOC (w/o
> 'always') as already done in the FE.)
> 
> Thus, all 'case' from your patch should go to a single group (possibly
> adding a comment about it). The question is what to do with the
> 'present,always' case. I think leaving them under 'default:' is fine,
> but I might have missed something.

I've made this change (i.e.: grouping all "GOMP_MAP_PRESENT_*" nodes
together), and in fact that restores the dump output for the
gfortran.dg/gomp/map-12.f90 that needed to be adjusted for the previous
version of the patch (so that hunk has now disappeared).

> >   default:
> > *tf_tail = w;
> > w->next = NULL;
> > @@ -10118,8 +10139,10 @@ omp_segregate_mapping_groups
> > (omp_mapping_group *inlist)  
> * * *
> > @@ -11922,119 +11945,30 @@ gimplify_scan_omp_clauses (tree *list_p,
> > gimple_seq *pre_p, break;
> > }
> >
> > -  if (code == OMP_TARGET
> > -  || code == OMP_TARGET_DATA
> > -  || code == OMP_TARGET_ENTER_DATA
> > -  || code == OMP_TARGET_EXIT_DATA)
> > -{
> > -  vec *groups;
> > -  groups = omp_gather_mapping_groups (list_p);
> > -  if (groups)
> > - {
> > -   hash_map
> > *grpmap;
> > -   grpmap = omp_index_mapping_groups (groups);
> > +  vec *groups = omp_gather_mapping_groups
> > (list_p);
> > +  hash_map *grpmap =
> > NULL;
> > +  unsigned grpnum = 0;
> > +  tree *grp_start_p = NULL, grp_end = NULL_TREE;  
> 
> ...
> 
> > -  else if (region_type & ORT_ACC)
> > -{  
> I wonder whether you should not better call
> 'omp_gather_mapping_groups' only for the 'code == OMP_TARGET...' and
> for ORT_ACC (or some subset of OACC *), given that this function is
> also called bygimplify_omp_parallel, gimplify_omp_task,
> gimplify_omp_for, ...
> 
> This avoids some memory allocation and list_p walking, i.e. it is not
> too bad - but also not really needed for task, parallel, for, ...

I've made that change -- OpenACC uses OMP_CLAUSE_MAP in quite a wide
range of directives, but the new version of the patch lists them
individually anyway, rather than using a catch-all for ORT_ACC regions.
That seems OK, I think.

> > @@ -14008,26 +13926,73 @@ gimplify_adjust_omp_clauses (gimple_seq
> > *pre_p, gimple_seq body, tree *list_p, default:
> > break;
> >   }
> > -   if (code == OMP_TARGET_EXIT_DATA
> > -   && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ALWAYS_POINTER)
> > +   switch (code)
> >   {
> > + case OMP_TARGET:
> > +   break;
> > + case OACC_DATA:
> > +   if (TREE_CODE (TREE_TYPE (decl)) != ARRAY_TYPE)
> > + break;
> > +   goto check_firstprivate;
> > + case OACC_ENTER_DATA:
> > + case OACC_EXIT_DATA:
> > + case OMP_TARGET_DATA:
> > + case OMP_TARGET_ENTER_DATA:
> > + case OMP_TARGET_EXIT_DATA:
> > + case OACC_HOST_DATA:
> > + check_firstprivate:
> > +   if (OMP_CLAUSE_MAP_KIND (c) ==
> > GOMP_MAP_FIRSTPRIVATE_POINTER  
> 
> I think it looks nicer if the OACC_HOST is before OMP_* such that all
> OACC_* are together. (In the old code, oacc_enter/exit was treated
> differently than OMP_* and OACC_HOST_DATA; your order is a leftover
> from that code movement/change.)

I've fixed this bit -- which actually doesn't need the goto any more
either, so that's now a fallthrough instead.

> > + flags = GOVD_MAP | GOVD_EXPLICIT;
> > + if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ALWAYS_TO
> > +   

Re: [PATCH v7 5/5] OpenMP/OpenACC: Reorganise OMP map clause handling in gimplify.cc

2023-12-19 Thread Tobias Burnus

Hi Julian,

On 16.12.23 14:25, Julian Brown wrote:

 OpenMP/OpenACC: Reorganise OMP map clause handling in gimplify.cc

 This patch has been separated out from the C++ "declare mapper"
 support patch.  It contains just the gimplify.cc rearrangement
 work, mostly moving gimplification from gimplify_scan_omp_clauses
 to gimplify_adjust_omp_clauses for map clauses.

 The motivation for doing this was that we don't know if we need to
 instantiate mappers implicitly until the body of an offload region has
 been scanned, i.e. in gimplify_adjust_omp_clauses, but we also need the
 un-gimplified form of clauses to sort by base-pointer dependencies after
 mapper instantiation has taken place.

 The patch also reimplements the "present" clause sorting code to avoid
 another sorting pass on mapping nodes.

 This version of the patch is based on the version posted for og13, and
 additionally incorporates a follow-on fix for DECL_VALUE_EXPR handling
 in gimplify_adjust_omp_clauses:

 "OpenMP/OpenACC: Reorganise OMP map clause handling in gimplify.cc"
 https://gcc.gnu.org/pipermail/gcc-patches/2023-June/63.html

 Parts of:
 "OpenMP: OpenMP 5.2 semantics for pointers with unmapped target"
 https://gcc.gnu.org/pipermail/gcc-patches/2023-June/623351.html


I find the patch hard to digest - and I wouldn't be surprised if I
missed something.

However, I think the patch is OK - except for a few minor observations:


 2023-12-16  Julian Brown

 gcc/
 * gimplify.cc (omp_segregate_mapping_groups): Handle "present" 
groups.
 (gimplify_scan_omp_clauses): Use mapping group functionality to
 iterate through mapping nodes.  Remove most gimplification of
 OMP_CLAUSE_MAP nodes from here, but still populate ctx->variables
 splay tree.
 (gimplify_adjust_omp_clauses): Move most gimplification of
 OMP_CLAUSE_MAP nodes here.

 gcc/testsuite/
 * gfortran.dg/gomp/map-12.f90: Adjust scan output.

 libgomp/
 * testsuite/libgomp.fortran/target-enter-data-6.f90: Remove XFAIL.



diff --git a/gcc/gimplify.cc b/gcc/gimplify.cc
index a6bdceab45d..fa6ddd546f8 100644
--- a/gcc/gimplify.cc
+++ b/gcc/gimplify.cc
@@ -10107,6 +10114,20 @@ omp_segregate_mapping_groups (omp_mapping_group 
*inlist)
ard_tail = >next;
break;

+ case GOMP_MAP_PRESENT_ALLOC:
+   *pa_tail = w;
+   w->next = NULL;
+   pa_tail = >next;
+   break;
+
+ case GOMP_MAP_PRESENT_FROM:
+ case GOMP_MAP_PRESENT_TO:
+ case GOMP_MAP_PRESENT_TOFROM:
+   *ptf_tail = w;
+   w->next = NULL;
+   ptf_tail = >next;
+   break;
+


First, I note that GOMP_MAP_PRESENT_ALLOC and
GOMP_MAP_PRESENT_{FROM,TO,TOFROM} are semantically identical: If the
variable is not present, error termination will happen - otherwise, if
present, no data movement will happen. Hence, they will be changed to
GOMP_MAP_FORCE_PRESENT in gimplify_adjust_omp_clauses.

That's also the reason that the old code handled all of them identical.

However, besides a plain 'present', there is also 'always' + 'present'.
Those are different as after a normal 'present' check (abort if not
present), the data copying will happen: GOMP_MAP_ALWAYS_PRESENT_TO,
GOMP_MAP_ALWAYS_PRESENT_FROM, GOMP_MAP_ALWAYS_PRESENT_TOFROM.

(Note that: always + present + alloc = GOMP_MAP_PRESENT_ALLOC (w/o
'always') as already done in the FE.)

Thus, all 'case' from your patch should go to a single group (possibly
adding a comment about it). The question is what to do with the
'present,always' case. I think leaving them under 'default:' is fine,
but I might have missed something.


  default:
*tf_tail = w;
w->next = NULL;
@@ -10118,8 +10139,10 @@ omp_segregate_mapping_groups (omp_mapping_group 
*inlist)

* * *

@@ -11922,119 +11945,30 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq 
*pre_p,
  break;
}

-  if (code == OMP_TARGET
-  || code == OMP_TARGET_DATA
-  || code == OMP_TARGET_ENTER_DATA
-  || code == OMP_TARGET_EXIT_DATA)
-{
-  vec *groups;
-  groups = omp_gather_mapping_groups (list_p);
-  if (groups)
- {
-   hash_map *grpmap;
-   grpmap = omp_index_mapping_groups (groups);
+  vec *groups = omp_gather_mapping_groups (list_p);
+  hash_map *grpmap = NULL;
+  unsigned grpnum = 0;
+  tree *grp_start_p = NULL, grp_end = NULL_TREE;


...


-  else if (region_type & ORT_ACC)
-{

I wonder whether you should not better call 'omp_gather_mapping_groups'
only for the 'code == OMP_TARGET...' and for ORT_ACC (or some subset of
OACC *), given that this function is also called
bygimplify_omp_parallel, gimplify_omp_task, gimplify_omp_for, ...

This avoids some memory allocation and list_p walking, i.e. it is not
too bad - but also not really needed for task, parallel, for, ...


@@ -14008,26 +13926,73 @@ 

[PATCH v7 5/5] OpenMP/OpenACC: Reorganise OMP map clause handling in gimplify.cc

2023-08-18 Thread Julian Brown
This patch has been separated out from the C++ "declare mapper"
support patch.  It contains just the gimplify.cc rearrangement
work, mostly moving gimplification from gimplify_scan_omp_clauses
to gimplify_adjust_omp_clauses for map clauses.

The motivation for doing this was that we don't know if we need to
instantiate mappers implicitly until the body of an offload region has
been scanned, i.e. in gimplify_adjust_omp_clauses, but we also need the
un-gimplified form of clauses to sort by base-pointer dependencies after
mapper instantiation has taken place.

The patch also reimplements the "present" clause sorting code to avoid
another sorting pass on mapping nodes.

This version of the patch is based on the version posted for og13, and
additionally incorporates a follow-on fix for DECL_VALUE_EXPR handling
in gimplify_adjust_omp_clauses:

"OpenMP/OpenACC: Reorganise OMP map clause handling in gimplify.cc"
https://gcc.gnu.org/pipermail/gcc-patches/2023-June/63.html

Parts of:
"OpenMP: OpenMP 5.2 semantics for pointers with unmapped target"
https://gcc.gnu.org/pipermail/gcc-patches/2023-June/623351.html

2023-08-18  Julian Brown  

gcc/
* gimplify.cc (omp_segregate_mapping_groups): Handle "present" groups.
(gimplify_scan_omp_clauses): Use mapping group functionality to
iterate through mapping nodes.  Remove most gimplification of
OMP_CLAUSE_MAP nodes from here, but still populate ctx->variables
splay tree.
(gimplify_adjust_omp_clauses): Move most gimplification of
OMP_CLAUSE_MAP nodes here.

gcc/testsuite/
* gfortran.dg/gomp/map-12.f90: Adjust scan output.
---
 gcc/gimplify.cc   | 667 +-
 gcc/testsuite/gfortran.dg/gomp/map-12.f90 |   2 +-
 2 files changed, 386 insertions(+), 283 deletions(-)

diff --git a/gcc/gimplify.cc b/gcc/gimplify.cc
index e682583054b0..1e32ad48b844 100644
--- a/gcc/gimplify.cc
+++ b/gcc/gimplify.cc
@@ -9804,10 +9804,15 @@ omp_tsort_mapping_groups (vec 
*groups,
   return outlist;
 }
 
-/* Split INLIST into two parts, moving groups corresponding to
-   ALLOC/RELEASE/DELETE mappings to one list, and other mappings to another.
-   The former list is then appended to the latter.  Each sub-list retains the
-   order of the original list.
+/* Split INLIST into four parts:
+
+ - "present" to/from groups
+ - "present" alloc groups
+ - other to/from groups
+ - other alloc/release/delete groups
+
+   These sub-lists are then concatenated together to form the final list.
+   Each sub-list retains the order of the original list.
Note that ATTACH nodes are later moved to the end of the list in
gimplify_adjust_omp_clauses, for target regions.  */
 
@@ -9815,7 +9820,9 @@ static omp_mapping_group *
 omp_segregate_mapping_groups (omp_mapping_group *inlist)
 {
   omp_mapping_group *ard_groups = NULL, *tf_groups = NULL;
+  omp_mapping_group *pa_groups = NULL, *ptf_groups = NULL;
   omp_mapping_group **ard_tail = _groups, **tf_tail = _groups;
+  omp_mapping_group **pa_tail = _groups, **ptf_tail = _groups;
 
   for (omp_mapping_group *w = inlist; w;)
 {
@@ -9834,6 +9841,20 @@ omp_segregate_mapping_groups (omp_mapping_group *inlist)
  ard_tail = >next;
  break;
 
+   case GOMP_MAP_PRESENT_ALLOC:
+ *pa_tail = w;
+ w->next = NULL;
+ pa_tail = >next;
+ break;
+
+   case GOMP_MAP_PRESENT_FROM:
+   case GOMP_MAP_PRESENT_TO:
+   case GOMP_MAP_PRESENT_TOFROM:
+ *ptf_tail = w;
+ w->next = NULL;
+ ptf_tail = >next;
+ break;
+
default:
  *tf_tail = w;
  w->next = NULL;
@@ -9845,8 +9866,10 @@ omp_segregate_mapping_groups (omp_mapping_group *inlist)
 
   /* Now splice the lists together...  */
   *tf_tail = ard_groups;
+  *pa_tail = tf_groups;
+  *ptf_tail = pa_groups;
 
-  return tf_groups;
+  return ptf_groups;
 }
 
 /* Given a list LIST_P containing groups of mappings given by GROUPS, reorder
@@ -11698,119 +11721,30 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq 
*pre_p,
break;
   }
 
-  if (code == OMP_TARGET
-  || code == OMP_TARGET_DATA
-  || code == OMP_TARGET_ENTER_DATA
-  || code == OMP_TARGET_EXIT_DATA)
-{
-  vec *groups;
-  groups = omp_gather_mapping_groups (list_p);
-  if (groups)
-   {
- hash_map *grpmap;
- grpmap = omp_index_mapping_groups (groups);
+  vec *groups = omp_gather_mapping_groups (list_p);
+  hash_map *grpmap = NULL;
+  unsigned grpnum = 0;
+  tree *grp_start_p = NULL, grp_end = NULL_TREE;
 
- omp_resolve_clause_dependencies (code, groups, grpmap);
- omp_build_struct_sibling_lists (code, region_type, groups, ,
- list_p);
-
- omp_mapping_group *outlist = NULL;
- bool enter_exit = (code == OMP_TARGET_ENTER_DATA
-|| code == OMP_TARGET_EXIT_DATA);
-
- /* Topological