diff options
author | Thomas Schwinge <thomas@codesourcery.com> | 2023-02-12 16:26:22 +0100 |
---|---|---|
committer | Thomas Schwinge <thomas@codesourcery.com> | 2023-02-12 16:26:22 +0100 |
commit | ab1305234f566eb2bc3a7c9d020a2dd11948a754 (patch) | |
tree | 2d980847eca3a0d7f27fc3ccb5e20aa5de2ae040 /gcc/fortran | |
parent | 09e9d996b0a7f12b713807b5d166a014c392b0a2 (diff) | |
parent | 32582c190b91287a0d1239162333f5ad0ac81e72 (diff) | |
download | gcc-ab1305234f566eb2bc3a7c9d020a2dd11948a754.zip gcc-ab1305234f566eb2bc3a7c9d020a2dd11948a754.tar.gz gcc-ab1305234f566eb2bc3a7c9d020a2dd11948a754.tar.bz2 |
Merge commit '9cf9f3c7629d768d940d9f87cddcd616bb0449e0^' into HEAD
Diffstat (limited to 'gcc/fortran')
-rw-r--r-- | gcc/fortran/ChangeLog | 13 | ||||
-rw-r--r-- | gcc/fortran/gfortran.h | 30 | ||||
-rw-r--r-- | gcc/fortran/openmp.cc | 109 | ||||
-rw-r--r-- | gcc/fortran/trans-openmp.cc | 37 |
4 files changed, 161 insertions, 28 deletions
diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog index cbb0ecf..ed728eb 100644 --- a/gcc/fortran/ChangeLog +++ b/gcc/fortran/ChangeLog @@ -1,3 +1,16 @@ +2022-12-14 Julian Brown <julian@codesourcery.com> + + PR fortran/107214 + * gfortran.h (gfc_symbol): Add data_mark, dev_mark, gen_mark and + reduc_mark bitfields. + * openmp.cc (resolve_omp_clauses): Use above bitfields to improve + duplicate clause detection. + +2022-12-14 Julian Brown <julian@codesourcery.com> + + * trans-openmp.cc (gfc_add_firstprivate_if_unmapped): New function. + (gfc_split_omp_clauses): Call above. + 2022-12-13 Steve Kargl <kargl@gcc.gnu.org> PR fortran/107423 diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h index 5f8a81a..219ef8c 100644 --- a/gcc/fortran/gfortran.h +++ b/gcc/fortran/gfortran.h @@ -1871,22 +1871,34 @@ typedef struct gfc_symbol gfc_namelist *namelist, *namelist_tail; + /* The tlink field is used in the front end to carry the module + declaration of separate module procedures so that the characteristics + can be compared with the corresponding declaration in a submodule. In + translation this field carries a linked list of symbols that require + deferred initialization. */ + struct gfc_symbol *tlink; + /* Change management fields. Symbols that might be modified by the current statement have the mark member nonzero. Of these symbols, symbols with old_symbol equal to NULL are symbols created within the current statement. Otherwise, old_symbol points to a copy of the old symbol. gfc_new is used in symbol.cc to flag new symbols. comp_mark is used to indicate variables which have component accesses - in OpenMP/OpenACC directive clauses. */ + in OpenMP/OpenACC directive clauses (cf. c-typeck.cc:c_finish_omp_clauses, + map_field_head). + data_mark is used to check duplicate mappings for OpenMP data-sharing + clauses (see firstprivate_head/lastprivate_head in the above function). + dev_mark is used to check duplicate mappings for OpenMP + is_device_ptr/has_device_addr clauses (see is_on_device_head in above + function). + gen_mark is used to check duplicate mappings for OpenMP + use_device_ptr/use_device_addr/private/shared clauses (see generic_head in + above functon). + reduc_mark is used to check duplicate mappings for OpenMP reduction + clauses. */ struct gfc_symbol *old_symbol; - unsigned mark:1, comp_mark:1, gfc_new:1; - - /* The tlink field is used in the front end to carry the module - declaration of separate module procedures so that the characteristics - can be compared with the corresponding declaration in a submodule. In - translation this field carries a linked list of symbols that require - deferred initialization. */ - struct gfc_symbol *tlink; + unsigned mark:1, comp_mark:1, data_mark:1, dev_mark:1, gen_mark:1; + unsigned reduc_mark:1, gfc_new:1; /* Nonzero if all equivalences associated with this symbol have been processed. */ diff --git a/gcc/fortran/openmp.cc b/gcc/fortran/openmp.cc index 686f924..b71ee46 100644 --- a/gcc/fortran/openmp.cc +++ b/gcc/fortran/openmp.cc @@ -7150,6 +7150,10 @@ resolve_omp_clauses (gfc_code *code, gfc_omp_clauses *omp_clauses, continue; n->sym->mark = 0; n->sym->comp_mark = 0; + n->sym->data_mark = 0; + n->sym->dev_mark = 0; + n->sym->gen_mark = 0; + n->sym->reduc_mark = 0; if (n->sym->attr.flavor == FL_VARIABLE || n->sym->attr.proc_pointer || (!code && (!n->sym->attr.dummy || n->sym->ns != ns))) @@ -7218,14 +7222,9 @@ resolve_omp_clauses (gfc_code *code, gfc_omp_clauses *omp_clauses, && list != OMP_LIST_LASTPRIVATE && list != OMP_LIST_ALIGNED && list != OMP_LIST_DEPEND - && (list != OMP_LIST_MAP || openacc) && list != OMP_LIST_FROM && list != OMP_LIST_TO && (list != OMP_LIST_REDUCTION || !openacc) - && list != OMP_LIST_REDUCTION_INSCAN - && list != OMP_LIST_REDUCTION_TASK - && list != OMP_LIST_IN_REDUCTION - && list != OMP_LIST_TASK_REDUCTION && list != OMP_LIST_ALLOCATE) for (n = omp_clauses->lists[list]; n; n = n->next) { @@ -7237,10 +7236,58 @@ resolve_omp_clauses (gfc_code *code, gfc_omp_clauses *omp_clauses, for (gfc_ref *ref = n->expr->ref; ref; ref = ref->next) if (ref->type == REF_COMPONENT) component_ref_p = true; - if ((!component_ref_p && n->sym->comp_mark) - || (component_ref_p && n->sym->mark)) - gfc_error ("Symbol %qs has mixed component and non-component " - "accesses at %L", n->sym->name, &n->where); + if ((list == OMP_LIST_IS_DEVICE_PTR + || list == OMP_LIST_HAS_DEVICE_ADDR) + && !component_ref_p) + { + if (n->sym->gen_mark + || n->sym->dev_mark + || n->sym->reduc_mark + || n->sym->mark) + gfc_error ("Symbol %qs present on multiple clauses at %L", + n->sym->name, &n->where); + else + n->sym->dev_mark = 1; + } + else if ((list == OMP_LIST_USE_DEVICE_PTR + || list == OMP_LIST_USE_DEVICE_ADDR + || list == OMP_LIST_PRIVATE + || list == OMP_LIST_SHARED) + && !component_ref_p) + { + if (n->sym->gen_mark || n->sym->dev_mark || n->sym->reduc_mark) + gfc_error ("Symbol %qs present on multiple clauses at %L", + n->sym->name, &n->where); + else + { + n->sym->gen_mark = 1; + /* Set both generic and device bits if we have + use_device_*(x) or shared(x). This allows us to diagnose + "map(x) private(x)" below. */ + if (list != OMP_LIST_PRIVATE) + n->sym->dev_mark = 1; + } + } + else if ((list == OMP_LIST_REDUCTION + || list == OMP_LIST_REDUCTION_TASK + || list == OMP_LIST_REDUCTION_INSCAN + || list == OMP_LIST_IN_REDUCTION + || list == OMP_LIST_TASK_REDUCTION) + && !component_ref_p) + { + /* Attempts to mix reduction types are diagnosed below. */ + if (n->sym->gen_mark || n->sym->dev_mark) + gfc_error ("Symbol %qs present on multiple clauses at %L", + n->sym->name, &n->where); + n->sym->reduc_mark = 1; + } + else if ((!component_ref_p && n->sym->comp_mark) + || (component_ref_p && n->sym->mark)) + { + if (openacc) + gfc_error ("Symbol %qs has mixed component and non-component " + "accesses at %L", n->sym->name, &n->where); + } else if (n->sym->mark) gfc_error ("Symbol %qs present on multiple clauses at %L", n->sym->name, &n->where); @@ -7253,34 +7300,62 @@ resolve_omp_clauses (gfc_code *code, gfc_omp_clauses *omp_clauses, } } + /* Detect specifically the case where we have "map(x) private(x)" and raise + an error. If we have "...simd" combined directives though, the "private" + applies to the simd part, so this is permitted though. */ + for (n = omp_clauses->lists[OMP_LIST_PRIVATE]; n; n = n->next) + if (n->sym->mark + && n->sym->gen_mark + && !n->sym->dev_mark + && !n->sym->reduc_mark + && code->op != EXEC_OMP_TARGET_SIMD + && code->op != EXEC_OMP_TARGET_PARALLEL_DO_SIMD + && code->op != EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD + && code->op != EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD) + gfc_error ("Symbol %qs present on multiple clauses at %L", + n->sym->name, &n->where); + gcc_assert (OMP_LIST_LASTPRIVATE == OMP_LIST_FIRSTPRIVATE + 1); for (list = OMP_LIST_FIRSTPRIVATE; list <= OMP_LIST_LASTPRIVATE; list++) for (n = omp_clauses->lists[list]; n; n = n->next) - if (n->sym->mark) + if (n->sym->data_mark || n->sym->gen_mark || n->sym->dev_mark) { gfc_error ("Symbol %qs present on multiple clauses at %L", n->sym->name, &n->where); - n->sym->mark = 0; - } + n->sym->data_mark = n->sym->gen_mark = n->sym->dev_mark = 0; + } + else if (n->sym->mark + && code->op != EXEC_OMP_TARGET_TEAMS + && code->op != EXEC_OMP_TARGET_TEAMS_DISTRIBUTE + && code->op != EXEC_OMP_TARGET_TEAMS_LOOP + && code->op != EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD + && code->op != EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO + && code->op != EXEC_OMP_TARGET_PARALLEL + && code->op != EXEC_OMP_TARGET_PARALLEL_DO + && code->op != EXEC_OMP_TARGET_PARALLEL_LOOP + && code->op != EXEC_OMP_TARGET_PARALLEL_DO_SIMD + && code->op != EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD) + gfc_error ("Symbol %qs present on both data and map clauses " + "at %L", n->sym->name, &n->where); for (n = omp_clauses->lists[OMP_LIST_FIRSTPRIVATE]; n; n = n->next) { - if (n->sym->mark) + if (n->sym->data_mark || n->sym->gen_mark || n->sym->dev_mark) gfc_error ("Symbol %qs present on multiple clauses at %L", n->sym->name, &n->where); else - n->sym->mark = 1; + n->sym->data_mark = 1; } for (n = omp_clauses->lists[OMP_LIST_LASTPRIVATE]; n; n = n->next) - n->sym->mark = 0; + n->sym->data_mark = 0; for (n = omp_clauses->lists[OMP_LIST_LASTPRIVATE]; n; n = n->next) { - if (n->sym->mark) + if (n->sym->data_mark || n->sym->gen_mark || n->sym->dev_mark) gfc_error ("Symbol %qs present on multiple clauses at %L", n->sym->name, &n->where); else - n->sym->mark = 1; + n->sym->data_mark = 1; } for (n = omp_clauses->lists[OMP_LIST_ALIGNED]; n; n = n->next) diff --git a/gcc/fortran/trans-openmp.cc b/gcc/fortran/trans-openmp.cc index 7a4a339..395bcc9 100644 --- a/gcc/fortran/trans-openmp.cc +++ b/gcc/fortran/trans-openmp.cc @@ -5968,6 +5968,39 @@ gfc_add_clause_implicitly (gfc_omp_clauses *clauses_out, } } +/* Kind of opposite to above, add firstprivate to CLAUSES_OUT if it is mapped + in CLAUSES_IN's FIRSTPRIVATE list but not its MAP list. */ + +static void +gfc_add_firstprivate_if_unmapped (gfc_omp_clauses *clauses_out, + gfc_omp_clauses *clauses_in) +{ + gfc_omp_namelist *n = clauses_in->lists[OMP_LIST_FIRSTPRIVATE]; + gfc_omp_namelist **tail = NULL; + + for (; n != NULL; n = n->next) + { + gfc_omp_namelist *n2 = clauses_out->lists[OMP_LIST_MAP]; + for (; n2 != NULL; n2 = n2->next) + if (n->sym == n2->sym) + break; + if (n2 == NULL) + { + gfc_omp_namelist *dup = gfc_get_omp_namelist (); + *dup = *n; + dup->next = NULL; + if (!tail) + { + tail = &clauses_out->lists[OMP_LIST_FIRSTPRIVATE]; + while (*tail && (*tail)->next) + tail = &(*tail)->next; + } + *tail = dup; + tail = &(*tail)->next; + } + } +} + static void gfc_free_split_omp_clauses (gfc_code *code, gfc_omp_clauses *clausesa) { @@ -6351,8 +6384,8 @@ gfc_split_omp_clauses (gfc_code *code, simd and masked/master. Put it on the outermost of those and duplicate on parallel and teams. */ if (mask & GFC_OMP_MASK_TARGET) - clausesa[GFC_OMP_SPLIT_TARGET].lists[OMP_LIST_FIRSTPRIVATE] - = code->ext.omp_clauses->lists[OMP_LIST_FIRSTPRIVATE]; + gfc_add_firstprivate_if_unmapped (&clausesa[GFC_OMP_SPLIT_TARGET], + code->ext.omp_clauses); if (mask & GFC_OMP_MASK_TEAMS) clausesa[GFC_OMP_SPLIT_TEAMS].lists[OMP_LIST_FIRSTPRIVATE] = code->ext.omp_clauses->lists[OMP_LIST_FIRSTPRIVATE]; |