Hi! If we add shared (FRAME.NN) clause to some parallel/task OpenMP construct or map (tofrom: FRAME.NN) clause to some target construct, we need to add one of those to all outer parallel/task/target constructs too.
Fixed thusly, bootstrapped/regtested on x86_64-linux and i686-linux, committed to trunk, queued for backporting. 2016-11-28 Jakub Jelinek <ja...@redhat.com> PR fortran/78298 * tree-nested.c (convert_local_reference_stmt): After adding shared (FRAME.NN) clause to omp parallel, task or target, add it also to all outer omp parallel, task or target constructs. * gfortran.dg/gomp/pr78298.f90: New test. --- gcc/tree-nested.c.jj 2016-10-31 13:28:12.000000000 +0100 +++ gcc/tree-nested.c 2016-11-28 15:00:08.755214563 +0100 @@ -2083,6 +2083,8 @@ convert_local_reference_stmt (gimple_stm struct nesting_info *info = (struct nesting_info *) wi->info; tree save_local_var_chain; bitmap save_suppress; + char save_static_chain_added; + bool frame_decl_added; gimple *stmt = gsi_stmt (*gsi); switch (gimple_code (stmt)) @@ -2090,29 +2092,44 @@ convert_local_reference_stmt (gimple_stm case GIMPLE_OMP_PARALLEL: case GIMPLE_OMP_TASK: save_suppress = info->suppress_expansion; + frame_decl_added = false; if (convert_local_omp_clauses (gimple_omp_taskreg_clauses_ptr (stmt), wi)) { - tree c; + tree c = build_omp_clause (gimple_location (stmt), + OMP_CLAUSE_SHARED); (void) get_frame_type (info); - c = build_omp_clause (gimple_location (stmt), - OMP_CLAUSE_SHARED); OMP_CLAUSE_DECL (c) = info->frame_decl; OMP_CLAUSE_CHAIN (c) = gimple_omp_taskreg_clauses (stmt); gimple_omp_taskreg_set_clauses (stmt, c); + info->static_chain_added |= 4; + frame_decl_added = true; } save_local_var_chain = info->new_local_var_chain; + save_static_chain_added = info->static_chain_added; info->new_local_var_chain = NULL; + info->static_chain_added = 0; walk_body (convert_local_reference_stmt, convert_local_reference_op, info, gimple_omp_body_ptr (stmt)); + if ((info->static_chain_added & 4) != 0 && !frame_decl_added) + { + tree c = build_omp_clause (gimple_location (stmt), + OMP_CLAUSE_SHARED); + (void) get_frame_type (info); + OMP_CLAUSE_DECL (c) = info->frame_decl; + OMP_CLAUSE_CHAIN (c) = gimple_omp_taskreg_clauses (stmt); + info->static_chain_added |= 4; + gimple_omp_taskreg_set_clauses (stmt, c); + } if (info->new_local_var_chain) declare_vars (info->new_local_var_chain, gimple_seq_first_stmt (gimple_omp_body (stmt)), false); info->new_local_var_chain = save_local_var_chain; info->suppress_expansion = save_suppress; + info->static_chain_added |= save_static_chain_added; break; case GIMPLE_OMP_FOR: @@ -2153,29 +2170,46 @@ convert_local_reference_stmt (gimple_stm break; } save_suppress = info->suppress_expansion; + frame_decl_added = false; if (convert_local_omp_clauses (gimple_omp_target_clauses_ptr (stmt), wi)) { - tree c; + tree c = build_omp_clause (gimple_location (stmt), OMP_CLAUSE_MAP); (void) get_frame_type (info); - c = build_omp_clause (gimple_location (stmt), OMP_CLAUSE_MAP); OMP_CLAUSE_DECL (c) = info->frame_decl; OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_TOFROM); OMP_CLAUSE_SIZE (c) = DECL_SIZE_UNIT (info->frame_decl); OMP_CLAUSE_CHAIN (c) = gimple_omp_target_clauses (stmt); gimple_omp_target_set_clauses (as_a <gomp_target *> (stmt), c); + info->static_chain_added |= 4; + frame_decl_added = true; } save_local_var_chain = info->new_local_var_chain; + save_static_chain_added = info->static_chain_added; info->new_local_var_chain = NULL; + info->static_chain_added = 0; walk_body (convert_local_reference_stmt, convert_local_reference_op, info, gimple_omp_body_ptr (stmt)); + if ((info->static_chain_added & 4) != 0 && !frame_decl_added) + { + tree c = build_omp_clause (gimple_location (stmt), OMP_CLAUSE_MAP); + (void) get_frame_type (info); + OMP_CLAUSE_DECL (c) = info->frame_decl; + OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_TOFROM); + OMP_CLAUSE_SIZE (c) = DECL_SIZE_UNIT (info->frame_decl); + OMP_CLAUSE_CHAIN (c) = gimple_omp_target_clauses (stmt); + gimple_omp_target_set_clauses (as_a <gomp_target *> (stmt), c); + info->static_chain_added |= 4; + } + if (info->new_local_var_chain) declare_vars (info->new_local_var_chain, gimple_seq_first_stmt (gimple_omp_body (stmt)), false); info->new_local_var_chain = save_local_var_chain; info->suppress_expansion = save_suppress; + info->static_chain_added |= save_static_chain_added; break; case GIMPLE_OMP_TEAMS: --- gcc/testsuite/gfortran.dg/gomp/pr78298.f90.jj 2016-11-28 15:11:30.905546859 +0100 +++ gcc/testsuite/gfortran.dg/gomp/pr78298.f90 2016-11-28 15:12:22.861887658 +0100 @@ -0,0 +1,28 @@ +! PR fortran/78298 +! { dg-do compile } +! { dg-additional-options "-O2" } + +program pr78298 + integer :: i, j, n + n = 2 + !$omp parallel + !$omp do + do i = 1, n + !$omp parallel + !$omp do + do j = 1, n + call sub(i) + end do + !$omp end parallel + end do + !$omp end parallel + !call unused() +contains + subroutine sub(x) + integer :: x + end + subroutine unused() + i = 0 + j = 0 + end +end Jakub