aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/c-family/c-omp.c11
-rw-r--r--gcc/c/c-typeck.c27
-rw-r--r--gcc/cp/semantics.c27
-rw-r--r--gcc/gimplify.c45
-rw-r--r--gcc/testsuite/c-c++-common/gomp/pr99928-15.c26
-rw-r--r--gcc/testsuite/c-c++-common/gomp/pr99928-3.c12
-rw-r--r--gcc/tree.h5
7 files changed, 140 insertions, 13 deletions
diff --git a/gcc/c-family/c-omp.c b/gcc/c-family/c-omp.c
index fb1a0d6..0945a1e 100644
--- a/gcc/c-family/c-omp.c
+++ b/gcc/c-family/c-omp.c
@@ -1733,10 +1733,21 @@ c_omp_split_clauses (location_t loc, enum tree_code code,
{
/* This must be #pragma omp target simd. */
s = C_OMP_CLAUSE_SPLIT_TARGET;
+ OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (clauses) = 1;
+ OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT_TARGET (clauses) = 1;
break;
}
c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
OMP_CLAUSE_FIRSTPRIVATE);
+ /* firstprivate should not be applied to target if it is
+ also lastprivate or on the combined/composite construct,
+ or if it is mentioned in map clause. OMP_CLAUSE_DECLs
+ may need to go through FE handling though (instantiation,
+ C++ non-static data members, array section lowering), so
+ add the clause with OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT and
+ let *finish_omp_clauses and the gimplifier handle it
+ right. */
+ OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (c) = 1;
OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clauses);
OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_TARGET];
cclauses[C_OMP_CLAUSE_SPLIT_TARGET] = c;
diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c
index c3b85da..fc64ef9 100644
--- a/gcc/c/c-typeck.c
+++ b/gcc/c/c-typeck.c
@@ -13936,6 +13936,7 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
has been seen, -2 if mixed inscan/normal reduction diagnosed. */
int reduction_seen = 0;
bool allocate_seen = false;
+ bool firstprivate_implicit_moved = false;
bitmap_obstack_initialize (NULL);
bitmap_initialize (&generic_head, &bitmap_default_obstack);
@@ -14377,6 +14378,29 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
break;
case OMP_CLAUSE_FIRSTPRIVATE:
+ if (OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (c)
+ && !firstprivate_implicit_moved)
+ {
+ firstprivate_implicit_moved = true;
+ /* Move firstprivate clauses with
+ OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT set to the end of
+ clauses chain. */
+ tree cl = NULL, *pc1 = pc, *pc2 = &cl;
+ while (*pc1)
+ if (OMP_CLAUSE_CODE (*pc1) == OMP_CLAUSE_FIRSTPRIVATE
+ && OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (*pc1))
+ {
+ *pc2 = *pc1;
+ pc2 = &OMP_CLAUSE_CHAIN (*pc2);
+ *pc1 = OMP_CLAUSE_CHAIN (*pc1);
+ }
+ else
+ pc1 = &OMP_CLAUSE_CHAIN (*pc1);
+ *pc2 = NULL;
+ *pc1 = cl;
+ if (pc1 != pc)
+ continue;
+ }
t = OMP_CLAUSE_DECL (c);
need_complete = true;
need_implicitly_determined = true;
@@ -14398,6 +14422,9 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
if (ort == C_ORT_ACC)
error_at (OMP_CLAUSE_LOCATION (c),
"%qD appears more than once in data clauses", t);
+ else if (OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (c)
+ && !OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT_TARGET (c))
+ /* Silently drop the clause. */;
else
error_at (OMP_CLAUSE_LOCATION (c),
"%qD appears both in data and map clauses", t);
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 0d590c3..fffbe40 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -6519,6 +6519,7 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
bool allocate_seen = false;
tree detach_seen = NULL_TREE;
bool mergeable_seen = false;
+ bool firstprivate_implicit_moved = false;
bitmap_obstack_initialize (NULL);
bitmap_initialize (&generic_head, &bitmap_default_obstack);
@@ -6843,6 +6844,29 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
break;
case OMP_CLAUSE_FIRSTPRIVATE:
+ if (OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (c)
+ && !firstprivate_implicit_moved)
+ {
+ firstprivate_implicit_moved = true;
+ /* Move firstprivate clauses with
+ OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT set to the end of
+ clauses chain. */
+ tree cl = NULL, *pc1 = pc, *pc2 = &cl;
+ while (*pc1)
+ if (OMP_CLAUSE_CODE (*pc1) == OMP_CLAUSE_FIRSTPRIVATE
+ && OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (*pc1))
+ {
+ *pc2 = *pc1;
+ pc2 = &OMP_CLAUSE_CHAIN (*pc2);
+ *pc1 = OMP_CLAUSE_CHAIN (*pc1);
+ }
+ else
+ pc1 = &OMP_CLAUSE_CHAIN (*pc1);
+ *pc2 = NULL;
+ *pc1 = cl;
+ if (pc1 != pc)
+ continue;
+ }
t = omp_clause_decl_field (OMP_CLAUSE_DECL (c));
if (t)
omp_note_field_privatization (t, OMP_CLAUSE_DECL (c));
@@ -6884,6 +6908,9 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
if (ort == C_ORT_ACC)
error_at (OMP_CLAUSE_LOCATION (c),
"%qD appears more than once in data clauses", t);
+ else if (OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (c)
+ && !OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT_TARGET (c))
+ /* Silently drop the clause. */;
else
error_at (OMP_CLAUSE_LOCATION (c),
"%qD appears both in data and map clauses", t);
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index 28bf1b0..b62ea0e 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -126,7 +126,10 @@ enum gimplify_omp_var_data
/* Flag for GOVD_MAP: (struct) vars that have pointer attachments for
fields. */
- GOVD_MAP_HAS_ATTACHMENTS = 8388608,
+ GOVD_MAP_HAS_ATTACHMENTS = 0x4000000,
+
+ /* Flag for GOVD_FIRSTPRIVATE: OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT. */
+ GOVD_FIRSTPRIVATE_IMPLICIT = 0x8000000,
GOVD_DATA_SHARE_CLASS = (GOVD_SHARED | GOVD_PRIVATE | GOVD_FIRSTPRIVATE
| GOVD_LASTPRIVATE | GOVD_REDUCTION | GOVD_LINEAR
@@ -8586,13 +8589,24 @@ omp_lastprivate_for_combined_outer_constructs (struct gimplify_omp_ctx *octx,
omp_add_variable (octx, decl, GOVD_LASTPRIVATE | GOVD_SEEN);
continue;
}
- if (octx->region_type == ORT_COMBINED_TARGET
- && splay_tree_lookup (octx->variables,
- (splay_tree_key) decl) == NULL)
+ if (octx->region_type == ORT_COMBINED_TARGET)
{
- omp_add_variable (octx, decl, GOVD_MAP | GOVD_SEEN);
- octx = octx->outer_context;
- break;
+ splay_tree_node n = splay_tree_lookup (octx->variables,
+ (splay_tree_key) decl);
+ if (n == NULL)
+ {
+ omp_add_variable (octx, decl, GOVD_MAP | GOVD_SEEN);
+ octx = octx->outer_context;
+ }
+ else if (!implicit_p
+ && (n->value & GOVD_FIRSTPRIVATE_IMPLICIT))
+ {
+ n->value &= ~(GOVD_FIRSTPRIVATE
+ | GOVD_FIRSTPRIVATE_IMPLICIT
+ | GOVD_EXPLICIT);
+ omp_add_variable (octx, decl, GOVD_MAP | GOVD_SEEN);
+ octx = octx->outer_context;
+ }
}
break;
}
@@ -8673,6 +8687,11 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
case OMP_CLAUSE_FIRSTPRIVATE:
flags = GOVD_FIRSTPRIVATE | GOVD_EXPLICIT;
check_non_private = "firstprivate";
+ if (OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (c))
+ {
+ gcc_assert (code == OMP_TARGET);
+ flags |= GOVD_FIRSTPRIVATE_IMPLICIT;
+ }
goto do_add;
case OMP_CLAUSE_LASTPRIVATE:
if (OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c))
@@ -10532,6 +10551,18 @@ gimplify_adjust_omp_clauses (gimple_seq *pre_p, gimple_seq body, tree *list_p,
remove = true;
break;
}
+ if (OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (c))
+ {
+ decl = OMP_CLAUSE_DECL (c);
+ n = splay_tree_lookup (ctx->variables, (splay_tree_key) decl);
+ if ((n->value & GOVD_MAP) != 0)
+ {
+ remove = true;
+ break;
+ }
+ OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT_TARGET (c) = 0;
+ OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (c) = 0;
+ }
/* FALLTHRU */
case OMP_CLAUSE_PRIVATE:
case OMP_CLAUSE_SHARED:
diff --git a/gcc/testsuite/c-c++-common/gomp/pr99928-15.c b/gcc/testsuite/c-c++-common/gomp/pr99928-15.c
new file mode 100644
index 0000000..f0c6232
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/pr99928-15.c
@@ -0,0 +1,26 @@
+/* PR middle-end/99928 */
+
+int v;
+
+void
+foo (void)
+{
+ #pragma omp target parallel firstprivate (v) map(tofrom: v) /* { dg-bogus "'v' appears both in data and map clauses" } */
+ v++;
+}
+
+void
+bar (void)
+{
+ #pragma omp target firstprivate (v) map (tofrom: v) /* { dg-error "'v' appears both in data and map clauses" } */
+ v++;
+}
+
+void
+baz (void)
+{
+ int j;
+ #pragma omp target simd firstprivate (v) map (tofrom: v) private (j) /* { dg-error "'v' appears both in data and map clauses" } */
+ for (int i = 0; i < 1; i++)
+ j = v;
+}
diff --git a/gcc/testsuite/c-c++-common/gomp/pr99928-3.c b/gcc/testsuite/c-c++-common/gomp/pr99928-3.c
index 67f590b..cf9c72d 100644
--- a/gcc/testsuite/c-c++-common/gomp/pr99928-3.c
+++ b/gcc/testsuite/c-c++-common/gomp/pr99928-3.c
@@ -82,8 +82,8 @@ bar (void)
#pragma omp section
l07 = 2;
}
- /* { dg-final { scan-tree-dump "omp target\[^\n\r]*map\\(tofrom:l08" "gimple" { xfail *-*-* } } } */
- /* { dg-final { scan-tree-dump-not "omp target\[^\n\r]*firstprivate\\(l08\\)" "gimple" { xfail *-*-* } } } */
+ /* { dg-final { scan-tree-dump "omp target\[^\n\r]*map\\(tofrom:l08" "gimple" } } */
+ /* { dg-final { scan-tree-dump-not "omp target\[^\n\r]*firstprivate\\(l08\\)" "gimple" } } */
/* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*firstprivate\\(l08\\)" "gimple" } } *//* FIXME: This should be on for instead. */
/* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*lastprivate\\(l08\\)" "gimple" } } *//* FIXME: This should be on for instead. */
/* { dg-final { scan-tree-dump-not "omp for\[^\n\r]*firstprivate\\(l08\\)" "gimple" } } *//* FIXME. */
@@ -91,8 +91,8 @@ bar (void)
#pragma omp target parallel for firstprivate (l08) lastprivate (l08)
for (int i = 0; i < 64; i++)
l08 = i;
- /* { dg-final { scan-tree-dump "omp target\[^\n\r]*map\\(tofrom:l09" "gimple" { xfail *-*-* } } } */
- /* { dg-final { scan-tree-dump-not "omp target\[^\n\r]*firstprivate\\(l09\\)" "gimple" { xfail *-*-* } } } */
+ /* { dg-final { scan-tree-dump "omp target\[^\n\r]*map\\(tofrom:l09" "gimple" } } */
+ /* { dg-final { scan-tree-dump-not "omp target\[^\n\r]*firstprivate\\(l09\\)" "gimple" } } */
/* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*firstprivate\\(l09\\)" "gimple" } } *//* FIXME: This should be on for instead. */
/* { dg-final { scan-tree-dump "omp parallel\[^\n\r]*lastprivate\\(l09\\)" "gimple" } } *//* FIXME: This should be on for instead. */
/* { dg-final { scan-tree-dump-not "omp for\[^\n\r]*firstprivate\\(l09\\)" "gimple" } } *//* FIXME. */
@@ -102,8 +102,8 @@ bar (void)
#pragma omp target parallel for simd firstprivate (l09) lastprivate (l09)
for (int i = 0; i < 64; i++)
l09 = i;
- /* { dg-final { scan-tree-dump "omp target\[^\n\r]*map\\(tofrom:l10" "gimple" { xfail *-*-* } } } */
- /* { dg-final { scan-tree-dump-not "omp target\[^\n\r]*firstprivate\\(l10\\)" "gimple" { xfail *-*-* } } } */
+ /* { dg-final { scan-tree-dump "omp target\[^\n\r]*map\\(tofrom:l10" "gimple" } } */
+ /* { dg-final { scan-tree-dump-not "omp target\[^\n\r]*firstprivate\\(l10\\)" "gimple" } } */
/* { dg-final { scan-tree-dump-not "omp simd\[^\n\r]*firstprivate\\(l10\\)" "gimple" } } */
/* { dg-final { scan-tree-dump "omp simd\[^\n\r]*lastprivate\\(l10\\)" "gimple" } } */
#pragma omp target simd firstprivate (l10) lastprivate (l10)
diff --git a/gcc/tree.h b/gcc/tree.h
index 64612cf..37aca89 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -1538,6 +1538,11 @@ class auto_suppress_location_wrappers
#define OMP_CLAUSE_FIRSTPRIVATE_NO_REFERENCE(NODE) \
TREE_PRIVATE (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_FIRSTPRIVATE))
+/* True on a FIRSTPRIVATE clause with OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT also
+ set if target construct is the only one that accepts the clause. */
+#define OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT_TARGET(NODE) \
+ TREE_PROTECTED (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_FIRSTPRIVATE))
+
/* True on a LASTPRIVATE clause if a FIRSTPRIVATE clause for the same
decl is present in the chain. */
#define OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE(NODE) \