This is a follow-up to r16-5789-g05c2ad4a2e7104.

Consider the following code, assuming tiles is allocatable:

type t
 integer, allocatable :: den1(:,:), den2(:,:)
end type t
[...]
!$omp target enter data map(var%tiles(1)%den2, var%tiles(1)%den1)

r16-5789-g05c2ad4a2e7104 allowed mapping several components from the same
allocatable derived type, provided they are in the right order in user code.
This patch relaxes this constraint by computing offsets and sorting to-be-mapped
components at gimplification time.

        PR fortran/120505

gcc/ChangeLog:

        * gimplify.cc (omp_accumulate_sibling_list): When the containing struct
        is a Fortran array descriptor, sort mapped components by offset.

libgomp/ChangeLog:

        * testsuite/libgomp.fortran/map-subarray-12.f90: New test.

gcc/testsuite/ChangeLog:

        * gfortran.dg/gomp/map-subarray-4.f90: New test.
---
 gcc/gimplify.cc                               | 42 ++++++++++++-------
 .../gfortran.dg/gomp/map-subarray-4.f90       | 34 +++++++++++++++
 .../libgomp.fortran/map-subarray-12.f90       | 40 ++++++++++++++++++
 3 files changed, 101 insertions(+), 15 deletions(-)
 create mode 100644 gcc/testsuite/gfortran.dg/gomp/map-subarray-4.f90
 create mode 100644 libgomp/testsuite/libgomp.fortran/map-subarray-12.f90

diff --git a/gcc/gimplify.cc b/gcc/gimplify.cc
index 8559b7ff2ad..0c08949b8cd 100644
--- a/gcc/gimplify.cc
+++ b/gcc/gimplify.cc
@@ -12934,10 +12934,6 @@ omp_accumulate_sibling_list (enum omp_region_type 
region_type,
     {
       tree *osc = struct_map_to_clause->get (base);
       tree *sc = NULL, *scp = NULL;
-      bool unordered = false;
-
-      if (osc && OMP_CLAUSE_MAP_KIND (*osc) == GOMP_MAP_STRUCT_UNORD)
-       unordered = true;
 
       unsigned HOST_WIDE_INT i, elems = tree_to_uhwi (OMP_CLAUSE_SIZE (*osc));
       sc = &OMP_CLAUSE_CHAIN (*osc);
@@ -12989,8 +12985,33 @@ omp_accumulate_sibling_list (enum omp_region_type 
region_type,
            if (variable_offset2)
              {
                OMP_CLAUSE_SET_MAP_KIND (*osc, GOMP_MAP_STRUCT_UNORD);
-               unordered = true;
-               break;
+
+               if (has_descriptor)
+                 {
+                   poly_int64 bitsize;
+                   tree offset, coffset;
+                   machine_mode mode;
+                   int unsignedp, reversep, volatilep;
+                   tree inner_ref1
+                     = get_inner_reference (sc_decl, &bitsize, &bitpos,
+                                            &offset, &mode, &unsignedp,
+                                            &reversep, &volatilep);
+                   tree osc_decl = ocd;
+                   STRIP_NOPS (osc_decl);
+                   tree inner_ref2
+                     = get_inner_reference (osc_decl, &bitsize, &bitpos,
+                                            &coffset, &mode, &unsignedp,
+                                            &reversep, &volatilep);
+                   gcc_assert (operand_equal_p (inner_ref1, inner_ref2, 0));
+                   tree offset_diff
+                     = fold_binary_to_constant (MINUS_EXPR, size_type_node,
+                                                coffset, offset);
+                   if (offset_diff == NULL_TREE
+                       || TREE_INT_CST_ELT (offset_diff, 0) > 0)
+                     continue;
+                   else
+                     break;
+                 }
              }
            else if ((region_type & ORT_ACC) != 0)
              {
@@ -13024,15 +13045,6 @@ omp_accumulate_sibling_list (enum omp_region_type 
region_type,
              }
          }
 
-      /* If this is an unordered struct, just insert the new element at the
-        end of the list.  */
-      if (unordered)
-       {
-         for (; i < elems; i++)
-           sc = &OMP_CLAUSE_CHAIN (*sc);
-         scp = NULL;
-       }
-
       OMP_CLAUSE_SIZE (*osc)
        = size_binop (PLUS_EXPR, OMP_CLAUSE_SIZE (*osc), size_one_node);
 
diff --git a/gcc/testsuite/gfortran.dg/gomp/map-subarray-4.f90 
b/gcc/testsuite/gfortran.dg/gomp/map-subarray-4.f90
new file mode 100644
index 00000000000..31db184733b
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/map-subarray-4.f90
@@ -0,0 +1,34 @@
+! { dg-do compile }
+! { dg-additional-options "-fdump-tree-gimple" }
+
+! PR fortran/120505
+
+! Check that struct components are mapped in increasing address order.
+
+module m
+type t
+ integer, allocatable :: den1(:,:), den2(:,:)
+end type t
+
+type t2
+ type(t), allocatable :: tiles(:)
+end type t2
+
+type(t2) :: var
+end
+
+use m
+
+allocate(var%tiles(1))
+var%tiles(1)%den1 = reshape([1,2,3,4],[2,2])
+var%tiles(1)%den2 = reshape([11,22,33,44],[2,2])
+
+!$omp target enter data map(var%tiles(1)%den2, var%tiles(1)%den1)
+
+! { dg-final { scan-tree-dump { map\(struct_unord:MEM <struct t\[0:\]> 
\[\(struct t\[0:\] \*\)_[0-9]+\] \[len: 2\]\) map\(to:MEM <struct t\[0:\]> 
\[\(struct t\[0:\] \*\)_[0-9]+\]\[_[0-9]+\]\.den1 \[pointer set, len: 88\]\) 
map\(to:MEM <struct t\[0:\]> \[\(struct t\[0:\] \*\)_[0-9]+\]\[_[0-9]+\]\.den2 
\[pointer set, len: 88\]\) } "gimple" } }
+
+!$omp target exit data map(var%tiles(1)%den2, var%tiles(1)%den1)
+
+! { dg-final { scan-tree-dump { map\(release:MEM <struct t\[0:\]> \[\(struct 
t\[0:\] \*\)_[0-9]+\]\[_[0-9]+\]\.den1 \[pointer set, len: 88\]\) 
map\(release:MEM <struct t\[0:\]> \[\(struct t\[0:\] 
\*\)_[0-9]+\]\[_[0-9]+\]\.den2 \[pointer set, len: 88\]\) } "gimple" } }
+
+end
diff --git a/libgomp/testsuite/libgomp.fortran/map-subarray-12.f90 
b/libgomp/testsuite/libgomp.fortran/map-subarray-12.f90
new file mode 100644
index 00000000000..21ee90d97e6
--- /dev/null
+++ b/libgomp/testsuite/libgomp.fortran/map-subarray-12.f90
@@ -0,0 +1,40 @@
+! { dg-do run }
+
+! PR fortran/120505
+
+! Check that struct components are mapped in increasing address order.
+
+module m
+type t
+ integer, allocatable :: den1(:,:), den2(:,:)
+end type t
+
+type t2
+ type(t), allocatable :: tiles(:)
+end type t2
+
+type(t2) :: var
+end
+
+use m
+
+allocate(var%tiles(1))
+var%tiles(1)%den1 = reshape([1,2,3,4],[2,2])
+var%tiles(1)%den2 = reshape([11,22,33,44],[2,2])
+
+!$omp target enter data map(var%tiles(1)%den2, var%tiles(1)%den1)
+
+!$omp target
+ if (any (var%tiles(1)%den1 /= reshape([1,2,3,4],[2,2]))) stop 1
+ if (any (var%tiles(1)%den2 /= reshape([11,22,33,44],[2,2]))) stop 1
+ var%tiles(1)%den1 = var%tiles(1)%den1 + 5
+ var%tiles(1)%den2 = var%tiles(1)%den2 + 7
+!$omp end target
+
+!$omp target exit data map(var%tiles(1)%den2, var%tiles(1)%den1)
+
+if (any (var%tiles(1)%den1 /= 5 + reshape([1,2,3,4],[2,2]))) stop 1
+if (any (var%tiles(1)%den2 /= 7 + reshape([11,22,33,44],[2,2]))) stop 1
+
+
+end
-- 
2.51.0

Reply via email to