{
/* 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;
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);
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;
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);
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);
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));
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);
/* 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
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;
}
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))
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:
--- /dev/null
+/* 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;
+}
#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. */
#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. */
#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)
#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) \