aboutsummaryrefslogtreecommitdiff
path: root/gcc/fortran
diff options
context:
space:
mode:
authorThomas Schwinge <thomas@codesourcery.com>2023-02-12 16:26:22 +0100
committerThomas Schwinge <thomas@codesourcery.com>2023-02-12 16:26:22 +0100
commitab1305234f566eb2bc3a7c9d020a2dd11948a754 (patch)
tree2d980847eca3a0d7f27fc3ccb5e20aa5de2ae040 /gcc/fortran
parent09e9d996b0a7f12b713807b5d166a014c392b0a2 (diff)
parent32582c190b91287a0d1239162333f5ad0ac81e72 (diff)
downloadgcc-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/ChangeLog13
-rw-r--r--gcc/fortran/gfortran.h30
-rw-r--r--gcc/fortran/openmp.cc109
-rw-r--r--gcc/fortran/trans-openmp.cc37
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];