This patch fixes a case where POINTER attribute arrays are deep copied when not 
supposed to.

This creates a new langhook 'omp_array_data_privatize' to differentiate cases 
in certain
places during omp-low.

Still under final testing. Okay for mainline if everything passes?

Thanks,
Chung-Lin

gcc/fortran/ChangeLog:

        * f95-lang.cc (LANG_HOOKS_OMP_ARRAY_DATA_PRIVATIZE): Define as
        gfc_omp_array_data_privatize.
        * trans-openmp.cc (gfc_omp_array_data_privatize): New function.
        * trans.h (gfc_omp_array_data_privatize): New declaration.

gcc/ChangeLog:

        * langhooks-def.h (LANG_HOOKS_OMP_ARRAY_DATA_PRIVATIZE): Define.
        * langhooks.h (struct lang_hooks_for_decls): Define
        omp_array_data_privatize hook.
        * omp-low.cc (scan_sharing_clauses): Add new calls to
        lang_hooks.decls.omp_array_data_privatize,
        (lower_omp_target): Likewise.

libgomp/ChangeLog:

        * testsuite/libgomp.fortran/pr122910.f90: New test.
diff --git a/gcc/fortran/f95-lang.cc b/gcc/fortran/f95-lang.cc
index 45aab34865f..12ab1d251da 100644
--- a/gcc/fortran/f95-lang.cc
+++ b/gcc/fortran/f95-lang.cc
@@ -135,6 +135,7 @@ gfc_get_sarif_source_language (const char *)
 #undef LANG_HOOKS_TYPE_FOR_SIZE
 #undef LANG_HOOKS_INIT_TS
 #undef LANG_HOOKS_OMP_ARRAY_DATA
+#undef LANG_HOOKS_OMP_ARRAY_DATA_PRIVATIZE
 #undef LANG_HOOKS_OMP_ARRAY_SIZE
 #undef LANG_HOOKS_OMP_IS_ALLOCATABLE_OR_PTR
 #undef LANG_HOOKS_OMP_CHECK_OPTIONAL_ARGUMENT
@@ -178,6 +179,7 @@ gfc_get_sarif_source_language (const char *)
 #define LANG_HOOKS_TYPE_FOR_SIZE       gfc_type_for_size
 #define LANG_HOOKS_INIT_TS             gfc_init_ts
 #define LANG_HOOKS_OMP_ARRAY_DATA              gfc_omp_array_data
+#define LANG_HOOKS_OMP_ARRAY_DATA_PRIVATIZE    gfc_omp_array_data_privatize
 #define LANG_HOOKS_OMP_ARRAY_SIZE              gfc_omp_array_size
 #define LANG_HOOKS_OMP_IS_ALLOCATABLE_OR_PTR   gfc_omp_is_allocatable_or_ptr
 #define LANG_HOOKS_OMP_CHECK_OPTIONAL_ARGUMENT gfc_omp_check_optional_argument
diff --git a/gcc/fortran/trans-openmp.cc b/gcc/fortran/trans-openmp.cc
index b9c09d114b7..e64fa82a238 100644
--- a/gcc/fortran/trans-openmp.cc
+++ b/gcc/fortran/trans-openmp.cc
@@ -176,6 +176,24 @@ gfc_omp_array_data (tree decl, bool type_only)
   return decl;
 }
 
+/* Returns true if it is an array descriptor where the data is to be copied
+   and privatized.  Assumes the above 'omp_array_data' to already be true
+   (hence the assertion of descriptor type here).  */
+
+bool
+gfc_omp_array_data_privatize (tree decl)
+{
+  tree type = TREE_TYPE (decl);
+
+  if (POINTER_TYPE_P (type))
+    type = TREE_TYPE (type);
+
+  gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
+
+  return (GFC_TYPE_ARRAY_AKIND (type) != GFC_ARRAY_POINTER
+         && GFC_TYPE_ARRAY_AKIND (type) != GFC_ARRAY_POINTER_CONT);
+}
+
 /* Return the byte-size of the passed array descriptor. */
 
 tree
diff --git a/gcc/fortran/trans.h b/gcc/fortran/trans.h
index f97fefd2ac0..0bdee5820fd 100644
--- a/gcc/fortran/trans.h
+++ b/gcc/fortran/trans.h
@@ -827,6 +827,7 @@ tree gfc_omp_call_is_alloc (tree);
 bool gfc_omp_is_allocatable_or_ptr (const_tree);
 tree gfc_omp_check_optional_argument (tree, bool);
 tree gfc_omp_array_data (tree, bool);
+bool gfc_omp_array_data_privatize (tree);
 tree gfc_omp_array_size (tree, gimple_seq *);
 bool gfc_omp_privatize_by_reference (const_tree);
 enum omp_clause_default_kind gfc_omp_predetermined_sharing (tree);
diff --git a/gcc/langhooks-def.h b/gcc/langhooks-def.h
index fc409ec08b9..33a99266187 100644
--- a/gcc/langhooks-def.h
+++ b/gcc/langhooks-def.h
@@ -263,6 +263,7 @@ extern tree lhd_unit_size_without_reusable_padding (tree);
 #define LANG_HOOKS_POST_COMPILATION_PARSING_CLEANUPS NULL
 #define LANG_HOOKS_DECL_OK_FOR_SIBCALL lhd_decl_ok_for_sibcall
 #define LANG_HOOKS_OMP_ARRAY_DATA      hook_tree_tree_bool_null
+#define LANG_HOOKS_OMP_ARRAY_DATA_PRIVATIZE hook_bool_tree_false
 #define LANG_HOOKS_OMP_ARRAY_SIZE      lhd_omp_array_size
 #define LANG_HOOKS_OMP_IS_ALLOCATABLE_OR_PTR hook_bool_const_tree_false
 #define LANG_HOOKS_OMP_CHECK_OPTIONAL_ARGUMENT hook_tree_tree_bool_null
@@ -305,7 +306,8 @@ extern tree lhd_unit_size_without_reusable_padding (tree);
   LANG_HOOKS_POST_COMPILATION_PARSING_CLEANUPS, \
   LANG_HOOKS_DECL_OK_FOR_SIBCALL, \
   LANG_HOOKS_OMP_ARRAY_DATA, \
-  LANG_HOOKS_OMP_ARRAY_SIZE, \
+  LANG_HOOKS_OMP_ARRAY_DATA_PRIVATIZE, \
+  LANG_HOOKS_OMP_ARRAY_SIZE,           \
   LANG_HOOKS_OMP_IS_ALLOCATABLE_OR_PTR, \
   LANG_HOOKS_OMP_CHECK_OPTIONAL_ARGUMENT, \
   LANG_HOOKS_OMP_PRIVATIZE_BY_REFERENCE, \
diff --git a/gcc/langhooks.h b/gcc/langhooks.h
index 6eb5c1602f8..aa983165ab5 100644
--- a/gcc/langhooks.h
+++ b/gcc/langhooks.h
@@ -243,6 +243,10 @@ struct lang_hooks_for_decls
      is true, only the TREE_TYPE is returned without generating a new tree.  */
   tree (*omp_array_data) (tree, bool);
 
+  /* Return true if the data of an array descriptor is to be copied and
+     privatized.  Assumes omp_array_data returns non-NULL_TREE.  */
+  bool (*omp_array_data_privatize) (tree);
+
   /* Return a tree for the actual data of an array descriptor - or NULL_TREE
      if original tree is not an array descriptor.  If the second argument
      is true, only the TREE_TYPE is returned without generating a new tree.  */
diff --git a/gcc/omp-low.cc b/gcc/omp-low.cc
index b93012107f1..79228b6350a 100644
--- a/gcc/omp-low.cc
+++ b/gcc/omp-low.cc
@@ -1443,7 +1443,8 @@ scan_sharing_clauses (tree clauses, omp_context *ctx)
          if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE
              && is_gimple_omp_offloaded (ctx->stmt)
              && !is_gimple_omp_oacc (ctx->stmt)
-             && lang_hooks.decls.omp_array_data (decl, true))
+             && lang_hooks.decls.omp_array_data (decl, true)
+             && lang_hooks.decls.omp_array_data_privatize (decl))
            {
              install_var_field (decl, false, 16 | 3, ctx);
              install_var_field (decl, true, 8 | 3, ctx);
@@ -13046,7 +13047,8 @@ lower_omp_target (gimple_stmt_iterator *gsi_p, 
omp_context *ctx)
          }
          /* Fortran array descriptors: firstprivate of data + attach.  */
          if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_HAS_DEVICE_ADDR
-             && lang_hooks.decls.omp_array_data (var, true))
+             && lang_hooks.decls.omp_array_data (var, true)
+             && lang_hooks.decls.omp_array_data_privatize (var))
            map_cnt += 2;
 
       do_dtor:
@@ -13725,7 +13727,8 @@ lower_omp_target (gimple_stmt_iterator *gsi_p, 
omp_context *ctx)
                                    build_int_cstu (tkind_type, tkind));
            /* Fortran array descriptors: firstprivate of data + attach.  */
            if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_HAS_DEVICE_ADDR
-               && lang_hooks.decls.omp_array_data (ovar, true))
+               && lang_hooks.decls.omp_array_data (ovar, true)
+               && lang_hooks.decls.omp_array_data_privatize (ovar))
              {
                tree not_null_lb, null_lb, after_lb;
                tree var1, var2, size1, size2;
diff --git a/libgomp/testsuite/libgomp.fortran/pr122910.f90 
b/libgomp/testsuite/libgomp.fortran/pr122910.f90
new file mode 100644
index 00000000000..6081dfa4ea9
--- /dev/null
+++ b/libgomp/testsuite/libgomp.fortran/pr122910.f90
@@ -0,0 +1,23 @@
+! { dg-do run { target { ! offload_device } } }
+
+program main
+  implicit none
+
+  !$omp requires self_maps
+
+  integer :: i
+  INTEGER, POINTER :: fptr(:)
+  integer, parameter :: N = 5
+
+  ALLOCATE(fptr(N))
+  fptr = 0
+
+  !$omp target firstprivate(fptr)
+  DO i=1, N
+     fptr(i) = 5*i
+  END DO
+  !$omp end target
+
+  if (any (fptr /= 5*[1,2,3,4,5])) stop 1
+
+end program

Reply via email to