diff options
author | jakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4> | 2014-06-10 06:05:22 +0000 |
---|---|---|
committer | jakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4> | 2014-06-10 06:05:22 +0000 |
commit | cf5f881fe5d2ce6122d582582b72901a0896e6fb (patch) | |
tree | d0ec7ff75f32129f09cb9bd294a6cdde28a88977 /gcc | |
parent | 35402d60a25a2def2ffb4e867818b4132f165a88 (diff) | |
download | gcc-cf5f881fe5d2ce6122d582582b72901a0896e6fb.tar.gz |
PR fortran/60928
* omp-low.c (lower_rec_input_clauses) <case OMP_CLAUSE_LASTPRIVATE>:
Set lastprivate_firstprivate even if omp_private_outer_ref
langhook returns true.
<case OMP_CLAUSE_REDUCTION>: When calling omp_clause_default_ctor
langhook, call unshare_expr on new_var and call
build_outer_var_ref to get the last argument.
gcc/c-family/
* c-pragma.c (omp_pragmas_simd): Move PRAGMA_OMP_TASK...
(omp_pragmas): ... back here.
gcc/fortran/
* f95-lang.c (gfc_init_builtin_functions): Handle -fopenmp-simd
like -fopenmp.
* openmp.c (resolve_omp_clauses): Remove allocatable components
diagnostics. Add associate-name and intent(in) pointer
diagnostics for various clauses, diagnose procedure pointers in
reduction clause.
* parse.c (match_word_omp_simd): New function.
(matchs, matcho): New macros.
(decode_omp_directive): Change match macros to either matchs
or matcho. Handle -fopenmp-simd.
(next_free, next_fixed): Handle -fopenmp-simd like -fopenmp.
* scanner.c (skip_free_comments, skip_fixed_comments, include_line):
Likewise.
* trans-array.c (get_full_array_size): Rename to...
(gfc_full_array_size): ... this. No longer static.
(duplicate_allocatable): Adjust caller. Add NO_MEMCPY argument
and handle it.
(gfc_duplicate_allocatable, gfc_copy_allocatable_data): Adjust
duplicate_allocatable callers.
(gfc_duplicate_allocatable_nocopy): New function.
(structure_alloc_comps): Adjust g*_full_array_size and
duplicate_allocatable caller.
* trans-array.h (gfc_full_array_size,
gfc_duplicate_allocatable_nocopy): New prototypes.
* trans-common.c (create_common): Call gfc_finish_decl_attrs.
* trans-decl.c (gfc_finish_decl_attrs): New function.
(gfc_finish_var_decl, create_function_arglist,
gfc_get_fake_result_decl): Call it.
(gfc_allocate_lang_decl): If DECL_LANG_SPECIFIC is already allocated,
don't allocate it again.
(gfc_get_symbol_decl): Set GFC_DECL_ASSOCIATE_VAR_P on
associate-names.
* trans.h (gfc_finish_decl_attrs): New prototype.
(struct lang_decl): Add scalar_allocatable and scalar_pointer
bitfields.
(GFC_DECL_SCALAR_ALLOCATABLE, GFC_DECL_SCALAR_POINTER,
GFC_DECL_GET_SCALAR_ALLOCATABLE, GFC_DECL_GET_SCALAR_POINTER,
GFC_DECL_ASSOCIATE_VAR_P): Define.
(GFC_POINTER_TYPE_P): Remove.
* trans-openmp.c (gfc_omp_privatize_by_reference): Don't check
GFC_POINTER_TYPE_P, instead test GFC_DECL_GET_SCALAR_ALLOCATABLE,
GFC_DECL_GET_SCALAR_POINTER or GFC_DECL_CRAY_POINTEE on decl.
(gfc_omp_predetermined_sharing): Associate-names are predetermined.
(enum walk_alloc_comps): New.
(gfc_has_alloc_comps, gfc_omp_unshare_expr_r, gfc_omp_unshare_expr,
gfc_walk_alloc_comps): New functions.
(gfc_omp_private_outer_ref): Return true for scalar allocatables or
decls with allocatable components.
(gfc_omp_clause_default_ctor, gfc_omp_clause_copy_ctor,
gfc_omp_clause_assign_op, gfc_omp_clause_dtor): Fix up handling of
allocatables, handle also OMP_CLAUSE_REDUCTION, handle scalar
allocatables and decls with allocatable components.
(gfc_trans_omp_array_reduction_or_udr): Don't handle allocatable
arrays here.
(gfc_trans_omp_reduction_list): Call
gfc_trans_omp_array_reduction_or_udr even for allocatable scalars.
(gfc_trans_omp_do_simd): If -fno-openmp, just expand it as OMP_SIMD.
(gfc_trans_omp_parallel_do_simd): Likewise.
* trans-types.c (gfc_sym_type): Don't set GFC_POINTER_TYPE_P.
(gfc_get_derived_type): Call gfc_finish_decl_attrs.
gcc/testsuite/
* gfortran.dg/gomp/allocatable_components_1.f90: Remove dg-error
directives.
* gfortran.dg/gomp/associate1.f90: New test.
* gfortran.dg/gomp/intentin1.f90: New test.
* gfortran.dg/gomp/openmp-simd-1.f90: New test.
* gfortran.dg/gomp/openmp-simd-2.f90: New test.
* gfortran.dg/gomp/openmp-simd-3.f90: New test.
* gfortran.dg/gomp/proc_ptr_2.f90: New test.
libgomp/
* testsuite/libgomp.fortran/allocatable9.f90: New test.
* testsuite/libgomp.fortran/allocatable10.f90: New test.
* testsuite/libgomp.fortran/allocatable11.f90: New test.
* testsuite/libgomp.fortran/allocatable12.f90: New test.
* testsuite/libgomp.fortran/alloc-comp-1.f90: New test.
* testsuite/libgomp.fortran/alloc-comp-2.f90: New test.
* testsuite/libgomp.fortran/alloc-comp-3.f90: New test.
* testsuite/libgomp.fortran/associate1.f90: New test.
* testsuite/libgomp.fortran/associate2.f90: New test.
* testsuite/libgomp.fortran/procptr1.f90: New test.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@211397 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc')
24 files changed, 1326 insertions, 291 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 3fdd5a5ae75..e277f229b13 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,13 @@ +2014-06-10 Jakub Jelinek <jakub@redhat.com> + + PR fortran/60928 + * omp-low.c (lower_rec_input_clauses) <case OMP_CLAUSE_LASTPRIVATE>: + Set lastprivate_firstprivate even if omp_private_outer_ref + langhook returns true. + <case OMP_CLAUSE_REDUCTION>: When calling omp_clause_default_ctor + langhook, call unshare_expr on new_var and call + build_outer_var_ref to get the last argument. + 2014-06-10 Marek Polacek <polacek@redhat.com> PR c/60988 diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog index 07bcdab2e4c..b976f21988d 100644 --- a/gcc/c-family/ChangeLog +++ b/gcc/c-family/ChangeLog @@ -1,3 +1,9 @@ +2014-06-10 Jakub Jelinek <jakub@redhat.com> + + PR fortran/60928 + * c-pragma.c (omp_pragmas_simd): Move PRAGMA_OMP_TASK... + (omp_pragmas): ... back here. + 2014-06-05 Marek Polacek <polacek@redhat.com> PR c/49706 diff --git a/gcc/c-family/c-pragma.c b/gcc/c-family/c-pragma.c index 7b016abad08..5e57de39b13 100644 --- a/gcc/c-family/c-pragma.c +++ b/gcc/c-family/c-pragma.c @@ -1185,6 +1185,7 @@ static const struct omp_pragma_def omp_pragmas[] = { { "section", PRAGMA_OMP_SECTION }, { "sections", PRAGMA_OMP_SECTIONS }, { "single", PRAGMA_OMP_SINGLE }, + { "task", PRAGMA_OMP_TASK }, { "taskgroup", PRAGMA_OMP_TASKGROUP }, { "taskwait", PRAGMA_OMP_TASKWAIT }, { "taskyield", PRAGMA_OMP_TASKYIELD }, @@ -1197,7 +1198,6 @@ static const struct omp_pragma_def omp_pragmas_simd[] = { { "parallel", PRAGMA_OMP_PARALLEL }, { "simd", PRAGMA_OMP_SIMD }, { "target", PRAGMA_OMP_TARGET }, - { "task", PRAGMA_OMP_TASK }, { "teams", PRAGMA_OMP_TEAMS }, }; diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog index c0443337c53..f945dd1c2f6 100644 --- a/gcc/fortran/ChangeLog +++ b/gcc/fortran/ChangeLog @@ -1,3 +1,67 @@ +2014-06-10 Jakub Jelinek <jakub@redhat.com> + + PR fortran/60928 + * f95-lang.c (gfc_init_builtin_functions): Handle -fopenmp-simd + like -fopenmp. + * openmp.c (resolve_omp_clauses): Remove allocatable components + diagnostics. Add associate-name and intent(in) pointer + diagnostics for various clauses, diagnose procedure pointers in + reduction clause. + * parse.c (match_word_omp_simd): New function. + (matchs, matcho): New macros. + (decode_omp_directive): Change match macros to either matchs + or matcho. Handle -fopenmp-simd. + (next_free, next_fixed): Handle -fopenmp-simd like -fopenmp. + * scanner.c (skip_free_comments, skip_fixed_comments, include_line): + Likewise. + * trans-array.c (get_full_array_size): Rename to... + (gfc_full_array_size): ... this. No longer static. + (duplicate_allocatable): Adjust caller. Add NO_MEMCPY argument + and handle it. + (gfc_duplicate_allocatable, gfc_copy_allocatable_data): Adjust + duplicate_allocatable callers. + (gfc_duplicate_allocatable_nocopy): New function. + (structure_alloc_comps): Adjust g*_full_array_size and + duplicate_allocatable caller. + * trans-array.h (gfc_full_array_size, + gfc_duplicate_allocatable_nocopy): New prototypes. + * trans-common.c (create_common): Call gfc_finish_decl_attrs. + * trans-decl.c (gfc_finish_decl_attrs): New function. + (gfc_finish_var_decl, create_function_arglist, + gfc_get_fake_result_decl): Call it. + (gfc_allocate_lang_decl): If DECL_LANG_SPECIFIC is already allocated, + don't allocate it again. + (gfc_get_symbol_decl): Set GFC_DECL_ASSOCIATE_VAR_P on + associate-names. + * trans.h (gfc_finish_decl_attrs): New prototype. + (struct lang_decl): Add scalar_allocatable and scalar_pointer + bitfields. + (GFC_DECL_SCALAR_ALLOCATABLE, GFC_DECL_SCALAR_POINTER, + GFC_DECL_GET_SCALAR_ALLOCATABLE, GFC_DECL_GET_SCALAR_POINTER, + GFC_DECL_ASSOCIATE_VAR_P): Define. + (GFC_POINTER_TYPE_P): Remove. + * trans-openmp.c (gfc_omp_privatize_by_reference): Don't check + GFC_POINTER_TYPE_P, instead test GFC_DECL_GET_SCALAR_ALLOCATABLE, + GFC_DECL_GET_SCALAR_POINTER or GFC_DECL_CRAY_POINTEE on decl. + (gfc_omp_predetermined_sharing): Associate-names are predetermined. + (enum walk_alloc_comps): New. + (gfc_has_alloc_comps, gfc_omp_unshare_expr_r, gfc_omp_unshare_expr, + gfc_walk_alloc_comps): New functions. + (gfc_omp_private_outer_ref): Return true for scalar allocatables or + decls with allocatable components. + (gfc_omp_clause_default_ctor, gfc_omp_clause_copy_ctor, + gfc_omp_clause_assign_op, gfc_omp_clause_dtor): Fix up handling of + allocatables, handle also OMP_CLAUSE_REDUCTION, handle scalar + allocatables and decls with allocatable components. + (gfc_trans_omp_array_reduction_or_udr): Don't handle allocatable + arrays here. + (gfc_trans_omp_reduction_list): Call + gfc_trans_omp_array_reduction_or_udr even for allocatable scalars. + (gfc_trans_omp_do_simd): If -fno-openmp, just expand it as OMP_SIMD. + (gfc_trans_omp_parallel_do_simd): Likewise. + * trans-types.c (gfc_sym_type): Don't set GFC_POINTER_TYPE_P. + (gfc_get_derived_type): Call gfc_finish_decl_attrs. + 2014-06-09 Paul Thomas <pault@gcc.gnu.org> PR fortran/61406 diff --git a/gcc/fortran/f95-lang.c b/gcc/fortran/f95-lang.c index f5d57a8e8fc..19621449767 100644 --- a/gcc/fortran/f95-lang.c +++ b/gcc/fortran/f95-lang.c @@ -1044,7 +1044,9 @@ gfc_init_builtin_functions (void) #include "../sync-builtins.def" #undef DEF_SYNC_BUILTIN - if (gfc_option.gfc_flag_openmp || flag_tree_parallelize_loops) + if (gfc_option.gfc_flag_openmp + || gfc_option.gfc_flag_openmp_simd + || flag_tree_parallelize_loops) { #undef DEF_GOMP_BUILTIN #define DEF_GOMP_BUILTIN(code, name, type, attr) \ diff --git a/gcc/fortran/openmp.c b/gcc/fortran/openmp.c index 4d92575da0d..a6e5f6c2cf8 100644 --- a/gcc/fortran/openmp.c +++ b/gcc/fortran/openmp.c @@ -1763,9 +1763,6 @@ resolve_omp_clauses (gfc_code *code, locus *where, if (!n->sym->attr.threadprivate) gfc_error ("Non-THREADPRIVATE object '%s' in COPYIN clause" " at %L", n->sym->name, where); - if (n->sym->ts.type == BT_DERIVED && n->sym->ts.u.derived->attr.alloc_comp) - gfc_error ("COPYIN clause object '%s' at %L has ALLOCATABLE components", - n->sym->name, where); } break; case OMP_LIST_COPYPRIVATE: @@ -1774,9 +1771,9 @@ resolve_omp_clauses (gfc_code *code, locus *where, if (n->sym->as && n->sym->as->type == AS_ASSUMED_SIZE) gfc_error ("Assumed size array '%s' in COPYPRIVATE clause " "at %L", n->sym->name, where); - if (n->sym->ts.type == BT_DERIVED && n->sym->ts.u.derived->attr.alloc_comp) - gfc_error ("COPYPRIVATE clause object '%s' at %L has ALLOCATABLE components", - n->sym->name, where); + if (n->sym->attr.pointer && n->sym->attr.intent == INTENT_IN) + gfc_error ("INTENT(IN) POINTER '%s' in COPYPRIVATE clause " + "at %L", n->sym->name, where); } break; case OMP_LIST_SHARED: @@ -1788,6 +1785,9 @@ resolve_omp_clauses (gfc_code *code, locus *where, if (n->sym->attr.cray_pointee) gfc_error ("Cray pointee '%s' in SHARED clause at %L", n->sym->name, where); + if (n->sym->attr.associate_var) + gfc_error ("ASSOCIATE name '%s' in SHARED clause at %L", + n->sym->name, where); } break; case OMP_LIST_ALIGNED: @@ -1879,17 +1879,17 @@ resolve_omp_clauses (gfc_code *code, locus *where, if (n->sym->attr.cray_pointee) gfc_error ("Cray pointee '%s' in %s clause at %L", n->sym->name, name, where); + if (n->sym->attr.associate_var) + gfc_error ("ASSOCIATE name '%s' in %s clause at %L", + n->sym->name, name, where); if (list != OMP_LIST_PRIVATE) { + if (n->sym->attr.proc_pointer && list == OMP_LIST_REDUCTION) + gfc_error ("Procedure pointer '%s' in %s clause at %L", + n->sym->name, name, where); if (n->sym->attr.pointer && list == OMP_LIST_REDUCTION) gfc_error ("POINTER object '%s' in %s clause at %L", n->sym->name, name, where); - /* Variables in REDUCTION-clauses must be of intrinsic type (flagged below). */ - if (list != OMP_LIST_REDUCTION - && n->sym->ts.type == BT_DERIVED - && n->sym->ts.u.derived->attr.alloc_comp) - gfc_error ("%s clause object '%s' has ALLOCATABLE components at %L", - name, n->sym->name, where); if (n->sym->attr.cray_pointer && list == OMP_LIST_REDUCTION) gfc_error ("Cray pointer '%s' in %s clause at %L", n->sym->name, name, where); @@ -1901,6 +1901,19 @@ resolve_omp_clauses (gfc_code *code, locus *where, gfc_error ("Variable '%s' in %s clause is used in " "NAMELIST statement at %L", n->sym->name, name, where); + if (n->sym->attr.pointer && n->sym->attr.intent == INTENT_IN) + switch (list) + { + case OMP_LIST_PRIVATE: + case OMP_LIST_LASTPRIVATE: + case OMP_LIST_LINEAR: + /* case OMP_LIST_REDUCTION: */ + gfc_error ("INTENT(IN) POINTER '%s' in %s clause at %L", + n->sym->name, name, where); + break; + default: + break; + } switch (list) { case OMP_LIST_REDUCTION: diff --git a/gcc/fortran/parse.c b/gcc/fortran/parse.c index b7c42731750..bdee831ae4d 100644 --- a/gcc/fortran/parse.c +++ b/gcc/fortran/parse.c @@ -74,6 +74,34 @@ match_word (const char *str, match (*subr) (void), locus *old_locus) } +/* Like match_word, but if str is matched, set a flag that it + was matched. */ +static match +match_word_omp_simd (const char *str, match (*subr) (void), locus *old_locus, + bool *simd_matched) +{ + match m; + + if (str != NULL) + { + m = gfc_match (str); + if (m != MATCH_YES) + return m; + *simd_matched = true; + } + + m = (*subr) (); + + if (m != MATCH_YES) + { + gfc_current_locus = *old_locus; + reject_statement (); + } + + return m; +} + + /* Load symbols from all USE statements encountered in this scoping unit. */ static void @@ -103,7 +131,7 @@ use_modules (void) if (match_word (keyword, subr, &old_locus) == MATCH_YES) \ return st; \ else \ - undo_new_statement (); \ + undo_new_statement (); \ } while (0); @@ -531,11 +559,34 @@ decode_statement (void) return ST_NONE; } +/* Like match, but set a flag simd_matched if keyword matched. */ +#define matchs(keyword, subr, st) \ + do { \ + if (match_word_omp_simd (keyword, subr, &old_locus, \ + &simd_matched) == MATCH_YES) \ + return st; \ + else \ + undo_new_statement (); \ + } while (0); + +/* Like match, but don't match anything if not -fopenmp. */ +#define matcho(keyword, subr, st) \ + do { \ + if (!gfc_option.gfc_flag_openmp) \ + ; \ + else if (match_word (keyword, subr, &old_locus) \ + == MATCH_YES) \ + return st; \ + else \ + undo_new_statement (); \ + } while (0); + static gfc_statement decode_omp_directive (void) { locus old_locus; char c; + bool simd_matched = false; gfc_enforce_clean_symbol_state (); @@ -560,94 +611,102 @@ decode_omp_directive (void) c = gfc_peek_ascii_char (); + /* match is for directives that should be recognized only if + -fopenmp, matchs for directives that should be recognized + if either -fopenmp or -fopenmp-simd. */ switch (c) { case 'a': - match ("atomic", gfc_match_omp_atomic, ST_OMP_ATOMIC); + matcho ("atomic", gfc_match_omp_atomic, ST_OMP_ATOMIC); break; case 'b': - match ("barrier", gfc_match_omp_barrier, ST_OMP_BARRIER); + matcho ("barrier", gfc_match_omp_barrier, ST_OMP_BARRIER); break; case 'c': - match ("cancellation% point", gfc_match_omp_cancellation_point, - ST_OMP_CANCELLATION_POINT); - match ("cancel", gfc_match_omp_cancel, ST_OMP_CANCEL); - match ("critical", gfc_match_omp_critical, ST_OMP_CRITICAL); + matcho ("cancellation% point", gfc_match_omp_cancellation_point, + ST_OMP_CANCELLATION_POINT); + matcho ("cancel", gfc_match_omp_cancel, ST_OMP_CANCEL); + matcho ("critical", gfc_match_omp_critical, ST_OMP_CRITICAL); break; case 'd': - match ("declare reduction", gfc_match_omp_declare_reduction, - ST_OMP_DECLARE_REDUCTION); - match ("declare simd", gfc_match_omp_declare_simd, - ST_OMP_DECLARE_SIMD); - match ("do simd", gfc_match_omp_do_simd, ST_OMP_DO_SIMD); - match ("do", gfc_match_omp_do, ST_OMP_DO); + matchs ("declare reduction", gfc_match_omp_declare_reduction, + ST_OMP_DECLARE_REDUCTION); + matchs ("declare simd", gfc_match_omp_declare_simd, + ST_OMP_DECLARE_SIMD); + matchs ("do simd", gfc_match_omp_do_simd, ST_OMP_DO_SIMD); + matcho ("do", gfc_match_omp_do, ST_OMP_DO); break; case 'e': - match ("end atomic", gfc_match_omp_eos, ST_OMP_END_ATOMIC); - match ("end critical", gfc_match_omp_critical, ST_OMP_END_CRITICAL); - match ("end do simd", gfc_match_omp_end_nowait, ST_OMP_END_DO_SIMD); - match ("end do", gfc_match_omp_end_nowait, ST_OMP_END_DO); - match ("end simd", gfc_match_omp_eos, ST_OMP_END_SIMD); - match ("end master", gfc_match_omp_eos, ST_OMP_END_MASTER); - match ("end ordered", gfc_match_omp_eos, ST_OMP_END_ORDERED); - match ("end parallel do simd", gfc_match_omp_eos, - ST_OMP_END_PARALLEL_DO_SIMD); - match ("end parallel do", gfc_match_omp_eos, ST_OMP_END_PARALLEL_DO); - match ("end parallel sections", gfc_match_omp_eos, - ST_OMP_END_PARALLEL_SECTIONS); - match ("end parallel workshare", gfc_match_omp_eos, - ST_OMP_END_PARALLEL_WORKSHARE); - match ("end parallel", gfc_match_omp_eos, ST_OMP_END_PARALLEL); - match ("end sections", gfc_match_omp_end_nowait, ST_OMP_END_SECTIONS); - match ("end single", gfc_match_omp_end_single, ST_OMP_END_SINGLE); - match ("end taskgroup", gfc_match_omp_eos, ST_OMP_END_TASKGROUP); - match ("end task", gfc_match_omp_eos, ST_OMP_END_TASK); - match ("end workshare", gfc_match_omp_end_nowait, - ST_OMP_END_WORKSHARE); + matcho ("end atomic", gfc_match_omp_eos, ST_OMP_END_ATOMIC); + matcho ("end critical", gfc_match_omp_critical, ST_OMP_END_CRITICAL); + matchs ("end do simd", gfc_match_omp_end_nowait, ST_OMP_END_DO_SIMD); + matcho ("end do", gfc_match_omp_end_nowait, ST_OMP_END_DO); + matchs ("end simd", gfc_match_omp_eos, ST_OMP_END_SIMD); + matcho ("end master", gfc_match_omp_eos, ST_OMP_END_MASTER); + matcho ("end ordered", gfc_match_omp_eos, ST_OMP_END_ORDERED); + matchs ("end parallel do simd", gfc_match_omp_eos, + ST_OMP_END_PARALLEL_DO_SIMD); + matcho ("end parallel do", gfc_match_omp_eos, ST_OMP_END_PARALLEL_DO); + matcho ("end parallel sections", gfc_match_omp_eos, + ST_OMP_END_PARALLEL_SECTIONS); + matcho ("end parallel workshare", gfc_match_omp_eos, + ST_OMP_END_PARALLEL_WORKSHARE); + matcho ("end parallel", gfc_match_omp_eos, ST_OMP_END_PARALLEL); + matcho ("end sections", gfc_match_omp_end_nowait, ST_OMP_END_SECTIONS); + matcho ("end single", gfc_match_omp_end_single, ST_OMP_END_SINGLE); + matcho ("end taskgroup", gfc_match_omp_eos, ST_OMP_END_TASKGROUP); + matcho ("end task", gfc_match_omp_eos, ST_OMP_END_TASK); + matcho ("end workshare", gfc_match_omp_end_nowait, + ST_OMP_END_WORKSHARE); break; case 'f': - match ("flush", gfc_match_omp_flush, ST_OMP_FLUSH); + matcho ("flush", gfc_match_omp_flush, ST_OMP_FLUSH); break; case 'm': - match ("master", gfc_match_omp_master, ST_OMP_MASTER); + matcho ("master", gfc_match_omp_master, ST_OMP_MASTER); break; case 'o': - match ("ordered", gfc_match_omp_ordered, ST_OMP_ORDERED); + matcho ("ordered", gfc_match_omp_ordered, ST_OMP_ORDERED); break; case 'p': - match ("parallel do simd", gfc_match_omp_parallel_do_simd, - ST_OMP_PARALLEL_DO_SIMD); - match ("parallel do", gfc_match_omp_parallel_do, ST_OMP_PARALLEL_DO); - match ("parallel sections", gfc_match_omp_parallel_sections, - ST_OMP_PARALLEL_SECTIONS); - match ("parallel workshare", gfc_match_omp_parallel_workshare, - ST_OMP_PARALLEL_WORKSHARE); - match ("parallel", gfc_match_omp_parallel, ST_OMP_PARALLEL); + matchs ("parallel do simd", gfc_match_omp_parallel_do_simd, + ST_OMP_PARALLEL_DO_SIMD); + matcho ("parallel do", gfc_match_omp_parallel_do, ST_OMP_PARALLEL_DO); + matcho ("parallel sections", gfc_match_omp_parallel_sections, + ST_OMP_PARALLEL_SECTIONS); + matcho ("parallel workshare", gfc_match_omp_parallel_workshare, + ST_OMP_PARALLEL_WORKSHARE); + matcho ("parallel", gfc_match_omp_parallel, ST_OMP_PARALLEL); break; case 's': - match ("sections", gfc_match_omp_sections, ST_OMP_SECTIONS); - match ("section", gfc_match_omp_eos, ST_OMP_SECTION); - match ("simd", gfc_match_omp_simd, ST_OMP_SIMD); - match ("single", gfc_match_omp_single, ST_OMP_SINGLE); + matcho ("sections", gfc_match_omp_sections, ST_OMP_SECTIONS); + matcho ("section", gfc_match_omp_eos, ST_OMP_SECTION); + matchs ("simd", gfc_match_omp_simd, ST_OMP_SIMD); + matcho ("single", gfc_match_omp_single, ST_OMP_SINGLE); break; case 't': - match ("taskgroup", gfc_match_omp_taskgroup, ST_OMP_TASKGROUP); - match ("taskwait", gfc_match_omp_taskwait, ST_OMP_TASKWAIT); - match ("taskyield", gfc_match_omp_taskyield, ST_OMP_TASKYIELD); - match ("task", gfc_match_omp_task, ST_OMP_TASK); - match ("threadprivate", gfc_match_omp_threadprivate, - ST_OMP_THREADPRIVATE); + matcho ("taskgroup", gfc_match_omp_taskgroup, ST_OMP_TASKGROUP); + matcho ("taskwait", gfc_match_omp_taskwait, ST_OMP_TASKWAIT); + matcho ("taskyield", gfc_match_omp_taskyield, ST_OMP_TASKYIELD); + matcho ("task", gfc_match_omp_task, ST_OMP_TASK); + matcho ("threadprivate", gfc_match_omp_threadprivate, + ST_OMP_THREADPRIVATE); break; case 'w': - match ("workshare", gfc_match_omp_workshare, ST_OMP_WORKSHARE); + matcho ("workshare", gfc_match_omp_workshare, ST_OMP_WORKSHARE); break; } /* All else has failed, so give up. See if any of the matchers has - stored an error message of some sort. */ + stored an error message of some sort. Don't error out if + not -fopenmp and simd_matched is false, i.e. if a directive other + than one marked with match has been seen. */ - if (gfc_error_check () == 0) - gfc_error_now ("Unclassifiable OpenMP directive at %C"); + if (gfc_option.gfc_flag_openmp || simd_matched) + { + if (gfc_error_check () == 0) + gfc_error_now ("Unclassifiable OpenMP directive at %C"); + } reject_statement (); @@ -770,7 +829,9 @@ next_free (void) return decode_gcc_attribute (); } - else if (c == '$' && gfc_option.gfc_flag_openmp) + else if (c == '$' + && (gfc_option.gfc_flag_openmp + || gfc_option.gfc_flag_openmp_simd)) { int i; @@ -859,7 +920,9 @@ next_fixed (void) return decode_gcc_attribute (); } - else if (c == '$' && gfc_option.gfc_flag_openmp) + else if (c == '$' + && (gfc_option.gfc_flag_openmp + || gfc_option.gfc_flag_openmp_simd)) { for (i = 0; i < 4; i++, c = gfc_next_char_literal (NONSTRING)) gcc_assert ((char) gfc_wide_tolower (c) == "$omp"[i]); diff --git a/gcc/fortran/scanner.c b/gcc/fortran/scanner.c index 8f517342129..8934924d876 100644 --- a/gcc/fortran/scanner.c +++ b/gcc/fortran/scanner.c @@ -752,7 +752,8 @@ skip_free_comments (void) 2) handle OpenMP conditional compilation, where !$ should be treated as 2 spaces (for initial lines only if followed by space). */ - if (gfc_option.gfc_flag_openmp && at_bol) + if ((gfc_option.gfc_flag_openmp + || gfc_option.gfc_flag_openmp_simd) && at_bol) { locus old_loc = gfc_current_locus; if (next_char () == '$') @@ -878,7 +879,7 @@ skip_fixed_comments (void) && continue_line < gfc_linebuf_linenum (gfc_current_locus.lb)) continue_line = gfc_linebuf_linenum (gfc_current_locus.lb); - if (gfc_option.gfc_flag_openmp) + if (gfc_option.gfc_flag_openmp || gfc_option.gfc_flag_openmp_simd) { if (next_char () == '$') { @@ -1821,7 +1822,7 @@ include_line (gfc_char_t *line) c = line; - if (gfc_option.gfc_flag_openmp) + if (gfc_option.gfc_flag_openmp || gfc_option.gfc_flag_openmp_simd) { if (gfc_current_form == FORM_FREE) { diff --git a/gcc/fortran/trans-array.c b/gcc/fortran/trans-array.c index 5255969c84c..5558217ab48 100644 --- a/gcc/fortran/trans-array.c +++ b/gcc/fortran/trans-array.c @@ -7381,8 +7381,8 @@ gfc_trans_dealloc_allocated (tree descriptor, bool coarray, gfc_expr *expr) /* This helper function calculates the size in words of a full array. */ -static tree -get_full_array_size (stmtblock_t *block, tree decl, int rank) +tree +gfc_full_array_size (stmtblock_t *block, tree decl, int rank) { tree idx; tree nelems; @@ -7408,7 +7408,7 @@ get_full_array_size (stmtblock_t *block, tree decl, int rank) static tree duplicate_allocatable (tree dest, tree src, tree type, int rank, - bool no_malloc, tree str_sz) + bool no_malloc, bool no_memcpy, tree str_sz) { tree tmp; tree size; @@ -7442,9 +7442,13 @@ duplicate_allocatable (tree dest, tree src, tree type, int rank, gfc_add_expr_to_block (&block, tmp); } - tmp = builtin_decl_explicit (BUILT_IN_MEMCPY); - tmp = build_call_expr_loc (input_location, tmp, 3, dest, src, - fold_convert (size_type_node, size)); + if (!no_memcpy) + { + tmp = builtin_decl_explicit (BUILT_IN_MEMCPY); + tmp = build_call_expr_loc (input_location, tmp, 3, dest, src, + fold_convert (size_type_node, size)); + gfc_add_expr_to_block (&block, tmp); + } } else { @@ -7453,7 +7457,7 @@ duplicate_allocatable (tree dest, tree src, tree type, int rank, gfc_init_block (&block); if (rank) - nelems = get_full_array_size (&block, src, rank); + nelems = gfc_full_array_size (&block, src, rank); else nelems = gfc_index_one_node; @@ -7473,14 +7477,17 @@ duplicate_allocatable (tree dest, tree src, tree type, int rank, /* We know the temporary and the value will be the same length, so can use memcpy. */ - tmp = builtin_decl_explicit (BUILT_IN_MEMCPY); - tmp = build_call_expr_loc (input_location, - tmp, 3, gfc_conv_descriptor_data_get (dest), - gfc_conv_descriptor_data_get (src), - fold_convert (size_type_node, size)); + if (!no_memcpy) + { + tmp = builtin_decl_explicit (BUILT_IN_MEMCPY); + tmp = build_call_expr_loc (input_location, tmp, 3, + gfc_conv_descriptor_data_get (dest), + gfc_conv_descriptor_data_get (src), + fold_convert (size_type_node, size)); + gfc_add_expr_to_block (&block, tmp); + } } - gfc_add_expr_to_block (&block, tmp); tmp = gfc_finish_block (&block); /* Null the destination if the source is null; otherwise do @@ -7502,7 +7509,8 @@ duplicate_allocatable (tree dest, tree src, tree type, int rank, tree gfc_duplicate_allocatable (tree dest, tree src, tree type, int rank) { - return duplicate_allocatable (dest, src, type, rank, false, NULL_TREE); + return duplicate_allocatable (dest, src, type, rank, false, false, + NULL_TREE); } @@ -7511,7 +7519,16 @@ gfc_duplicate_allocatable (tree dest, tree src, tree type, int rank) tree gfc_copy_allocatable_data (tree dest, tree src, tree type, int rank) { - return duplicate_allocatable (dest, src, type, rank, true, NULL_TREE); + return duplicate_allocatable (dest, src, type, rank, true, false, + NULL_TREE); +} + +/* Allocate dest to the same size as src, but don't copy anything. */ + +tree +gfc_duplicate_allocatable_nocopy (tree dest, tree src, tree type, int rank) +{ + return duplicate_allocatable (dest, src, type, rank, false, true, NULL_TREE); } @@ -7571,7 +7588,7 @@ structure_alloc_comps (gfc_symbol * der_type, tree decl, /* Use the descriptor for an allocatable array. Since this is a full array reference, we only need the descriptor information from dimension = rank. */ - tmp = get_full_array_size (&fnblock, decl, rank); + tmp = gfc_full_array_size (&fnblock, decl, rank); tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type, tmp, gfc_index_one_node); @@ -7930,7 +7947,7 @@ structure_alloc_comps (gfc_symbol * der_type, tree decl, gfc_add_expr_to_block (&fnblock, tmp); size = size_of_string_in_bytes (c->ts.kind, len); tmp = duplicate_allocatable (dcmp, comp, ctype, rank, - false, size); + false, false, size); gfc_add_expr_to_block (&fnblock, tmp); } else if (c->attr.allocatable && !c->attr.proc_pointer diff --git a/gcc/fortran/trans-array.h b/gcc/fortran/trans-array.h index c4c09c1c51e..e0bb82071fa 100644 --- a/gcc/fortran/trans-array.h +++ b/gcc/fortran/trans-array.h @@ -44,10 +44,14 @@ void gfc_trans_g77_array (gfc_symbol *, gfc_wrapped_block *); /* Generate code to deallocate an array, if it is allocated. */ tree gfc_trans_dealloc_allocated (tree, bool, gfc_expr *); +tree gfc_full_array_size (stmtblock_t *, tree, int); + tree gfc_duplicate_allocatable (tree dest, tree src, tree type, int rank); tree gfc_copy_allocatable_data (tree dest, tree src, tree type, int rank); +tree gfc_duplicate_allocatable_nocopy (tree, tree, tree, int); + tree gfc_nullify_alloc_comp (gfc_symbol *, tree, int); tree gfc_deallocate_alloc_comp (gfc_symbol *, tree, int); diff --git a/gcc/fortran/trans-common.c b/gcc/fortran/trans-common.c index 19eaddae2ce..36aa8f3efd8 100644 --- a/gcc/fortran/trans-common.c +++ b/gcc/fortran/trans-common.c @@ -705,6 +705,7 @@ create_common (gfc_common_head *com, segment_info *head, bool saw_equiv) TREE_ADDRESSABLE (var_decl) = 1; /* Fake variables are not visible from other translation units. */ TREE_PUBLIC (var_decl) = 0; + gfc_finish_decl_attrs (var_decl, &s->sym->attr); /* To preserve identifier names in COMMON, chain to procedure scope unless at top level in a module definition. */ diff --git a/gcc/fortran/trans-decl.c b/gcc/fortran/trans-decl.c index 959bcb19926..863e596c639 100644 --- a/gcc/fortran/trans-decl.c +++ b/gcc/fortran/trans-decl.c @@ -496,6 +496,29 @@ gfc_finish_decl (tree decl) } +/* Handle setting of GFC_DECL_SCALAR* on DECL. */ + +void +gfc_finish_decl_attrs (tree decl, symbol_attribute *attr) +{ + if (!attr->dimension && !attr->codimension) + { + /* Handle scalar allocatable variables. */ + if (attr->allocatable) + { + gfc_allocate_lang_decl (decl); + GFC_DECL_SCALAR_ALLOCATABLE (decl) = 1; + } + /* Handle scalar pointer variables. */ + if (attr->pointer) + { + gfc_allocate_lang_decl (decl); + GFC_DECL_SCALAR_POINTER (decl) = 1; + } + } +} + + /* Apply symbol attributes to a variable, and add it to the function scope. */ static void @@ -607,6 +630,8 @@ gfc_finish_var_decl (tree decl, gfc_symbol * sym) if (sym->attr.threadprivate && (TREE_STATIC (decl) || DECL_EXTERNAL (decl))) DECL_TLS_MODEL (decl) = decl_default_tls_model (decl); + + gfc_finish_decl_attrs (decl, &sym->attr); } @@ -615,7 +640,8 @@ gfc_finish_var_decl (tree decl, gfc_symbol * sym) void gfc_allocate_lang_decl (tree decl) { - DECL_LANG_SPECIFIC (decl) = ggc_cleared_alloc<struct lang_decl> (); + if (DECL_LANG_SPECIFIC (decl) == NULL) + DECL_LANG_SPECIFIC (decl) = ggc_cleared_alloc<struct lang_decl> (); } /* Remember a symbol to generate initialization/cleanup code at function @@ -1517,6 +1543,9 @@ gfc_get_symbol_decl (gfc_symbol * sym) && !sym->attr.select_type_temporary) DECL_BY_REFERENCE (decl) = 1; + if (sym->attr.associate_var) + GFC_DECL_ASSOCIATE_VAR_P (decl) = 1; + if (sym->attr.vtab || (sym->name[0] == '_' && strncmp ("__def_init", sym->name, 10) == 0)) TREE_READONLY (decl) = 1; @@ -2236,6 +2265,7 @@ create_function_arglist (gfc_symbol * sym) DECL_BY_REFERENCE (parm) = 1; gfc_finish_decl (parm); + gfc_finish_decl_attrs (parm, &f->sym->attr); f->sym->backend_decl = parm; @@ -2690,6 +2720,7 @@ gfc_get_fake_result_decl (gfc_symbol * sym, int parent_flag) TREE_ADDRESSABLE (decl) = 1; layout_decl (decl, 0); + gfc_finish_decl_attrs (decl, &sym->attr); if (parent_flag) gfc_add_decl_to_parent_function (decl); diff --git a/gcc/fortran/trans-openmp.c b/gcc/fortran/trans-openmp.c index 3851a4e522d..998d687761b 100644 --- a/gcc/fortran/trans-openmp.c +++ b/gcc/fortran/trans-openmp.c @@ -55,7 +55,9 @@ gfc_omp_privatize_by_reference (const_tree decl) /* Array POINTER/ALLOCATABLE have aggregate types, all user variables that have POINTER_TYPE type and don't have GFC_POINTER_TYPE_P set are supposed to be privatized by reference. */ - if (GFC_POINTER_TYPE_P (type)) + if (GFC_DECL_GET_SCALAR_POINTER (decl) + || GFC_DECL_GET_SCALAR_ALLOCATABLE (decl) + || GFC_DECL_CRAY_POINTEE (decl)) return false; if (!DECL_ARTIFICIAL (decl) @@ -77,6 +79,19 @@ gfc_omp_privatize_by_reference (const_tree decl) enum omp_clause_default_kind gfc_omp_predetermined_sharing (tree decl) { + /* Associate names preserve the association established during ASSOCIATE. + As they are implemented either as pointers to the selector or array + descriptor and shouldn't really change in the ASSOCIATE region, + this decl can be either shared or firstprivate. If it is a pointer, + use firstprivate, as it is cheaper that way, otherwise make it shared. */ + if (GFC_DECL_ASSOCIATE_VAR_P (decl)) + { + if (TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE) + return OMP_CLAUSE_DEFAULT_FIRSTPRIVATE; + else + return OMP_CLAUSE_DEFAULT_SHARED; + } + if (DECL_ARTIFICIAL (decl) && ! GFC_DECL_RESULT (decl) && ! (DECL_LANG_SPECIFIC (decl) @@ -135,6 +150,41 @@ gfc_omp_report_decl (tree decl) return decl; } +/* Return true if TYPE has any allocatable components. */ + +static bool +gfc_has_alloc_comps (tree type, tree decl) +{ + tree field, ftype; + + if (POINTER_TYPE_P (type)) + { + if (GFC_DECL_GET_SCALAR_ALLOCATABLE (decl)) + type = TREE_TYPE (type); + else if (GFC_DECL_GET_SCALAR_POINTER (decl)) + return false; + } + + while (GFC_DESCRIPTOR_TYPE_P (type) || GFC_ARRAY_TYPE_P (type)) + type = gfc_get_element_type (type); + + if (TREE_CODE (type) != RECORD_TYPE) + return false; + + for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field)) + { + ftype = TREE_TYPE (field); + if (GFC_DECL_GET_SCALAR_ALLOCATABLE (field)) + return true; + if (GFC_DESCRIPTOR_TYPE_P (ftype) + && GFC_TYPE_ARRAY_AKIND (ftype) == GFC_ARRAY_ALLOCATABLE) + return true; + if (gfc_has_alloc_comps (ftype, field)) + return true; + } + return false; +} + /* Return true if DECL in private clause needs OMP_CLAUSE_PRIVATE_OUTER_REF on the private clause. */ bool @@ -146,68 +196,335 @@ gfc_omp_private_outer_ref (tree decl) && GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_ALLOCATABLE) return true; + if (GFC_DECL_GET_SCALAR_ALLOCATABLE (decl)) + return true; + + if (gfc_omp_privatize_by_reference (decl)) + type = TREE_TYPE (type); + + if (gfc_has_alloc_comps (type, decl)) + return true; + return false; } +/* Callback for gfc_omp_unshare_expr. */ + +static tree +gfc_omp_unshare_expr_r (tree *tp, int *walk_subtrees, void *) +{ + tree t = *tp; + enum tree_code code = TREE_CODE (t); + + /* Stop at types, decls, constants like copy_tree_r. */ + if (TREE_CODE_CLASS (code) == tcc_type + || TREE_CODE_CLASS (code) == tcc_declaration + || TREE_CODE_CLASS (code) == tcc_constant + || code == BLOCK) + *walk_subtrees = 0; + else if (handled_component_p (t) + || TREE_CODE (t) == MEM_REF) + { + *tp = unshare_expr (t); + *walk_subtrees = 0; + } + + return NULL_TREE; +} + +/* Unshare in expr anything that the FE which normally doesn't + care much about tree sharing (because during gimplification + everything is unshared) could cause problems with tree sharing + at omp-low.c time. */ + +static tree +gfc_omp_unshare_expr (tree expr) +{ + walk_tree (&expr, gfc_omp_unshare_expr_r, NULL, NULL); + return expr; +} + +enum walk_alloc_comps +{ + WALK_ALLOC_COMPS_DTOR, + WALK_ALLOC_COMPS_DEFAULT_CTOR, + WALK_ALLOC_COMPS_COPY_CTOR +}; + +/* Handle allocatable components in OpenMP clauses. */ + +static tree +gfc_walk_alloc_comps (tree decl, tree dest, tree var, + enum walk_alloc_comps kind) +{ + stmtblock_t block, tmpblock; + tree type = TREE_TYPE (decl), then_b, tem, field; + gfc_init_block (&block); + + if (GFC_ARRAY_TYPE_P (type) || GFC_DESCRIPTOR_TYPE_P (type)) + { + if (GFC_DESCRIPTOR_TYPE_P (type)) + { + gfc_init_block (&tmpblock); + tem = gfc_full_array_size (&tmpblock, decl, + GFC_TYPE_ARRAY_RANK (type)); + then_b = gfc_finish_block (&tmpblock); + gfc_add_expr_to_block (&block, gfc_omp_unshare_expr (then_b)); + tem = gfc_omp_unshare_expr (tem); + tem = fold_build2_loc (input_location, MINUS_EXPR, + gfc_array_index_type, tem, + gfc_index_one_node); + } + else + { + if (!TYPE_DOMAIN (type) + || TYPE_MAX_VALUE (TYPE_DOMAIN (type)) == NULL_TREE + || TYPE_MIN_VALUE (TYPE_DOMAIN (type)) == error_mark_node + || TYPE_MAX_VALUE (TYPE_DOMAIN (type)) == error_mark_node) + { + tem = fold_build2 (EXACT_DIV_EXPR, sizetype, + TYPE_SIZE_UNIT (type), + TYPE_SIZE_UNIT (TREE_TYPE (type))); + tem = size_binop (MINUS_EXPR, tem, size_one_node); + } + else + tem = array_type_nelts (type); + tem = fold_convert (gfc_array_index_type, tem); + } + + tree nelems = gfc_evaluate_now (tem, &block); + tree index = gfc_create_var (gfc_array_index_type, "S"); + + gfc_init_block (&tmpblock); + tem = gfc_conv_array_data (decl); + tree declvar = build_fold_indirect_ref_loc (input_location, tem); + tree declvref = gfc_build_array_ref (declvar, index, NULL); + tree destvar, destvref = NULL_TREE; + if (dest) + { + tem = gfc_conv_array_data (dest); + destvar = build_fold_indirect_ref_loc (input_location, tem); + destvref = gfc_build_array_ref (destvar, index, NULL); + } + gfc_add_expr_to_block (&tmpblock, + gfc_walk_alloc_comps (declvref, destvref, + var, kind)); + + gfc_loopinfo loop; + gfc_init_loopinfo (&loop); + loop.dimen = 1; + loop.from[0] = gfc_index_zero_node; + loop.loopvar[0] = index; + loop.to[0] = nelems; + gfc_trans_scalarizing_loops (&loop, &tmpblock); + gfc_add_block_to_block (&block, &loop.pre); + return gfc_finish_block (&block); + } + else if (GFC_DECL_GET_SCALAR_ALLOCATABLE (var)) + { + decl = build_fold_indirect_ref_loc (input_location, decl); + if (dest) + dest = build_fold_indirect_ref_loc (input_location, dest); + type = TREE_TYPE (decl); + } + + gcc_assert (TREE_CODE (type) == RECORD_TYPE); + for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field)) + { + tree ftype = TREE_TYPE (field); + tree declf, destf = NULL_TREE; + bool has_alloc_comps = gfc_has_alloc_comps (ftype, field); + if ((!GFC_DESCRIPTOR_TYPE_P (ftype) + || GFC_TYPE_ARRAY_AKIND (ftype) != GFC_ARRAY_ALLOCATABLE) + && !GFC_DECL_GET_SCALAR_ALLOCATABLE (field) + && !has_alloc_comps) + continue; + declf = fold_build3_loc (input_location, COMPONENT_REF, ftype, + decl, field, NULL_TREE); + if (dest) + destf = fold_build3_loc (input_location, COMPONENT_REF, ftype, + dest, field, NULL_TREE); + + tem = NULL_TREE; + switch (kind) + { + case WALK_ALLOC_COMPS_DTOR: + break; + case WALK_ALLOC_COMPS_DEFAULT_CTOR: + if (GFC_DESCRIPTOR_TYPE_P (ftype) + && GFC_TYPE_ARRAY_AKIND (ftype) == GFC_ARRAY_ALLOCATABLE) + { + gfc_add_modify (&block, unshare_expr (destf), + unshare_expr (declf)); + tem = gfc_duplicate_allocatable_nocopy + (destf, declf, ftype, + GFC_TYPE_ARRAY_RANK (ftype)); + } + else if (GFC_DECL_GET_SCALAR_ALLOCATABLE (field)) + tem = gfc_duplicate_allocatable_nocopy (destf, declf, ftype, 0); + break; + case WALK_ALLOC_COMPS_COPY_CTOR: + if (GFC_DESCRIPTOR_TYPE_P (ftype) + && GFC_TYPE_ARRAY_AKIND (ftype) == GFC_ARRAY_ALLOCATABLE) + tem = gfc_duplicate_allocatable (destf, declf, ftype, + GFC_TYPE_ARRAY_RANK (ftype)); + else if (GFC_DECL_GET_SCALAR_ALLOCATABLE (field)) + tem = gfc_duplicate_allocatable (destf, declf, ftype, 0); + break; + } + if (tem) + gfc_add_expr_to_block (&block, gfc_omp_unshare_expr (tem)); + if (has_alloc_comps) + { + gfc_init_block (&tmpblock); + gfc_add_expr_to_block (&tmpblock, + gfc_walk_alloc_comps (declf, destf, + field, kind)); + then_b = gfc_finish_block (&tmpblock); + if (GFC_DESCRIPTOR_TYPE_P (ftype) + && GFC_TYPE_ARRAY_AKIND (ftype) == GFC_ARRAY_ALLOCATABLE) + tem = gfc_conv_descriptor_data_get (unshare_expr (declf)); + else if (GFC_DECL_GET_SCALAR_ALLOCATABLE (field)) + tem = unshare_expr (declf); + else + tem = NULL_TREE; + if (tem) + { + tem = fold_convert (pvoid_type_node, tem); + tem = fold_build2_loc (input_location, NE_EXPR, + boolean_type_node, tem, + null_pointer_node); + then_b = build3_loc (input_location, COND_EXPR, void_type_node, + tem, then_b, + build_empty_stmt (input_location)); + } + gfc_add_expr_to_block (&block, then_b); + } + if (kind == WALK_ALLOC_COMPS_DTOR) + { + if (GFC_DESCRIPTOR_TYPE_P (ftype) + && GFC_TYPE_ARRAY_AKIND (ftype) == GFC_ARRAY_ALLOCATABLE) + { + tem = gfc_trans_dealloc_allocated (unshare_expr (declf), + false, NULL); + gfc_add_expr_to_block (&block, gfc_omp_unshare_expr (tem)); + } + else if (GFC_DECL_GET_SCALAR_ALLOCATABLE (field)) + { + tem = gfc_call_free (unshare_expr (declf)); + gfc_add_expr_to_block (&block, gfc_omp_unshare_expr (tem)); + } + } + } + + return gfc_finish_block (&block); +} + /* Return code to initialize DECL with its default constructor, or NULL if there's nothing to do. */ tree gfc_omp_clause_default_ctor (tree clause, tree decl, tree outer) { - tree type = TREE_TYPE (decl), rank, size, esize, ptr, cond, then_b, else_b; + tree type = TREE_TYPE (decl), size, ptr, cond, then_b, else_b; stmtblock_t block, cond_block; - if (! GFC_DESCRIPTOR_TYPE_P (type) - || GFC_TYPE_ARRAY_AKIND (type) != GFC_ARRAY_ALLOCATABLE) - return NULL; + gcc_assert (OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_PRIVATE + || OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_LASTPRIVATE + || OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_LINEAR + || OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_REDUCTION); - if (OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_REDUCTION) - return NULL; + if ((! GFC_DESCRIPTOR_TYPE_P (type) + || GFC_TYPE_ARRAY_AKIND (type) != GFC_ARRAY_ALLOCATABLE) + && !GFC_DECL_GET_SCALAR_ALLOCATABLE (OMP_CLAUSE_DECL (clause))) + { + if (gfc_has_alloc_comps (type, OMP_CLAUSE_DECL (clause))) + { + gcc_assert (outer); + gfc_start_block (&block); + tree tem = gfc_walk_alloc_comps (outer, decl, + OMP_CLAUSE_DECL (clause), + WALK_ALLOC_COMPS_DEFAULT_CTOR); + gfc_add_expr_to_block (&block, tem); + return gfc_finish_block (&block); + } + return NULL_TREE; + } - gcc_assert (outer != NULL); - gcc_assert (OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_PRIVATE - || OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_LASTPRIVATE); + gcc_assert (outer != NULL_TREE); - /* Allocatable arrays in PRIVATE clauses need to be set to + /* Allocatable arrays and scalars in PRIVATE clauses need to be set to "not currently allocated" allocation status if outer array is "not currently allocated", otherwise should be allocated. */ gfc_start_block (&block); gfc_init_block (&cond_block); - gfc_add_modify (&cond_block, decl, outer); - rank = gfc_rank_cst[GFC_TYPE_ARRAY_RANK (type) - 1]; - size = gfc_conv_descriptor_ubound_get (decl, rank); - size = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type, - size, gfc_conv_descriptor_lbound_get (decl, rank)); - size = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type, - size, gfc_index_one_node); - if (GFC_TYPE_ARRAY_RANK (type) > 1) - size = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type, - size, gfc_conv_descriptor_stride_get (decl, rank)); - esize = fold_convert (gfc_array_index_type, - TYPE_SIZE_UNIT (gfc_get_element_type (type))); - size = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type, - size, esize); - size = gfc_evaluate_now (fold_convert (size_type_node, size), &cond_block); - + if (GFC_DESCRIPTOR_TYPE_P (type)) + { + gfc_add_modify (&cond_block, decl, outer); + tree rank = gfc_rank_cst[GFC_TYPE_ARRAY_RANK (type) - 1]; + size = gfc_conv_descriptor_ubound_get (decl, rank); + size = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type, + size, + gfc_conv_descriptor_lbound_get (decl, rank)); + size = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type, + size, gfc_index_one_node); + if (GFC_TYPE_ARRAY_RANK (type) > 1) + size = fold_build2_loc (input_location, MULT_EXPR, + gfc_array_index_type, size, + gfc_conv_descriptor_stride_get (decl, rank)); + tree esize = fold_convert (gfc_array_index_type, + TYPE_SIZE_UNIT (gfc_get_element_type (type))); + size = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type, + size, esize); + size = unshare_expr (size); + size = gfc_evaluate_now (fold_convert (size_type_node, size), + &cond_block); + } + else + size = fold_convert (size_type_node, TYPE_SIZE_UNIT (TREE_TYPE (type))); ptr = gfc_create_var (pvoid_type_node, NULL); gfc_allocate_using_malloc (&cond_block, ptr, size, NULL_TREE); - gfc_conv_descriptor_data_set (&cond_block, decl, ptr); - + if (GFC_DESCRIPTOR_TYPE_P (type)) + gfc_conv_descriptor_data_set (&cond_block, unshare_expr (decl), ptr); + else + gfc_add_modify (&cond_block, unshare_expr (decl), + fold_convert (TREE_TYPE (decl), ptr)); + if (gfc_has_alloc_comps (type, OMP_CLAUSE_DECL (clause))) + { + tree tem = gfc_walk_alloc_comps (outer, decl, + OMP_CLAUSE_DECL (clause), + WALK_ALLOC_COMPS_DEFAULT_CTOR); + gfc_add_expr_to_block (&cond_block, tem); + } then_b = gfc_finish_block (&cond_block); - gfc_init_block (&cond_block); - gfc_conv_descriptor_data_set (&cond_block, decl, null_pointer_node); - else_b = gfc_finish_block (&cond_block); - - cond = fold_build2_loc (input_location, NE_EXPR, boolean_type_node, - fold_convert (pvoid_type_node, - gfc_conv_descriptor_data_get (outer)), - null_pointer_node); - gfc_add_expr_to_block (&block, build3_loc (input_location, COND_EXPR, - void_type_node, cond, then_b, else_b)); + /* Reduction clause requires allocated ALLOCATABLE. */ + if (OMP_CLAUSE_CODE (clause) != OMP_CLAUSE_REDUCTION) + { + gfc_init_block (&cond_block); + if (GFC_DESCRIPTOR_TYPE_P (type)) + gfc_conv_descriptor_data_set (&cond_block, unshare_expr (decl), + null_pointer_node); + else + gfc_add_modify (&cond_block, unshare_expr (decl), + build_zero_cst (TREE_TYPE (decl))); + else_b = gfc_finish_block (&cond_block); + + tree tem = fold_convert (pvoid_type_node, + GFC_DESCRIPTOR_TYPE_P (type) + ? gfc_conv_descriptor_data_get (outer) : outer); + tem = unshare_expr (tem); + cond = fold_build2_loc (input_location, NE_EXPR, boolean_type_node, + tem, null_pointer_node); + gfc_add_expr_to_block (&block, + build3_loc (input_location, COND_EXPR, + void_type_node, cond, then_b, + else_b)); + } + else + gfc_add_expr_to_block (&block, then_b); return gfc_finish_block (&block); } @@ -217,15 +534,29 @@ gfc_omp_clause_default_ctor (tree clause, tree decl, tree outer) tree gfc_omp_clause_copy_ctor (tree clause, tree dest, tree src) { - tree type = TREE_TYPE (dest), ptr, size, esize, rank, call; + tree type = TREE_TYPE (dest), ptr, size, call; tree cond, then_b, else_b; stmtblock_t block, cond_block; - if (! GFC_DESCRIPTOR_TYPE_P (type) - || GFC_TYPE_ARRAY_AKIND (type) != GFC_ARRAY_ALLOCATABLE) - return build2_v (MODIFY_EXPR, dest, src); + gcc_assert (OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_FIRSTPRIVATE + || OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_LINEAR); - gcc_assert (OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_FIRSTPRIVATE); + if ((! GFC_DESCRIPTOR_TYPE_P (type) + || GFC_TYPE_ARRAY_AKIND (type) != GFC_ARRAY_ALLOCATABLE) + && !GFC_DECL_GET_SCALAR_ALLOCATABLE (OMP_CLAUSE_DECL (clause))) + { + if (gfc_has_alloc_comps (type, OMP_CLAUSE_DECL (clause))) + { + gfc_start_block (&block); + gfc_add_modify (&block, dest, src); + tree tem = gfc_walk_alloc_comps (src, dest, OMP_CLAUSE_DECL (clause), + WALK_ALLOC_COMPS_COPY_CTOR); + gfc_add_expr_to_block (&block, tem); + return gfc_finish_block (&block); + } + else + return build2_v (MODIFY_EXPR, dest, src); + } /* Allocatable arrays in FIRSTPRIVATE clauses need to be allocated and copied from SRC. */ @@ -234,85 +565,257 @@ gfc_omp_clause_copy_ctor (tree clause, tree dest, tree src) gfc_init_block (&cond_block); gfc_add_modify (&cond_block, dest, src); - rank = gfc_rank_cst[GFC_TYPE_ARRAY_RANK (type) - 1]; - size = gfc_conv_descriptor_ubound_get (dest, rank); - size = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type, - size, gfc_conv_descriptor_lbound_get (dest, rank)); - size = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type, - size, gfc_index_one_node); - if (GFC_TYPE_ARRAY_RANK (type) > 1) - size = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type, - size, gfc_conv_descriptor_stride_get (dest, rank)); - esize = fold_convert (gfc_array_index_type, - TYPE_SIZE_UNIT (gfc_get_element_type (type))); - size = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type, - size, esize); - size = gfc_evaluate_now (fold_convert (size_type_node, size), &cond_block); - + if (GFC_DESCRIPTOR_TYPE_P (type)) + { + tree rank = gfc_rank_cst[GFC_TYPE_ARRAY_RANK (type) - 1]; + size = gfc_conv_descriptor_ubound_get (dest, rank); + size = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type, + size, + gfc_conv_descriptor_lbound_get (dest, rank)); + size = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type, + size, gfc_index_one_node); + if (GFC_TYPE_ARRAY_RANK (type) > 1) + size = fold_build2_loc (input_location, MULT_EXPR, + gfc_array_index_type, size, + gfc_conv_descriptor_stride_get (dest, rank)); + tree esize = fold_convert (gfc_array_index_type, + TYPE_SIZE_UNIT (gfc_get_element_type (type))); + size = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type, + size, esize); + size = unshare_expr (size); + size = gfc_evaluate_now (fold_convert (size_type_node, size), + &cond_block); + } + else + size = fold_convert (size_type_node, TYPE_SIZE_UNIT (TREE_TYPE (type))); ptr = gfc_create_var (pvoid_type_node, NULL); gfc_allocate_using_malloc (&cond_block, ptr, size, NULL_TREE); - gfc_conv_descriptor_data_set (&cond_block, dest, ptr); + if (GFC_DESCRIPTOR_TYPE_P (type)) + gfc_conv_descriptor_data_set (&cond_block, unshare_expr (dest), ptr); + else + gfc_add_modify (&cond_block, unshare_expr (dest), + fold_convert (TREE_TYPE (dest), ptr)); + tree srcptr = GFC_DESCRIPTOR_TYPE_P (type) + ? gfc_conv_descriptor_data_get (src) : src; + srcptr = unshare_expr (srcptr); + srcptr = fold_convert (pvoid_type_node, srcptr); call = build_call_expr_loc (input_location, - builtin_decl_explicit (BUILT_IN_MEMCPY), - 3, ptr, - fold_convert (pvoid_type_node, - gfc_conv_descriptor_data_get (src)), - size); + builtin_decl_explicit (BUILT_IN_MEMCPY), 3, ptr, + srcptr, size); gfc_add_expr_to_block (&cond_block, fold_convert (void_type_node, call)); + if (gfc_has_alloc_comps (type, OMP_CLAUSE_DECL (clause))) + { + tree tem = gfc_walk_alloc_comps (src, dest, + OMP_CLAUSE_DECL (clause), + WALK_ALLOC_COMPS_COPY_CTOR); + gfc_add_expr_to_block (&cond_block, tem); + } then_b = gfc_finish_block (&cond_block); gfc_init_block (&cond_block); - gfc_conv_descriptor_data_set (&cond_block, dest, null_pointer_node); + if (GFC_DESCRIPTOR_TYPE_P (type)) + gfc_conv_descriptor_data_set (&cond_block, unshare_expr (dest), + null_pointer_node); + else + gfc_add_modify (&cond_block, unshare_expr (dest), + build_zero_cst (TREE_TYPE (dest))); else_b = gfc_finish_block (&cond_block); cond = fold_build2_loc (input_location, NE_EXPR, boolean_type_node, - fold_convert (pvoid_type_node, - gfc_conv_descriptor_data_get (src)), - null_pointer_node); - gfc_add_expr_to_block (&block, build3_loc (input_location, COND_EXPR, - void_type_node, cond, then_b, else_b)); + unshare_expr (srcptr), null_pointer_node); + gfc_add_expr_to_block (&block, + build3_loc (input_location, COND_EXPR, + void_type_node, cond, then_b, else_b)); return gfc_finish_block (&block); } -/* Similarly, except use an assignment operator instead. */ +/* Similarly, except use an intrinsic or pointer assignment operator + instead. */ tree -gfc_omp_clause_assign_op (tree clause ATTRIBUTE_UNUSED, tree dest, tree src) +gfc_omp_clause_assign_op (tree clause, tree dest, tree src) { - tree type = TREE_TYPE (dest), rank, size, esize, call; - stmtblock_t block; + tree type = TREE_TYPE (dest), ptr, size, call, nonalloc; + tree cond, then_b, else_b; + stmtblock_t block, cond_block, cond_block2, inner_block; - if (! GFC_DESCRIPTOR_TYPE_P (type) - || GFC_TYPE_ARRAY_AKIND (type) != GFC_ARRAY_ALLOCATABLE) - return build2_v (MODIFY_EXPR, dest, src); + if ((! GFC_DESCRIPTOR_TYPE_P (type) + || GFC_TYPE_ARRAY_AKIND (type) != GFC_ARRAY_ALLOCATABLE) + && !GFC_DECL_GET_SCALAR_ALLOCATABLE (OMP_CLAUSE_DECL (clause))) + { + if (gfc_has_alloc_comps (type, OMP_CLAUSE_DECL (clause))) + { + gfc_start_block (&block); + /* First dealloc any allocatable components in DEST. */ + tree tem = gfc_walk_alloc_comps (dest, NULL_TREE, + OMP_CLAUSE_DECL (clause), + WALK_ALLOC_COMPS_DTOR); + gfc_add_expr_to_block (&block, tem); + /* Then copy over toplevel data. */ + gfc_add_modify (&block, dest, src); + /* Finally allocate any allocatable components and copy. */ + tem = gfc_walk_alloc_comps (src, dest, OMP_CLAUSE_DECL (clause), + WALK_ALLOC_COMPS_COPY_CTOR); + gfc_add_expr_to_block (&block, tem); + return gfc_finish_block (&block); + } + else + return build2_v (MODIFY_EXPR, dest, src); + } - /* Handle copying allocatable arrays. */ gfc_start_block (&block); - rank = gfc_rank_cst[GFC_TYPE_ARRAY_RANK (type) - 1]; - size = gfc_conv_descriptor_ubound_get (dest, rank); - size = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type, - size, gfc_conv_descriptor_lbound_get (dest, rank)); - size = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type, - size, gfc_index_one_node); - if (GFC_TYPE_ARRAY_RANK (type) > 1) - size = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type, - size, gfc_conv_descriptor_stride_get (dest, rank)); - esize = fold_convert (gfc_array_index_type, - TYPE_SIZE_UNIT (gfc_get_element_type (type))); - size = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type, - size, esize); - size = gfc_evaluate_now (fold_convert (size_type_node, size), &block); + if (gfc_has_alloc_comps (type, OMP_CLAUSE_DECL (clause))) + { + then_b = gfc_walk_alloc_comps (dest, NULL_TREE, OMP_CLAUSE_DECL (clause), + WALK_ALLOC_COMPS_DTOR); + tree tem = fold_convert (pvoid_type_node, + GFC_DESCRIPTOR_TYPE_P (type) + ? gfc_conv_descriptor_data_get (dest) : dest); + tem = unshare_expr (tem); + cond = fold_build2_loc (input_location, NE_EXPR, boolean_type_node, + tem, null_pointer_node); + tem = build3_loc (input_location, COND_EXPR, void_type_node, cond, + then_b, build_empty_stmt (input_location)); + gfc_add_expr_to_block (&block, tem); + } + + gfc_init_block (&cond_block); + + if (GFC_DESCRIPTOR_TYPE_P (type)) + { + tree rank = gfc_rank_cst[GFC_TYPE_ARRAY_RANK (type) - 1]; + size = gfc_conv_descriptor_ubound_get (src, rank); + size = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type, + size, + gfc_conv_descriptor_lbound_get (src, rank)); + size = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type, + size, gfc_index_one_node); + if (GFC_TYPE_ARRAY_RANK (type) > 1) + size = fold_build2_loc (input_location, MULT_EXPR, + gfc_array_index_type, size, + gfc_conv_descriptor_stride_get (src, rank)); + tree esize = fold_convert (gfc_array_index_type, + TYPE_SIZE_UNIT (gfc_get_element_type (type))); + size = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type, + size, esize); + size = unshare_expr (size); + size = gfc_evaluate_now (fold_convert (size_type_node, size), + &cond_block); + } + else + size = fold_convert (size_type_node, TYPE_SIZE_UNIT (TREE_TYPE (type))); + ptr = gfc_create_var (pvoid_type_node, NULL); + + tree destptr = GFC_DESCRIPTOR_TYPE_P (type) + ? gfc_conv_descriptor_data_get (dest) : dest; + destptr = unshare_expr (destptr); + destptr = fold_convert (pvoid_type_node, destptr); + gfc_add_modify (&cond_block, ptr, destptr); + + nonalloc = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, + destptr, null_pointer_node); + cond = nonalloc; + if (GFC_DESCRIPTOR_TYPE_P (type)) + { + int i; + for (i = 0; i < GFC_TYPE_ARRAY_RANK (type); i++) + { + tree rank = gfc_rank_cst[i]; + tree tem = gfc_conv_descriptor_ubound_get (src, rank); + tem = fold_build2_loc (input_location, MINUS_EXPR, + gfc_array_index_type, tem, + gfc_conv_descriptor_lbound_get (src, rank)); + tem = fold_build2_loc (input_location, PLUS_EXPR, + gfc_array_index_type, tem, + gfc_conv_descriptor_lbound_get (dest, rank)); + tem = fold_build2_loc (input_location, NE_EXPR, boolean_type_node, + tem, gfc_conv_descriptor_ubound_get (dest, + rank)); + cond = fold_build2_loc (input_location, TRUTH_ORIF_EXPR, + boolean_type_node, cond, tem); + } + } + + gfc_init_block (&cond_block2); + + if (GFC_DESCRIPTOR_TYPE_P (type)) + { + gfc_init_block (&inner_block); + gfc_allocate_using_malloc (&inner_block, ptr, size, NULL_TREE); + then_b = gfc_finish_block (&inner_block); + + gfc_init_block (&inner_block); + gfc_add_modify (&inner_block, ptr, + gfc_call_realloc (&inner_block, ptr, size)); + else_b = gfc_finish_block (&inner_block); + + gfc_add_expr_to_block (&cond_block2, + build3_loc (input_location, COND_EXPR, + void_type_node, + unshare_expr (nonalloc), + then_b, else_b)); + gfc_add_modify (&cond_block2, dest, src); + gfc_conv_descriptor_data_set (&cond_block2, unshare_expr (dest), ptr); + } + else + { + gfc_allocate_using_malloc (&cond_block2, ptr, size, NULL_TREE); + gfc_add_modify (&cond_block2, unshare_expr (dest), + fold_convert (type, ptr)); + } + then_b = gfc_finish_block (&cond_block2); + else_b = build_empty_stmt (input_location); + + gfc_add_expr_to_block (&cond_block, + build3_loc (input_location, COND_EXPR, + void_type_node, unshare_expr (cond), + then_b, else_b)); + + tree srcptr = GFC_DESCRIPTOR_TYPE_P (type) + ? gfc_conv_descriptor_data_get (src) : src; + srcptr = unshare_expr (srcptr); + srcptr = fold_convert (pvoid_type_node, srcptr); call = build_call_expr_loc (input_location, - builtin_decl_explicit (BUILT_IN_MEMCPY), 3, - fold_convert (pvoid_type_node, - gfc_conv_descriptor_data_get (dest)), - fold_convert (pvoid_type_node, - gfc_conv_descriptor_data_get (src)), - size); - gfc_add_expr_to_block (&block, fold_convert (void_type_node, call)); + builtin_decl_explicit (BUILT_IN_MEMCPY), 3, ptr, + srcptr, size); + gfc_add_expr_to_block (&cond_block, fold_convert (void_type_node, call)); + if (gfc_has_alloc_comps (type, OMP_CLAUSE_DECL (clause))) + { + tree tem = gfc_walk_alloc_comps (src, dest, + OMP_CLAUSE_DECL (clause), + WALK_ALLOC_COMPS_COPY_CTOR); + gfc_add_expr_to_block (&cond_block, tem); + } + then_b = gfc_finish_block (&cond_block); + + if (OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_COPYIN) + { + gfc_init_block (&cond_block); + if (GFC_DESCRIPTOR_TYPE_P (type)) + gfc_add_expr_to_block (&cond_block, + gfc_trans_dealloc_allocated (unshare_expr (dest), + false, NULL)); + else + { + destptr = gfc_evaluate_now (destptr, &cond_block); + gfc_add_expr_to_block (&cond_block, gfc_call_free (destptr)); + gfc_add_modify (&cond_block, unshare_expr (dest), + build_zero_cst (TREE_TYPE (dest))); + } + else_b = gfc_finish_block (&cond_block); + + cond = fold_build2_loc (input_location, NE_EXPR, boolean_type_node, + unshare_expr (srcptr), null_pointer_node); + gfc_add_expr_to_block (&block, + build3_loc (input_location, COND_EXPR, + void_type_node, cond, + then_b, else_b)); + } + else + gfc_add_expr_to_block (&block, then_b); return gfc_finish_block (&block); } @@ -321,20 +824,52 @@ gfc_omp_clause_assign_op (tree clause ATTRIBUTE_UNUSED, tree dest, tree src) to be done. */ tree -gfc_omp_clause_dtor (tree clause ATTRIBUTE_UNUSED, tree decl) +gfc_omp_clause_dtor (tree clause, tree decl) { - tree type = TREE_TYPE (decl); + tree type = TREE_TYPE (decl), tem; - if (! GFC_DESCRIPTOR_TYPE_P (type) - || GFC_TYPE_ARRAY_AKIND (type) != GFC_ARRAY_ALLOCATABLE) - return NULL; + if ((! GFC_DESCRIPTOR_TYPE_P (type) + || GFC_TYPE_ARRAY_AKIND (type) != GFC_ARRAY_ALLOCATABLE) + && !GFC_DECL_GET_SCALAR_ALLOCATABLE (OMP_CLAUSE_DECL (clause))) + { + if (gfc_has_alloc_comps (type, OMP_CLAUSE_DECL (clause))) + return gfc_walk_alloc_comps (decl, NULL_TREE, + OMP_CLAUSE_DECL (clause), + WALK_ALLOC_COMPS_DTOR); + return NULL_TREE; + } - if (OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_REDUCTION) - return NULL; + if (GFC_DESCRIPTOR_TYPE_P (type)) + /* Allocatable arrays in FIRSTPRIVATE/LASTPRIVATE etc. clauses need + to be deallocated if they were allocated. */ + tem = gfc_trans_dealloc_allocated (decl, false, NULL); + else + tem = gfc_call_free (decl); + tem = gfc_omp_unshare_expr (tem); - /* Allocatable arrays in FIRSTPRIVATE/LASTPRIVATE etc. clauses need - to be deallocated if they were allocated. */ - return gfc_trans_dealloc_allocated (decl, false, NULL); + if (gfc_has_alloc_comps (type, OMP_CLAUSE_DECL (clause))) + { + stmtblock_t block; + tree then_b; + + gfc_init_block (&block); + gfc_add_expr_to_block (&block, + gfc_walk_alloc_comps (decl, NULL_TREE, + OMP_CLAUSE_DECL (clause), + WALK_ALLOC_COMPS_DTOR)); + gfc_add_expr_to_block (&block, tem); + then_b = gfc_finish_block (&block); + + tem = fold_convert (pvoid_type_node, + GFC_DESCRIPTOR_TYPE_P (type) + ? gfc_conv_descriptor_data_get (decl) : decl); + tem = unshare_expr (tem); + tree cond = fold_build2_loc (input_location, NE_EXPR, boolean_type_node, + tem, null_pointer_node); + tem = build3_loc (input_location, COND_EXPR, void_type_node, cond, + then_b, build_empty_stmt (input_location)); + } + return tem; } @@ -881,47 +1416,7 @@ gfc_trans_omp_array_reduction_or_udr (tree c, gfc_omp_namelist *n, locus where) /* Create the init statement list. */ pushlevel (); - if (sym->attr.dimension - && GFC_DESCRIPTOR_TYPE_P (type) - && GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_ALLOCATABLE) - { - /* If decl is an allocatable array, it needs to be allocated - with the same bounds as the outer var. */ - tree rank, size, esize, ptr; - stmtblock_t block; - - gfc_start_block (&block); - - gfc_add_modify (&block, decl, outer_sym.backend_decl); - rank = gfc_rank_cst[GFC_TYPE_ARRAY_RANK (type) - 1]; - size = gfc_conv_descriptor_ubound_get (decl, rank); - size = fold_build2_loc (input_location, MINUS_EXPR, - gfc_array_index_type, size, - gfc_conv_descriptor_lbound_get (decl, rank)); - size = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type, - size, gfc_index_one_node); - if (GFC_TYPE_ARRAY_RANK (type) > 1) - size = fold_build2_loc (input_location, MULT_EXPR, - gfc_array_index_type, size, - gfc_conv_descriptor_stride_get (decl, rank)); - esize = fold_convert (gfc_array_index_type, - TYPE_SIZE_UNIT (gfc_get_element_type (type))); - size = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type, - size, esize); - size = gfc_evaluate_now (fold_convert (size_type_node, size), &block); - - ptr = gfc_create_var (pvoid_type_node, NULL); - gfc_allocate_using_malloc (&block, ptr, size, NULL_TREE); - gfc_conv_descriptor_data_set (&block, decl, ptr); - - if (e2) - stmt = gfc_trans_assignment (e1, e2, false, false); - else - stmt = gfc_trans_omp_udr_expr (n, true, e1, e3); - gfc_add_expr_to_block (&block, stmt); - stmt = gfc_finish_block (&block); - } - else if (e2) + if (e2) stmt = gfc_trans_assignment (e1, e2, false, false); else if (sym->attr.dimension) stmt = gfc_trans_omp_udr_expr (n, true, e1, e3); @@ -936,25 +1431,7 @@ gfc_trans_omp_array_reduction_or_udr (tree c, gfc_omp_namelist *n, locus where) /* Create the merge statement list. */ pushlevel (); - if (sym->attr.dimension - && GFC_DESCRIPTOR_TYPE_P (type) - && GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_ALLOCATABLE) - { - /* If decl is an allocatable array, it needs to be deallocated - afterwards. */ - stmtblock_t block; - - gfc_start_block (&block); - if (e4) - stmt = gfc_trans_assignment (e3, e4, false, true); - else - stmt = gfc_trans_omp_udr_expr (n, false, e1, e3); - gfc_add_expr_to_block (&block, stmt); - gfc_add_expr_to_block (&block, gfc_trans_dealloc_allocated (decl, false, - NULL)); - stmt = gfc_finish_block (&block); - } - else if (e4) + if (e4) stmt = gfc_trans_assignment (e3, e4, false, true); else if (sym->attr.dimension) stmt = gfc_trans_omp_udr_expr (n, false, e1, e3); @@ -1055,7 +1532,8 @@ gfc_trans_omp_reduction_list (gfc_omp_namelist *namelist, tree list, gcc_unreachable (); } if (namelist->sym->attr.dimension - || namelist->rop == OMP_REDUCTION_USER) + || namelist->rop == OMP_REDUCTION_USER + || namelist->sym->attr.allocatable) gfc_trans_omp_array_reduction_or_udr (node, namelist, where); list = gfc_trans_add_clause (node, list); } @@ -2274,8 +2752,9 @@ gfc_trans_omp_do_simd (gfc_code *code, gfc_omp_clauses *clausesa, clausesa = clausesa_buf; gfc_split_omp_clauses (code, clausesa); } - omp_do_clauses - = gfc_trans_omp_clauses (&block, &clausesa[GFC_OMP_SPLIT_DO], code->loc); + if (gfc_option.gfc_flag_openmp) + omp_do_clauses + = gfc_trans_omp_clauses (&block, &clausesa[GFC_OMP_SPLIT_DO], code->loc); pblock = █ body = gfc_trans_omp_do (code, EXEC_OMP_SIMD, pblock, &clausesa[GFC_OMP_SPLIT_SIMD], omp_clauses); @@ -2283,10 +2762,15 @@ gfc_trans_omp_do_simd (gfc_code *code, gfc_omp_clauses *clausesa, body = build3_v (BIND_EXPR, NULL, body, poplevel (1, 0)); else poplevel (0, 0); - stmt = make_node (OMP_FOR); - TREE_TYPE (stmt) = void_type_node; - OMP_FOR_BODY (stmt) = body; - OMP_FOR_CLAUSES (stmt) = omp_do_clauses; + if (gfc_option.gfc_flag_openmp) + { + stmt = make_node (OMP_FOR); + TREE_TYPE (stmt) = void_type_node; + OMP_FOR_BODY (stmt) = body; + OMP_FOR_CLAUSES (stmt) = omp_do_clauses; + } + else + stmt = body; gfc_add_expr_to_block (&block, stmt); return gfc_finish_block (&block); } @@ -2332,18 +2816,22 @@ gfc_trans_omp_parallel_do_simd (gfc_code *code) gfc_start_block (&block); gfc_split_omp_clauses (code, clausesa); - omp_clauses - = gfc_trans_omp_clauses (&block, &clausesa[GFC_OMP_SPLIT_PARALLEL], - code->loc); + if (gfc_option.gfc_flag_openmp) + omp_clauses + = gfc_trans_omp_clauses (&block, &clausesa[GFC_OMP_SPLIT_PARALLEL], + code->loc); pushlevel (); stmt = gfc_trans_omp_do_simd (code, clausesa, omp_clauses); if (TREE_CODE (stmt) != BIND_EXPR) stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0)); else poplevel (0, 0); - stmt = build2_loc (input_location, OMP_PARALLEL, void_type_node, stmt, - omp_clauses); - OMP_PARALLEL_COMBINED (stmt) = 1; + if (gfc_option.gfc_flag_openmp) + { + stmt = build2_loc (input_location, OMP_PARALLEL, void_type_node, stmt, + omp_clauses); + OMP_PARALLEL_COMBINED (stmt) = 1; + } gfc_add_expr_to_block (&block, stmt); return gfc_finish_block (&block); } diff --git a/gcc/fortran/trans-types.c b/gcc/fortran/trans-types.c index d9aab474a75..71a159b6b99 100644 --- a/gcc/fortran/trans-types.c +++ b/gcc/fortran/trans-types.c @@ -2160,9 +2160,6 @@ gfc_sym_type (gfc_symbol * sym) restricted); byref = 0; } - - if (sym->attr.cray_pointee) - GFC_POINTER_TYPE_P (type) = 1; } else { @@ -2181,8 +2178,6 @@ gfc_sym_type (gfc_symbol * sym) if (sym->attr.allocatable || sym->attr.pointer || gfc_is_associate_pointer (sym)) type = gfc_build_pointer_type (sym, type); - if (sym->attr.pointer || sym->attr.cray_pointee) - GFC_POINTER_TYPE_P (type) = 1; } /* We currently pass all parameters by reference. @@ -2552,6 +2547,8 @@ gfc_get_derived_type (gfc_symbol * derived) else if (derived->declared_at.lb) gfc_set_decl_location (field, &derived->declared_at); + gfc_finish_decl_attrs (field, &c->attr); + DECL_PACKED (field) |= TYPE_PACKED (typenode); gcc_assert (field); diff --git a/gcc/fortran/trans.h b/gcc/fortran/trans.h index def6b9df00c..7e8d08cda85 100644 --- a/gcc/fortran/trans.h +++ b/gcc/fortran/trans.h @@ -547,6 +547,9 @@ void gfc_set_decl_assembler_name (tree, tree); /* Returns true if a variable of specified size should go on the stack. */ int gfc_can_put_var_on_stack (tree); +/* Set GFC_DECL_SCALAR_* on decl from sym if needed. */ +void gfc_finish_decl_attrs (tree, symbol_attribute *); + /* Allocate the lang-specific part of a decl node. */ void gfc_allocate_lang_decl (tree); @@ -822,6 +825,8 @@ struct GTY(()) lang_decl { tree span; /* For assumed-shape coarrays. */ tree token, caf_offset; + unsigned int scalar_allocatable : 1; + unsigned int scalar_pointer : 1; }; @@ -832,6 +837,14 @@ struct GTY(()) lang_decl { #define GFC_DECL_CAF_OFFSET(node) DECL_LANG_SPECIFIC(node)->caf_offset #define GFC_DECL_SAVED_DESCRIPTOR(node) \ (DECL_LANG_SPECIFIC(node)->saved_descriptor) +#define GFC_DECL_SCALAR_ALLOCATABLE(node) \ + (DECL_LANG_SPECIFIC (node)->scalar_allocatable) +#define GFC_DECL_SCALAR_POINTER(node) \ + (DECL_LANG_SPECIFIC (node)->scalar_pointer) +#define GFC_DECL_GET_SCALAR_ALLOCATABLE(node) \ + (DECL_LANG_SPECIFIC (node) ? GFC_DECL_SCALAR_ALLOCATABLE (node) : 0) +#define GFC_DECL_GET_SCALAR_POINTER(node) \ + (DECL_LANG_SPECIFIC (node) ? GFC_DECL_SCALAR_POINTER (node) : 0) #define GFC_DECL_PACKED_ARRAY(node) DECL_LANG_FLAG_0(node) #define GFC_DECL_PARTIAL_PACKED_ARRAY(node) DECL_LANG_FLAG_1(node) #define GFC_DECL_ASSIGN(node) DECL_LANG_FLAG_2(node) @@ -839,14 +852,13 @@ struct GTY(()) lang_decl { #define GFC_DECL_CRAY_POINTEE(node) DECL_LANG_FLAG_4(node) #define GFC_DECL_RESULT(node) DECL_LANG_FLAG_5(node) #define GFC_DECL_SUBREF_ARRAY_P(node) DECL_LANG_FLAG_6(node) +#define GFC_DECL_ASSOCIATE_VAR_P(node) DECL_LANG_FLAG_7(node) #define GFC_DECL_CLASS(node) DECL_LANG_FLAG_8(node) /* An array descriptor. */ #define GFC_DESCRIPTOR_TYPE_P(node) TYPE_LANG_FLAG_1(node) /* An array without a descriptor. */ #define GFC_ARRAY_TYPE_P(node) TYPE_LANG_FLAG_2(node) -/* Fortran POINTER type. */ -#define GFC_POINTER_TYPE_P(node) TYPE_LANG_FLAG_3(node) /* Fortran CLASS type. */ #define GFC_CLASS_TYPE_P(node) TYPE_LANG_FLAG_4(node) /* The GFC_TYPE_ARRAY_* members are present in both descriptor and diff --git a/gcc/omp-low.c b/gcc/omp-low.c index 0f400b0e3af..ddb049d3ea1 100644 --- a/gcc/omp-low.c +++ b/gcc/omp-low.c @@ -3110,6 +3110,13 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist, if (pass != 0) continue; } + /* Even without corresponding firstprivate, if + decl is Fortran allocatable, it needs outer var + reference. */ + else if (pass == 0 + && lang_hooks.decls.omp_private_outer_ref + (OMP_CLAUSE_DECL (c))) + lastprivate_firstprivate = true; break; case OMP_CLAUSE_ALIGNED: if (pass == 0) @@ -3545,7 +3552,8 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist, else if (is_reference (var) && is_simd) handle_simd_reference (clause_loc, new_vard, ilist); x = lang_hooks.decls.omp_clause_default_ctor - (c, new_var, unshare_expr (x)); + (c, unshare_expr (new_var), + build_outer_var_ref (var, ctx)); if (x) gimplify_and_add (x, ilist); if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c)) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index b307bd33215..b8a164983fb 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,15 @@ +2014-06-10 Jakub Jelinek <jakub@redhat.com> + + PR fortran/60928 + * gfortran.dg/gomp/allocatable_components_1.f90: Remove dg-error + directives. + * gfortran.dg/gomp/associate1.f90: New test. + * gfortran.dg/gomp/intentin1.f90: New test. + * gfortran.dg/gomp/openmp-simd-1.f90: New test. + * gfortran.dg/gomp/openmp-simd-2.f90: New test. + * gfortran.dg/gomp/openmp-simd-3.f90: New test. + * gfortran.dg/gomp/proc_ptr_2.f90: New test. + 2014-06-09 Marek Polacek <polacek@redhat.com> PR c/36446 diff --git a/gcc/testsuite/gfortran.dg/gomp/allocatable_components_1.f90 b/gcc/testsuite/gfortran.dg/gomp/allocatable_components_1.f90 index 8e4e5390d11..bc06cc8662c 100644 --- a/gcc/testsuite/gfortran.dg/gomp/allocatable_components_1.f90 +++ b/gcc/testsuite/gfortran.dg/gomp/allocatable_components_1.f90 @@ -14,7 +14,7 @@ CONTAINS TYPE(t), SAVE :: a !$omp threadprivate(a) - !$omp parallel copyin(a) ! { dg-error "has ALLOCATABLE components" } + !$omp parallel copyin(a) ! do something !$omp end parallel END SUBROUTINE @@ -22,7 +22,7 @@ CONTAINS SUBROUTINE test_copyprivate() TYPE(t) :: a - !$omp single ! { dg-error "has ALLOCATABLE components" } + !$omp single ! do something !$omp end single copyprivate (a) END SUBROUTINE @@ -30,7 +30,7 @@ CONTAINS SUBROUTINE test_firstprivate TYPE(t) :: a - !$omp parallel firstprivate(a) ! { dg-error "has ALLOCATABLE components" } + !$omp parallel firstprivate(a) ! do something !$omp end parallel END SUBROUTINE @@ -39,7 +39,7 @@ CONTAINS TYPE(t) :: a INTEGER :: i - !$omp parallel do lastprivate(a) ! { dg-error "has ALLOCATABLE components" } + !$omp parallel do lastprivate(a) DO i = 1, 1 END DO !$omp end parallel do diff --git a/gcc/testsuite/gfortran.dg/gomp/associate1.f90 b/gcc/testsuite/gfortran.dg/gomp/associate1.f90 new file mode 100644 index 00000000000..abc5ae95a0d --- /dev/null +++ b/gcc/testsuite/gfortran.dg/gomp/associate1.f90 @@ -0,0 +1,83 @@ +! { dg-do compile } + +program associate1 + type dl + integer :: i + end type + type dt + integer :: i + real :: a(3, 3) + type(dl) :: c(3, 3) + end type + integer :: v, i, j + real :: a(3, 3) + type(dt) :: b(3) + i = 1 + j = 2 + associate(k => v, l => a(i, j), m => a(i, :)) + associate(n => b(j)%c(:, :)%i, o => a, p => b) +!$omp parallel shared (l) ! { dg-error "ASSOCIATE name" } +!$omp end parallel +!$omp parallel firstprivate (m) ! { dg-error "ASSOCIATE name" } +!$omp end parallel +!$omp parallel reduction (+: k) ! { dg-error "ASSOCIATE name" } +!$omp end parallel +!$omp parallel do firstprivate (k) ! { dg-error "ASSOCIATE name" } + do i = 1, 10 + end do +!$omp parallel do lastprivate (n) ! { dg-error "ASSOCIATE name" } + do i = 1, 10 + end do +!$omp parallel do private (o) ! { dg-error "ASSOCIATE name" } + do i = 1, 10 + end do +!$omp parallel do shared (p) ! { dg-error "ASSOCIATE name" } + do i = 1, 10 + end do +!$omp task private (k) ! { dg-error "ASSOCIATE name" } +!$omp end task +!$omp task shared (l) ! { dg-error "ASSOCIATE name" } +!$omp end task +!$omp task firstprivate (m) ! { dg-error "ASSOCIATE name" } +!$omp end task +!$omp do private (l) ! { dg-error "ASSOCIATE name" } + do i = 1, 10 + end do +!$omp do reduction (*: k) ! { dg-error "ASSOCIATE name" } + do i = 1, 10 + end do +!$omp sections private(o) ! { dg-error "ASSOCIATE name" } +!$omp section +!$omp section +!$omp end sections +!$omp parallel sections firstprivate(p) ! { dg-error "ASSOCIATE name" } +!$omp section +!$omp section +!$omp endparallelsections +!$omp parallelsections lastprivate(m) ! { dg-error "ASSOCIATE name" } +!$omp section +!$omp section +!$omp endparallelsections +!$omp sections reduction(+:k) ! { dg-error "ASSOCIATE name" } +!$omp section +!$omp section +!$omp end sections +!$omp simd private (l) ! { dg-error "ASSOCIATE name" } + do i = 1, 10 + end do + k = 1 +!$omp simd lastprivate (m) ! { dg-error "ASSOCIATE name" } + do i = 1, 10 + end do + k = 1 +!$omp simd reduction (+: k) ! { dg-error "ASSOCIATE name" } + do i = 1, 10 + end do + k = 1 +!$omp simd linear (k : 2) ! { dg-error "ASSOCIATE name" } + do i = 1, 10 + k = k + 2 + end do + end associate + end associate +end program diff --git a/gcc/testsuite/gfortran.dg/gomp/intentin1.f90 b/gcc/testsuite/gfortran.dg/gomp/intentin1.f90 new file mode 100644 index 00000000000..f2a2e98fd76 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/gomp/intentin1.f90 @@ -0,0 +1,16 @@ +! { dg-do compile } + +subroutine foo (x) + integer, pointer, intent (in) :: x + integer :: i +!$omp parallel private (x) ! { dg-error "INTENT.IN. POINTER" } +!$omp end parallel +!$omp parallel do lastprivate (x) ! { dg-error "INTENT.IN. POINTER" } + do i = 1, 10 + end do +!$omp simd linear (x) ! { dg-error "INTENT.IN. POINTER" } + do i = 1, 10 + end do +!$omp single ! { dg-error "INTENT.IN. POINTER" } +!$omp end single copyprivate (x) +end diff --git a/gcc/testsuite/gfortran.dg/gomp/openmp-simd-1.f90 b/gcc/testsuite/gfortran.dg/gomp/openmp-simd-1.f90 new file mode 100644 index 00000000000..c9ce70c4f44 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/gomp/openmp-simd-1.f90 @@ -0,0 +1,137 @@ +! { dg-do compile } +! { dg-options "-fno-openmp -fopenmp-simd -fdump-tree-original -O2" } + +!$omp declare reduction (foo:integer:omp_out = omp_out + omp_in) + interface + integer function foo (x, y) + integer, value :: x, y +!$omp declare simd (foo) linear (y : 2) + end function foo + end interface + integer :: i, a(64), b, c + integer, save :: d +!$omp threadprivate (d) + d = 5 + a = 6 +!$omp simd + do i = 1, 64 + a(i) = foo (a(i), 2 * i) + end do + b = 0 + c = 0 +!$omp simd reduction (+:b) reduction (foo:c) + do i = 1, 64 + b = b + a(i) + c = c + a(i) * 2 + end do + print *, b + b = 0 +!$omp parallel +!$omp do simd schedule(static, 4) safelen (8) reduction (+:b) + do i = 1, 64 + a(i) = a(i) + 1 + b = b + 1 + end do +!$omp end parallel + print *, b + b = 0 +!$omp parallel do simd schedule(static, 4) safelen (8) & +!$omp num_threads (4) if (.true.) reduction (+:b) + do i = 1, 64 + a(i) = a(i) + 1 + b = b + 1 + end do + print *, b + b = 0 +!$omp parallel +!$omp do simd schedule(static, 4) safelen (8) reduction (+:b) + do i = 1, 64 + a(i) = a(i) + 1 + b = b + 1 + end do +!$omp enddosimd +!$omp end parallel + print *, b + b = 0 +!$omp parallel do simd schedule(static, 4) safelen (8) & +!$omp num_threads (4) if (.true.) reduction (+:b) + do i = 1, 64 + a(i) = a(i) + 1 + b = b + 1 + end do +!$omp end parallel do simd +!$omp atomic seq_cst + b = b + 1 +!$omp end atomic +!$omp barrier +!$omp parallel private (i) +!$omp cancellation point parallel +!$omp critical (bar) + b = b + 1 +!$omp end critical (bar) +!$omp flush(b) +!$omp single + b = b + 1 +!$omp end single +!$omp do ordered + do i = 1, 10 + !$omp atomic + b = b + 1 + !$omp end atomic + !$omp ordered + print *, b + !$omp end ordered + end do +!$omp end do +!$omp master + b = b + 1 +!$omp end master +!$omp cancel parallel +!$omp end parallel +!$omp parallel do schedule(runtime) num_threads(8) + do i = 1, 10 + print *, b + end do +!$omp end parallel do +!$omp sections +!$omp section + b = b + 1 +!$omp section + c = c + 1 +!$omp end sections + print *, b +!$omp parallel sections firstprivate (b) if (.true.) +!$omp section + b = b + 1 +!$omp section + c = c + 1 +!$omp endparallelsections +!$omp workshare + b = 24 +!$omp end workshare +!$omp parallel workshare num_threads (2) + b = b + 1 + c = c + 1 +!$omp end parallel workshare + print *, b +!$omp parallel +!$omp single +!$omp taskgroup +!$omp task firstprivate (b) + b = b + 1 +!$omp taskyield +!$omp end task +!$omp task firstprivate (b) + b = b + 1 +!$omp end task +!$omp taskwait +!$omp end taskgroup +!$omp end single +!$omp end parallel + print *, a, c +end + +! { dg-final { scan-tree-dump-times "pragma omp simd" 6 "original" } } +! { dg-final { scan-tree-dump-times "pragma omp" 6 "original" } } +! { dg-final { scan-tree-dump-times "__builtin_GOMP" 0 "original" } } +! { dg-final { cleanup-tree-dump "original" } } diff --git a/gcc/testsuite/gfortran.dg/gomp/openmp-simd-2.f90 b/gcc/testsuite/gfortran.dg/gomp/openmp-simd-2.f90 new file mode 100644 index 00000000000..4b2046a58cc --- /dev/null +++ b/gcc/testsuite/gfortran.dg/gomp/openmp-simd-2.f90 @@ -0,0 +1,28 @@ +! { dg-do compile } +! { dg-options "-fopenmp -fopenmp-simd -fdump-tree-original -O2" } + +include 'openmp-simd-1.f90' + +! { dg-final { scan-tree-dump-times "pragma omp simd" 6 "original" } } +! { dg-final { scan-tree-dump-times "pragma omp" 39 "original" } } +! { dg-final { scan-tree-dump-times "pragma omp for" 6 "original" } } +! { dg-final { scan-tree-dump-times "pragma omp parallel" 9 "original" } } +! { dg-final { scan-tree-dump-times "pragma omp taskgroup" 1 "original" } } +! Includes the above taskgroup +! { dg-final { scan-tree-dump-times "pragma omp task" 3 "original" } } +! { dg-final { scan-tree-dump-times "pragma omp critical" 1 "original" } } +! { dg-final { scan-tree-dump-times "pragma omp atomic" 2 "original" } } +! { dg-final { scan-tree-dump-times "pragma omp sections" 2 "original" } } +! Includes the above sections +! { dg-final { scan-tree-dump-times "pragma omp section" 6 "original" } } +! { dg-final { scan-tree-dump-times "pragma omp single" 4 "original" } } +! { dg-final { scan-tree-dump-times "pragma omp ordered" 1 "original" } } +! { dg-final { scan-tree-dump-times "pragma omp master" 1 "original" } } +! { dg-final { scan-tree-dump-times "__builtin_GOMP" 5 "original" } } +! { dg-final { scan-tree-dump-times "__builtin_GOMP_barrier" 1 "original" } } +! { dg-final { scan-tree-dump-times "__builtin_GOMP_cancellation_point" 1 "original" } } +! Includes the above cancellation point +! { dg-final { scan-tree-dump-times "__builtin_GOMP_cancel" 2 "original" } } +! { dg-final { scan-tree-dump-times "__builtin_GOMP_taskyield" 1 "original" } } +! { dg-final { scan-tree-dump-times "__builtin_GOMP_taskwait" 1 "original" } } +! { dg-final { cleanup-tree-dump "original" } } diff --git a/gcc/testsuite/gfortran.dg/gomp/openmp-simd-3.f90 b/gcc/testsuite/gfortran.dg/gomp/openmp-simd-3.f90 new file mode 100644 index 00000000000..2dece895f39 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/gomp/openmp-simd-3.f90 @@ -0,0 +1,28 @@ +! { dg-do compile } +! { dg-options "-fopenmp -fno-openmp-simd -fdump-tree-original -O2" } + +include 'openmp-simd-1.f90' + +! { dg-final { scan-tree-dump-times "pragma omp simd" 6 "original" } } +! { dg-final { scan-tree-dump-times "pragma omp" 39 "original" } } +! { dg-final { scan-tree-dump-times "pragma omp for" 6 "original" } } +! { dg-final { scan-tree-dump-times "pragma omp parallel" 9 "original" } } +! { dg-final { scan-tree-dump-times "pragma omp taskgroup" 1 "original" } } +! Includes the above taskgroup +! { dg-final { scan-tree-dump-times "pragma omp task" 3 "original" } } +! { dg-final { scan-tree-dump-times "pragma omp critical" 1 "original" } } +! { dg-final { scan-tree-dump-times "pragma omp atomic" 2 "original" } } +! { dg-final { scan-tree-dump-times "pragma omp sections" 2 "original" } } +! Includes the above sections +! { dg-final { scan-tree-dump-times "pragma omp section" 6 "original" } } +! { dg-final { scan-tree-dump-times "pragma omp single" 4 "original" } } +! { dg-final { scan-tree-dump-times "pragma omp ordered" 1 "original" } } +! { dg-final { scan-tree-dump-times "pragma omp master" 1 "original" } } +! { dg-final { scan-tree-dump-times "__builtin_GOMP" 5 "original" } } +! { dg-final { scan-tree-dump-times "__builtin_GOMP_barrier" 1 "original" } } +! { dg-final { scan-tree-dump-times "__builtin_GOMP_cancellation_point" 1 "original" } } +! Includes the above cancellation point +! { dg-final { scan-tree-dump-times "__builtin_GOMP_cancel" 2 "original" } } +! { dg-final { scan-tree-dump-times "__builtin_GOMP_taskyield" 1 "original" } } +! { dg-final { scan-tree-dump-times "__builtin_GOMP_taskwait" 1 "original" } } +! { dg-final { cleanup-tree-dump "original" } } diff --git a/gcc/testsuite/gfortran.dg/gomp/proc_ptr_2.f90 b/gcc/testsuite/gfortran.dg/gomp/proc_ptr_2.f90 new file mode 100644 index 00000000000..d993429a76f --- /dev/null +++ b/gcc/testsuite/gfortran.dg/gomp/proc_ptr_2.f90 @@ -0,0 +1,14 @@ +! { dg-do compile } + procedure(foo), pointer :: ptr + integer :: i + ptr => foo +!$omp do reduction (+ : ptr) ! { dg-error "Procedure pointer|not found" } + do i = 1, 10 + end do +!$omp simd linear (ptr) ! { dg-error "must be INTEGER" } + do i = 1, 10 + end do +contains + subroutine foo + end subroutine +end |