This patch fixes "exit data" for (C++) reference-to-pointer struct
components with array sections, such as:

  struct S { int *&ptr; [...] };
  ...
  #pragma omp target exit data map(from: str->ptr, str->ptr[0:n])

Such exits need two "detach" operations. We need to unmap
both the pointer and the slice. That idiom is recognized by
omp_resolve_clause_dependencies, but before omp_build_struct_sibling_lists
finishes the resulting mapping nodes are represented like this:

  GOMP_MAP_FROM GOMP_MAP_DETACH GOMP_MAP_ATTACH_DETACH

And at the moment, that won't be recognized as a single mapping group
as it should be. This patch fixes that.

(This is covered by a test case added in later patches in this series,
e.g. libgomp/testsuite/libgomp.c++/array-shaping-8.C.)

2023-07-03  Julian Brown  <jul...@codesourcery.com>

gcc/
        * gimplify.cc (omp_get_attachment): Handle GOMP_MAP_DETACH here.
        (omp_group_last): Handle *, GOMP_MAP_DETACH, GOMP_MAP_ATTACH_DETACH
        groups for "exit data" of reference-to-pointer component array
        sections.
        (omp_group_base): Handle GOMP_MAP_DETACH.
---
 gcc/gimplify.cc | 30 ++++++++++++++++++++++++++----
 1 file changed, 26 insertions(+), 4 deletions(-)

diff --git a/gcc/gimplify.cc b/gcc/gimplify.cc
index 20aba45110f..6280eb7e028 100644
--- a/gcc/gimplify.cc
+++ b/gcc/gimplify.cc
@@ -9171,6 +9171,7 @@ omp_get_attachment (omp_mapping_group *grp)
 
          case GOMP_MAP_ATTACH_DETACH:
          case GOMP_MAP_ATTACH_ZERO_LENGTH_ARRAY_SECTION:
+         case GOMP_MAP_DETACH:
            return OMP_CLAUSE_DECL (node);
 
          default:
@@ -9247,23 +9248,43 @@ omp_group_last (tree *start_p)
                     == GOMP_MAP_POINTER_TO_ZERO_LENGTH_ARRAY_SECTION)
                 || (OMP_CLAUSE_MAP_KIND (nc)
                     == GOMP_MAP_ATTACH_ZERO_LENGTH_ARRAY_SECTION)
+                || OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_DETACH
                 || OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_ALWAYS_POINTER
                 || omp_map_clause_descriptor_p (nc)))
        {
-         grp_last_p = &OMP_CLAUSE_CHAIN (c);
-         c = nc;
          tree nc2 = OMP_CLAUSE_CHAIN (nc);
+         if (OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_DETACH)
+           {
+             /* In the specific case we're doing "exit data" on an array
+                slice of a reference-to-pointer struct component, we will see
+                DETACH followed by ATTACH_DETACH here.  We want to treat that
+                as a single group. In other cases DETACH might represent a
+                stand-alone "detach" clause, so we don't want to consider
+                that part of the group.  */
+             if (nc2
+                 && OMP_CLAUSE_CODE (nc2) == OMP_CLAUSE_MAP
+                 && OMP_CLAUSE_MAP_KIND (nc2) == GOMP_MAP_ATTACH_DETACH)
+               goto consume_two_nodes;
+             else
+               break;
+           }
          if (nc2
              && OMP_CLAUSE_CODE (nc2) == OMP_CLAUSE_MAP
              && (OMP_CLAUSE_MAP_KIND (nc)
                  == GOMP_MAP_POINTER_TO_ZERO_LENGTH_ARRAY_SECTION)
              && OMP_CLAUSE_MAP_KIND (nc2) == GOMP_MAP_ATTACH)
            {
+           consume_two_nodes:
              grp_last_p = &OMP_CLAUSE_CHAIN (nc);
              c = nc2;
-             nc2 = OMP_CLAUSE_CHAIN (nc2);
+             nc = OMP_CLAUSE_CHAIN (nc2);
+           }
+         else
+           {
+             grp_last_p = &OMP_CLAUSE_CHAIN (c);
+             c = nc;
+             nc = nc2;
            }
-          nc = nc2;
        }
       break;
 
@@ -9416,6 +9437,7 @@ omp_group_base (omp_mapping_group *grp, unsigned int 
*chained,
        case GOMP_MAP_ALWAYS_POINTER:
        case GOMP_MAP_ATTACH_DETACH:
        case GOMP_MAP_ATTACH_ZERO_LENGTH_ARRAY_SECTION:
+       case GOMP_MAP_DETACH:
          return *grp->grp_start;
 
        default:
-- 
2.25.1

Reply via email to