Currently we are only handling omp allocate directive that is associated
with an allocate statement. This statement results in malloc and free calls.
The malloc calls are easy to get to as they are in the same block as allocate
directive. But the free calls come in a separate cleanup block. To help any
later passes finding them, an allocate directive is generated in the
cleanup block with kind=free. The normal allocate directive is given
kind=allocate.
gcc/fortran/ChangeLog:
* gfortran.h (struct access_ref): Declare new members
omp_allocated and omp_allocated_end.
* openmp.cc (gfc_match_omp_allocate): Set new_st.resolved_sym to
NULL.
(prepare_omp_allocated_var_list_for_cleanup): New function.
(gfc_resolve_omp_allocate): Call it.
* trans-decl.cc (gfc_trans_deferred_vars): Process omp_allocated.
* trans-openmp.cc (gfc_trans_omp_allocate): Set kind for the stmt
generated for allocate directive.
gcc/ChangeLog:
* tree-core.h (struct tree_base): Add comments.
* tree-pretty-print.cc (dump_generic_node): Handle allocate directive
kind.
* tree.h (OMP_ALLOCATE_KIND_ALLOCATE): New define.
(OMP_ALLOCATE_KIND_FREE): Likewise.
gcc/testsuite/ChangeLog:
* gfortran.dg/gomp/allocate-6.f90: Test kind of allocate directive.
---
gcc/fortran/gfortran.h | 1 +
gcc/fortran/openmp.cc | 30 +++++++++++++++++++
gcc/fortran/trans-decl.cc | 20 +++++++++++++
gcc/fortran/trans-openmp.cc | 6 ++++
gcc/testsuite/gfortran.dg/gomp/allocate-6.f90 | 3 +-
gcc/tree-core.h | 6 ++++
gcc/tree-pretty-print.cc | 4 +++
gcc/tree.h | 4 +++
8 files changed, 73 insertions(+), 1 deletion(-)
@@ -1829,6 +1829,7 @@ typedef struct gfc_symbol
gfc_array_spec *as;
struct gfc_symbol *result; /* function result symbol */
gfc_component *components; /* Derived type components */
+ gfc_omp_namelist *omp_allocated, *omp_allocated_end;
/* Defined only for Cray pointees; points to their pointer. */
struct gfc_symbol *cp_pointer;
@@ -6057,6 +6057,7 @@ gfc_match_omp_allocate (void)
new_st.op = EXEC_OMP_ALLOCATE;
new_st.ext.omp_clauses = c;
+ new_st.resolved_sym = NULL;
gfc_free_expr (allocator);
return MATCH_YES;
}
@@ -9548,6 +9549,34 @@ gfc_resolve_oacc_routines (gfc_namespace *ns)
}
}
+static void
+prepare_omp_allocated_var_list_for_cleanup (gfc_omp_namelist *cn, locus loc)
+{
+ gfc_symbol *proc = cn->sym->ns->proc_name;
+ gfc_omp_namelist *p, *n;
+
+ for (n = cn; n; n = n->next)
+ {
+ if (n->sym->attr.allocatable && !n->sym->attr.save
+ && !n->sym->attr.result && !proc->attr.is_main_program)
+ {
+ p = gfc_get_omp_namelist ();
+ p->sym = n->sym;
+ p->expr = gfc_copy_expr (n->expr);
+ p->where = loc;
+ p->next = NULL;
+ if (proc->omp_allocated == NULL)
+ proc->omp_allocated_end = proc->omp_allocated = p;
+ else
+ {
+ proc->omp_allocated_end->next = p;
+ proc->omp_allocated_end = p;
+ }
+
+ }
+ }
+}
+
static void
check_allocate_directive_restrictions (gfc_symbol *sym, gfc_expr *omp_al,
gfc_namespace *ns, locus loc)
@@ -9678,6 +9707,7 @@ gfc_resolve_omp_allocate (gfc_code *code, gfc_namespace *ns)
code->loc);
}
}
+ prepare_omp_allocated_var_list_for_cleanup (cn, code->loc);
}
@@ -4588,6 +4588,26 @@ gfc_trans_deferred_vars (gfc_symbol * proc_sym, gfc_wrapped_block * block)
}
}
+ /* Generate a dummy allocate pragma with free kind so that cleanup
+ of those variables which were allocated using the allocate statement
+ associated with an allocate clause happens correctly. */
+
+ if (proc_sym->omp_allocated)
+ {
+ gfc_clear_new_st ();
+ new_st.op = EXEC_OMP_ALLOCATE;
+ gfc_omp_clauses *c = gfc_get_omp_clauses ();
+ c->lists[OMP_LIST_ALLOCATOR] = proc_sym->omp_allocated;
+ new_st.ext.omp_clauses = c;
+ /* This is just a hacky way to convey to handler that we are
+ dealing with cleanup here. Saves us from using another field
+ for it. */
+ new_st.resolved_sym = proc_sym->omp_allocated->sym;
+ gfc_add_init_cleanup (block, NULL,
+ gfc_trans_omp_directive (&new_st));
+ gfc_free_omp_clauses (c);
+ proc_sym->omp_allocated = NULL;
+ }
/* Initialize the INTENT(OUT) derived type dummy arguments. This
should be done here so that the offsets and lbounds of arrays
@@ -5019,6 +5019,12 @@ gfc_trans_omp_allocate (gfc_code *code)
OMP_ALLOCATE_CLAUSES (stmt) = gfc_trans_omp_clauses (&block, clauses,
code->loc, false,
true);
+ if (code->next == NULL && code->block == NULL
+ && code->resolved_sym != NULL)
+ OMP_ALLOCATE_KIND_FREE (stmt) = 1;
+ else
+ OMP_ALLOCATE_KIND_ALLOCATE (stmt) = 1;
+
gfc_add_expr_to_block (&block, stmt);
gfc_merge_block_scope (&block);
return gfc_finish_block (&block);
@@ -69,4 +69,5 @@ end type
allocate(pii, parr(5))
end subroutine
-! { dg-final { scan-tree-dump-times "#pragma omp allocate" 6 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp allocate \\(kind=allocate\\)" 6 "original" } }
+! { dg-final { scan-tree-dump "#pragma omp allocate \\(kind=free\\)" "original" } }
@@ -1257,6 +1257,9 @@ struct GTY(()) tree_base {
EXPR_LOCATION_WRAPPER_P in
NON_LVALUE_EXPR, VIEW_CONVERT_EXPR
+ OMP_ALLOCATE_KIND_ALLOCATE in
+ OMP_ALLOCATE
+
private_flag:
TREE_PRIVATE in
@@ -1283,6 +1286,9 @@ struct GTY(()) tree_base {
ENUM_IS_OPAQUE in
ENUMERAL_TYPE
+ OMP_ALLOCATE_KIND_FREE in
+ OMP_ALLOCATE
+
protected_flag:
TREE_PROTECTED in
@@ -3541,6 +3541,10 @@ dump_generic_node (pretty_printer *pp, tree node, int spc, dump_flags_t flags,
case OMP_ALLOCATE:
pp_string (pp, "#pragma omp allocate ");
+ if (OMP_ALLOCATE_KIND_ALLOCATE (node))
+ pp_string (pp, "(kind=allocate) ");
+ else if (OMP_ALLOCATE_KIND_FREE (node))
+ pp_string (pp, "(kind=free) ");
dump_omp_clauses (pp, OMP_ALLOCATE_CLAUSES (node), spc, flags);
break;
@@ -1467,6 +1467,10 @@ class auto_suppress_location_wrappers
TREE_OPERAND (OACC_UPDATE_CHECK (NODE), 0)
#define OMP_ALLOCATE_CLAUSES(NODE) TREE_OPERAND (OMP_ALLOCATE_CHECK (NODE), 0)
+#define OMP_ALLOCATE_KIND_ALLOCATE(NODE) \
+ (OMP_ALLOCATE_CHECK (NODE)->base.public_flag)
+#define OMP_ALLOCATE_KIND_FREE(NODE) \
+ (OMP_ALLOCATE_CHECK (NODE)->base.private_flag)
#define OMP_PARALLEL_BODY(NODE) TREE_OPERAND (OMP_PARALLEL_CHECK (NODE), 0)
#define OMP_PARALLEL_CLAUSES(NODE) TREE_OPERAND (OMP_PARALLEL_CHECK (NODE), 1)