aboutsummaryrefslogtreecommitdiff
path: root/gcc/fortran/trans-openmp.cc
diff options
context:
space:
mode:
authorJulian Brown <julian@codesourcery.com>2022-12-06 12:18:33 +0000
committerJulian Brown <julian@codesourcery.com>2022-12-14 14:11:45 +0000
commit9316ad3b4354cbf2980f86902e54884e918c472a (patch)
treecb5a59f6ed70616e18e38d1036166ffa79b5283e /gcc/fortran/trans-openmp.cc
parent881c6cabce5d0b27285ed41bd6dabdf48848cce7 (diff)
downloadgcc-9316ad3b4354cbf2980f86902e54884e918c472a.zip
gcc-9316ad3b4354cbf2980f86902e54884e918c472a.tar.gz
gcc-9316ad3b4354cbf2980f86902e54884e918c472a.tar.bz2
OpenMP/Fortran: Combined directives with map/firstprivate of same symbol
This patch fixes a case where a combined directive (e.g. "!$omp target parallel ...") contains both a map and a firstprivate clause for the same variable. When the combined directive is split into two nested directives, the outer "target" gets the "map" clause, and the inner "parallel" gets the "firstprivate" clause, like so: !$omp target parallel map(x) firstprivate(x) --> !$omp target map(x) !$omp parallel firstprivate(x) ... When there is no map of the same variable, the firstprivate is distributed to both directives, e.g. for 'y' in: !$omp target parallel map(x) firstprivate(y) --> !$omp target map(x) firstprivate(y) !$omp parallel firstprivate(y) ... This is not a recent regression, but appear to fix a long-standing ICE. (The included testcase is based on one by Tobias.) 2022-12-06 Julian Brown <julian@codesourcery.com> gcc/fortran/ * trans-openmp.cc (gfc_add_firstprivate_if_unmapped): New function. (gfc_split_omp_clauses): Call above. libgomp/ * testsuite/libgomp.fortran/combined-directive-splitting-1.f90: New test.
Diffstat (limited to 'gcc/fortran/trans-openmp.cc')
-rw-r--r--gcc/fortran/trans-openmp.cc37
1 files changed, 35 insertions, 2 deletions
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];