]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
OpenMP/Fortran: Implement omp allocators/allocate for ptr/allocatables
authorTobias Burnus <tobias@codesourcery.com>
Fri, 8 Dec 2023 14:18:25 +0000 (15:18 +0100)
committerTobias Burnus <tobias@codesourcery.com>
Fri, 8 Dec 2023 14:18:25 +0000 (15:18 +0100)
This commit adds -fopenmp-allocators which enables support for
'omp allocators' and 'omp allocate' that are associated with a Fortran
allocate-stmt. If such a construct is encountered, an error is shown,
unless the -fopenmp-allocators flag is present.

With -fopenmp -fopenmp-allocators, those constructs get turned into
GOMP_alloc allocations, while -fopenmp-allocators (also without -fopenmp)
ensures deallocation and reallocation (via intrinsic assignments) are
properly directed to GOMP_free/omp_realloc - while normal Fortran
allocations are processed by free/realloc.

In order to distinguish a 'malloc'ed from a 'GOMP_alloc'ed memory, the
version field of the Fortran array discriptor is (mis)used: 0 indicates
the normal Fortran allocation while 1 denotes GOMP_alloc. For scalars,
there is record keeping in libgomp: GOMP_add_alloc(ptr) will add the
pointer address to a splay_tree while GOMP_is_alloc(ptr) will return
true it was previously added but also removes it from the list.

Besides Fortran FE work, BUILT_IN_GOMP_REALLOC is no part of
omp-builtins.def and libgomp gains the mentioned two new function.

gcc/ChangeLog:

* builtin-types.def (BT_FN_PTR_PTR_SIZE_PTRMODE_PTRMODE): New.
* omp-builtins.def (BUILT_IN_GOMP_REALLOC): New.
* builtins.cc (builtin_fnspec): Handle it.
* gimple-ssa-warn-access.cc (fndecl_alloc_p,
matching_alloc_calls_p): Likewise.
* gimple.cc (nonfreeing_call_p): Likewise.
* predict.cc (expr_expected_value_1): Likewise.
* tree-ssa-ccp.cc (evaluate_stmt): Likewise.
* tree.cc (fndecl_dealloc_argno): Likewise.

gcc/fortran/ChangeLog:

* dump-parse-tree.cc (show_omp_node): Handle EXEC_OMP_ALLOCATE
and EXEC_OMP_ALLOCATORS.
* f95-lang.cc (ATTR_ALLOC_WARN_UNUSED_RESULT_SIZE_2_NOTHROW_LIST):
Add 'ECF_LEAF | ECF_MALLOC' to existing 'ECF_NOTHROW'.
(ATTR_ALLOC_WARN_UNUSED_RESULT_SIZE_2_NOTHROW_LEAF_LIST): Define.
* gfortran.h (gfc_omp_clauses): Add contained_in_target_construct.
* invoke.texi (-fopenacc, -fopenmp): Update based on C version.
(-fopenmp-simd): New, based on C version.
(-fopenmp-allocators): New.
* lang.opt (fopenmp-allocators): Add.
* openmp.cc (resolve_omp_clauses): For allocators/allocate directive,
add target and no dynamic_allocators diagnostic and more invalid
diagnostic.
* parse.cc (decode_omp_directive): Set contains_teams_construct.
* trans-array.h (gfc_array_allocate): Update prototype.
(gfc_conv_descriptor_version): New prototype.
* trans-decl.cc (gfc_init_default_dt): Fix comment.
* trans-array.cc (gfc_conv_descriptor_version): New.
(gfc_array_allocate): Support GOMP_alloc allocation.
(gfc_alloc_allocatable_for_assignment, structure_alloc_comps):
Handle GOMP_free/omp_realloc as needed.
* trans-expr.cc (gfc_conv_procedure_call): Likewise.
(alloc_scalar_allocatable_for_assignment): Likewise.
* trans-intrinsic.cc (conv_intrinsic_move_alloc): Likewise.
* trans-openmp.cc (gfc_trans_omp_allocators,
gfc_trans_omp_directive): Handle allocators/allocate directive.
(gfc_omp_call_add_alloc, gfc_omp_call_is_alloc): New.
* trans-stmt.h (gfc_trans_allocate): Update prototype.
* trans-stmt.cc (gfc_trans_allocate): Support GOMP_alloc.
* trans-types.cc (gfc_get_dtype_rank_type): Set version field.
* trans.cc (gfc_allocate_using_malloc, gfc_allocate_allocatable):
Update to handle GOMP_alloc.
(gfc_deallocate_with_status, gfc_deallocate_scalar_with_status):
Handle GOMP_free.
(trans_code): Update call.
* trans.h (gfc_allocate_allocatable, gfc_allocate_using_malloc):
Update prototype.
(gfc_omp_call_add_alloc, gfc_omp_call_is_alloc): New prototype.
* types.def (BT_FN_PTR_PTR_SIZE_PTRMODE_PTRMODE): New.

libgomp/ChangeLog:

* allocator.c (struct fort_alloc_splay_tree_key_s,
fort_alloc_splay_compare, GOMP_add_alloc, GOMP_is_alloc): New.
* libgomp.h: Define splay_tree_static for 'reverse' splay tree.
* libgomp.map (GOMP_5.1.2): New; add GOMP_add_alloc and
GOMP_is_alloc; move GOMP_target_map_indirect_ptr from ...
(GOMP_5.1.1): ... here.
* libgomp.texi (Impl. Status, Memory management): Update for
allocators/allocate directives.
* splay-tree.c: Handle splay_tree_static define to declare all
functions as static.
(splay_tree_lookup_node): New.
* splay-tree.h: Handle splay_tree_decl_only define.
(splay_tree_lookup_node): New prototype.
* target.c: Define splay_tree_static for 'reverse'.
* testsuite/libgomp.fortran/allocators-1.f90: New test.
* testsuite/libgomp.fortran/allocators-2.f90: New test.
* testsuite/libgomp.fortran/allocators-3.f90: New test.
* testsuite/libgomp.fortran/allocators-4.f90: New test.
* testsuite/libgomp.fortran/allocators-5.f90: New test.

gcc/testsuite/ChangeLog:

* gfortran.dg/gomp/allocate-14.f90: Add coarray and
not-listed tests.
* gfortran.dg/gomp/allocate-5.f90: Remove sorry dg-message.
* gfortran.dg/bind_c_array_params_2.f90: Update expected
dump for dtype '.version=0'.
* gfortran.dg/gomp/allocate-16.f90: New test.
* gfortran.dg/gomp/allocators-3.f90: New test.
* gfortran.dg/gomp/allocators-4.f90: New test.

45 files changed:
gcc/builtin-types.def
gcc/builtins.cc
gcc/fortran/dump-parse-tree.cc
gcc/fortran/f95-lang.cc
gcc/fortran/gfortran.h
gcc/fortran/invoke.texi
gcc/fortran/lang.opt
gcc/fortran/openmp.cc
gcc/fortran/parse.cc
gcc/fortran/trans-array.cc
gcc/fortran/trans-array.h
gcc/fortran/trans-decl.cc
gcc/fortran/trans-expr.cc
gcc/fortran/trans-intrinsic.cc
gcc/fortran/trans-openmp.cc
gcc/fortran/trans-stmt.cc
gcc/fortran/trans-stmt.h
gcc/fortran/trans-types.cc
gcc/fortran/trans.cc
gcc/fortran/trans.h
gcc/fortran/types.def
gcc/gimple-ssa-warn-access.cc
gcc/gimple.cc
gcc/omp-builtins.def
gcc/predict.cc
gcc/testsuite/gfortran.dg/bind_c_array_params_2.f90
gcc/testsuite/gfortran.dg/gomp/allocate-14.f90
gcc/testsuite/gfortran.dg/gomp/allocate-16.f90 [new file with mode: 0644]
gcc/testsuite/gfortran.dg/gomp/allocate-5.f90
gcc/testsuite/gfortran.dg/gomp/allocators-3.f90 [new file with mode: 0644]
gcc/testsuite/gfortran.dg/gomp/allocators-4.f90 [new file with mode: 0644]
gcc/tree-ssa-ccp.cc
gcc/tree.cc
libgomp/allocator.c
libgomp/libgomp.h
libgomp/libgomp.map
libgomp/libgomp.texi
libgomp/splay-tree.c
libgomp/splay-tree.h
libgomp/target.c
libgomp/testsuite/libgomp.fortran/allocators-1.f90 [new file with mode: 0644]
libgomp/testsuite/libgomp.fortran/allocators-2.f90 [new file with mode: 0644]
libgomp/testsuite/libgomp.fortran/allocators-3.f90 [new file with mode: 0644]
libgomp/testsuite/libgomp.fortran/allocators-4.f90 [new file with mode: 0644]
libgomp/testsuite/libgomp.fortran/allocators-5.f90 [new file with mode: 0644]

index 43381bc89493a36b3fe31d87810a5f9bd283185e..183ef62bad2a768b053d8dd2072e639d12f63d60 100644 (file)
@@ -840,6 +840,8 @@ DEF_FUNCTION_TYPE_4 (BT_FN_PTR_PTR_CONST_PTR_SIZE_SIZE,
                     BT_PTR, BT_PTR, BT_CONST_PTR, BT_SIZE, BT_SIZE)
 DEF_FUNCTION_TYPE_4 (BT_FN_PTR_PTR_INT_SIZE_SIZE,
                     BT_PTR, BT_PTR, BT_INT, BT_SIZE, BT_SIZE)
+DEF_FUNCTION_TYPE_4 (BT_FN_PTR_PTR_SIZE_PTRMODE_PTRMODE,
+                    BT_PTR, BT_PTR, BT_SIZE, BT_PTRMODE, BT_PTRMODE)
 DEF_FUNCTION_TYPE_4 (BT_FN_UINT_UINT_UINT_UINT_UINT,
                     BT_UINT, BT_UINT, BT_UINT, BT_UINT, BT_UINT)
 DEF_FUNCTION_TYPE_4 (BT_FN_UINT_UINT_UINT_UINT_UINTPTR,
index afa9be5144373779475e5f58918b90e7c1f57e57..38b0acff131249579c39d397e40107deddef56b8 100644 (file)
@@ -12410,6 +12410,7 @@ builtin_fnspec (tree callee)
        return ".cO ";
       /* Realloc serves both as allocation point and deallocation point.  */
       case BUILT_IN_REALLOC:
+      case BUILT_IN_GOMP_REALLOC:
        return ".Cw ";
       case BUILT_IN_GAMMA_R:
       case BUILT_IN_GAMMAF_R:
index cc4846e5d745fc64c73579b23d5ca4ed6bf7c919..ecf71036444ce51cdb62594e197805bafdad1375 100644 (file)
@@ -2241,6 +2241,8 @@ show_omp_node (int level, gfc_code *c)
     case EXEC_OACC_CACHE:
     case EXEC_OACC_ENTER_DATA:
     case EXEC_OACC_EXIT_DATA:
+    case EXEC_OMP_ALLOCATE:
+    case EXEC_OMP_ALLOCATORS:
     case EXEC_OMP_ASSUME:
     case EXEC_OMP_CANCEL:
     case EXEC_OMP_CANCELLATION_POINT:
index 32fddcde9571977f5a25af892f70db47636d162e..539bc271e78fec7d05b28a223fbf08af8bdaa853 100644 (file)
@@ -566,7 +566,9 @@ gfc_builtin_function (tree decl)
 #define ATTR_NOTHROW_LIST              (ECF_NOTHROW)
 #define ATTR_CONST_NOTHROW_LIST                (ECF_NOTHROW | ECF_CONST)
 #define ATTR_ALLOC_WARN_UNUSED_RESULT_SIZE_2_NOTHROW_LIST \
-                                       (ECF_NOTHROW)
+                                       (ECF_NOTHROW | ECF_LEAF | ECF_MALLOC)
+#define ATTR_ALLOC_WARN_UNUSED_RESULT_SIZE_2_NOTHROW_LEAF_LIST \
+                                       (ECF_NOTHROW | ECF_LEAF)
 #define ATTR_COLD_NORETURN_NOTHROW_LEAF_LIST \
                                        (ECF_COLD | ECF_NORETURN | \
                                         ECF_NOTHROW | ECF_LEAF)
index a77441f38e7cf5eb230c615a4263622bbb2c7dfe..28569d07e7161fd502d53f8bf4f09b5e86c6aa28 100644 (file)
@@ -1579,6 +1579,7 @@ typedef struct gfc_omp_clauses
   unsigned grainsize_strict:1, num_tasks_strict:1, compare:1, weak:1;
   unsigned non_rectangular:1, order_concurrent:1;
   unsigned contains_teams_construct:1, target_first_st_is_teams:1;
+  unsigned contained_in_target_construct:1;
   ENUM_BITFIELD (gfc_omp_sched_kind) sched_kind:3;
   ENUM_BITFIELD (gfc_omp_device_type) device_type:2;
   ENUM_BITFIELD (gfc_omp_memorder) memorder:3;
index 2f1d1f284292e1d7ef888a2f93ddab5239143bce..7523d7595328e27ce6d16e7d27c6e70602d2d56a 100644 (file)
@@ -126,8 +126,9 @@ by type.  Explanations are in the following sections.
 -ffree-form -ffree-line-length-@var{n} -ffree-line-length-none
 -fimplicit-none -finteger-4-integer-8 -fmax-identifier-length
 -fmodule-private -ffixed-form -fno-range-check -fopenacc -fopenmp
--freal-4-real-10 -freal-4-real-16 -freal-4-real-8 -freal-8-real-10
--freal-8-real-16 -freal-8-real-4 -std=@var{std} -ftest-forall-temp
+-fopenmp-allocators -fopenmp-simd -freal-4-real-10 -freal-4-real-16
+-freal-4-real-8 -freal-8-real-10 -freal-8-real-16 -freal-8-real-4
+-std=@var{std} -ftest-forall-temp
 }
 
 @item Preprocessing Options
@@ -410,26 +411,64 @@ Specify that no implicit typing is allowed, unless overridden by explicit
 Enable the Cray pointer extension, which provides C-like pointer
 functionality.
 
-@opindex @code{fopenacc}
-@cindex OpenACC
+
+@opindex fopenacc
+@cindex OpenACC accelerator programming
 @item -fopenacc
-Enable the OpenACC extensions.  This includes OpenACC @code{!$acc}
-directives in free form and @code{c$acc}, @code{*$acc} and
-@code{!$acc} directives in fixed form, @code{!$} conditional
-compilation sentinels in free form and @code{c$}, @code{*$} and
-@code{!$} sentinels in fixed form, and when linking arranges for the
-OpenACC runtime library to be linked in.
-
-@opindex @code{fopenmp}
-@cindex OpenMP
+Enable handling of OpenACC directives @samp{!$acc} in free-form Fortran and
+@samp{!$acc}, @samp{c$acc} and @samp{*$acc} in fixed-form Fortran.  When
+@option{-fopenacc} is specified, the compiler generates accelerated code
+according to the OpenACC Application Programming Interface v2.6
+@w{@uref{https://www.openacc.org}}.  This option implies @option{-pthread},
+and thus is only supported on targets that have support for @option{-pthread}.
+The option @option{-fopenacc} implies @option{-frecursive}.
+
+@opindex fopenmp
+@cindex OpenMP parallel
 @item -fopenmp
-Enable the OpenMP extensions.  This includes OpenMP @code{!$omp} directives
-in free form
-and @code{c$omp}, @code{*$omp} and @code{!$omp} directives in fixed form,
-@code{!$} conditional compilation sentinels in free form
-and @code{c$}, @code{*$} and @code{!$} sentinels in fixed form, 
-and when linking arranges for the OpenMP runtime library to be linked
-in.  The option @option{-fopenmp} implies @option{-frecursive}.
+Enable handling of OpenMP directives @samp{!$omp} in Fortran.  It
+additionally enables the conditional compilation sentinel @samp{!$} in
+Fortran.  In fixed source form Fortran, the sentinels can also start with
+@samp{c} or @samp{*}.  When @option{-fopenmp} is specified, the
+compiler generates parallel code according to the OpenMP Application
+Program Interface v4.5 @w{@uref{https://www.openmp.org}}.  This option
+implies @option{-pthread}, and thus is only supported on targets that
+have support for @option{-pthread}. @option{-fopenmp} implies
+@option{-fopenmp-simd} and @option{-frecursive}.
+
+@opindex fopenmp-allocators
+@cindex OpenMP Allocators
+@item -fopenmp-allocators
+Enables handling of allocation, reallocation and deallocation of Fortran
+allocatable and pointer variables that are allocated using the
+@samp{!$omp allocators} and @samp{!$omp allocate} constructs.  Files
+containing either directive have to be compiled with this option in addition
+to @option{-fopenmp}.  Additionally, all files that might deallocate or
+reallocate a variable that has been allocated with an OpenMP allocator
+have to be compiled with this option.  This includes intrinsic assignment
+to allocatable variables when reallocation may occur and deallocation
+due to either of the following: end of scope, explicit deallocation,
+@samp{intent(out)}, deallocation of allocatable components etc.
+Files not changing the allocation status or only for components of
+a derived type that have not been allocated using those two directives
+do not need to be compiled with this option.  Nor do files that handle
+such variables after they have been deallocated or allocated by the
+normal Fortran allocator.
+
+@opindex fopenmp-simd
+@cindex OpenMP SIMD
+@cindex SIMD
+@item -fopenmp-simd
+Enable handling of OpenMP's @code{simd}, @code{declare simd},
+@code{declare reduction}, @code{assume}, @code{ordered}, @code{scan}
+and @code{loop} directive, and of combined or composite directives with
+@code{simd} as constituent with  @code{!$omp} in Fortran.  It additionally
+enables the conditional compilation sentinel @samp{!$} in Fortran.  In
+fixed source form Fortran, the sentinels can also start with @samp{c} or
+@samp{*}.  Other OpenMP directives are ignored.  Unless @option{-fopenmp}
+is additionally specified, the @code{loop} region binds to the current task
+region, independent of the specified @code{bind} clause.
+
 
 @opindex @code{frange-check}
 @item -fno-range-check
index adcfc280b5ae29c7486a02d13ec7c023c69522ab..7c301431cbcd4958c080882ffa96b1a5c8ab6b72 100644 (file)
@@ -716,6 +716,10 @@ fopenmp-simd
 Fortran
 ; Documented in C
 
+fopenmp-allocators
+Fortran Var(flag_openmp_allocators)
+Handle OpenMP allocators for allocatables and pointers.
+
 fpack-derived
 Fortran Var(flag_pack_derived)
 Try to lay out derived types as compactly as possible.
index 794df19a4d1accd083b4418d0e718423e1f251d3..251da667236d6379b1a58b3a5d08b02caa6ded95 100644 (file)
@@ -7424,6 +7424,9 @@ resolve_omp_clauses (gfc_code *code, gfc_omp_clauses *omp_clauses,
   if (omp_clauses == NULL)
     return;
 
+  if (ns == NULL)
+    ns = gfc_current_ns;
+
   if (omp_clauses->orderedc && omp_clauses->orderedc < omp_clauses->collapse)
     gfc_error ("ORDERED clause parameter is less than COLLAPSE at %L",
               &code->loc);
@@ -7657,23 +7660,22 @@ resolve_omp_clauses (gfc_code *code, gfc_omp_clauses *omp_clauses,
            && n->sym->result == n->sym
            && n->sym->attr.function)
          {
-           if (gfc_current_ns->proc_name == n->sym
-               || (gfc_current_ns->parent
-                   && gfc_current_ns->parent->proc_name == n->sym))
+           if (ns->proc_name == n->sym
+               || (ns->parent && ns->parent->proc_name == n->sym))
              continue;
-           if (gfc_current_ns->proc_name->attr.entry_master)
+           if (ns->proc_name->attr.entry_master)
              {
-               gfc_entry_list *el = gfc_current_ns->entries;
+               gfc_entry_list *el = ns->entries;
                for (; el; el = el->next)
                  if (el->sym == n->sym)
                    break;
                if (el)
                  continue;
              }
-           if (gfc_current_ns->parent
-               && gfc_current_ns->parent->proc_name->attr.entry_master)
+           if (ns->parent
+               && ns->parent->proc_name->attr.entry_master)
              {
-               gfc_entry_list *el = gfc_current_ns->parent->entries;
+               gfc_entry_list *el = ns->parent->entries;
                for (; el; el = el->next)
                  if (el->sym == n->sym)
                    break;
@@ -7973,24 +7975,120 @@ resolve_omp_clauses (gfc_code *code, gfc_omp_clauses *omp_clauses,
          && code->block->next->op == EXEC_ALLOCATE)
        {
          gfc_alloc *a;
+         gfc_omp_namelist *n_null = NULL;
+         bool missing_allocator = false;
+         gfc_symbol *missing_allocator_sym = NULL;
          for (n = omp_clauses->lists[OMP_LIST_ALLOCATE]; n; n = n->next)
            {
+             if (n->u2.allocator == NULL)
+               {
+                 if (!missing_allocator_sym)
+                   missing_allocator_sym = n->sym;
+                 missing_allocator = true;
+               }
              if (n->sym == NULL)
-               continue;
+               {
+                 n_null = n;
+                 continue;
+               }
              if (n->sym->attr.codimension)
                gfc_error ("Unexpected coarray %qs in %<allocate%> at %L",
                           n->sym->name, &n->where);
              for (a = code->block->next->ext.alloc.list; a; a = a->next)
                if (a->expr->expr_type == EXPR_VARIABLE
                    && a->expr->symtree->n.sym == n->sym)
-                 break;
+                 {
+                   gfc_ref *ref;
+                   for (ref = a->expr->ref; ref; ref = ref->next)
+                     if (ref->type == REF_COMPONENT)
+                       break;
+                   if (ref == NULL)
+                     break;
+                 }
              if (a == NULL)
                gfc_error ("%qs specified in %<allocate%> at %L but not "
                           "in the associated ALLOCATE statement",
                           n->sym->name, &n->where);
            }
-       }
+         /* If there is an ALLOCATE directive without list argument, a
+            namelist with its allocator/align clauses and n->sym = NULL is
+            created during parsing; here, we add all not otherwise specified
+            items from the Fortran allocate to that list.
+            For an ALLOCATORS directive, not listed items use the normal
+            Fortran way.
+            The behavior of an ALLOCATE directive that does not list all
+            arguments but there is no directive without list argument is not
+            well specified.  Thus, we reject such code below. In OpenMP 5.2
+            the executable ALLOCATE directive is deprecated and in 6.0
+            deleted such that no spec clarification is to be expected.  */
+         for (a = code->block->next->ext.alloc.list; a; a = a->next)
+           if (a->expr->expr_type == EXPR_VARIABLE)
+             {
+               for (n = omp_clauses->lists[OMP_LIST_ALLOCATE]; n; n = n->next)
+                 if (a->expr->symtree->n.sym == n->sym)
+                   {
+                     gfc_ref *ref;
+                     for (ref = a->expr->ref; ref; ref = ref->next)
+                       if (ref->type == REF_COMPONENT)
+                         break;
+                     if (ref == NULL)
+                       break;
+                   }
+               if (n == NULL && n_null == NULL)
+                 {
+                   /* OK for ALLOCATORS but for ALLOCATE: Unspecified whether
+                      that should use the default allocator of OpenMP or the
+                      Fortran allocator. Thus, just reject it.  */
+                   if (code->op == EXEC_OMP_ALLOCATE)
+                     gfc_error ("%qs listed in %<allocate%> statement at %L "
+                                "but it is neither explicitly in listed in "
+                                "the %<!$OMP ALLOCATE%> directive nor exists"
+                                " a directive without argument list",
+                                a->expr->symtree->n.sym->name,
+                                &a->expr->where);
+                   break;
+                 }
+               if (n == NULL)
+                 {
+                   if (a->expr->symtree->n.sym->attr.codimension)
+                     gfc_error ("Unexpected coarray %qs in %<allocate%> at "
+                                "%L, implicitly listed in %<!$OMP ALLOCATE%>"
+                                " at %L", a->expr->symtree->n.sym->name,
+                                &a->expr->where, &n_null->where);
+                   break;
+                 }
+           }
+         gfc_namespace *prog_unit = ns;
+         while (prog_unit->parent)
+           prog_unit = prog_unit->parent;
+         gfc_namespace *fn_ns = ns;
+         while (fn_ns)
+           {
+             if (ns->proc_name
+                 && (ns->proc_name->attr.subroutine
+                     || ns->proc_name->attr.function))
+               break;
+             fn_ns = fn_ns->parent;
+           }
+         if (missing_allocator
+             && !(prog_unit->omp_requires & OMP_REQ_DYNAMIC_ALLOCATORS)
+             && ((fn_ns && fn_ns->proc_name->attr.omp_declare_target)
+                 || omp_clauses->contained_in_target_construct))
+           {
+             if (code->op == EXEC_OMP_ALLOCATORS)
+               gfc_error ("ALLOCATORS directive at %L inside a target region "
+                          "must specify an ALLOCATOR modifier for %qs",
+                          &code->loc, missing_allocator_sym->name);
+             else if (missing_allocator_sym)
+               gfc_error ("ALLOCATE directive at %L inside a target region "
+                          "must specify an ALLOCATOR clause for %qs",
+                          &code->loc, missing_allocator_sym->name);
+             else
+               gfc_error ("ALLOCATE directive at %L inside a target region "
+                          "must specify an ALLOCATOR clause", &code->loc);
+           }
 
+       }
     }
 
   /* OpenACC reductions.  */
index abd3a424f385ae912707e64c32363490132a2d84..c0eb0575a90ff3a3596ec6094a83f606d79bfb5a 100644 (file)
@@ -1364,6 +1364,8 @@ decode_omp_directive (void)
          prog_unit->omp_target_seen = true;
        break;
       }
+    case ST_OMP_ALLOCATE_EXEC:
+    case ST_OMP_ALLOCATORS:
     case ST_OMP_TEAMS:
     case ST_OMP_TEAMS_DISTRIBUTE:
     case ST_OMP_TEAMS_DISTRIBUTE_SIMD:
@@ -1386,7 +1388,10 @@ decode_omp_directive (void)
            case EXEC_OMP_TARGET_PARALLEL_DO_SIMD:
            case EXEC_OMP_TARGET_PARALLEL_LOOP:
            case EXEC_OMP_TARGET_SIMD:
-             stk->tail->ext.omp_clauses->contains_teams_construct = 1;
+             if (ret == ST_OMP_ALLOCATE_EXEC || ret == ST_OMP_ALLOCATORS)
+               new_st.ext.omp_clauses->contained_in_target_construct = 1;
+             else
+               stk->tail->ext.omp_clauses->contains_teams_construct = 1;
              break;
            default:
              break;
index 82f60a656f3e70f3093b65453a6648fe8f72147a..2930406a8e42a78019806a2aeeccaddd85fb2ec9 100644 (file)
@@ -363,6 +363,21 @@ gfc_conv_descriptor_rank (tree desc)
 }
 
 
+tree
+gfc_conv_descriptor_version (tree desc)
+{
+  tree tmp;
+  tree dtype;
+
+  dtype = gfc_conv_descriptor_dtype (desc);
+  tmp = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (dtype)), GFC_DTYPE_VERSION);
+  gcc_assert (tmp != NULL_TREE
+             && TREE_TYPE (tmp) == integer_type_node);
+  return fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (tmp),
+                         dtype, tmp, NULL_TREE);
+}
+
+
 /* Return the element length from the descriptor dtype field.  */
 
 tree
@@ -6196,7 +6211,7 @@ bool
 gfc_array_allocate (gfc_se * se, gfc_expr * expr, tree status, tree errmsg,
                    tree errlen, tree label_finish, tree expr3_elem_size,
                    tree *nelems, gfc_expr *expr3, tree e3_arr_desc,
-                   bool e3_has_nodescriptor)
+                   bool e3_has_nodescriptor, gfc_omp_namelist *omp_alloc)
 {
   tree tmp;
   tree pointer;
@@ -6218,6 +6233,7 @@ gfc_array_allocate (gfc_se * se, gfc_expr * expr, tree status, tree errmsg,
   gfc_ref *ref, *prev_ref = NULL, *coref;
   bool allocatable, coarray, dimension, alloc_w_e3_arr_spec = false,
       non_ulimate_coarray_ptr_comp;
+  tree omp_cond = NULL_TREE, omp_alt_alloc = NULL_TREE;
 
   ref = expr->ref;
 
@@ -6368,7 +6384,11 @@ gfc_array_allocate (gfc_se * se, gfc_expr * expr, tree status, tree errmsg,
       token = gfc_build_addr_expr (NULL_TREE, token);
     }
   else
-    pointer = gfc_conv_descriptor_data_get (se->expr);
+    {
+      pointer = gfc_conv_descriptor_data_get (se->expr);
+      if (omp_alloc)
+       omp_cond = boolean_true_node;
+    }
   STRIP_NOPS (pointer);
 
   if (allocatable)
@@ -6384,18 +6404,66 @@ gfc_array_allocate (gfc_se * se, gfc_expr * expr, tree status, tree errmsg,
 
   gfc_start_block (&elseblock);
 
+  tree succ_add_expr = NULL_TREE;
+  if (omp_cond)
+    {
+      tree align, alloc, sz;
+      gfc_se se2;
+      if (omp_alloc->u2.allocator)
+       {
+         gfc_init_se (&se2, NULL);
+         gfc_conv_expr (&se2, omp_alloc->u2.allocator);
+         gfc_add_block_to_block (&elseblock, &se2.pre);
+         alloc = gfc_evaluate_now (se2.expr, &elseblock);
+         gfc_add_block_to_block (&elseblock, &se2.post);
+       }
+      else
+       alloc = build_zero_cst (ptr_type_node);
+      tmp = TREE_TYPE (TREE_TYPE (pointer));
+      if (tmp == void_type_node)
+       tmp = gfc_typenode_for_spec (&expr->ts, 0);
+      if (omp_alloc->u.align)
+       {
+         gfc_init_se (&se2, NULL);
+         gfc_conv_expr (&se2, omp_alloc->u.align);
+         gcc_assert (CONSTANT_CLASS_P (se2.expr)
+                     && se2.pre.head == NULL
+                     && se2.post.head == NULL);
+         align = build_int_cst (size_type_node,
+                                MAX (tree_to_uhwi (se2.expr),
+                                     TYPE_ALIGN_UNIT (tmp)));
+       }
+      else
+       align = build_int_cst (size_type_node, TYPE_ALIGN_UNIT (tmp));
+      sz = fold_build2_loc (input_location, MAX_EXPR, size_type_node,
+                           fold_convert (size_type_node, size),
+                           build_int_cst (size_type_node, 1));
+      omp_alt_alloc = builtin_decl_explicit (BUILT_IN_GOMP_ALLOC);
+      DECL_ATTRIBUTES (omp_alt_alloc)
+       = tree_cons (get_identifier ("omp allocator"),
+                    build_tree_list (NULL_TREE, alloc),
+                    DECL_ATTRIBUTES (omp_alt_alloc));
+      omp_alt_alloc = build_call_expr (omp_alt_alloc, 3, align, sz, alloc);
+      succ_add_expr = fold_build2_loc (input_location, MODIFY_EXPR,
+                                      void_type_node,
+                                      gfc_conv_descriptor_version (se->expr),
+                                      build_int_cst (integer_type_node, 1));
+    }
+
   /* The allocatable variant takes the old pointer as first argument.  */
   if (allocatable)
     gfc_allocate_allocatable (&elseblock, pointer, size, token,
                              status, errmsg, errlen, label_finish, expr,
-                             coref != NULL ? coref->u.ar.as->corank : 0);
+                             coref != NULL ? coref->u.ar.as->corank : 0,
+                             omp_cond, omp_alt_alloc, succ_add_expr);
   else if (non_ulimate_coarray_ptr_comp && token)
     /* The token is set only for GFC_FCOARRAY_LIB mode.  */
     gfc_allocate_using_caf_lib (&elseblock, pointer, size, token, status,
                                errmsg, errlen,
                                GFC_CAF_COARRAY_ALLOC_ALLOCATE_ONLY);
   else
-    gfc_allocate_using_malloc (&elseblock, pointer, size, status);
+    gfc_allocate_using_malloc (&elseblock, pointer, size, status,
+                              omp_cond, omp_alt_alloc, succ_add_expr);
 
   if (dimension)
     {
@@ -9603,11 +9671,6 @@ structure_alloc_comps (gfc_symbol * der_type, tree decl, tree dest,
                  else if (attr->dimension && !attr->proc_pointer)
                    caf_token = gfc_conv_descriptor_token (comp);
                }
-             if (attr->dimension && !attr->codimension && !attr->proc_pointer)
-               /* When this is an array but not in conjunction with a coarray
-                  then add the data-ref.  For coarray'ed arrays the data-ref
-                  is added by deallocate_with_status.  */
-               comp = gfc_conv_descriptor_data_get (comp);
 
              tmp = gfc_deallocate_with_status (comp, NULL_TREE, NULL_TREE,
                                                NULL_TREE, NULL_TREE, true,
@@ -10292,29 +10355,50 @@ structure_alloc_comps (gfc_symbol * der_type, tree decl, tree dest,
              gfc_add_expr_to_block (&fnblock, tmp);
            }
 
-         if (c->attr.pdt_array)
+         if (c->attr.pdt_array || c->attr.pdt_string)
            {
-             tmp = gfc_conv_descriptor_data_get (comp);
+             tmp = comp;
+             if (c->attr.pdt_array)
+               tmp = gfc_conv_descriptor_data_get (comp);
              null_cond = fold_build2_loc (input_location, NE_EXPR,
                                           logical_type_node, tmp,
                                           build_int_cst (TREE_TYPE (tmp), 0));
-             tmp = gfc_call_free (tmp);
-             tmp = build3_v (COND_EXPR, null_cond, tmp,
-                             build_empty_stmt (input_location));
-             gfc_add_expr_to_block (&fnblock, tmp);
-             gfc_conv_descriptor_data_set (&fnblock, comp, null_pointer_node);
-           }
-         else if (c->attr.pdt_string)
-           {
-             null_cond = fold_build2_loc (input_location, NE_EXPR,
-                                          logical_type_node, comp,
-                                          build_int_cst (TREE_TYPE (comp), 0));
-             tmp = gfc_call_free (comp);
+             if (flag_openmp_allocators)
+               {
+                 tree cd, t;
+                 if (c->attr.pdt_array)
+                   cd = fold_build2_loc (input_location, EQ_EXPR,
+                                         boolean_type_node,
+                                         gfc_conv_descriptor_version (comp),
+                                         build_int_cst (integer_type_node, 1));
+                 else
+                   cd = gfc_omp_call_is_alloc (tmp);
+                 t = builtin_decl_explicit (BUILT_IN_GOMP_FREE);
+                 t = build_call_expr_loc (input_location, t, 1, tmp);
+
+                 stmtblock_t tblock;
+                 gfc_init_block (&tblock);
+                 gfc_add_expr_to_block (&tblock, t);
+                 if (c->attr.pdt_array)
+                   gfc_add_modify (&tblock, gfc_conv_descriptor_version (comp),
+                                   build_zero_cst (integer_type_node));
+                 tmp = build3_loc (input_location, COND_EXPR, void_type_node,
+                                   cd, gfc_finish_block (&tblock),
+                                   gfc_call_free (tmp));
+               }
+             else
+               tmp = gfc_call_free (tmp);
              tmp = build3_v (COND_EXPR, null_cond, tmp,
                              build_empty_stmt (input_location));
              gfc_add_expr_to_block (&fnblock, tmp);
-             tmp = fold_convert (TREE_TYPE (comp), null_pointer_node);
-             gfc_add_modify (&fnblock, comp, tmp);
+
+             if (c->attr.pdt_array)
+               gfc_conv_descriptor_data_set (&fnblock, comp, null_pointer_node);
+             else
+               {
+                 tmp = fold_convert (TREE_TYPE (comp), null_pointer_node);
+                 gfc_add_modify (&fnblock, comp, tmp);
+               }
            }
 
          break;
@@ -11248,8 +11332,22 @@ gfc_alloc_allocatable_for_assignment (gfc_loopinfo *loop,
                                 builtin_decl_explicit (BUILT_IN_REALLOC), 2,
                                 fold_convert (pvoid_type_node, array1),
                                 size2);
-      gfc_conv_descriptor_data_set (&realloc_block,
-                                   desc, tmp);
+      if (flag_openmp_allocators)
+       {
+         tree cond, omp_tmp;
+         cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
+                                 gfc_conv_descriptor_version (desc),
+                                 build_int_cst (integer_type_node, 1));
+         omp_tmp = builtin_decl_explicit (BUILT_IN_GOMP_REALLOC);
+         omp_tmp = build_call_expr_loc (input_location, omp_tmp, 4,
+                                fold_convert (pvoid_type_node, array1), size2,
+                                build_zero_cst (ptr_type_node),
+                                build_zero_cst (ptr_type_node));
+         tmp = build3_loc (input_location, COND_EXPR, TREE_TYPE (tmp), cond,
+                           omp_tmp, tmp);
+       }
+
+      gfc_conv_descriptor_data_set (&realloc_block, desc, tmp);
     }
   else
     {
index 5408755138ea2847802c5207a0ddacfe5fef0f60..6cdcc9a3e750c41808bcdb26c80e155f00257c09 100644 (file)
@@ -21,7 +21,8 @@ along with GCC; see the file COPYING3.  If not see
 /* Generate code to initialize and allocate an array.  Statements are added to
    se, which should contain an expression for the array descriptor.  */
 bool gfc_array_allocate (gfc_se *, gfc_expr *, tree, tree, tree, tree,
-                        tree, tree *, gfc_expr *, tree, bool);
+                        tree, tree *, gfc_expr *, tree, bool,
+                        gfc_omp_namelist *);
 
 /* Allow the bounds of a loop to be set from a callee's array spec.  */
 void gfc_set_loop_bounds_from_array_spec (gfc_interface_mapping *,
@@ -177,6 +178,7 @@ tree gfc_conv_descriptor_span_get (tree);
 tree gfc_conv_descriptor_dtype (tree);
 tree gfc_conv_descriptor_rank (tree);
 tree gfc_conv_descriptor_elem_len (tree);
+tree gfc_conv_descriptor_version (tree);
 tree gfc_conv_descriptor_attribute (tree);
 tree gfc_conv_descriptor_type (tree);
 tree gfc_get_descriptor_dimension (tree);
index b86cfec7d499a041f506e64658c316c3de989fdd..cf848406a05ac306aec34ab4a34edcda7e5bf05e 100644 (file)
@@ -4350,7 +4350,7 @@ gfc_init_default_dt (gfc_symbol * sym, stmtblock_t * block, bool dealloc)
 
 
 /* Initialize INTENT(OUT) derived type dummies.  As well as giving
-   them their default initializer, if they do not have allocatable
+   them their default initializer, if they have allocatable
    components, they have their allocatable components deallocated.  */
 
 static void
index ea0872942499e6d324cb6bb2c0628ed1503fe847..b2463a28748f6c0cf236b05c7f4e8909f2e4a3d4 100644 (file)
@@ -7173,8 +7173,6 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym,
                  if  (TREE_TYPE(tmp) != pvoid_type_node)
                    tmp = build_fold_indirect_ref_loc (input_location,
                                                       parmse.expr);
-                 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (tmp)))
-                   tmp = gfc_conv_descriptor_data_get (tmp);
                  tmp = gfc_deallocate_with_status (tmp, NULL_TREE, NULL_TREE,
                                                    NULL_TREE, NULL_TREE, true,
                                                    e,
@@ -11731,8 +11729,30 @@ alloc_scalar_allocatable_for_assignment (stmtblock_t *block,
                                 builtin_decl_explicit (BUILT_IN_REALLOC),
                                 2, fold_convert (pvoid_type_node, lse.expr),
                                 size_in_bytes);
+      tree omp_cond = NULL_TREE;
+      if (flag_openmp_allocators)
+       {
+         tree omp_tmp;
+         omp_cond = gfc_omp_call_is_alloc (lse.expr);
+         omp_cond = gfc_evaluate_now (omp_cond, block);
+
+         omp_tmp = builtin_decl_explicit (BUILT_IN_GOMP_REALLOC);
+         omp_tmp = build_call_expr_loc (input_location, omp_tmp, 4,
+                                        fold_convert (pvoid_type_node,
+                                                      lse.expr), size_in_bytes,
+                                        build_zero_cst (ptr_type_node),
+                                        build_zero_cst (ptr_type_node));
+         tmp = build3_loc (input_location, COND_EXPR, TREE_TYPE (tmp),
+                           omp_cond, omp_tmp, tmp);
+       }
       tmp = fold_convert (TREE_TYPE (lse.expr), tmp);
       gfc_add_modify (block, lse.expr, tmp);
+      if (omp_cond)
+       gfc_add_expr_to_block (block,
+                              build3_loc (input_location, COND_EXPR,
+                              void_type_node, omp_cond,
+                              gfc_omp_call_add_alloc (lse.expr),
+                              build_empty_stmt (input_location)));
       tmp = build1_v (LABEL_EXPR, jump_label2);
       gfc_add_expr_to_block (block, tmp);
 
index 289309190a5e4820b6afb5d5bcd22aba5ebd5f0f..05e111c0fcc39f0ed724bc16019d6e8633dd9e05 100644 (file)
@@ -12819,9 +12819,8 @@ conv_intrinsic_move_alloc (gfc_code *code)
          gfc_add_expr_to_block (&block, tmp);
        }
 
-      tmp = gfc_conv_descriptor_data_get (to_se.expr);
-      tmp = gfc_deallocate_with_status (tmp, NULL_TREE, NULL_TREE, NULL_TREE,
-                                       NULL_TREE, true, to_expr,
+      tmp = gfc_deallocate_with_status (to_se.expr, NULL_TREE, NULL_TREE,
+                                       NULL_TREE, NULL_TREE, true, to_expr,
                                        GFC_CAF_COARRAY_NOCOARRAY);
       gfc_add_expr_to_block (&block, tmp);
     }
index 82bbc41b388683140475fa7a2379b979145ed547..9e166c94f8e6a801631f1f2035f15b0e91e5a01a 100644 (file)
@@ -4841,6 +4841,30 @@ gfc_trans_oacc_wait_directive (gfc_code *code)
 static tree gfc_trans_omp_sections (gfc_code *, gfc_omp_clauses *);
 static tree gfc_trans_omp_workshare (gfc_code *, gfc_omp_clauses *);
 
+static tree
+gfc_trans_omp_allocators (gfc_code *code)
+{
+  static bool warned = false;
+  gfc_omp_namelist *omp_allocate
+    = code->ext.omp_clauses->lists[OMP_LIST_ALLOCATE];
+  if (!flag_openmp_allocators && !warned)
+    {
+      omp_allocate = NULL;
+      gfc_error ("%<!$OMP %s%> at %L requires %<-fopenmp-allocators%>",
+                code->op == EXEC_OMP_ALLOCATE ? "ALLOCATE" : "ALLOCATORS",
+                &code->loc);
+      warning (0, "All files that might deallocate such a variable must be "
+                 "compiled with %<-fopenmp-allocators%>");
+      inform (UNKNOWN_LOCATION,
+             "This includes explicit DEALLOCATE, reallocation on intrinsic "
+             "assignment, INTENT(OUT) for allocatable dummy arguments, and "
+             "reallocation of allocatable components allocated with an "
+             "OpenMP allocator");
+      warned = true;
+    }
+  return gfc_trans_allocate (code->block->next, omp_allocate);
+}
+
 static tree
 gfc_trans_omp_assume (gfc_code *code)
 {
@@ -7992,9 +8016,7 @@ gfc_trans_omp_directive (gfc_code *code)
     {
     case EXEC_OMP_ALLOCATE:
     case EXEC_OMP_ALLOCATORS:
-      sorry ("%<!$OMP %s%> not yet supported",
-            code->op == EXEC_OMP_ALLOCATE ? "ALLOCATE" : "ALLOCATORS");
-      return NULL_TREE;
+      return gfc_trans_omp_allocators (code);
     case EXEC_OMP_ASSUME:
       return gfc_trans_omp_assume (code);
     case EXEC_OMP_ATOMIC:
@@ -8329,3 +8351,36 @@ gfc_trans_omp_declare_variant (gfc_namespace *ns)
        }
     }
 }
+
+/* Add ptr for tracking as being allocated by GOMP_alloc. */
+
+tree
+gfc_omp_call_add_alloc (tree ptr)
+{
+  static tree fn = NULL_TREE;
+  if (fn == NULL_TREE)
+    {
+      fn = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE);
+      fn = build_fn_decl ("GOMP_add_alloc", fn);
+/* FIXME: attributes.  */
+    }
+  return build_call_expr_loc (input_location, fn, 1, ptr);
+}
+
+/* Generated function returns true when it was tracked via GOMP_add_alloc and
+   removes it from the tracking.  As called just before GOMP_free or omp_realloc
+   the pointer is or might become invalid, thus, it is always removed. */
+
+tree
+gfc_omp_call_is_alloc (tree ptr)
+{
+  static tree fn = NULL_TREE;
+  if (fn == NULL_TREE)
+    {
+      fn = build_function_type_list (boolean_type_node, ptr_type_node,
+                                    NULL_TREE);
+      fn = build_fn_decl ("GOMP_is_alloc", fn);
+/* FIXME: attributes.  */
+    }
+  return build_call_expr_loc (input_location, fn, 1, ptr);
+}
index 50b71e67234c9fe71d1d7074f0e192a6cf0eca37..5530e893a620d126eedeaae50909ec99c87cb350 100644 (file)
@@ -6228,7 +6228,7 @@ allocate_get_initializer (gfc_code * code, gfc_expr * expr)
 /* Translate the ALLOCATE statement.  */
 
 tree
-gfc_trans_allocate (gfc_code * code)
+gfc_trans_allocate (gfc_code * code, gfc_omp_namelist *omp_allocate)
 {
   gfc_alloc *al;
   gfc_expr *expr, *e3rhs = NULL, *init_expr;
@@ -6790,11 +6790,38 @@ gfc_trans_allocate (gfc_code * code)
       else
        tmp = expr3_esize;
 
+      gfc_omp_namelist *omp_alloc_item = NULL;
+      if (omp_allocate)
+       {
+         gfc_omp_namelist *n = NULL;
+         gfc_omp_namelist *n_null = NULL;
+         for (n = omp_allocate; n; n = n->next)
+           {
+             if (n->sym == NULL)
+               {
+                 n_null = n;
+                 continue;
+               }
+             if (expr->expr_type == EXPR_VARIABLE
+                 && expr->symtree->n.sym == n->sym)
+               {
+                 gfc_ref *ref;
+                 for (ref = expr->ref; ref; ref = ref->next)
+                   if (ref->type == REF_COMPONENT)
+                     break;
+                 if (ref == NULL)
+                   break;
+               }
+           }
+         omp_alloc_item = n ? n : n_null;
+
+       }
+
       if (!gfc_array_allocate (&se, expr, stat, errmsg, errlen,
                               label_finish, tmp, &nelems,
                               e3rhs ? e3rhs : code->expr3,
                               e3_is == E3_DESC ? expr3 : NULL_TREE,
-                              e3_has_nodescriptor))
+                              e3_has_nodescriptor, omp_alloc_item))
        {
          /* A scalar or derived type.  First compute the size to
             allocate.
@@ -6874,10 +6901,59 @@ gfc_trans_allocate (gfc_code * code)
            /* Handle size computation of the type declared to alloc.  */
            memsz = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (se.expr)));
 
+         bool use_coarray_alloc
+           = (flag_coarray == GFC_FCOARRAY_LIB
+              && (caf_attr = gfc_caf_attr (expr, true, &caf_refs_comp))
+                               .codimension);
+         tree omp_cond = NULL_TREE;
+         tree omp_alt_alloc = NULL_TREE;
+         tree succ_add_expr = NULL_TREE;
+         if (!use_coarray_alloc && omp_alloc_item)
+           {
+             tree align, alloc, sz;
+             gfc_se se2;
+
+             omp_cond = boolean_true_node;
+             if (omp_alloc_item->u2.allocator)
+               {
+                 gfc_init_se (&se2, NULL);
+                 gfc_conv_expr (&se2, omp_alloc_item->u2.allocator);
+                 gfc_add_block_to_block (&se.pre, &se2.pre);
+                 alloc = gfc_evaluate_now (se2.expr, &se.pre);
+                 gfc_add_block_to_block (&se.pre, &se2.post);
+               }
+             else
+               alloc = build_zero_cst (ptr_type_node);
+             tmp = TREE_TYPE (TREE_TYPE (se.expr));
+             if (tmp == void_type_node)
+               tmp = gfc_typenode_for_spec (&expr->ts, 0);
+             if (omp_alloc_item->u.align)
+               {
+                 gfc_init_se (&se2, NULL);
+                 gfc_conv_expr (&se2, omp_alloc_item->u.align);
+                 gcc_assert (CONSTANT_CLASS_P (se2.expr)
+                             && se2.pre.head == NULL
+                             && se2.post.head == NULL);
+                 align = build_int_cst (size_type_node,
+                                        MAX (tree_to_uhwi (se2.expr),
+                                        TYPE_ALIGN_UNIT (tmp)));
+               }
+             else
+               align = build_int_cst (size_type_node, TYPE_ALIGN_UNIT (tmp));
+             sz = fold_build2_loc (input_location, MAX_EXPR, size_type_node,
+                           fold_convert (size_type_node, memsz),
+                           build_int_cst (size_type_node, 1));
+             omp_alt_alloc = builtin_decl_explicit (BUILT_IN_GOMP_ALLOC);
+             DECL_ATTRIBUTES (omp_alt_alloc)
+               = tree_cons (get_identifier ("omp allocator"),
+                            build_tree_list (NULL_TREE, alloc),
+                            DECL_ATTRIBUTES (omp_alt_alloc));
+             omp_alt_alloc = build_call_expr (omp_alt_alloc, 3, align, sz, alloc);
+             succ_add_expr = gfc_omp_call_add_alloc (se.expr);
+           }
+
          /* Store the caf-attributes for latter use.  */
-         if (flag_coarray == GFC_FCOARRAY_LIB
-             && (caf_attr = gfc_caf_attr (expr, true, &caf_refs_comp))
-                .codimension)
+         if (use_coarray_alloc)
            {
              /* Scalar allocatable components in coarray'ed derived types make
                 it here and are treated now.  */
@@ -6904,9 +6980,11 @@ gfc_trans_allocate (gfc_code * code)
          else if (gfc_expr_attr (expr).allocatable)
            gfc_allocate_allocatable (&se.pre, se.expr, memsz,
                                      NULL_TREE, stat, errmsg, errlen,
-                                     label_finish, expr, 0);
+                                     label_finish, expr, 0,
+                                     omp_cond, omp_alt_alloc, succ_add_expr);
          else
-           gfc_allocate_using_malloc (&se.pre, se.expr, memsz, stat);
+           gfc_allocate_using_malloc (&se.pre, se.expr, memsz, stat,
+                                     omp_cond, omp_alt_alloc, succ_add_expr);
        }
       else
        {
index 101a0540ef491067488909cba73fcf26e9a87183..270ebcf9915b33d83eb24c05bb16fd9d6a9a2a9e 100644 (file)
@@ -64,7 +64,7 @@ tree gfc_trans_change_team (gfc_code *);
 tree gfc_trans_end_team (gfc_code *);
 tree gfc_trans_sync_team (gfc_code *);
 tree gfc_trans_where (gfc_code *);
-tree gfc_trans_allocate (gfc_code *);
+tree gfc_trans_allocate (gfc_code *, gfc_omp_namelist *);
 tree gfc_trans_deallocate (gfc_code *);
 
 /* trans-openmp.cc */
index 5b11ffc3cc94e28ba3e24efe8fe0a196c07ee188..11a583ca92cfa7432fdd7c890f2e246363675332 100644 (file)
@@ -1601,6 +1601,10 @@ gfc_get_dtype_rank_type (int rank, tree etype)
                             GFC_DTYPE_ELEM_LEN);
   CONSTRUCTOR_APPEND_ELT (v, field,
                          fold_convert (TREE_TYPE (field), size));
+  field = gfc_advance_chain (TYPE_FIELDS (dtype_type_node),
+                            GFC_DTYPE_VERSION);
+  CONSTRUCTOR_APPEND_ELT (v, field,
+                         build_zero_cst (TREE_TYPE (field)));
 
   field = gfc_advance_chain (TYPE_FIELDS (dtype_type_node),
                             GFC_DTYPE_RANK);
index e2e1b694012368f60176f8107e0f16b03e120f11..961b0b5a573f372884a58c4c433f35c925acdb7a 100644 (file)
@@ -796,7 +796,10 @@ gfc_call_malloc (stmtblock_t * block, tree type, tree size)
       if (stat requested)
        stat = 0;
 
+      // if cond == NULL_NULL:
       newmem = malloc (MAX (size, 1));
+      // otherwise:
+      newmem = <cond> ? <alt_alloc> : malloc (MAX (size, 1))
       if (newmem == NULL)
       {
         if (stat)
@@ -808,7 +811,8 @@ gfc_call_malloc (stmtblock_t * block, tree type, tree size)
     }  */
 void
 gfc_allocate_using_malloc (stmtblock_t * block, tree pointer,
-                          tree size, tree status)
+                          tree size, tree status, tree cond, tree alt_alloc,
+                          tree extra_success_expr)
 {
   tree tmp, error_cond;
   stmtblock_t on_error;
@@ -822,13 +826,18 @@ gfc_allocate_using_malloc (stmtblock_t * block, tree pointer,
 
   /* The allocation itself.  */
   size = fold_convert (size_type_node, size);
-  gfc_add_modify (block, pointer,
-         fold_convert (TREE_TYPE (pointer),
-               build_call_expr_loc (input_location,
-                            builtin_decl_explicit (BUILT_IN_MALLOC), 1,
-                            fold_build2_loc (input_location,
-                                     MAX_EXPR, size_type_node, size,
-                                     build_int_cst (size_type_node, 1)))));
+  tmp = fold_build2_loc (input_location, MAX_EXPR, size_type_node,
+                        size, build_int_cst (size_type_node, 1));
+
+  tmp = build_call_expr_loc (input_location,
+                            builtin_decl_explicit (BUILT_IN_MALLOC), 1, tmp);
+  if (cond == boolean_true_node)
+    tmp = alt_alloc;
+  else if (cond)
+    tmp = build3_loc (input_location, COND_EXPR, TREE_TYPE (tmp), cond,
+                     alt_alloc, tmp);
+
+  gfc_add_modify (block, pointer, fold_convert (TREE_TYPE (pointer), tmp));
 
   /* What to do in case of error.  */
   gfc_start_block (&on_error);
@@ -852,7 +861,9 @@ gfc_allocate_using_malloc (stmtblock_t * block, tree pointer,
   tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
                         gfc_unlikely (error_cond, PRED_FORTRAN_FAIL_ALLOC),
                         gfc_finish_block (&on_error),
-                        build_empty_stmt (input_location));
+                        extra_success_expr
+                        ? extra_success_expr
+                        : build_empty_stmt (input_location));
 
   gfc_add_expr_to_block (block, tmp);
 }
@@ -938,7 +949,8 @@ gfc_allocate_using_caf_lib (stmtblock_t * block, tree pointer, tree size,
 void
 gfc_allocate_allocatable (stmtblock_t * block, tree mem, tree size,
                          tree token, tree status, tree errmsg, tree errlen,
-                         tree label_finish, gfc_expr* expr, int corank)
+                         tree label_finish, gfc_expr* expr, int corank,
+                         tree cond, tree alt_alloc, tree extra_success_expr)
 {
   stmtblock_t alloc_block;
   tree tmp, null_mem, alloc, error;
@@ -963,7 +975,7 @@ gfc_allocate_allocatable (stmtblock_t * block, tree mem, tree size,
   if (flag_coarray == GFC_FCOARRAY_LIB
       && (corank > 0 || caf_attr.codimension))
     {
-      tree cond, sub_caf_tree;
+      tree cond2, sub_caf_tree;
       gfc_se se;
       bool compute_special_caf_types_size = false;
 
@@ -1027,16 +1039,17 @@ gfc_allocate_allocatable (stmtblock_t * block, tree mem, tree size,
        {
          TREE_USED (label_finish) = 1;
          tmp = build1_v (GOTO_EXPR, label_finish);
-         cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
-                                 status, build_zero_cst (TREE_TYPE (status)));
+         cond2 = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
+                                  status, build_zero_cst (TREE_TYPE (status)));
          tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
-                                gfc_unlikely (cond, PRED_FORTRAN_FAIL_ALLOC),
+                                gfc_unlikely (cond2, PRED_FORTRAN_FAIL_ALLOC),
                                 tmp, build_empty_stmt (input_location));
          gfc_add_expr_to_block (&alloc_block, tmp);
        }
     }
   else
-    gfc_allocate_using_malloc (&alloc_block, mem, size, status);
+    gfc_allocate_using_malloc (&alloc_block, mem, size, status,
+                              cond, alt_alloc, extra_success_expr);
 
   alloc = gfc_finish_block (&alloc_block);
 
@@ -1781,6 +1794,7 @@ gfc_deallocate_with_status (tree pointer, tree status, tree errmsg,
   tree cond, tmp, error;
   tree status_type = NULL_TREE;
   tree token = NULL_TREE;
+  tree descr = NULL_TREE;
   gfc_coarray_deregtype caf_dereg_type = GFC_CAF_COARRAY_DEREGISTER;
 
   if (coarray_dealloc_mode >= GFC_CAF_COARRAY_ANALYZE)
@@ -1788,7 +1802,11 @@ gfc_deallocate_with_status (tree pointer, tree status, tree errmsg,
       if (flag_coarray == GFC_FCOARRAY_LIB)
        {
          if (caf_token)
-           token = caf_token;
+           {
+             token = caf_token;
+             if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (pointer)))
+               pointer = gfc_conv_descriptor_data_get (pointer);
+           }
          else
            {
              tree caf_type, caf_decl = pointer;
@@ -1824,7 +1842,10 @@ gfc_deallocate_with_status (tree pointer, tree status, tree errmsg,
        pointer = gfc_conv_descriptor_data_get (pointer);
     }
   else if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (pointer)))
-    pointer = gfc_conv_descriptor_data_get (pointer);
+    {
+      descr = pointer;
+      pointer = gfc_conv_descriptor_data_get (pointer);
+    }
 
   cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, pointer,
                          build_int_cst (TREE_TYPE (pointer), 0));
@@ -1876,9 +1897,27 @@ gfc_deallocate_with_status (tree pointer, tree status, tree errmsg,
       tmp = build_call_expr_loc (input_location,
                                 builtin_decl_explicit (BUILT_IN_FREE), 1,
                                 fold_convert (pvoid_type_node, pointer));
+      if (flag_openmp_allocators && coarray_dealloc_mode < GFC_CAF_COARRAY_ANALYZE)
+       {
+         tree cond, omp_tmp;
+         if (descr)
+           cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
+                                   gfc_conv_descriptor_version (descr),
+                                   build_int_cst (integer_type_node, 1));
+         else
+           cond = gfc_omp_call_is_alloc (pointer);
+         omp_tmp = builtin_decl_explicit (BUILT_IN_GOMP_FREE);
+         omp_tmp = build_call_expr_loc (input_location, omp_tmp, 2, pointer,
+                                        build_zero_cst (ptr_type_node));
+         tmp = build3_loc (input_location, COND_EXPR, TREE_TYPE (tmp), cond,
+                           omp_tmp, tmp);
+       }
       gfc_add_expr_to_block (&non_null, tmp);
       gfc_add_modify (&non_null, pointer, build_int_cst (TREE_TYPE (pointer),
                                                         0));
+      if (flag_openmp_allocators && descr)
+       gfc_add_modify (&non_null, gfc_conv_descriptor_version (descr),
+                       build_zero_cst (integer_type_node));
 
       if (status != NULL_TREE && !integer_zerop (status))
        {
@@ -2050,6 +2089,16 @@ gfc_deallocate_scalar_with_status (tree pointer, tree status, tree label_finish,
       tmp = build_call_expr_loc (input_location,
                                 builtin_decl_explicit (BUILT_IN_FREE), 1,
                                 fold_convert (pvoid_type_node, pointer));
+      if (flag_openmp_allocators)
+       {
+         tree cond, omp_tmp;
+         cond = gfc_omp_call_is_alloc (pointer);
+         omp_tmp = builtin_decl_explicit (BUILT_IN_GOMP_FREE);
+         omp_tmp = build_call_expr_loc (input_location, omp_tmp, 2, pointer,
+                                        build_zero_cst (ptr_type_node));
+         tmp = build3_loc (input_location, COND_EXPR, TREE_TYPE (tmp), cond,
+                           omp_tmp, tmp);
+       }
       gfc_add_expr_to_block (&non_null, tmp);
 
       if (status != NULL_TREE && !integer_zerop (status))
@@ -2483,7 +2532,7 @@ trans_code (gfc_code * code, tree cond)
          break;
 
        case EXEC_ALLOCATE:
-         res = gfc_trans_allocate (code);
+         res = gfc_trans_allocate (code, NULL);
          break;
 
        case EXEC_DEALLOCATE:
index 109d764723544c973fda81264e9b5fd5ba78e455..728d4f8f43f93411d2d043b438b6619ef1c28883 100644 (file)
@@ -764,10 +764,14 @@ void gfc_allocate_using_caf_lib (stmtblock_t *, tree, tree, tree, tree, tree,
 
 /* Allocate memory for allocatable variables, with optional status variable.  */
 void gfc_allocate_allocatable (stmtblock_t*, tree, tree, tree, tree,
-                              tree, tree, tree, gfc_expr*, int);
+                              tree, tree, tree, gfc_expr*, int,
+                              tree = NULL_TREE, tree = NULL_TREE,
+                              tree = NULL_TREE);
 
 /* Allocate memory, with optional status variable.  */
-void gfc_allocate_using_malloc (stmtblock_t *, tree, tree, tree);
+void gfc_allocate_using_malloc (stmtblock_t *, tree, tree, tree,
+                               tree = NULL_TREE, tree = NULL_TREE,
+                               tree = NULL_TREE);
 
 /* Generate code to deallocate an array.  */
 tree gfc_deallocate_with_status (tree, tree, tree, tree, tree, bool,
@@ -817,6 +821,8 @@ struct array_descr_info;
 bool gfc_get_array_descr_info (const_tree, struct array_descr_info *);
 
 /* In trans-openmp.cc */
+tree gfc_omp_call_add_alloc (tree);
+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);
index 7a465c89c5fbd912792481c6844b759504b9c13d..5462381cdd40b2b977dbeb90ed4947e6e710a9c7 100644 (file)
@@ -155,6 +155,8 @@ DEF_FUNCTION_TYPE_3 (BT_FN_UINT_UINT_PTR_PTR, BT_UINT, BT_UINT, BT_PTR, BT_PTR)
 DEF_FUNCTION_TYPE_3 (BT_FN_PTR_SIZE_SIZE_PTRMODE,
                     BT_PTR, BT_SIZE, BT_SIZE, BT_PTRMODE)
 
+DEF_FUNCTION_TYPE_4 (BT_FN_PTR_PTR_SIZE_PTRMODE_PTRMODE,
+                    BT_PTR, BT_PTR, BT_SIZE, BT_PTRMODE, BT_PTRMODE)
 DEF_FUNCTION_TYPE_4 (BT_FN_VOID_OMPFN_PTR_UINT_UINT,
                      BT_VOID, BT_PTR_FN_VOID_PTR, BT_PTR, BT_UINT, BT_UINT)
 DEF_FUNCTION_TYPE_4 (BT_FN_UINT_OMPFN_PTR_UINT_UINT,
index da2e3fe3a0dc0a2dbc46449be1ec68480762a474..1646bd1be14c140c33c7ed53f09f5f1bb29dc9f4 100644 (file)
@@ -1574,6 +1574,7 @@ fndecl_alloc_p (tree fndecl, bool all_alloc)
        case BUILT_IN_ALIGNED_ALLOC:
        case BUILT_IN_CALLOC:
        case BUILT_IN_GOMP_ALLOC:
+       case BUILT_IN_GOMP_REALLOC:
        case BUILT_IN_MALLOC:
        case BUILT_IN_REALLOC:
        case BUILT_IN_STRDUP:
@@ -1801,9 +1802,20 @@ matching_alloc_calls_p (tree alloc_decl, tree dealloc_decl)
        case BUILT_IN_ALLOCA_WITH_ALIGN:
          return false;
 
+       case BUILT_IN_GOMP_ALLOC:
+       case BUILT_IN_GOMP_REALLOC:
+         if (DECL_IS_OPERATOR_DELETE_P (dealloc_decl))
+           return false;
+
+         if (fndecl_built_in_p (dealloc_decl, BUILT_IN_GOMP_FREE,
+                                              BUILT_IN_GOMP_REALLOC))
+           return true;
+
+         alloc_dealloc_kind = alloc_kind_t::builtin;
+         break;
+
        case BUILT_IN_ALIGNED_ALLOC:
        case BUILT_IN_CALLOC:
-       case BUILT_IN_GOMP_ALLOC:
        case BUILT_IN_MALLOC:
        case BUILT_IN_REALLOC:
        case BUILT_IN_STRDUP:
@@ -1829,7 +1841,8 @@ matching_alloc_calls_p (tree alloc_decl, tree dealloc_decl)
   if (fndecl_built_in_p (dealloc_decl, BUILT_IN_NORMAL))
     {
       built_in_function dealloc_code = DECL_FUNCTION_CODE (dealloc_decl);
-      if (dealloc_code == BUILT_IN_REALLOC)
+      if (dealloc_code == BUILT_IN_REALLOC
+         || dealloc_code == BUILT_IN_GOMP_REALLOC)
        realloc_kind = alloc_kind_t::builtin;
 
       for (tree amats = DECL_ATTRIBUTES (alloc_decl);
@@ -1882,6 +1895,7 @@ matching_alloc_calls_p (tree alloc_decl, tree dealloc_decl)
            case BUILT_IN_ALIGNED_ALLOC:
            case BUILT_IN_CALLOC:
            case BUILT_IN_GOMP_ALLOC:
+           case BUILT_IN_GOMP_REALLOC:
            case BUILT_IN_MALLOC:
            case BUILT_IN_REALLOC:
            case BUILT_IN_STRDUP:
index 7924d900b358e6ffecc7f59e33b40a85fc224ef3..67f3fb2dabf0eb802f2aa7edd99ea922076b9f0c 100644 (file)
@@ -2988,6 +2988,8 @@ nonfreeing_call_p (gimple *call)
        case BUILT_IN_TM_FREE:
        case BUILT_IN_REALLOC:
        case BUILT_IN_STACK_RESTORE:
+       case BUILT_IN_GOMP_FREE:
+       case BUILT_IN_GOMP_REALLOC:
          return false;
        default:
          return true;
index ed78d49d20539959b66648e76ba9d5c9f50dbbb4..7b6b1dca3e34e5d1e2d797f5ad750e9f9d02927f 100644 (file)
@@ -467,6 +467,9 @@ DEF_GOMP_BUILTIN (BUILT_IN_GOMP_WORKSHARE_TASK_REDUCTION_UNREGISTER,
 DEF_GOMP_BUILTIN (BUILT_IN_GOMP_ALLOC,
                  "GOMP_alloc", BT_FN_PTR_SIZE_SIZE_PTRMODE,
                  ATTR_ALLOC_WARN_UNUSED_RESULT_SIZE_2_NOTHROW_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_REALLOC,
+                 "omp_realloc", BT_FN_PTR_PTR_SIZE_PTRMODE_PTRMODE,
+                 ATTR_ALLOC_WARN_UNUSED_RESULT_SIZE_2_NOTHROW_LEAF_LIST)
 DEF_GOMP_BUILTIN (BUILT_IN_GOMP_FREE,
                  "GOMP_free", BT_FN_VOID_PTR_PTRMODE, ATTR_NOTHROW_LEAF_LIST)
 DEF_GOMP_BUILTIN (BUILT_IN_GOMP_WARNING, "GOMP_warning",
index 396746cbfd1ad446f7ae07067a78dc0005474e16..2e9b7dd07a7c3ba37921ed1614b2660e509eab7b 100644 (file)
@@ -2566,6 +2566,7 @@ expr_expected_value_1 (tree type, tree op0, enum tree_code code,
                *predictor = PRED_COMPARE_AND_SWAP;
                return boolean_true_node;
              case BUILT_IN_REALLOC:
+             case BUILT_IN_GOMP_REALLOC:
                if (predictor)
                  *predictor = PRED_MALLOC_NONNULL;
                /* FIXME: This is wrong and we need to convert the logic
index 04faa433435e4120bebe0086c79dd5c91f9dfd2e..0825efc7a2ff449773c94ad5b24c8388bb7ad323 100644 (file)
@@ -25,7 +25,7 @@ end
 
 
 ! { dg-final { scan-tree-dump "parm...span = 4;" "original" } }
-! { dg-final { scan-tree-dump "parm...dtype = {.elem_len=4, .rank=2, .type=1};" "original" } }
+! { dg-final { scan-tree-dump "parm...dtype = {.elem_len=4, .version=0, .rank=2, .type=1};" "original" } }
 ! { dg-final { scan-tree-dump "parm...dim\\\[0\\\].lbound = 1;" "original" } }
 ! { dg-final { scan-tree-dump "parm...dim\\\[0\\\].ubound = 4;" "original" } }
 ! { dg-final { scan-tree-dump "parm...dim\\\[0\\\].stride = 1;" "original" } }
index 8ff9c252e49b2d50f4c53e6820ba5a679ddf8ac6..4fed19249a3dc133cc9e8954a453d22e71ff1ec7 100644 (file)
@@ -93,3 +93,44 @@ subroutine c_and_func_ptrs
   !$omp allocate(cfunptr) ! OK? A normal derived-type var?
   !$omp allocate(p)  ! { dg-error "Argument 'p' at .1. to declarative !.OMP ALLOCATE directive must be a variable" }
 end
+
+
+subroutine coarray_2
+  use m
+  implicit none
+  integer :: x
+  integer, allocatable :: a, b, c[:], d
+  x = 5 ! executable stmt
+  !$omp allocate(a,b) align(16)
+  !$omp allocate        ! { dg-error "Unexpected coarray 'c' in 'allocate' at .1., implicitly listed in '!.OMP ALLOCATE' at .2." }
+  !$omp allocate(d) align(32)
+  allocate(a,b,c[*],d)  ! { dg-error "Unexpected coarray 'c' in 'allocate' at .1., implicitly listed in '!.OMP ALLOCATE' at .2." }
+end
+
+
+subroutine coarray_3
+  use m
+  implicit none
+  integer :: x
+  integer, allocatable :: a, b, c[:], d
+  x = 5 ! executable stmt
+  !$omp allocators allocate(align(16): a,b) allocate(align(32) : d) 
+  allocate(a,b,c[*],d)  ! OK - Fortran allocator used for 'C'
+end
+
+
+subroutine unclear
+  use m
+  implicit none
+  integer :: x
+  integer, allocatable :: a, b, c[:], d
+
+  ! OpenMP is unclear which allocator is used for 'C' - the fortran one or the OpenMP one.
+  ! GCC therefore rejects it.
+
+  x = 5 ! executable stmt
+
+  !$omp allocate(a,b) align(16)
+  !$omp allocate(d) align(32)
+  allocate(a,b,c[*],d)  ! { dg-error "'c' listed in 'allocate' statement at .1. but it is neither explicitly in listed in the '!.OMP ALLOCATE' directive nor exists a directive without argument list" }
+end
diff --git a/gcc/testsuite/gfortran.dg/gomp/allocate-16.f90 b/gcc/testsuite/gfortran.dg/gomp/allocate-16.f90
new file mode 100644 (file)
index 0000000..6c203e0
--- /dev/null
@@ -0,0 +1,10 @@
+integer, pointer :: ptr
+
+!$omp flush
+!$omp allocate(ptr)
+allocate(ptr)
+end
+
+! { dg-error "'!.OMP ALLOCATE' at .1. requires '-fopenmp-allocators'" "" { target *-*-* } 4 }
+! { dg-warning "All files that might deallocate such a variable must be compiled with '-fopenmp-allocators'" "" { target *-*-* } 4 }
+! { dg-note "This includes explicit DEALLOCATE, reallocation on intrinsic assignment, INTENT\\(OUT\\) for allocatable dummy arguments, and reallocation of allocatable components allocated with an OpenMP allocator" "" { target *-*-* } 0 }
index bf9c781dcc50ac9f360ca3c7ad1d964562feb9cf..28369ae876bfb1ef289d87ed3aeaf9cfdaec8960 100644 (file)
@@ -1,3 +1,4 @@
+! { dg-additional-options "-fopenmp-allocators" }
 module my_omp_lib
   use iso_c_binding, only: c_intptr_t
   !use omp_lib
@@ -45,15 +46,15 @@ subroutine two(c,x2,y2)
   class(t), pointer :: y2(:)
 
   !$omp flush  ! some executable statement
-  !$omp allocate(a)  ! { dg-message "not yet supported" }
-  allocate(a,b(4),c(3,4))
-  deallocate(a,b,c)
+  !$omp allocate(a)
+  allocate(a)
+  deallocate(a)
 
-  !$omp allocate(x1,y1,x2,y2)  ! { dg-message "not yet supported" }
+  !$omp allocate(x1,y1,x2,y2)
   allocate(x1,y1,x2(5),y2(5))
   deallocate(x1,y1,x2,y2)
 
-  !$omp allocate(b,a) align ( 128 )  ! { dg-message "not yet supported" }
+  !$omp allocate(b,a) align ( 128 )
   !$omp allocate align ( 64 )
   allocate(a,b(4),c(3,4))
   deallocate(a,b,c)
@@ -66,7 +67,7 @@ subroutine three(c)
   integer, allocatable :: a, b(:), c(:,:)
 
   call foo()  ! executable stmt
-  !$omp allocate allocator( omp_large_cap_mem_alloc ) , align(64)  ! { dg-message "not yet supported" }
+  !$omp allocate allocator( omp_large_cap_mem_alloc ) , align(64)
   !$omp allocate(b) allocator( omp_high_bw_mem_alloc )
   !$omp allocate(c) allocator( omp_high_bw_mem_alloc )
   allocate(a,b(4),c(3,4))
@@ -74,7 +75,7 @@ subroutine three(c)
 
   block
     q = 5  ! executable stmt
-    !$omp allocate(a) align(64)  ! { dg-message "not yet supported" }
+    !$omp allocate(a) align(64)
     !$omp allocate(b) allocator( omp_high_bw_mem_alloc ), align(32)
     !$omp allocate(c) allocator( omp_thread_mem_alloc )
     allocate(a,b(4),c(3,4))
@@ -84,7 +85,7 @@ subroutine three(c)
 contains
   subroutine inner
     call foo()  ! executable stmt
-    !$omp allocate(a) align(64)  ! { dg-message "not yet supported" }
+    !$omp allocate(a) align(64)
     !$omp allocate(b) allocator( omp_high_bw_mem_alloc ), align(32)
     !$omp allocate(c) allocator( omp_thread_mem_alloc )
     allocate(a,b(4),c(3,4))
diff --git a/gcc/testsuite/gfortran.dg/gomp/allocators-3.f90 b/gcc/testsuite/gfortran.dg/gomp/allocators-3.f90
new file mode 100644 (file)
index 0000000..d0e31ee
--- /dev/null
@@ -0,0 +1,36 @@
+subroutine f
+  integer, allocatable :: A1, A2, B(:), C
+  !$omp declare target
+
+  !$omp allocators  ! OK
+  allocate(A1)
+
+  !$omp allocators allocate(align(8) : a2) ! { dg-error "ALLOCATORS directive at .1. inside a target region must specify an ALLOCATOR modifier for 'a2'" }
+  allocate(A2)
+
+  !$omp allocate  ! { dg-error "ALLOCATE directive at .1. inside a target region must specify an ALLOCATOR clause" }
+  allocate(B(5))
+
+  !$omp allocate(c)  ! { dg-error "ALLOCATE directive at .1. inside a target region must specify an ALLOCATOR clause for 'c'" }
+  allocate(C)
+end
+
+subroutine g
+  integer, allocatable :: A1, A2, B(:), C
+
+  !$omp target
+  !$omp single
+    !$omp allocators  ! OK
+    allocate(A1)
+
+    !$omp allocators allocate(align(8) : a2) ! { dg-error "ALLOCATORS directive at .1. inside a target region must specify an ALLOCATOR modifier for 'a2'" }
+    allocate(A2)
+
+    !$omp allocate  ! { dg-error "ALLOCATE directive at .1. inside a target region must specify an ALLOCATOR clause" }
+    allocate(B(5))
+
+    !$omp allocate(c)  ! { dg-error "ALLOCATE directive at .1. inside a target region must specify an ALLOCATOR clause for 'c'" }
+    allocate(C)
+  !$omp end single
+  !$omp end target
+end
diff --git a/gcc/testsuite/gfortran.dg/gomp/allocators-4.f90 b/gcc/testsuite/gfortran.dg/gomp/allocators-4.f90
new file mode 100644 (file)
index 0000000..55ae48d
--- /dev/null
@@ -0,0 +1,9 @@
+integer, pointer :: ptr
+
+!$omp allocators allocate(ptr)
+allocate(ptr)
+end
+
+! { dg-error "'!.OMP ALLOCATORS' at .1. requires '-fopenmp-allocators'" "" { target *-*-* } 3 }
+! { dg-warning "All files that might deallocate such a variable must be compiled with '-fopenmp-allocators'" "" { target *-*-* } 3 }
+! { dg-note "This includes explicit DEALLOCATE, reallocation on intrinsic assignment, INTENT\\(OUT\\) for allocatable dummy arguments, and reallocation of allocatable components allocated with an OpenMP allocator" "" { target *-*-* } 0 }
index 03ff88afadddd72e6608087ba480caf6c9cbc5e6..ddcbaaaa417de6ca9b2d5279da990c3b600b07a4 100644 (file)
@@ -2346,6 +2346,7 @@ evaluate_stmt (gimple *stmt)
            {
            case BUILT_IN_MALLOC:
            case BUILT_IN_REALLOC:
+           case BUILT_IN_GOMP_REALLOC:
            case BUILT_IN_CALLOC:
            case BUILT_IN_STRDUP:
            case BUILT_IN_STRNDUP:
index 10c6e1ecc588f6824e6173d97cf6e1a8a0651c04..b626553a1e13ced5cdfc36dadcd3bf65cef1c925 100644 (file)
@@ -15023,6 +15023,8 @@ fndecl_dealloc_argno (tree fndecl)
        {
        case BUILT_IN_FREE:
        case BUILT_IN_REALLOC:
+       case BUILT_IN_GOMP_FREE:
+       case BUILT_IN_GOMP_REALLOC:
          return 0;
        default:
          break;
index a8a80f8028dd089463149161995c0cc5f4a9ee78..58a4c57f88356f51b1e5c0dbe497df43f79e022d 100644 (file)
 #include <dlfcn.h>
 #endif
 
+/* Keeping track whether a Fortran scalar allocatable/pointer has been
+   allocated via 'omp allocators'/'omp allocate'.  */
+
+struct fort_alloc_splay_tree_key_s {
+  void *ptr;
+};
+
+typedef struct fort_alloc_splay_tree_node_s *fort_alloc_splay_tree_node;
+typedef struct fort_alloc_splay_tree_s *fort_alloc_splay_tree;
+typedef struct fort_alloc_splay_tree_key_s *fort_alloc_splay_tree_key;
+
+static inline int
+fort_alloc_splay_compare (fort_alloc_splay_tree_key x, fort_alloc_splay_tree_key y)
+{
+  if (x->ptr < y->ptr)
+    return -1;
+  if (x->ptr > y->ptr)
+    return 1;
+  return 0;
+}
+#define splay_tree_prefix fort_alloc
+#define splay_tree_static
+#include "splay-tree.h"
+
+#define splay_tree_prefix fort_alloc
+#define splay_tree_static
+#define splay_tree_c
+#include "splay-tree.h"
+
+static struct fort_alloc_splay_tree_s fort_alloc_scalars;
+
+/* Add pointer as being alloced by GOMP_alloc.  */
+void
+GOMP_add_alloc (void *ptr)
+{
+  if (ptr == NULL)
+    return;
+  fort_alloc_splay_tree_node item;
+  item = gomp_malloc (sizeof (struct splay_tree_node_s));
+  item->key.ptr = ptr;
+  item->left = NULL;
+  item->right = NULL;
+  fort_alloc_splay_tree_insert (&fort_alloc_scalars, item);
+}
+
+/* Remove pointer, either called by FREE or by REALLOC,
+   either of them can change the allocation status.  */
+bool
+GOMP_is_alloc (void *ptr)
+{
+  struct fort_alloc_splay_tree_key_s needle;
+  fort_alloc_splay_tree_node n;
+  needle.ptr = ptr;
+  n = fort_alloc_splay_tree_lookup_node (&fort_alloc_scalars, &needle);
+  if (n)
+    {
+      fort_alloc_splay_tree_remove (&fort_alloc_scalars, &n->key);
+      free (n);
+    }
+  return n != NULL;
+}
+
+
 #define omp_max_predefined_alloc omp_thread_mem_alloc
 
 /* These macros may be overridden in config/<target>/allocator.c.
index fa29f42897688be9c10ac63f327dee67fae1a19b..7831e7bffe3871cbf9f7fa9d726eb451dfafeb8e 100644 (file)
@@ -1269,6 +1269,7 @@ reverse_splay_compare (reverse_splay_tree_key x, reverse_splay_tree_key y)
 }
 
 #define splay_tree_prefix reverse
+#define splay_tree_static
 #include "splay-tree.h"
 
 /* Indirect target function splay-tree handling.  */
index 90c401453b292e4bdc790caf9162b1da5bd46c00..65901dff235920b2849a4ba09ab37f43c5d3942b 100644 (file)
@@ -419,9 +419,15 @@ GOMP_5.1 {
 GOMP_5.1.1 {
   global:
        GOMP_taskwait_depend_nowait;
-       GOMP_target_map_indirect_ptr;
 } GOMP_5.1;
 
+GOMP_5.1.2 {
+  global:
+       GOMP_add_alloc;
+       GOMP_is_alloc;
+       GOMP_target_map_indirect_ptr;
+} GOMP_5.1.1;
+
 OACC_2.0 {
   global:
        acc_get_num_devices;
index 67a111265a0178dad691f0d8c92845eac1825bcd..cff2a2a008008ec6dd87979f3138bca9189e6162 100644 (file)
@@ -232,7 +232,9 @@ The OpenMP 4.5 specification is fully supported.
 @item Predefined memory spaces, memory allocators, allocator traits
       @tab Y @tab See also @ref{Memory allocation}
 @item Memory management routines @tab Y @tab
-@item @code{allocate} directive @tab P @tab Only C and Fortran, only stack variables
+@item @code{allocate} directive @tab P
+      @tab Only C for stack/automatic and Fortran for stack/automatic
+      and allocatable/pointer variables
 @item @code{allocate} clause @tab P @tab Initial support
 @item @code{use_device_addr} clause on @code{target data} @tab Y @tab
 @item @code{ancestor} modifier on @code{device} clause @tab Y @tab
@@ -304,7 +306,7 @@ The OpenMP 4.5 specification is fully supported.
 @item @code{strict} modifier in the @code{grainsize} and @code{num_tasks}
       clauses of the @code{taskloop} construct @tab Y @tab
 @item @code{align} clause in @code{allocate} directive @tab P
-      @tab Only C and Fortran (and only stack variables)
+      @tab Only C and Fortran (and not for static variables)
 @item @code{align} modifier in @code{allocate} clause @tab Y @tab
 @item @code{thread_limit} clause to @code{target} construct @tab Y @tab
 @item @code{has_device_addr} clause to @code{target} construct @tab Y @tab
@@ -402,7 +404,7 @@ to address of matching mapped list item per 5.1, Sect. 2.21.7.2 @tab N @tab
 @item Deprecation of @code{to} clause on declare target directive @tab N @tab
 @item Extended list of directives permitted in Fortran pure procedures
       @tab Y @tab
-@item New @code{allocators} directive for Fortran @tab N @tab
+@item New @code{allocators} directive for Fortran @tab Y @tab
 @item Deprecation of @code{allocate} directive for Fortran
       allocatables/pointers @tab N @tab
 @item Optional paired @code{end} directive with @code{dispatch} @tab N @tab
@@ -5697,8 +5699,12 @@ The description below applies to:
       @option{-fstack-arrays}].)
 @item Using the @code{allocate} directive for variable in static memory is
       currently not supported (compile time error).
-@item Using the @code{allocators} directive for Fortran pointers and
-      allocatables is currently not supported (compile time error).
+@item In Fortran, the @code{allocators} directive and the executable
+      @code{allocate} directive for Fortran pointers and allocatables is
+      supported, but requires that files containing those directives has to be
+      compiled with @option{-fopenmp-allocators}.  Additionally, all files that
+      might explicitly or implicitly deallocate memory allocated that way must
+      also be compiled with that option.
 @end itemize
 
 For the available predefined allocators and, as applicable, their associated
index 02695d4b2bd7b5b8af5642f962216979c8134bfc..9e076f551806a87fc844ba8d94b125a5e7ea3687 100644 (file)
@@ -131,7 +131,11 @@ splay_tree_splay (splay_tree sp, splay_tree_key key)
 
 /* Insert a new NODE into SP.  The NODE shouldn't exist in the tree.  */
 
+#ifdef splay_tree_static
+__attribute__((unused)) static void
+#else
 attribute_hidden void
+#endif
 splay_tree_insert (splay_tree sp, splay_tree_node node)
 {
   int comparison = 0;
@@ -167,7 +171,11 @@ splay_tree_insert (splay_tree sp, splay_tree_node node)
 
 /* Remove node with KEY from SP.  It is not an error if it did not exist.  */
 
+#ifdef splay_tree_static
+__attribute__((unused)) static void
+#else
 attribute_hidden void
+#endif
 splay_tree_remove (splay_tree sp, splay_tree_key key)
 {
   splay_tree_splay (sp, key);
@@ -202,7 +210,28 @@ splay_tree_remove (splay_tree sp, splay_tree_key key)
 /* Lookup KEY in SP, returning NODE if present, and NULL
    otherwise.  */
 
+#ifdef splay_tree_static
+__attribute__((unused)) static splay_tree_node
+#else
+attribute_hidden splay_tree_node
+#endif
+splay_tree_lookup_node (splay_tree sp, splay_tree_key key)
+{
+  splay_tree_splay (sp, key);
+
+  if (sp->root && splay_compare (&sp->root->key, key) == 0)
+    return sp->root;
+  else
+    return NULL;
+}
+
+/* Likewise but return the key.  */
+
+#ifdef splay_tree_static
+__attribute__((unused)) static splay_tree_key
+#else
 attribute_hidden splay_tree_key
+#endif
 splay_tree_lookup (splay_tree sp, splay_tree_key key)
 {
   splay_tree_splay (sp, key);
@@ -231,7 +260,11 @@ splay_tree_foreach_internal (splay_tree_node node, splay_tree_callback func,
 
 /* Run FUNC on each of the nodes in SP.  */
 
+#ifdef splay_tree_static
+__attribute__((unused)) static void
+#else
 attribute_hidden void
+#endif
 splay_tree_foreach (splay_tree sp, splay_tree_callback func, void *data)
 {
   splay_tree_foreach_internal (sp->root, func, data);
@@ -253,8 +286,13 @@ splay_tree_foreach_internal_lazy (splay_tree_node node,
   return splay_tree_foreach_internal_lazy (node->right, func, data);
 }
 
+#ifdef splay_tree_static
+__attribute__((unused)) static void
+#else
 attribute_hidden void
-splay_tree_foreach_lazy (splay_tree sp, splay_tree_callback_stop func, void *data)
+#endif
+splay_tree_foreach_lazy (splay_tree sp, splay_tree_callback_stop func,
+                        void *data)
 {
   splay_tree_foreach_internal_lazy (sp->root, func, data);
 }
index 978f1e49800dd325d76601922c071e38d87cc6c8..04ff94739b09533ee1e07c77db8cf4be2df085e1 100644 (file)
@@ -35,6 +35,8 @@ typedef struct splay_tree_key_s *splay_tree_key;
    define splay_tree_key_s structure, and define
    splay_compare inline function.
 
+   Define splay_tree_static to mark all functions as static.
+
    Alternatively, they can define splay_tree_prefix macro before
    including this header and then all the above types, the
    splay_compare function and the splay_tree_{lookup,insert_remove}
@@ -72,6 +74,8 @@ typedef struct splay_tree_key_s *splay_tree_key;
     splay_tree_name (splay_tree_prefix, splay_compare)
 # define splay_tree_lookup     \
     splay_tree_name (splay_tree_prefix, splay_tree_lookup)
+# define splay_tree_lookup_node        \
+    splay_tree_name (splay_tree_prefix, splay_tree_lookup_node)
 # define splay_tree_insert     \
     splay_tree_name (splay_tree_prefix, splay_tree_insert)
 # define splay_tree_remove     \
@@ -105,11 +109,19 @@ struct splay_tree_s {
 typedef void (*splay_tree_callback) (splay_tree_key, void *);
 typedef int (*splay_tree_callback_stop) (splay_tree_key, void *);
 
+#ifndef splay_tree_static
 extern splay_tree_key splay_tree_lookup (splay_tree, splay_tree_key);
+extern splay_tree_node splay_tree_lookup_node (splay_tree, splay_tree_key);
 extern void splay_tree_insert (splay_tree, splay_tree_node);
 extern void splay_tree_remove (splay_tree, splay_tree_key);
 extern void splay_tree_foreach (splay_tree, splay_tree_callback, void *);
 extern void splay_tree_foreach_lazy (splay_tree, splay_tree_callback_stop, void *);
+#endif
+
+#ifdef splay_tree_static_unused_attr
+#  undef splay_tree_static_unused_attr
+#endif
+
 #else  /* splay_tree_c */
 #  ifdef splay_tree_prefix
 #    include "splay-tree.c"
@@ -117,6 +129,10 @@ extern void splay_tree_foreach_lazy (splay_tree, splay_tree_callback_stop, void
 #  undef splay_tree_c
 #endif /* #ifndef splay_tree_c */
 
+#ifdef splay_tree_static
+#  undef splay_tree_static
+#endif
+
 #ifdef splay_tree_prefix
 #  undef splay_tree_name_1
 #  undef splay_tree_name
@@ -128,6 +144,7 @@ extern void splay_tree_foreach_lazy (splay_tree, splay_tree_callback_stop, void
 #  undef splay_tree_key
 #  undef splay_compare
 #  undef splay_tree_lookup
+#  undef splay_tree_lookup_node
 #  undef splay_tree_insert
 #  undef splay_tree_remove
 #  undef splay_tree_foreach
index f30c20255d3b56186a354416112c90df65c6abd0..0637d34f1258c2f115db7c416042885b90037c5f 100644 (file)
@@ -47,6 +47,7 @@
 
 /* Define another splay tree instantiation - for reverse offload.  */
 #define splay_tree_prefix reverse
+#define splay_tree_static
 #define splay_tree_c
 #include "splay-tree.h"
 
diff --git a/libgomp/testsuite/libgomp.fortran/allocators-1.f90 b/libgomp/testsuite/libgomp.fortran/allocators-1.f90
new file mode 100644 (file)
index 0000000..935a37c
--- /dev/null
@@ -0,0 +1,68 @@
+! { dg-additional-options "-fopenmp-allocators -fdump-tree-original" }
+module m
+  use omp_lib
+  use iso_c_binding, only: c_intptr_t
+  implicit none (type,external)
+  integer(omp_allocator_handle_kind) :: handle  
+  integer(c_intptr_t) :: iptr
+end module m
+
+subroutine scalar
+  use m
+  implicit none (type,external)
+  integer :: i
+  integer, allocatable :: SSS
+  i = 5  ! required executive statement before 'omp allocators'
+  !$omp allocate allocator(handle)
+  allocate(SSS)
+  if (mod (loc (sss), 64) /= 0) stop 1
+  deallocate(SSS)
+  allocate(SSS)
+end
+! { dg-final { scan-tree-dump-times "sss = \\(integer\\(kind=4\\) \\*\\) __builtin_GOMP_alloc \\(4, 4, D\\.\[0-9\]+\\);" 1 "original" } }
+! { dg-final { scan-tree-dump-times "GOMP_add_alloc \\(sss\\);" 1 "original" } }
+! { dg-final { scan-tree-dump-times "if \\(GOMP_is_alloc \\(sss\\)\\)" 2 "original" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_free \\(sss, 0B\\);" 2 "original" } }
+
+subroutine array
+  use m
+  implicit none (type,external)
+  integer :: i
+  integer, allocatable :: A(:)
+  i = 5  ! required executive statement before 'omp allocators'
+  !$omp allocate allocator(handle) align(512)
+  allocate(A(5))
+  if (mod (loc (A), 512) /= 0) stop 2
+  A=[1]
+  if (mod (loc (A), 64) /= 0) stop 3
+  deallocate(A)
+  A=[1]
+  deallocate(A)
+  call omp_set_default_allocator (handle)
+  !$omp allocate
+  allocate(A(7))
+  if (mod (loc (A), 64) /= 0) stop 4
+end
+! { dg-final { scan-tree-dump-times "a.dtype = {.elem_len=4, .version=0, .rank=1, .type=1};" 5 "original" } }
+! { dg-final { scan-tree-dump-times "\\.elem_len=4" 5 "original" } }
+! { dg-final { scan-tree-dump-times "a.data = \\(void \\* restrict\\) __builtin_GOMP_alloc \\(512, 20, D\\.\[0-9\]+\\);" 1 "original" } }
+! { dg-final { scan-tree-dump-times "a.data = \\(void \\* restrict\\) __builtin_GOMP_alloc \\(4, 28, 0B\\);" 1 "original" } }
+! { dg-final { scan-tree-dump-times "a.dtype.version = 1;" 2 "original" } }
+! { dg-final { scan-tree-dump-times "a.data = \\(void \\* restrict\\) \\(a.dtype.version == 1 \\? __builtin_omp_realloc \\(\\(void \\*\\) a.data, 4, 0B, 0B\\) : __builtin_realloc \\(\\(void \\*\\) a.data, 4\\)\\);" 2 "original" } }
+! { dg-final { scan-tree-dump-times "if \\(a.dtype.version == 1\\)" 3 "original" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_free \\(\\(integer\\(kind=4\\)\\\[0:\\\] \\* restrict\\) a.data, 0B\\);" 3 "original" } }
+! { dg-final { scan-tree-dump-times "a.dtype.version = 0;" 3 "original" } }
+
+program main
+  use m
+  implicit none (type,external)
+  external :: scalar, array
+  type (omp_alloctrait), parameter :: traits(*) &
+      = [omp_alloctrait(omp_atk_sync_hint, omp_atv_contended), &
+         omp_alloctrait(omp_atk_alignment, 64)]
+  handle = omp_init_allocator (omp_high_bw_mem_alloc, size(traits), traits)
+  call scalar
+  call array
+  call omp_destroy_allocator (handle)
+end
+
diff --git a/libgomp/testsuite/libgomp.fortran/allocators-2.f90 b/libgomp/testsuite/libgomp.fortran/allocators-2.f90
new file mode 100644 (file)
index 0000000..c42fbd3
--- /dev/null
@@ -0,0 +1,101 @@
+! { dg-additional-options "-fopenmp-allocators" }
+module m
+  implicit none (type, external)
+  type t
+    integer, allocatable :: Acomp, Bcomp(:)
+  end type t
+
+contains
+
+subroutine intent_out(aa, bb, cc, dd, ee, ff)
+  integer, allocatable,intent(out) :: aa, bb(:)
+  type(t), intent(out) :: cc, dd(4)
+  type(t), allocatable, intent(out) :: ee, ff(:)
+end
+
+subroutine q(qa, qb, qc, qd, qe, qf)
+  integer, allocatable :: qa, qb(:)
+  type(t) :: qc, qd(4)
+  type(t), allocatable :: qe, qf(:)
+  call intent_out (qa, qb, qc, qd, qe, qf)
+end subroutine q
+
+subroutine r
+  integer, allocatable :: r1, r2(:)
+  type(t) :: r3, r4(4)
+  type(t), allocatable :: r5, r6(:)
+
+  call q(r1,r2,r3,r4,r5,r6)
+
+  allocate(r1,r2(3))
+  allocate(r5,r6(4))
+  allocate(r3%Acomp, r3%Bcomp(2))
+  allocate(r4(2)%Acomp, r4(2)%Bcomp(2))
+  allocate(r5%Acomp, r5%Bcomp(2))
+  allocate(r6(3)%Acomp, r6(3)%Bcomp(2))
+  !$omp allocate align(128)
+  allocate(r4(3)%Acomp, r4(3)%Bcomp(2), &
+           r6(1)%Acomp, r6(1)%Bcomp(2))
+  if (mod (loc (r4(3)%Acomp), 128) /= 0) stop 1
+  if (mod (loc (r4(3)%Bcomp), 128) /= 0) stop 2
+  if (mod (loc (r6(1)%Acomp), 128) /= 0) stop 3
+  if (mod (loc (r6(1)%Bcomp), 128) /= 0) stop 3
+  call q(r1,r2,r3,r4,r5,r6)
+
+  !$omp allocate align(64)
+  allocate(r1,r2(3))
+  if (mod (loc (r1), 64) /= 0) stop 1
+  if (mod (loc (r2), 64) /= 0) stop 1
+  !$omp allocate align(64)
+  allocate(r5,r6(4))
+  if (mod (loc (r5), 64) /= 0) stop 1
+  if (mod (loc (r6), 64) /= 0) stop 1
+  !$omp allocate align(64)
+  allocate(r3%Acomp, r3%Bcomp(2))
+  if (mod (loc (r3%Acomp), 64) /= 0) stop 1
+  if (mod (loc (r3%Bcomp), 64) /= 0) stop 1
+  !$omp allocate align(64)
+  allocate(r4(2)%Acomp, r4(2)%Bcomp(2))
+  if (mod (loc (r4(2)%Acomp), 64) /= 0) stop 1
+  if (mod (loc (r4(2)%Bcomp), 64) /= 0) stop 1
+  !$omp allocate align(64)
+  allocate(r5%Acomp, r5%Bcomp(2))
+  if (mod (loc (r5%Acomp), 64) /= 0) stop 1
+  if (mod (loc (r5%Bcomp), 64) /= 0) stop 1
+  !$omp allocate align(64)
+  allocate(r6(3)%Acomp, r6(3)%Bcomp(2))
+  if (mod (loc (r6(3)%Acomp), 64) /= 0) stop 1
+  if (mod (loc (r6(3)%Bcomp), 64) /= 0) stop 1
+  !$omp allocate align(128)
+  allocate(r4(3)%Acomp, r4(3)%Bcomp(2), &
+           r6(1)%Acomp, r6(1)%Bcomp(2))
+  if (mod (loc (r4(3)%Acomp), 128) /= 0) stop 1
+  if (mod (loc (r4(3)%Bcomp), 128) /= 0) stop 2
+  if (mod (loc (r6(1)%Acomp), 128) /= 0) stop 3
+  if (mod (loc (r6(1)%Bcomp), 128) /= 0) stop 3
+  call q(r1,r2,r3,r4,r5,r6)
+end subroutine r
+end
+
+subroutine s
+  use m, only : t
+  implicit none (type, external)
+  type(t) :: xx
+  integer :: i, iiiiii
+  i = 4
+  !$omp allocate
+  allocate(xx%Acomp, xx%Bcomp(4))
+  deallocate(xx%Acomp, xx%Bcomp)
+
+  !$omp allocate
+  allocate(xx%Acomp, xx%Bcomp(4))
+  xx = t(1, [1,2])
+end
+
+program main
+  use m, only: r
+  implicit none (type, external)
+  external s
+  call s
+  call r
+end
diff --git a/libgomp/testsuite/libgomp.fortran/allocators-3.f90 b/libgomp/testsuite/libgomp.fortran/allocators-3.f90
new file mode 100644 (file)
index 0000000..2e05939
--- /dev/null
@@ -0,0 +1,25 @@
+! { dg-additional-options "-fdump-tree-original -fopenmp-allocators" }
+
+subroutine s
+  character(:), allocatable :: s1,s2
+
+  !$omp allocators allocate(s1)
+  allocate(character(len=3) :: s1)
+
+  !$omp allocators allocate(s2)
+  allocate(character(len=5) :: s2)
+
+  s2(1:5) = "12"
+  s1 = trim(s2)
+end
+! { dg-final { scan-tree-dump-times "s1 = \\(character\\(kind=1\\)\\\[1:.s1\\\] \\*\\) __builtin_GOMP_alloc \\(1, 3, 0B\\);" 1 "original" } }
+! { dg-final { scan-tree-dump-times "s2 = \\(character\\(kind=1\\)\\\[1:.s2\\\] \\*\\) __builtin_GOMP_alloc \\(1, 5, 0B\\);" 1 "original" } }
+! { dg-final { scan-tree-dump-times "s1 = \\(character\\(kind=1\\)\\\[1:.s1\\\] \\*\\) \\(D\\.\[0-9\]+ \\? __builtin_omp_realloc \\(\\(void \\*\\) s1, MAX_EXPR <\\(sizetype\\) len.1, 1>, 0B, 0B\\) : __builtin_realloc \\(\\(void \\*\\) s1, MAX_EXPR <\\(sizetype\\) len.1, 1>\\)\\);" 1 "original" } }
+! { dg-final { scan-tree-dump-times "GOMP_add_alloc \\(s1\\);" 2 "original" } }
+! { dg-final { scan-tree-dump-times "OMP_add_alloc \\(s2\\);" 1 "original" } }
+! { dg-final { scan-tree-dump-times "if \\(GOMP_is_alloc \\(s2\\)\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "__builtin_GOMP_free \\(s2, 0B\\);" 1 "original" } }
+
+
+call s
+end
diff --git a/libgomp/testsuite/libgomp.fortran/allocators-4.f90 b/libgomp/testsuite/libgomp.fortran/allocators-4.f90
new file mode 100644 (file)
index 0000000..12689ea
--- /dev/null
@@ -0,0 +1,57 @@
+! { dg-additional-options "-fopenmp-allocators" }
+module m
+implicit none
+type t
+  integer, allocatable :: Acomp, Bcomp(:)
+  class(*), allocatable :: Ccomp, Dcomp(:)
+end type t
+contains
+
+subroutine intout(c,d,e,f)
+implicit none
+class(t), intent(out) :: c,d(4)
+class(t), allocatable, intent(out) :: e,f(:)
+end
+
+subroutine q(c,d,e,f)
+implicit none
+class(t) :: c,d(4)
+class(t), allocatable :: e,f(:)
+call intout(c,d,e,f)
+end subroutine q
+
+subroutine s
+implicit none
+type(t) :: xx
+class(t), allocatable :: yy
+integer :: i, iiiiii
+i = 4
+!$omp allocate
+allocate(xx%Acomp, xx%Bcomp(4))
+deallocate(xx%Acomp, xx%Bcomp)
+
+!$omp allocate
+allocate(integer :: xx%Ccomp, xx%Dcomp(4))
+deallocate(xx%Ccomp, xx%Dcomp)
+
+!$omp allocators allocate(yy)
+allocate(t :: yy)
+
+!$omp allocate
+allocate(real :: xx%Ccomp, xx%Dcomp(4))
+deallocate(xx%Ccomp, xx%Dcomp)
+
+!$omp allocate
+allocate(xx%Acomp, xx%Bcomp(4))
+!$omp allocate
+allocate(logical :: xx%Ccomp, xx%Dcomp(4))
+
+iiiiii = 555
+xx = t(1, [1,2])
+end
+
+end module
+
+use m
+call s
+end
diff --git a/libgomp/testsuite/libgomp.fortran/allocators-5.f90 b/libgomp/testsuite/libgomp.fortran/allocators-5.f90
new file mode 100644 (file)
index 0000000..8708863
--- /dev/null
@@ -0,0 +1,27 @@
+! { dg-additional-options "-fopenmp-allocators" }
+module m
+contains
+subroutine s(a,b,c,d)
+integer, allocatable :: A, B
+integer, allocatable :: C(:), D(:)
+
+!$omp allocators allocate(A,B)
+allocate(A,B)
+call move_alloc(A,B)
+
+!$omp allocators allocate(C,D)
+allocate(C(5),D(5))
+call move_alloc(C,D)
+end
+
+subroutine q()
+integer, allocatable :: A, B
+integer, allocatable :: C(:), D(:)
+
+call s(a,b,c,d)
+end
+end
+
+use m
+call q
+end