@@ -345,6 +345,9 @@ enum omp_clause_code {
/* OpenMP clause: has_device_addr (variable-list). */
OMP_CLAUSE_HAS_DEVICE_ADDR,
+ /* OpenMP clause: doacross ({source,sink}:vec). */
+ OMP_CLAUSE_DOACROSS,
+
/* Internal structure to hold OpenACC cache directive's variable-list.
#pragma acc cache (variable-list). */
OMP_CLAUSE__CACHE_,
@@ -1525,12 +1527,18 @@ enum omp_clause_depend_kind
OMP_CLAUSE_DEPEND_INOUT,
OMP_CLAUSE_DEPEND_MUTEXINOUTSET,
OMP_CLAUSE_DEPEND_INOUTSET,
- OMP_CLAUSE_DEPEND_SOURCE,
- OMP_CLAUSE_DEPEND_SINK,
OMP_CLAUSE_DEPEND_DEPOBJ,
+ OMP_CLAUSE_DEPEND_INVALID,
OMP_CLAUSE_DEPEND_LAST
};
+enum omp_clause_doacross_kind
+{
+ OMP_CLAUSE_DOACROSS_SOURCE,
+ OMP_CLAUSE_DOACROSS_SINK,
+ OMP_CLAUSE_DOACROSS_LAST
+};
+
enum omp_clause_proc_bind_kind
{
/* Numbers should match omp_proc_bind_t enum in omp.h. */
@@ -1620,6 +1628,7 @@ struct GTY(()) tree_omp_clause {
enum omp_clause_default_kind default_kind;
enum omp_clause_schedule_kind schedule_kind;
enum omp_clause_depend_kind depend_kind;
+ enum omp_clause_doacross_kind doacross_kind;
/* See include/gomp-constants.h for enum gomp_map_kind's values. */
unsigned int map_kind;
enum omp_clause_proc_bind_kind proc_bind_kind;
@@ -1722,9 +1722,16 @@ class auto_suppress_location_wrappers
#define OMP_CLAUSE_DEPEND_KIND(NODE) \
(OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_DEPEND)->omp_clause.subcode.depend_kind)
-#define OMP_CLAUSE_DEPEND_SINK_NEGATIVE(NODE) \
+#define OMP_CLAUSE_DOACROSS_KIND(NODE) \
+ (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_DOACROSS)->omp_clause.subcode.doacross_kind)
+
+#define OMP_CLAUSE_DOACROSS_SINK_NEGATIVE(NODE) \
TREE_PUBLIC (TREE_LIST_CHECK (NODE))
+/* True if DOACROSS clause is spelled as DEPEND. */
+#define OMP_CLAUSE_DOACROSS_DEPEND(NODE) \
+ TREE_PROTECTED (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_DOACROSS))
+
#define OMP_CLAUSE_MAP_KIND(NODE) \
((enum gomp_map_kind) OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_MAP)->omp_clause.subcode.map_kind)
#define OMP_CLAUSE_SET_MAP_KIND(NODE, MAP_KIND) \
@@ -1786,6 +1793,11 @@ class auto_suppress_location_wrappers
#define OMP_CLAUSE_ORDERED_EXPR(NODE) \
OMP_CLAUSE_OPERAND (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_ORDERED), 0)
+/* True on an OMP_CLAUSE_ORDERED if stand-alone ordered construct is nested
+ inside of work-sharing loop the clause is on. */
+#define OMP_CLAUSE_ORDERED_DOACROSS(NODE) \
+ (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_ORDERED)->base.public_flag)
+
/* True for unconstrained modifier on order(concurrent) clause. */
#define OMP_CLAUSE_ORDER_UNCONSTRAINED(NODE) \
(OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_ORDER)->base.public_flag)
@@ -294,6 +294,7 @@ unsigned const char omp_clause_num_ops[]
2, /* OMP_CLAUSE_TO */
2, /* OMP_CLAUSE_MAP */
1, /* OMP_CLAUSE_HAS_DEVICE_ADDR */
+ 1, /* OMP_CLAUSE_DOACROSS */
2, /* OMP_CLAUSE__CACHE_ */
2, /* OMP_CLAUSE_GANG */
1, /* OMP_CLAUSE_ASYNC */
@@ -384,6 +385,7 @@ const char * const omp_clause_code_name[
"to",
"map",
"has_device_addr",
+ "doacross",
"_cache_",
"gang",
"async",
@@ -1368,6 +1368,7 @@ convert_nonlocal_omp_clauses (tree *pcla
case OMP_CLAUSE_IF:
case OMP_CLAUSE_NUM_THREADS:
case OMP_CLAUSE_DEPEND:
+ case OMP_CLAUSE_DOACROSS:
case OMP_CLAUSE_DEVICE:
case OMP_CLAUSE_NUM_TEAMS:
case OMP_CLAUSE_THREAD_LIMIT:
@@ -2157,6 +2158,7 @@ convert_local_omp_clauses (tree *pclause
case OMP_CLAUSE_IF:
case OMP_CLAUSE_NUM_THREADS:
case OMP_CLAUSE_DEPEND:
+ case OMP_CLAUSE_DOACROSS:
case OMP_CLAUSE_DEVICE:
case OMP_CLAUSE_NUM_TEAMS:
case OMP_CLAUSE_THREAD_LIMIT:
@@ -831,34 +831,9 @@ dump_omp_clause (pretty_printer *pp, tre
case OMP_CLAUSE_DEPEND_INOUTSET:
name = "inoutset";
break;
- case OMP_CLAUSE_DEPEND_SOURCE:
- pp_string (pp, "source)");
- return;
case OMP_CLAUSE_DEPEND_LAST:
name = "__internal__";
break;
- case OMP_CLAUSE_DEPEND_SINK:
- pp_string (pp, "sink:");
- for (tree t = OMP_CLAUSE_DECL (clause); t; t = TREE_CHAIN (t))
- if (TREE_CODE (t) == TREE_LIST)
- {
- dump_generic_node (pp, TREE_VALUE (t), spc, flags, false);
- if (TREE_PURPOSE (t) != integer_zero_node)
- {
- if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (t))
- pp_minus (pp);
- else
- pp_plus (pp);
- dump_generic_node (pp, TREE_PURPOSE (t), spc, flags,
- false);
- }
- if (TREE_CHAIN (t))
- pp_comma (pp);
- }
- else
- gcc_unreachable ();
- pp_right_paren (pp);
- return;
default:
gcc_unreachable ();
}
@@ -885,6 +860,49 @@ dump_omp_clause (pretty_printer *pp, tre
}
break;
+ case OMP_CLAUSE_DOACROSS:
+ pp_string (pp, OMP_CLAUSE_DOACROSS_DEPEND (clause)
+ ? "depend(" : "doacross(");
+ switch (OMP_CLAUSE_DOACROSS_KIND (clause))
+ {
+ case OMP_CLAUSE_DOACROSS_SOURCE:
+ if (OMP_CLAUSE_DOACROSS_DEPEND (clause))
+ pp_string (pp, "source)");
+ else
+ pp_string (pp, "source:)");
+ break;
+ case OMP_CLAUSE_DOACROSS_SINK:
+ pp_string (pp, "sink:");
+ if (OMP_CLAUSE_DECL (clause) == NULL_TREE)
+ {
+ pp_string (pp, "omp_cur_iteration-1)");
+ break;
+ }
+ for (tree t = OMP_CLAUSE_DECL (clause); t; t = TREE_CHAIN (t))
+ if (TREE_CODE (t) == TREE_LIST)
+ {
+ dump_generic_node (pp, TREE_VALUE (t), spc, flags, false);
+ if (TREE_PURPOSE (t) != integer_zero_node)
+ {
+ if (OMP_CLAUSE_DOACROSS_SINK_NEGATIVE (t))
+ pp_minus (pp);
+ else
+ pp_plus (pp);
+ dump_generic_node (pp, TREE_PURPOSE (t), spc, flags,
+ false);
+ }
+ if (TREE_CHAIN (t))
+ pp_comma (pp);
+ }
+ else
+ gcc_unreachable ();
+ pp_right_paren (pp);
+ break;
+ default:
+ gcc_unreachable ();
+ }
+ break;
+
case OMP_CLAUSE_MAP:
pp_string (pp, "map(");
switch (OMP_CLAUSE_MAP_KIND (clause))
@@ -8319,9 +8319,6 @@ gimplify_omp_depend (tree *list_p, gimpl
case OMP_CLAUSE_DEPEND_INOUTSET:
i = 4;
break;
- case OMP_CLAUSE_DEPEND_SOURCE:
- case OMP_CLAUSE_DEPEND_SINK:
- continue;
default:
gcc_unreachable ();
}
@@ -8560,9 +8557,6 @@ gimplify_omp_depend (tree *list_p, gimpl
case OMP_CLAUSE_DEPEND_INOUTSET:
i = 4;
break;
- case OMP_CLAUSE_DEPEND_SOURCE:
- case OMP_CLAUSE_DEPEND_SINK:
- continue;
default:
gcc_unreachable ();
}
@@ -10406,8 +10400,8 @@ gimplify_scan_omp_clauses (tree *list_p,
gimplify_omp_affinity (list_p, pre_p);
remove = true;
break;
- case OMP_CLAUSE_DEPEND:
- if (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SINK)
+ case OMP_CLAUSE_DOACROSS:
+ if (OMP_CLAUSE_DOACROSS_KIND (c) == OMP_CLAUSE_DOACROSS_SINK)
{
tree deps = OMP_CLAUSE_DECL (c);
while (deps && TREE_CODE (deps) == TREE_LIST)
@@ -10418,10 +10412,12 @@ gimplify_scan_omp_clauses (tree *list_p,
pre_p, NULL, is_gimple_val, fb_rvalue);
deps = TREE_CHAIN (deps);
}
- break;
}
- else if (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SOURCE)
- break;
+ else
+ gcc_assert (OMP_CLAUSE_DOACROSS_KIND (c)
+ == OMP_CLAUSE_DOACROSS_SOURCE);
+ break;
+ case OMP_CLAUSE_DEPEND:
if (handled_depend_iterators == -1)
handled_depend_iterators = gimplify_omp_depend (list_p, pre_p);
if (handled_depend_iterators)
@@ -11946,6 +11942,7 @@ gimplify_adjust_omp_clauses (gimple_seq
case OMP_CLAUSE_SAFELEN:
case OMP_CLAUSE_SIMDLEN:
case OMP_CLAUSE_DEPEND:
+ case OMP_CLAUSE_DOACROSS:
case OMP_CLAUSE_PRIORITY:
case OMP_CLAUSE_GRAINSIZE:
case OMP_CLAUSE_NUM_TASKS:
@@ -12429,6 +12426,29 @@ gimplify_omp_taskloop_expr (tree type, t
OMP_FOR_CLAUSES (orig_for_stmt) = c;
}
+/* Helper function of gimplify_omp_for, find OMP_ORDERED with
+ OMP_CLAUSE_DOACROSS clause inside of OMP_FOR's body. */
+
+static tree
+find_standalone_omp_ordered (tree *tp, int *walk_subtrees, void *)
+{
+ switch (TREE_CODE (*tp))
+ {
+ case OMP_ORDERED:
+ if (omp_find_clause (OMP_ORDERED_CLAUSES (*tp), OMP_CLAUSE_DOACROSS))
+ return *tp;
+ break;
+ case OMP_SIMD:
+ case OMP_PARALLEL:
+ case OMP_TARGET:
+ *walk_subtrees = 0;
+ break;
+ default:
+ break;
+ }
+ return NULL_TREE;
+}
+
/* Gimplify the gross structure of an OMP_FOR statement. */
static enum gimplify_status
@@ -12804,12 +12824,24 @@ gimplify_omp_for (tree *expr_p, gimple_s
tree c = omp_find_clause (OMP_FOR_CLAUSES (for_stmt), OMP_CLAUSE_ORDERED);
bool is_doacross = false;
- if (c && OMP_CLAUSE_ORDERED_EXPR (c))
+ if (c && walk_tree_without_duplicates (&OMP_FOR_BODY (for_stmt),
+ find_standalone_omp_ordered, NULL))
{
+ OMP_CLAUSE_ORDERED_DOACROSS (c) = 1;
is_doacross = true;
- gimplify_omp_ctxp->loop_iter_var.create (TREE_VEC_LENGTH
- (OMP_FOR_INIT (for_stmt))
- * 2);
+ int len = TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt));
+ gimplify_omp_ctxp->loop_iter_var.create (len * 2);
+ for (tree *pc = &OMP_FOR_CLAUSES (for_stmt); *pc; )
+ if (OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_LINEAR)
+ {
+ error_at (OMP_CLAUSE_LOCATION (*pc),
+ "%<linear%> clause may not be specified together "
+ "with %<ordered%> clause if stand-alone %<ordered%> "
+ "construct is nested in it");
+ *pc = OMP_CLAUSE_CHAIN (*pc);
+ }
+ else
+ pc = &OMP_CLAUSE_CHAIN (*pc);
}
int collapse = 1, tile = 0;
c = omp_find_clause (OMP_FOR_CLAUSES (for_stmt), OMP_CLAUSE_COLLAPSE);
@@ -14882,21 +14914,22 @@ gimplify_omp_ordered (tree expr, gimple_
if (gimplify_omp_ctxp)
{
for (c = OMP_ORDERED_CLAUSES (expr); c; c = OMP_CLAUSE_CHAIN (c))
- if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
- && gimplify_omp_ctxp->loop_iter_var.is_empty ()
- && (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SINK
- || OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SOURCE))
+ if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DOACROSS
+ && gimplify_omp_ctxp->loop_iter_var.is_empty ())
{
error_at (OMP_CLAUSE_LOCATION (c),
- "%<ordered%> construct with %<depend%> clause must be "
- "closely nested inside a loop with %<ordered%> clause "
- "with a parameter");
+ "%<ordered%> construct with %qs clause must be "
+ "closely nested inside a loop with %<ordered%> clause",
+ OMP_CLAUSE_DOACROSS_DEPEND (c) ? "depend" : "doacross");
failures++;
}
- else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
- && OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SINK)
+ else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DOACROSS
+ && OMP_CLAUSE_DOACROSS_KIND (c) == OMP_CLAUSE_DOACROSS_SINK)
{
bool fail = false;
+ sink_c = c;
+ if (OMP_CLAUSE_DECL (c) == NULL_TREE)
+ continue; /* omp_cur_iteration - 1 */
for (decls = OMP_CLAUSE_DECL (c), i = 0;
decls && TREE_CODE (decls) == TREE_LIST;
decls = TREE_CHAIN (decls), ++i)
@@ -14919,21 +14952,24 @@ gimplify_omp_ordered (tree expr, gimple_
if (!fail && i != gimplify_omp_ctxp->loop_iter_var.length () / 2)
{
error_at (OMP_CLAUSE_LOCATION (c),
- "number of variables in %<depend%> clause with "
+ "number of variables in %qs clause with "
"%<sink%> modifier does not match number of "
- "iteration variables");
+ "iteration variables",
+ OMP_CLAUSE_DOACROSS_DEPEND (c)
+ ? "depend" : "doacross");
failures++;
}
- sink_c = c;
}
- else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
- && OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SOURCE)
+ else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DOACROSS
+ && OMP_CLAUSE_DOACROSS_KIND (c) == OMP_CLAUSE_DOACROSS_SOURCE)
{
if (source_c)
{
error_at (OMP_CLAUSE_LOCATION (c),
- "more than one %<depend%> clause with %<source%> "
- "modifier on an %<ordered%> construct");
+ "more than one %qs clause with %<source%> "
+ "modifier on an %<ordered%> construct",
+ OMP_CLAUSE_DOACROSS_DEPEND (source_c)
+ ? "depend" : "doacross");
failures++;
}
else
@@ -14943,9 +14979,11 @@ gimplify_omp_ordered (tree expr, gimple_
if (source_c && sink_c)
{
error_at (OMP_CLAUSE_LOCATION (source_c),
- "%<depend%> clause with %<source%> modifier specified "
- "together with %<depend%> clauses with %<sink%> modifier "
- "on the same construct");
+ "%qs clause with %<source%> modifier specified "
+ "together with %qs clauses with %<sink%> modifier "
+ "on the same construct",
+ OMP_CLAUSE_DOACROSS_DEPEND (source_c) ? "depend" : "doacross",
+ OMP_CLAUSE_DOACROSS_DEPEND (sink_c) ? "depend" : "doacross");
failures++;
}
@@ -241,8 +241,13 @@ omp_extract_for_data (gomp_for *for_stmt
break;
case OMP_CLAUSE_ORDERED:
fd->have_ordered = true;
- if (OMP_CLAUSE_ORDERED_EXPR (t))
- fd->ordered = tree_to_shwi (OMP_CLAUSE_ORDERED_EXPR (t));
+ if (OMP_CLAUSE_ORDERED_DOACROSS (t))
+ {
+ if (OMP_CLAUSE_ORDERED_EXPR (t))
+ fd->ordered = tree_to_shwi (OMP_CLAUSE_ORDERED_EXPR (t));
+ else
+ fd->ordered = -1;
+ }
break;
case OMP_CLAUSE_SCHEDULE:
gcc_assert (!distribute && !taskloop);
@@ -301,6 +306,9 @@ omp_extract_for_data (gomp_for *for_stmt
break;
}
+ if (fd->ordered == -1)
+ fd->ordered = fd->collapse;
+
/* For order(reproducible:concurrent) schedule ({dynamic,guided,runtime})
we have either the option to expensively remember at runtime how we've
distributed work from first loop and reuse that in following loops with
@@ -3636,14 +3636,13 @@ check_omp_nesting_restrictions (gimple *
break;
case GIMPLE_OMP_TASK:
for (c = gimple_omp_task_clauses (stmt); c; c = OMP_CLAUSE_CHAIN (c))
- if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
- && (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SOURCE
- || OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SINK))
+ if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DOACROSS)
{
- enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_KIND (c);
+ enum omp_clause_doacross_kind kind = OMP_CLAUSE_DOACROSS_KIND (c);
error_at (OMP_CLAUSE_LOCATION (c),
- "%<depend(%s)%> is only allowed in %<omp ordered%>",
- kind == OMP_CLAUSE_DEPEND_SOURCE ? "source" : "sink");
+ "%<%s(%s)%> is only allowed in %<omp ordered%>",
+ OMP_CLAUSE_DOACROSS_DEPEND (c) ? "depend" : "doacross",
+ kind == OMP_CLAUSE_DOACROSS_SOURCE ? "source" : "sink");
return false;
}
break;
@@ -3651,43 +3650,30 @@ check_omp_nesting_restrictions (gimple *
for (c = gimple_omp_ordered_clauses (as_a <gomp_ordered *> (stmt));
c; c = OMP_CLAUSE_CHAIN (c))
{
- if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND)
+ if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DOACROSS)
{
- gcc_assert (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_THREADS
- || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SIMD);
- continue;
- }
- enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_KIND (c);
- if (kind == OMP_CLAUSE_DEPEND_SOURCE
- || kind == OMP_CLAUSE_DEPEND_SINK)
- {
- tree oclause;
- /* Look for containing ordered(N) loop. */
- if (ctx == NULL
- || gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
- || (oclause
- = omp_find_clause (gimple_omp_for_clauses (ctx->stmt),
- OMP_CLAUSE_ORDERED)) == NULL_TREE)
- {
- error_at (OMP_CLAUSE_LOCATION (c),
- "%<ordered%> construct with %<depend%> clause "
- "must be closely nested inside an %<ordered%> "
- "loop");
- return false;
- }
- else if (OMP_CLAUSE_ORDERED_EXPR (oclause) == NULL_TREE)
+ if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND)
{
error_at (OMP_CLAUSE_LOCATION (c),
- "%<ordered%> construct with %<depend%> clause "
- "must be closely nested inside a loop with "
- "%<ordered%> clause with a parameter");
+ "invalid depend kind in omp %<ordered%> %<depend%>");
return false;
}
+ gcc_assert (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_THREADS
+ || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SIMD);
+ continue;
}
- else
+
+ tree oclause;
+ /* Look for containing ordered(N) loop. */
+ if (ctx == NULL
+ || gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
+ || (oclause
+ = omp_find_clause (gimple_omp_for_clauses (ctx->stmt),
+ OMP_CLAUSE_ORDERED)) == NULL_TREE)
{
error_at (OMP_CLAUSE_LOCATION (c),
- "invalid depend kind in omp %<ordered%> %<depend%>");
+ "%<ordered%> construct with %<depend%> clause "
+ "must be closely nested inside an %<ordered%> loop");
return false;
}
}
@@ -3732,14 +3718,37 @@ check_omp_nesting_restrictions (gimple *
"a loop region with an %<ordered%> clause");
return false;
}
- if (OMP_CLAUSE_ORDERED_EXPR (o) != NULL_TREE
- && omp_find_clause (c, OMP_CLAUSE_DEPEND) == NULL_TREE)
+ if (omp_find_clause (c, OMP_CLAUSE_DOACROSS) == NULL_TREE)
{
- error_at (gimple_location (stmt),
- "%<ordered%> region without %<depend%> clause may "
- "not be closely nested inside a loop region with "
- "an %<ordered%> clause with a parameter");
- return false;
+ if (OMP_CLAUSE_ORDERED_DOACROSS (o))
+ {
+ error_at (gimple_location (stmt),
+ "%<ordered%> construct without %<doacross%> or "
+ "%<depend%> clauses must not have the same "
+ "binding region as %<ordered%> construct with "
+ "those clauses");
+ return false;
+ }
+ else if (OMP_CLAUSE_ORDERED_EXPR (o))
+ {
+ tree co
+ = omp_find_clause (gimple_omp_for_clauses (ctx->stmt),
+ OMP_CLAUSE_COLLAPSE);
+ HOST_WIDE_INT
+ o_n = tree_to_shwi (OMP_CLAUSE_ORDERED_EXPR (o));
+ HOST_WIDE_INT c_n = 1;
+ if (co)
+ c_n = tree_to_shwi (OMP_CLAUSE_COLLAPSE_EXPR (co));
+ if (o_n != c_n)
+ {
+ error_at (gimple_location (stmt),
+ "%<ordered%> construct without %<doacross%> "
+ "or %<depend%> clauses binds to loop where "
+ "%<collapse%> argument %wd is different from "
+ "%<ordered%> argument %wd", c_n, o_n);
+ return false;
+ }
+ }
}
return true;
case GIMPLE_OMP_TARGET:
@@ -3793,14 +3802,12 @@ check_omp_nesting_restrictions (gimple *
break;
case GIMPLE_OMP_TARGET:
for (c = gimple_omp_target_clauses (stmt); c; c = OMP_CLAUSE_CHAIN (c))
- if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
- && (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SOURCE
- || OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SINK))
+ if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DOACROSS)
{
- enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_KIND (c);
+ enum omp_clause_doacross_kind kind = OMP_CLAUSE_DOACROSS_KIND (c);
error_at (OMP_CLAUSE_LOCATION (c),
"%<depend(%s)%> is only allowed in %<omp ordered%>",
- kind == OMP_CLAUSE_DEPEND_SOURCE ? "source" : "sink");
+ kind == OMP_CLAUSE_DOACROSS_SOURCE ? "source" : "sink");
return false;
}
if (is_gimple_omp_offloaded (stmt)
@@ -9743,8 +9750,8 @@ lower_omp_ordered_clauses (gimple_stmt_i
tree *list_p = gimple_omp_ordered_clauses_ptr (ord_stmt);
tree c = gimple_omp_ordered_clauses (ord_stmt);
- if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
- && OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SINK)
+ if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DOACROSS
+ && OMP_CLAUSE_DOACROSS_KIND (c) == OMP_CLAUSE_DOACROSS_SINK)
{
/* Merge depend clauses from multiple adjacent
#pragma omp ordered depend(sink:...) constructs
@@ -9766,8 +9773,8 @@ lower_omp_ordered_clauses (gimple_stmt_i
gomp_ordered *ord_stmt2 = as_a <gomp_ordered *> (stmt);
c = gimple_omp_ordered_clauses (ord_stmt2);
if (c == NULL_TREE
- || OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND
- || OMP_CLAUSE_DEPEND_KIND (c) != OMP_CLAUSE_DEPEND_SINK)
+ || OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DOACROSS
+ || OMP_CLAUSE_DOACROSS_KIND (c) != OMP_CLAUSE_DOACROSS_SINK)
break;
while (*list_p)
list_p = &OMP_CLAUSE_CHAIN (*list_p);
@@ -9834,8 +9841,8 @@ lower_omp_ordered_clauses (gimple_stmt_i
{
bool remove = false;
- gcc_assert (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND);
- if (OMP_CLAUSE_DEPEND_KIND (c) != OMP_CLAUSE_DEPEND_SINK)
+ gcc_assert (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DOACROSS);
+ if (OMP_CLAUSE_DOACROSS_KIND (c) != OMP_CLAUSE_DOACROSS_SINK)
goto next_ordered_clause;
tree vec;
@@ -9986,7 +9993,7 @@ lower_omp_ordered (gimple_stmt_iterator
OMP_CLAUSE_THREADS);
if (omp_find_clause (gimple_omp_ordered_clauses (ord_stmt),
- OMP_CLAUSE_DEPEND))
+ OMP_CLAUSE_DOACROSS))
{
/* FIXME: This is needs to be moved to the expansion to verify various
conditions only testable on cfg with dominators computed, and also
@@ -12362,9 +12369,6 @@ lower_depend_clauses (tree *pclauses, gi
case OMP_CLAUSE_DEPEND_INOUTSET:
cnt[4]++;
break;
- case OMP_CLAUSE_DEPEND_SOURCE:
- case OMP_CLAUSE_DEPEND_SINK:
- /* FALLTHRU */
default:
gcc_unreachable ();
}
@@ -3298,6 +3298,11 @@ expand_omp_ordered_sink (gimple_stmt_ite
gimple_stmt_iterator gsi2 = *gsi;
bool warned_step = false;
+ if (deps == NULL)
+ {
+ sorry_at (loc, "%<doacross(sink:omp_cur_iteration-1)%> not supported yet");
+ return;
+ }
for (i = 0; i < fd->ordered; i++)
{
tree step = NULL_TREE;
@@ -3321,9 +3326,11 @@ expand_omp_ordered_sink (gimple_stmt_ite
break;
forward = tree_int_cst_sgn (step) != -1;
}
- if (forward ^ OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
- warning_at (loc, 0, "%<depend%> clause with %<sink%> modifier "
- "waiting for lexically later iteration");
+ if (forward ^ OMP_CLAUSE_DOACROSS_SINK_NEGATIVE (deps))
+ warning_at (loc, 0, "%qs clause with %<sink%> modifier "
+ "waiting for lexically later iteration",
+ OMP_CLAUSE_DOACROSS_DEPEND (c)
+ ? "depend" : "doacross");
break;
}
deps = TREE_CHAIN (deps);
@@ -3377,13 +3384,13 @@ expand_omp_ordered_sink (gimple_stmt_ite
tree co = fold_convert_loc (loc, itype, off);
if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i].v)))
{
- if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
+ if (OMP_CLAUSE_DOACROSS_SINK_NEGATIVE (deps))
co = fold_build1_loc (loc, NEGATE_EXPR, itype, co);
a = fold_build2_loc (loc, POINTER_PLUS_EXPR,
TREE_TYPE (fd->loops[i].v), fd->loops[i].v,
co);
}
- else if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
+ else if (OMP_CLAUSE_DOACROSS_SINK_NEGATIVE (deps))
a = fold_build2_loc (loc, MINUS_EXPR, TREE_TYPE (fd->loops[i].v),
fd->loops[i].v, co);
else
@@ -3392,13 +3399,13 @@ expand_omp_ordered_sink (gimple_stmt_ite
if (step)
{
tree t1, t2;
- if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
+ if (OMP_CLAUSE_DOACROSS_SINK_NEGATIVE (deps))
t1 = fold_build2_loc (loc, GE_EXPR, boolean_type_node, a,
fd->loops[i].n1);
else
t1 = fold_build2_loc (loc, LT_EXPR, boolean_type_node, a,
fd->loops[i].n2);
- if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
+ if (OMP_CLAUSE_DOACROSS_SINK_NEGATIVE (deps))
t2 = fold_build2_loc (loc, LT_EXPR, boolean_type_node, a,
fd->loops[i].n2);
else
@@ -3420,14 +3427,14 @@ expand_omp_ordered_sink (gimple_stmt_ite
}
else if (fd->loops[i].cond_code == LT_EXPR)
{
- if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
+ if (OMP_CLAUSE_DOACROSS_SINK_NEGATIVE (deps))
t = fold_build2_loc (loc, GE_EXPR, boolean_type_node, a,
fd->loops[i].n1);
else
t = fold_build2_loc (loc, LT_EXPR, boolean_type_node, a,
fd->loops[i].n2);
}
- else if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
+ else if (OMP_CLAUSE_DOACROSS_SINK_NEGATIVE (deps))
t = fold_build2_loc (loc, GT_EXPR, boolean_type_node, a,
fd->loops[i].n2);
else
@@ -3459,9 +3466,11 @@ expand_omp_ordered_sink (gimple_stmt_ite
build_int_cst (itype, 0));
if (integer_zerop (t) && !warned_step)
{
- warning_at (loc, 0, "%<depend%> clause with %<sink%> modifier "
+ warning_at (loc, 0, "%qs clause with %<sink%> modifier "
"refers to iteration never in the iteration "
- "space");
+ "space",
+ OMP_CLAUSE_DOACROSS_DEPEND (c)
+ ? "depend" : "doacross");
warned_step = true;
}
cond = fold_build2_loc (loc, BIT_AND_EXPR, boolean_type_node,
@@ -3486,7 +3495,7 @@ expand_omp_ordered_sink (gimple_stmt_ite
s));
else
off = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype, off, s);
- if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
+ if (OMP_CLAUSE_DOACROSS_SINK_NEGATIVE (deps))
off = fold_build1_loc (loc, NEGATE_EXPR, itype, off);
off = fold_convert_loc (loc, fd->iter_type, off);
if (i <= fd->collapse - 1 && fd->collapse > 1)
@@ -3559,13 +3568,13 @@ expand_omp_ordered_source_sink (struct o
tree c;
for (c = gimple_omp_ordered_clauses (ord_stmt);
c; c = OMP_CLAUSE_CHAIN (c))
- if (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SOURCE)
+ if (OMP_CLAUSE_DOACROSS_KIND (c) == OMP_CLAUSE_DOACROSS_SOURCE)
break;
if (c)
expand_omp_ordered_source (&gsi, fd, counts, loc);
for (c = gimple_omp_ordered_clauses (ord_stmt);
c; c = OMP_CLAUSE_CHAIN (c))
- if (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SINK)
+ if (OMP_CLAUSE_DOACROSS_KIND (c) == OMP_CLAUSE_DOACROSS_SINK)
expand_omp_ordered_sink (&gsi, fd, counts, c, loc);
gsi_remove (&gsi, true);
}
@@ -10479,7 +10488,7 @@ expand_omp (struct omp_region *region)
gomp_ordered *ord_stmt
= as_a <gomp_ordered *> (last_stmt (region->entry));
if (omp_find_clause (gimple_omp_ordered_clauses (ord_stmt),
- OMP_CLAUSE_DEPEND))
+ OMP_CLAUSE_DOACROSS))
{
/* We'll expand these when expanding corresponding
worksharing region with ordered(n) clause. */
@@ -10609,7 +10618,7 @@ build_omp_regions_1 (basic_block bb, str
else if (code == GIMPLE_OMP_ORDERED
&& omp_find_clause (gimple_omp_ordered_clauses
(as_a <gomp_ordered *> (stmt)),
- OMP_CLAUSE_DEPEND))
+ OMP_CLAUSE_DOACROSS))
/* #pragma omp ordered depend is also just a stand-alone
directive. */
region = NULL;
@@ -10835,7 +10844,7 @@ omp_make_gimple_edges (basic_block bb, s
fallthru = true;
if (omp_find_clause (gimple_omp_ordered_clauses
(as_a <gomp_ordered *> (last)),
- OMP_CLAUSE_DEPEND))
+ OMP_CLAUSE_DOACROSS))
cur_region = cur_region->outer;
break;
@@ -1553,6 +1553,9 @@ hash_tree (struct streamer_tree_cache_d
case OMP_CLAUSE_DEPEND:
val = OMP_CLAUSE_DEPEND_KIND (t);
break;
+ case OMP_CLAUSE_DOACROSS:
+ val = OMP_CLAUSE_DOACROSS_KIND (t);
+ break;
case OMP_CLAUSE_MAP:
val = OMP_CLAUSE_MAP_KIND (t);
break;
@@ -453,6 +453,11 @@ unpack_ts_omp_clause_value_fields (class
OMP_CLAUSE_DEPEND_KIND (expr)
= bp_unpack_enum (bp, omp_clause_depend_kind, OMP_CLAUSE_DEPEND_LAST);
break;
+ case OMP_CLAUSE_DOACROSS:
+ OMP_CLAUSE_DOACROSS_KIND (expr)
+ = bp_unpack_enum (bp, omp_clause_doacross_kind,
+ OMP_CLAUSE_DOACROSS_LAST);
+ break;
case OMP_CLAUSE_MAP:
OMP_CLAUSE_SET_MAP_KIND (expr, bp_unpack_enum (bp, gomp_map_kind,
GOMP_MAP_LAST));
@@ -419,6 +419,10 @@ pack_ts_omp_clause_value_fields (struct
bp_pack_enum (bp, omp_clause_depend_kind, OMP_CLAUSE_DEPEND_LAST,
OMP_CLAUSE_DEPEND_KIND (expr));
break;
+ case OMP_CLAUSE_DOACROSS:
+ bp_pack_enum (bp, omp_clause_doacross_kind, OMP_CLAUSE_DOACROSS_LAST,
+ OMP_CLAUSE_DOACROSS_KIND (expr));
+ break;
case OMP_CLAUSE_MAP:
bp_pack_enum (bp, gomp_map_kind, GOMP_MAP_LAST,
OMP_CLAUSE_MAP_KIND (expr));
@@ -108,6 +108,7 @@ enum pragma_omp_clause {
PRAGMA_OMP_CLAUSE_DEVICE,
PRAGMA_OMP_CLAUSE_DEVICE_TYPE,
PRAGMA_OMP_CLAUSE_DIST_SCHEDULE,
+ PRAGMA_OMP_CLAUSE_DOACROSS,
PRAGMA_OMP_CLAUSE_ENTER,
PRAGMA_OMP_CLAUSE_FILTER,
PRAGMA_OMP_CLAUSE_FINAL,
@@ -714,8 +714,17 @@ c_finish_omp_depobj (location_t loc, tre
if (clause)
{
- gcc_assert (TREE_CODE (clause) == OMP_CLAUSE
- && OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_DEPEND);
+ gcc_assert (TREE_CODE (clause) == OMP_CLAUSE);
+ if (OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_DOACROSS)
+ {
+ error_at (OMP_CLAUSE_LOCATION (clause),
+ "%<depend(%s)%> is only allowed in %<omp ordered%>",
+ OMP_CLAUSE_DOACROSS_KIND (clause)
+ == OMP_CLAUSE_DOACROSS_SOURCE
+ ? "source" : "sink");
+ return;
+ }
+ gcc_assert (OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_DEPEND);
if (OMP_CLAUSE_CHAIN (clause))
error_at (OMP_CLAUSE_LOCATION (clause),
"more than one locator in %<depend%> clause on %<depobj%> "
@@ -727,13 +736,6 @@ c_finish_omp_depobj (location_t loc, tre
"%<depobj%> dependence type specified in %<depend%> "
"clause on %<depobj%> construct");
return;
- case OMP_CLAUSE_DEPEND_SOURCE:
- case OMP_CLAUSE_DEPEND_SINK:
- error_at (OMP_CLAUSE_LOCATION (clause),
- "%<depend(%s)%> is only allowed in %<omp ordered%>",
- OMP_CLAUSE_DEPEND_KIND (clause) == OMP_CLAUSE_DEPEND_SOURCE
- ? "source" : "sink");
- return;
case OMP_CLAUSE_DEPEND_IN:
case OMP_CLAUSE_DEPEND_OUT:
case OMP_CLAUSE_DEPEND_INOUT:
@@ -764,8 +766,8 @@ c_finish_omp_depobj (location_t loc, tre
gcc_unreachable ();
}
}
else
- gcc_assert (kind != OMP_CLAUSE_DEPEND_SOURCE);
+ gcc_assert (kind != OMP_CLAUSE_DEPEND_INVALID);
if (depobj == error_mark_node)
return;
@@ -12814,6 +12814,8 @@ c_parser_omp_clause_name (c_parser *pars
result = PRAGMA_OMP_CLAUSE_DEVICE_TYPE;
else if (!strcmp ("dist_schedule", p))
result = PRAGMA_OMP_CLAUSE_DIST_SCHEDULE;
+ else if (!strcmp ("doacross", p))
+ result = PRAGMA_OMP_CLAUSE_DOACROSS;
break;
case 'e':
if (!strcmp ("enter", p))
@@ -15962,8 +15964,8 @@ c_parser_omp_clause_simdlen (c_parser *p
*/
static tree
-c_parser_omp_clause_depend_sink (c_parser *parser, location_t clause_loc,
- tree list)
+c_parser_omp_clause_doacross_sink (c_parser *parser, location_t clause_loc,
+ tree list, bool depend_p)
{
tree vec = NULL;
if (c_parser_next_token_is_not (parser, CPP_NAME)
@@ -15973,6 +15975,31 @@ c_parser_omp_clause_depend_sink (c_parse
return list;
}
+ if (!depend_p)
+ {
+ const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
+ if (strcmp (p, "omp_cur_iteration") == 0
+ && c_parser_peek_2nd_token (parser)->type == CPP_MINUS
+ && c_parser_peek_nth_token (parser, 3)->type == CPP_NUMBER
+ && c_parser_peek_nth_token (parser, 4)->type == CPP_CLOSE_PAREN)
+ {
+ tree val = c_parser_peek_nth_token (parser, 3)->value;
+ if (integer_onep (val)
+ && comptypes (TREE_TYPE (val), integer_type_node))
+ {
+ c_parser_consume_token (parser);
+ c_parser_consume_token (parser);
+ c_parser_consume_token (parser);
+ tree u = build_omp_clause (clause_loc, OMP_CLAUSE_DOACROSS);
+ OMP_CLAUSE_DOACROSS_KIND (u) = OMP_CLAUSE_DOACROSS_SINK;
+ OMP_CLAUSE_CHAIN (u) = list;
+ return u;
+ }
+ }
+ }
+
+
+
while (c_parser_next_token_is (parser, CPP_NAME)
&& c_parser_peek_token (parser)->id_kind == C_ID_ID)
{
@@ -16018,7 +16045,7 @@ c_parser_omp_clause_depend_sink (c_parse
{
vec = tree_cons (addend, t, vec);
if (neg)
- OMP_CLAUSE_DEPEND_SINK_NEGATIVE (vec) = 1;
+ OMP_CLAUSE_DOACROSS_SINK_NEGATIVE (vec) = 1;
}
if (c_parser_next_token_is_not (parser, CPP_COMMA)
@@ -16032,8 +16059,9 @@ c_parser_omp_clause_depend_sink (c_parse
if (vec == NULL_TREE)
return list;
- tree u = build_omp_clause (clause_loc, OMP_CLAUSE_DEPEND);
- OMP_CLAUSE_DEPEND_KIND (u) = OMP_CLAUSE_DEPEND_SINK;
+ tree u = build_omp_clause (clause_loc, OMP_CLAUSE_DOACROSS);
+ OMP_CLAUSE_DOACROSS_KIND (u) = OMP_CLAUSE_DOACROSS_SINK;
+ OMP_CLAUSE_DOACROSS_DEPEND (u) = depend_p;
OMP_CLAUSE_DECL (u) = nreverse (vec);
OMP_CLAUSE_CHAIN (u) = list;
return u;
@@ -16225,6 +16253,7 @@ c_parser_omp_clause_depend (c_parser *pa
{
location_t clause_loc = c_parser_peek_token (parser)->location;
enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_LAST;
+ enum omp_clause_doacross_kind dkind = OMP_CLAUSE_DOACROSS_LAST;
tree nl, c, iterators = NULL_TREE;
matching_parens parens;
@@ -16256,9 +16285,9 @@ c_parser_omp_clause_depend (c_parser *pa
else if (strcmp ("depobj", p) == 0)
kind = OMP_CLAUSE_DEPEND_DEPOBJ;
else if (strcmp ("sink", p) == 0)
- kind = OMP_CLAUSE_DEPEND_SINK;
+ dkind = OMP_CLAUSE_DOACROSS_SINK;
else if (strcmp ("source", p) == 0)
- kind = OMP_CLAUSE_DEPEND_SOURCE;
+ dkind = OMP_CLAUSE_DOACROSS_SOURCE;
else
goto invalid_kind;
break;
@@ -16268,18 +16297,20 @@ c_parser_omp_clause_depend (c_parser *pa
c_parser_consume_token (parser);
if (iterators
- && (kind == OMP_CLAUSE_DEPEND_SOURCE || kind == OMP_CLAUSE_DEPEND_SINK))
+ && (dkind == OMP_CLAUSE_DOACROSS_SOURCE
+ || dkind == OMP_CLAUSE_DOACROSS_SINK))
{
pop_scope ();
error_at (clause_loc, "%<iterator%> modifier incompatible with %qs",
- kind == OMP_CLAUSE_DEPEND_SOURCE ? "source" : "sink");
+ dkind == OMP_CLAUSE_DOACROSS_SOURCE ? "source" : "sink");
iterators = NULL_TREE;
}
- if (kind == OMP_CLAUSE_DEPEND_SOURCE)
+ if (dkind == OMP_CLAUSE_DOACROSS_SOURCE)
{
- c = build_omp_clause (clause_loc, OMP_CLAUSE_DEPEND);
- OMP_CLAUSE_DEPEND_KIND (c) = kind;
+ c = build_omp_clause (clause_loc, OMP_CLAUSE_DOACROSS);
+ OMP_CLAUSE_DOACROSS_KIND (c) = dkind;
+ OMP_CLAUSE_DOACROSS_DEPEND (c) = 1;
OMP_CLAUSE_DECL (c) = NULL_TREE;
OMP_CLAUSE_CHAIN (c) = list;
parens.skip_until_found_close (parser);
@@ -16289,8 +16320,8 @@ c_parser_omp_clause_depend (c_parser *pa
if (!c_parser_require (parser, CPP_COLON, "expected %<:%>"))
goto resync_fail;
- if (kind == OMP_CLAUSE_DEPEND_SINK)
- nl = c_parser_omp_clause_depend_sink (parser, clause_loc, list);
+ if (dkind == OMP_CLAUSE_DOACROSS_SINK)
+ nl = c_parser_omp_clause_doacross_sink (parser, clause_loc, list, true);
else
{
nl = c_parser_omp_variable_list (parser, clause_loc,
@@ -16326,6 +16357,65 @@ c_parser_omp_clause_depend (c_parser *pa
return list;
}
+/* OpenMP 5.2:
+ doacross ( source : )
+ doacross ( source : omp_cur_iteration )
+
+ doacross ( sink : vec )
+ doacross ( sink : omp_cur_iteration - logical_iteration ) */
+
+static tree
+c_parser_omp_clause_doacross (c_parser *parser, tree list)
+{
+ location_t clause_loc = c_parser_peek_token (parser)->location;
+ enum omp_clause_doacross_kind kind = OMP_CLAUSE_DOACROSS_LAST;
+ tree nl;
+ const char *p;
+
+ matching_parens parens;
+ if (!parens.require_open (parser))
+ return list;
+
+ if (c_parser_next_token_is_not (parser, CPP_NAME))
+ goto invalid_kind;
+
+ p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
+ if (strcmp ("sink", p) == 0)
+ kind = OMP_CLAUSE_DOACROSS_SINK;
+ else if (strcmp ("source", p) == 0)
+ kind = OMP_CLAUSE_DOACROSS_SOURCE;
+ else
+ goto invalid_kind;
+
+ c_parser_consume_token (parser);
+
+ if (!c_parser_require (parser, CPP_COLON, "expected %<:%>"))
+ goto resync_fail;
+
+ if (kind == OMP_CLAUSE_DOACROSS_SOURCE)
+ {
+ if (c_parser_next_token_is (parser, CPP_NAME)
+ && strcmp (IDENTIFIER_POINTER (c_parser_peek_token (parser)->value),
+ "omp_cur_iteration") == 0)
+ c_parser_consume_token (parser);
+ nl = build_omp_clause (clause_loc, OMP_CLAUSE_DOACROSS);
+ OMP_CLAUSE_DOACROSS_KIND (nl) = OMP_CLAUSE_DOACROSS_SOURCE;
+ OMP_CLAUSE_DECL (nl) = NULL_TREE;
+ OMP_CLAUSE_CHAIN (nl) = list;
+ }
+ else
+ nl = c_parser_omp_clause_doacross_sink (parser, clause_loc, list, false);
+
+ parens.skip_until_found_close (parser);
+ return nl;
+
+ invalid_kind:
+ c_parser_error (parser, "invalid doacross kind");
+ resync_fail:
+ parens.skip_until_found_close (parser);
+ return list;
+}
+
/* OpenMP 4.0:
map ( map-kind: variable-list )
map ( variable-list )
@@ -17243,6 +17333,10 @@ c_parser_omp_all_clauses (c_parser *pars
clauses = c_parser_omp_clause_depend (parser, clauses);
c_name = "depend";
break;
+ case PRAGMA_OMP_CLAUSE_DOACROSS:
+ clauses = c_parser_omp_clause_doacross (parser, clauses);
+ c_name = "doacross";
+ break;
case PRAGMA_OMP_CLAUSE_MAP:
clauses = c_parser_omp_clause_map (parser, clauses);
c_name = "map";
@@ -19187,7 +19281,7 @@ c_parser_omp_depobj (c_parser *parser)
parens.skip_until_found_close (parser);
tree clause = NULL_TREE;
- enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_SOURCE;
+ enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_INVALID;
location_t c_loc = c_parser_peek_token (parser)->location;
if (c_parser_next_token_is (parser, CPP_NAME))
{
@@ -19226,7 +19320,7 @@ c_parser_omp_depobj (c_parser *parser)
else if (!strcmp ("inoutset", p2))
kind = OMP_CLAUSE_DEPEND_INOUTSET;
}
- if (kind == OMP_CLAUSE_DEPEND_SOURCE)
+ if (kind == OMP_CLAUSE_DEPEND_INVALID)
{
clause = error_mark_node;
error_at (c2_loc, "expected %<in%>, %<out%>, %<inout%>, "
@@ -19238,7 +19332,7 @@ c_parser_omp_depobj (c_parser *parser)
clause = error_mark_node;
}
}
- if (!clause && kind == OMP_CLAUSE_DEPEND_SOURCE)
+ if (!clause && kind == OMP_CLAUSE_DEPEND_INVALID)
{
clause = error_mark_node;
error_at (c_loc, "expected %<depend%>, %<destroy%> or %<update%> clause");
@@ -19437,19 +19531,6 @@ c_parser_omp_for_loop (location_t loc, c
= build_int_cst (NULL_TREE, collapse);
ordered = collapse;
}
- if (ordered)
- {
- for (tree *pc = &clauses; *pc; )
- if (OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_LINEAR)
- {
- error_at (OMP_CLAUSE_LOCATION (*pc),
- "%<linear%> clause may not be specified together "
- "with %<ordered%> clause with a parameter");
- *pc = OMP_CLAUSE_CHAIN (*pc);
- }
- else
- pc = &OMP_CLAUSE_CHAIN (*pc);
- }
gcc_assert (tiling || (collapse >= 1 && ordered >= 0));
count = ordered ? ordered : collapse;
@@ -19887,15 +19968,6 @@ c_parser_omp_simd (location_t loc, c_par
{
omp_split_clauses (loc, OMP_SIMD, mask, clauses, cclauses);
clauses = cclauses[C_OMP_CLAUSE_SPLIT_SIMD];
- tree c = omp_find_clause (cclauses[C_OMP_CLAUSE_SPLIT_FOR],
- OMP_CLAUSE_ORDERED);
- if (c && OMP_CLAUSE_ORDERED_EXPR (c))
- {
- error_at (OMP_CLAUSE_LOCATION (c),
- "%<ordered%> clause with parameter may not be specified "
- "on %qs construct", p_name);
- OMP_CLAUSE_ORDERED_EXPR (c) = NULL_TREE;
- }
}
block = c_begin_compound_stmt (true);
@@ -20134,14 +20206,18 @@ c_parser_omp_masked (location_t loc, c_p
# pragma omp ordered ordered-clauses new-line
structured-block
- # pragma omp ordered depend-clauses new-line */
+ # pragma omp ordered depend-clauses new-line
+
+ OpenMP 5.2
+ # pragma omp ordered doacross-clauses new-line */
#define OMP_ORDERED_CLAUSE_MASK \
( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_THREADS) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SIMD))
#define OMP_ORDERED_DEPEND_CLAUSE_MASK \
- (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND)
+ ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DOACROSS))
static bool
c_parser_omp_ordered (c_parser *parser, enum pragma_context context,
@@ -20161,7 +20237,7 @@ c_parser_omp_ordered (c_parser *parser,
{
const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
- if (!strcmp ("depend", p))
+ if (!strcmp ("depend", p) || !strcmp ("doacross", p))
{
if (!flag_openmp) /* flag_openmp_simd */
{
@@ -20171,8 +20247,8 @@ c_parser_omp_ordered (c_parser *parser,
if (context == pragma_stmt)
{
error_at (loc,
- "%<#pragma omp ordered%> with %<depend%> clause may "
- "only be used in compound statements");
+ "%<#pragma omp ordered%> with %qs clause may "
+ "only be used in compound statements", p);
c_parser_skip_to_pragma_eol (parser, false);
return true;
}
@@ -14834,15 +14834,11 @@ c_finish_omp_clauses (tree clauses, enum
}
break;
- case OMP_CLAUSE_DEPEND:
+ case OMP_CLAUSE_DOACROSS:
t = OMP_CLAUSE_DECL (c);
if (t == NULL_TREE)
- {
- gcc_assert (OMP_CLAUSE_DEPEND_KIND (c)
- == OMP_CLAUSE_DEPEND_SOURCE);
- break;
- }
- if (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SINK)
+ break;
+ if (OMP_CLAUSE_DOACROSS_KIND (c) == OMP_CLAUSE_DOACROSS_SINK)
{
gcc_assert (TREE_CODE (t) == TREE_LIST);
for (; t; t = TREE_CHAIN (t))
@@ -14870,7 +14866,8 @@ c_finish_omp_clauses (tree clauses, enum
}
break;
}
- /* FALLTHRU */
+ gcc_unreachable ();
+ case OMP_CLAUSE_DEPEND:
case OMP_CLAUSE_AFFINITY:
t = OMP_CLAUSE_DECL (c);
if (TREE_CODE (t) == TREE_LIST
@@ -11979,14 +11979,18 @@ cp_parser_handle_statement_omp_attribute
if (dir->id == PRAGMA_OMP_ORDERED)
{
/* ordered is C_OMP_DIR_CONSTRUCT only if it doesn't contain
- depend clause. */
- if (directive[1] && strcmp (directive[1], "depend") == 0)
+ depend/doacross clause. */
+ if (directive[1]
+ && (strcmp (directive[1], "depend") == 0
+ || strcmp (directive[1], "doacross") == 0))
kind = C_OMP_DIR_STANDALONE;
else if (first + 2 < last
&& first[1].type == CPP_COMMA
&& first[2].type == CPP_NAME
- && strcmp (IDENTIFIER_POINTER (first[2].u.value),
- "depend") == 0)
+ && (strcmp (IDENTIFIER_POINTER (first[2].u.value),
+ "depend") == 0
+ || strcmp (IDENTIFIER_POINTER (first[2].u.value),
+ "doacross") == 0))
kind = C_OMP_DIR_STANDALONE;
}
else if (dir->id == PRAGMA_OMP_ERROR)
@@ -36587,6 +36591,8 @@ cp_parser_omp_clause_name (cp_parser *pa
result = PRAGMA_OMP_CLAUSE_DEVICE_TYPE;
else if (!strcmp ("dist_schedule", p))
result = PRAGMA_OMP_CLAUSE_DIST_SCHEDULE;
+ else if (!strcmp ("doacross", p))
+ result = PRAGMA_OMP_CLAUSE_DOACROSS;
break;
case 'e':
if (!strcmp ("enter", p))
@@ -39314,8 +39320,8 @@ cp_parser_omp_clause_simdlen (cp_parser
*/
static tree
-cp_parser_omp_clause_depend_sink (cp_parser *parser, location_t clause_loc,
- tree list)
+cp_parser_omp_clause_doacross_sink (cp_parser *parser, location_t clause_loc,
+ tree list, bool depend_p)
{
tree vec = NULL;
@@ -39325,6 +39331,29 @@ cp_parser_omp_clause_depend_sink (cp_par
return list;
}
+ if (!depend_p)
+ {
+ tree id = cp_lexer_peek_token (parser->lexer)->u.value;
+ if (strcmp (IDENTIFIER_POINTER (id), "omp_cur_iteration") == 0
+ && cp_lexer_nth_token_is (parser->lexer, 2, CPP_MINUS)
+ && cp_lexer_nth_token_is (parser->lexer, 3, CPP_NUMBER)
+ && cp_lexer_nth_token_is (parser->lexer, 4, CPP_CLOSE_PAREN))
+ {
+ tree val = cp_lexer_peek_nth_token (parser->lexer, 3)->u.value;
+ if (integer_onep (val)
+ && same_type_p (TREE_TYPE (val), integer_type_node))
+ {
+ cp_lexer_consume_token (parser->lexer);
+ cp_lexer_consume_token (parser->lexer);
+ cp_lexer_consume_token (parser->lexer);
+ tree u = build_omp_clause (clause_loc, OMP_CLAUSE_DOACROSS);
+ OMP_CLAUSE_DOACROSS_KIND (u) = OMP_CLAUSE_DOACROSS_SINK;
+ OMP_CLAUSE_CHAIN (u) = list;
+ return u;
+ }
+ }
+ }
+
while (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
{
location_t id_loc = cp_lexer_peek_token (parser->lexer)->location;
@@ -39372,7 +39401,7 @@ cp_parser_omp_clause_depend_sink (cp_par
{
vec = tree_cons (addend, t, vec);
if (neg)
- OMP_CLAUSE_DEPEND_SINK_NEGATIVE (vec) = 1;
+ OMP_CLAUSE_DOACROSS_SINK_NEGATIVE (vec) = 1;
}
if (cp_lexer_next_token_is_not (parser->lexer, CPP_COMMA)
@@ -39384,8 +39413,9 @@ cp_parser_omp_clause_depend_sink (cp_par
if (vec)
{
- tree u = build_omp_clause (clause_loc, OMP_CLAUSE_DEPEND);
- OMP_CLAUSE_DEPEND_KIND (u) = OMP_CLAUSE_DEPEND_SINK;
+ tree u = build_omp_clause (clause_loc, OMP_CLAUSE_DOACROSS);
+ OMP_CLAUSE_DOACROSS_KIND (u) = OMP_CLAUSE_DOACROSS_SINK;
+ OMP_CLAUSE_DOACROSS_DEPEND (u) = depend_p;
OMP_CLAUSE_DECL (u) = nreverse (vec);
OMP_CLAUSE_CHAIN (u) = list;
return u;
@@ -39634,6 +39664,7 @@ cp_parser_omp_clause_depend (cp_parser *
{
tree nlist, c, iterators = NULL_TREE;
enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_LAST;
+ enum omp_clause_doacross_kind dkind = OMP_CLAUSE_DOACROSS_LAST;
matching_parens parens;
if (!parens.require_open (parser))
@@ -39667,9 +39698,9 @@ cp_parser_omp_clause_depend (cp_parser *
else if (strcmp ("depobj", p) == 0)
kind = OMP_CLAUSE_DEPEND_DEPOBJ;
else if (strcmp ("sink", p) == 0)
- kind = OMP_CLAUSE_DEPEND_SINK;
+ dkind = OMP_CLAUSE_DOACROSS_SINK;
else if (strcmp ("source", p) == 0)
- kind = OMP_CLAUSE_DEPEND_SOURCE;
+ dkind = OMP_CLAUSE_DOACROSS_SOURCE;
else
goto invalid_kind;
break;
@@ -39679,18 +39710,20 @@ cp_parser_omp_clause_depend (cp_parser *
cp_lexer_consume_token (parser->lexer);
if (iterators
- && (kind == OMP_CLAUSE_DEPEND_SOURCE || kind == OMP_CLAUSE_DEPEND_SINK))
+ && (dkind == OMP_CLAUSE_DOACROSS_SOURCE
+ || dkind == OMP_CLAUSE_DOACROSS_SINK))
{
poplevel (0, 1, 0);
error_at (loc, "%<iterator%> modifier incompatible with %qs",
- kind == OMP_CLAUSE_DEPEND_SOURCE ? "source" : "sink");
+ dkind == OMP_CLAUSE_DOACROSS_SOURCE ? "source" : "sink");
iterators = NULL_TREE;
}
- if (kind == OMP_CLAUSE_DEPEND_SOURCE)
+ if (dkind == OMP_CLAUSE_DOACROSS_SOURCE)
{
- c = build_omp_clause (loc, OMP_CLAUSE_DEPEND);
- OMP_CLAUSE_DEPEND_KIND (c) = kind;
+ c = build_omp_clause (loc, OMP_CLAUSE_DOACROSS);
+ OMP_CLAUSE_DOACROSS_KIND (c) = dkind;
+ OMP_CLAUSE_DOACROSS_DEPEND (c) = 1;
OMP_CLAUSE_DECL (c) = NULL_TREE;
OMP_CLAUSE_CHAIN (c) = list;
if (!parens.require_close (parser))
@@ -39703,9 +39736,9 @@ cp_parser_omp_clause_depend (cp_parser *
if (!cp_parser_require (parser, CPP_COLON, RT_COLON))
goto resync_fail;
- if (kind == OMP_CLAUSE_DEPEND_SINK)
+ if (dkind == OMP_CLAUSE_DOACROSS_SINK)
{
- nlist = cp_parser_omp_clause_depend_sink (parser, loc, list);
+ nlist = cp_parser_omp_clause_doacross_sink (parser, loc, list, true);
if (!parens.require_close (parser))
cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true,
/*or_comma=*/false,
@@ -39746,6 +39779,73 @@ cp_parser_omp_clause_depend (cp_parser *
return list;
}
+/* OpenMP 5.2:
+ doacross ( source : )
+ doacross ( source : omp_cur_iteration )
+
+ doacross ( sink : vec )
+ doacross ( sink : omp_cur_iteration - logical_iteration ) */
+
+static tree
+cp_parser_omp_clause_doacross (cp_parser *parser, tree list, location_t loc)
+{
+ tree nlist;
+ enum omp_clause_doacross_kind kind = OMP_CLAUSE_DOACROSS_LAST;
+
+ matching_parens parens;
+ if (!parens.require_open (parser))
+ return list;
+
+ if (cp_lexer_next_token_is_not (parser->lexer, CPP_NAME))
+ {
+ invalid_kind:
+ cp_parser_error (parser, "invalid doacross kind");
+ resync_fail:
+ cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true,
+ /*or_comma=*/false,
+ /*consume_paren=*/true);
+ return list;
+ }
+
+ tree id = cp_lexer_peek_token (parser->lexer)->u.value;
+ const char *p = IDENTIFIER_POINTER (id);
+
+ if (strcmp ("sink", p) == 0)
+ kind = OMP_CLAUSE_DOACROSS_SINK;
+ else if (strcmp ("source", p) == 0)
+ kind = OMP_CLAUSE_DOACROSS_SOURCE;
+ else
+ goto invalid_kind;
+
+ cp_lexer_consume_token (parser->lexer);
+
+ if (!cp_parser_require (parser, CPP_COLON, RT_COLON))
+ goto resync_fail;
+
+ if (kind == OMP_CLAUSE_DOACROSS_SOURCE)
+ {
+ if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
+ {
+ id = cp_lexer_peek_token (parser->lexer)->u.value;
+ p = IDENTIFIER_POINTER (id);
+ if (strcmp (p, "omp_cur_iteration") == 0)
+ cp_lexer_consume_token (parser->lexer);
+ }
+ nlist = build_omp_clause (loc, OMP_CLAUSE_DOACROSS);
+ OMP_CLAUSE_DOACROSS_KIND (nlist) = OMP_CLAUSE_DOACROSS_SOURCE;
+ OMP_CLAUSE_DECL (nlist) = NULL_TREE;
+ OMP_CLAUSE_CHAIN (nlist) = list;
+ }
+ else
+ nlist = cp_parser_omp_clause_doacross_sink (parser, loc, list, false);
+
+ if (!parens.require_close (parser))
+ cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true,
+ /*or_comma=*/false,
+ /*consume_paren=*/true);
+ return nlist;
+}
+
/* OpenMP 4.0:
map ( map-kind : variable-list )
map ( variable-list )
@@ -40688,6 +40788,11 @@ cp_parser_omp_all_clauses (cp_parser *pa
token->location);
c_name = "depend";
break;
+ case PRAGMA_OMP_CLAUSE_DOACROSS:
+ clauses = cp_parser_omp_clause_doacross (parser, clauses,
+ token->location);
+ c_name = "doacross";
+ break;
case PRAGMA_OMP_CLAUSE_DETACH:
clauses = cp_parser_omp_clause_detach (parser, clauses);
c_name = "detach";
@@ -41926,7 +42031,7 @@ cp_parser_omp_depobj (cp_parser *parser,
/*consume_paren=*/true);
tree clause = NULL_TREE;
- enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_SOURCE;
+ enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_INVALID;
location_t c_loc = cp_lexer_peek_token (parser->lexer)->location;
/* For now only in C++ attributes, do it always for OpenMP 5.1. */
if (parser->lexer->in_omp_attribute_pragma
@@ -41974,7 +42079,7 @@ cp_parser_omp_depobj (cp_parser *parser,
else if (!strcmp ("inoutset", p2))
kind = OMP_CLAUSE_DEPEND_INOUTSET;
}
- if (kind == OMP_CLAUSE_DEPEND_SOURCE)
+ if (kind == OMP_CLAUSE_DEPEND_INVALID)
{
clause = error_mark_node;
error_at (c2_loc, "expected %<in%>, %<out%>, %<inout%>, "
@@ -41990,7 +42095,7 @@ cp_parser_omp_depobj (cp_parser *parser,
clause = error_mark_node;
}
}
- if (!clause && kind == OMP_CLAUSE_DEPEND_SOURCE)
+ if (!clause && kind == OMP_CLAUSE_DEPEND_INVALID)
{
clause = error_mark_node;
error_at (c_loc, "expected %<depend%>, %<destroy%> or %<update%> clause");
@@ -42822,19 +42927,6 @@ cp_parser_omp_for_loop (cp_parser *parse
= build_int_cst (NULL_TREE, collapse);
ordered = collapse;
}
- if (ordered)
- {
- for (tree *pc = &clauses; *pc; )
- if (OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_LINEAR)
- {
- error_at (OMP_CLAUSE_LOCATION (*pc),
- "%<linear%> clause may not be specified together "
- "with %<ordered%> clause with a parameter");
- *pc = OMP_CLAUSE_CHAIN (*pc);
- }
- else
- pc = &OMP_CLAUSE_CHAIN (*pc);
- }
gcc_assert (tiling || (collapse >= 1 && ordered >= 0));
count = ordered ? ordered : collapse;
@@ -43286,15 +43378,6 @@ cp_parser_omp_simd (cp_parser *parser, c
{
cp_omp_split_clauses (loc, OMP_SIMD, mask, clauses, cclauses);
clauses = cclauses[C_OMP_CLAUSE_SPLIT_SIMD];
- tree c = omp_find_clause (cclauses[C_OMP_CLAUSE_SPLIT_FOR],
- OMP_CLAUSE_ORDERED);
- if (c && OMP_CLAUSE_ORDERED_EXPR (c))
- {
- error_at (OMP_CLAUSE_LOCATION (c),
- "%<ordered%> clause with parameter may not be specified "
- "on %qs construct", p_name);
- OMP_CLAUSE_ORDERED_EXPR (c) = NULL_TREE;
- }
}
keep_next_level (true);
@@ -43556,7 +43639,8 @@ cp_parser_omp_masked (cp_parser *parser,
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SIMD))
#define OMP_ORDERED_DEPEND_CLAUSE_MASK \
- (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND)
+ ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DOACROSS))
static bool
cp_parser_omp_ordered (cp_parser *parser, cp_token *pragma_tok,
@@ -43575,7 +43659,7 @@ cp_parser_omp_ordered (cp_parser *parser
tree id = cp_lexer_peek_nth_token (parser->lexer, n)->u.value;
const char *p = IDENTIFIER_POINTER (id);
- if (strcmp (p, "depend") == 0)
+ if (strcmp (p, "depend") == 0 || strcmp (p, "doacross") == 0)
{
if (!flag_openmp) /* flag_openmp_simd */
{
@@ -43585,8 +43669,8 @@ cp_parser_omp_ordered (cp_parser *parser
if (context == pragma_stmt)
{
error_at (pragma_tok->location, "%<#pragma omp ordered%> with "
- "%<depend%> clause may only be used in compound "
- "statements");
+ "%qs clause may only be used in compound "
+ "statements", p);
cp_parser_skip_to_pragma_eol (parser, pragma_tok);
return true;
}
@@ -17830,8 +17830,8 @@ tsubst_omp_clause_decl (tree decl, tree
}
/* Handle an OpenMP array section represented as a TREE_LIST (or
- OMP_CLAUSE_DEPEND_KIND). An OMP_CLAUSE_DEPEND (with a depend
- kind of OMP_CLAUSE_DEPEND_SINK) can also be represented as a
+ OMP_CLAUSE_DOACROSS_KIND). An OMP_CLAUSE_DOACROSS (with a depend
+ kind of OMP_CLAUSE_DOACROSS_SINK) can also be represented as a
TREE_LIST. We can handle it exactly the same as an array section
(purpose, value, and a chain), even though the nomenclature
(low_bound, length, etc) is different. */
@@ -17849,8 +17849,8 @@ tsubst_omp_clause_decl (tree decl, tree
&& TREE_CHAIN (decl) == chain)
return decl;
tree ret = tree_cons (low_bound, length, chain);
- OMP_CLAUSE_DEPEND_SINK_NEGATIVE (ret)
- = OMP_CLAUSE_DEPEND_SINK_NEGATIVE (decl);
+ OMP_CLAUSE_DOACROSS_SINK_NEGATIVE (ret)
+ = OMP_CLAUSE_DOACROSS_SINK_NEGATIVE (decl);
return ret;
}
tree ret = tsubst_expr (decl, args, complain, in_decl,
@@ -17898,6 +17898,7 @@ tsubst_omp_clauses (tree clauses, enum c
case OMP_CLAUSE_COPYPRIVATE:
case OMP_CLAUSE_UNIFORM:
case OMP_CLAUSE_DEPEND:
+ case OMP_CLAUSE_DOACROSS:
case OMP_CLAUSE_AFFINITY:
case OMP_CLAUSE_FROM:
case OMP_CLAUSE_TO:
@@ -19414,7 +19415,7 @@ tsubst_expr (tree t, tree args, tsubst_f
r = RECUR (OMP_DEPOBJ_DEPOBJ (t));
if (OMP_DEPOBJ_CLAUSES (t) && OMP_DEPOBJ_CLAUSES (t) != error_mark_node)
{
- enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_SOURCE;
+ enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_INVALID;
if (TREE_CODE (OMP_DEPOBJ_CLAUSES (t)) == OMP_CLAUSE)
{
tmp = tsubst_omp_clauses (OMP_DEPOBJ_CLAUSES (t), C_ORT_OMP,
@@ -19432,7 +19433,7 @@ tsubst_expr (tree t, tree args, tsubst_f
}
else
finish_omp_depobj (EXPR_LOCATION (t), r,
- OMP_CLAUSE_DEPEND_SOURCE,
+ OMP_CLAUSE_DEPEND_INVALID,
OMP_DEPOBJ_CLAUSES (t));
break;
@@ -6477,13 +6477,13 @@ finish_omp_declare_simd_methods (tree t)
}
}
-/* Adjust sink depend clause to take into account pointer offsets.
+/* Adjust sink depend/doacross clause to take into account pointer offsets.
Return TRUE if there was a problem processing the offset, and the
whole clause should be removed. */
static bool
-cp_finish_omp_clause_depend_sink (tree sink_clause)
+cp_finish_omp_clause_doacross_sink (tree sink_clause)
{
tree t = OMP_CLAUSE_DECL (sink_clause);
gcc_assert (TREE_CODE (t) == TREE_LIST);
@@ -7795,21 +7795,18 @@ finish_omp_clauses (tree clauses, enum c
}
goto handle_field_decl;
- case OMP_CLAUSE_DEPEND:
+ case OMP_CLAUSE_DOACROSS:
t = OMP_CLAUSE_DECL (c);
if (t == NULL_TREE)
+ break;
+ if (OMP_CLAUSE_DOACROSS_KIND (c) == OMP_CLAUSE_DOACROSS_SINK)
{
- gcc_assert (OMP_CLAUSE_DEPEND_KIND (c)
- == OMP_CLAUSE_DEPEND_SOURCE);
- break;
- }
- if (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SINK)
- {
- if (cp_finish_omp_clause_depend_sink (c))
+ if (cp_finish_omp_clause_doacross_sink (c))
remove = true;
break;
}
- /* FALLTHRU */
+ gcc_unreachable ();
+ case OMP_CLAUSE_DEPEND:
case OMP_CLAUSE_AFFINITY:
t = OMP_CLAUSE_DECL (c);
if (TREE_CODE (t) == TREE_LIST
@@ -2897,7 +2897,7 @@ gfc_trans_omp_clauses (stmtblock_t *bloc
}
vec = tree_cons (addend, t, vec);
if (neg)
- OMP_CLAUSE_DEPEND_SINK_NEGATIVE (vec) = 1;
+ OMP_CLAUSE_DOACROSS_SINK_NEGATIVE (vec) = 1;
}
if (n->next == NULL
|| n->next->u.depend_op != OMP_DEPEND_SINK)
@@ -2908,8 +2908,9 @@ gfc_trans_omp_clauses (stmtblock_t *bloc
continue;
tree node = build_omp_clause (input_location,
- OMP_CLAUSE_DEPEND);
- OMP_CLAUSE_DEPEND_KIND (node) = OMP_CLAUSE_DEPEND_SINK;
+ OMP_CLAUSE_DOACROSS);
+ OMP_CLAUSE_DOACROSS_KIND (node) = OMP_CLAUSE_DOACROSS_SINK;
+ OMP_CLAUSE_DOACROSS_DEPEND (node) = 1;
OMP_CLAUSE_DECL (node) = nreverse (vec);
omp_clauses = gfc_trans_add_clause (node, omp_clauses);
continue;
@@ -4254,8 +4255,9 @@ gfc_trans_omp_clauses (stmtblock_t *bloc
if (clauses->depend_source)
{
- c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_DEPEND);
- OMP_CLAUSE_DEPEND_KIND (c) = OMP_CLAUSE_DEPEND_SOURCE;
+ c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_DOACROSS);
+ OMP_CLAUSE_DOACROSS_KIND (c) = OMP_CLAUSE_DOACROSS_SOURCE;
+ OMP_CLAUSE_DOACROSS_DEPEND (c) = 1;
omp_clauses = gfc_trans_add_clause (c, omp_clauses);
}
@@ -7,13 +7,13 @@ foo (void)
#pragma omp for ordered(1)
for (i = 0; i < 64; i++)
{
- #pragma omp ordered /* { dg-error "'ordered' region without 'depend' clause may not be closely nested inside a loop region with an 'ordered' clause with a parameter" } */
+ #pragma omp ordered
;
}
#pragma omp for ordered(1)
for (i = 0; i < 64; i++)
{
- #pragma omp ordered threads /* { dg-error "'ordered' region without 'depend' clause may not be closely nested inside a loop region with an 'ordered' clause with a parameter" } */
+ #pragma omp ordered threads
;
}
}
@@ -25,14 +25,20 @@ bar (void)
#pragma omp for ordered
for (i = 0; i < 64; i++)
{
- #pragma omp ordered depend(source) /* { dg-error "'ordered' construct with 'depend' clause must be closely nested inside a loop with 'ordered' clause with a parameter" } */
- #pragma omp ordered depend(sink: i - 1) /* { dg-error "'ordered' construct with 'depend' clause must be closely nested inside a loop with 'ordered' clause with a parameter" } */
+ #pragma omp ordered depend(source)
+ #pragma omp ordered depend(sink: i - 1)
+ }
+ #pragma omp for ordered
+ for (i = 0; i < 64; i++)
+ {
+ #pragma omp ordered doacross(source:)
+ #pragma omp ordered doacross(sink: i - 1)
}
#pragma omp for
for (i = 0; i < 64; i++)
{
- #pragma omp ordered depend(source) /* { dg-error "'ordered' construct with 'depend' clause must be closely nested inside a loop with 'ordered' clause with a parameter" } */
- #pragma omp ordered depend(sink: i - 1) /* { dg-error "'ordered' construct with 'depend' clause must be closely nested inside a loop with 'ordered' clause with a parameter" } */
+ #pragma omp ordered depend(source) /* { dg-error "'ordered' construct with 'depend' clause must be closely nested inside a loop with 'ordered' clause" } */
+ #pragma omp ordered depend(sink: i - 1) /* { dg-error "'ordered' construct with 'depend' clause must be closely nested inside a loop with 'ordered' clause" } */
}
#pragma omp for
for (i = 0; i < 64; i++)
@@ -0,0 +1,94 @@
+void
+foo (int n)
+{
+ int i;
+ #pragma omp for ordered
+ for (i = 0; i < 8; i += n)
+ {
+ #pragma omp ordered doacross(source:)
+ #pragma omp ordered doacross(sink: i - 2)
+ }
+}
+
+void
+bar (int n)
+{
+ int i, j;
+ #pragma omp for collapse(2) ordered(2)
+ for (i = 0; i < 8; i += n)
+ for (j = 0; j < 8; j += n)
+ {
+ #pragma omp ordered doacross(source:omp_cur_iteration)
+ #pragma omp ordered doacross(sink: i - 2, j + 2)
+ }
+}
+
+void
+baz (void)
+{
+ int i, j;
+ #pragma omp for ordered(1)
+ for (i = 0; i < 64; i++)
+ {
+ #pragma omp ordered /* { dg-error "'ordered' construct without 'doacross' or 'depend' clauses must not have the same binding region as 'ordered' construct with those clauses" } */
+ ;
+ #pragma omp ordered doacross(source:)
+ #pragma omp ordered doacross(sink: i - 1)
+ }
+ #pragma omp for ordered
+ for (i = 0; i < 64; i++)
+ {
+ #pragma omp ordered doacross(source: omp_cur_iteration )
+ #pragma omp ordered doacross(sink: i - 1)
+ #pragma omp ordered threads /* { dg-error "'ordered' construct without 'doacross' or 'depend' clauses must not have the same binding region as 'ordered' construct with those clauses" } */
+ ;
+ }
+ #pragma omp for ordered(2)
+ for (i = 0; i < 8; i++)
+ for (j = 0; j < 8; j++)
+ {
+ #pragma omp ordered /* { dg-error "'ordered' construct without 'doacross' or 'depend' clauses binds to loop where 'collapse' argument 1 is different from 'ordered' argument 2" } */
+ ;
+ }
+ #pragma omp for ordered(2) collapse(1)
+ for (i = 0; i < 8; i++)
+ for (j = 0; j < 8; j++)
+ {
+ #pragma omp ordered threads /* { dg-error "'ordered' construct without 'doacross' or 'depend' clauses binds to loop where 'collapse' argument 1 is different from 'ordered' argument 2" } */
+ ;
+ }
+}
+
+void
+qux (void)
+{
+ int i, j = 0;
+ #pragma omp for ordered linear(j)
+ for (i = 0; i < 64; i++)
+ {
+ ++j;
+ #pragma omp ordered
+ ;
+ }
+ #pragma omp for ordered linear(j) /* { dg-error "'linear' clause may not be specified together with 'ordered' clause if stand-alone 'ordered' construct is nested in it" } */
+ for (i = 0; i < 64; i++)
+ {
+ ++j;
+ #pragma omp ordered doacross(source:)
+ #pragma omp ordered doacross(sink:i-1)
+ }
+ #pragma omp for ordered(1) linear(j)
+ for (i = 0; i < 64; i++)
+ {
+ ++j;
+ #pragma omp ordered
+ ;
+ }
+ #pragma omp for ordered(1) linear(j) /* { dg-error "'linear' clause may not be specified together with 'ordered' clause if stand-alone 'ordered' construct is nested in it" } */
+ for (i = 0; i < 64; i++)
+ {
+ ++j;
+ #pragma omp ordered doacross(source:)
+ #pragma omp ordered doacross(sink:i-1)
+ }
+}
@@ -0,0 +1,74 @@
+void
+foo (int n)
+{
+ int i;
+ #pragma omp for ordered
+ for (i = 0; i < 8; i += n)
+ {
+ #pragma omp ordered doacross(source) /* { dg-error "expected ':' before '\\\)' token" } */
+ }
+ #pragma omp for ordered
+ for (i = 0; i < 8; i += n)
+ {
+ #pragma omp ordered doacross(source:omp_current_iteration) /* { dg-error "expected '\\\)' before 'omp_current_iteration'" } */
+ }
+ #pragma omp for ordered
+ for (i = 0; i < 8; i += n)
+ {
+ #pragma omp ordered doacross(source:i - 2) /* { dg-error "expected '\\\)' before 'i'" } */
+ }
+ #pragma omp for ordered
+ for (i = 0; i < 8; i += n)
+ {
+ #pragma omp ordered doacross(sink) /* { dg-error "expected ':' before '\\\)' token" } */
+ }
+}
+
+void
+bar (int n)
+{
+ int i;
+ #pragma omp for ordered
+ for (i = 0; i < 8; i += n)
+ {
+ #pragma omp ordered doacross(sink:omp_current_iteration - 1) /* { dg-error "'omp_current_iteration' undeclared \\\(first use in this function\\\)" "" { target c } } */
+ } /* { dg-error "'omp_current_iteration' has not been declared" "" { target c++ } .-1 } */
+ #pragma omp for ordered
+ for (i = 0; i < 8; i += n)
+ {
+ #pragma omp ordered doacross(sink:omp_cur_iteration) /* { dg-error "'omp_cur_iteration' undeclared \\\(first use in this function\\\)" "" { target c } } */
+ } /* { dg-error "'omp_cur_iteration' has not been declared" "" { target c++ } .-1 } */
+}
+
+void
+baz (int n)
+{
+ int i;
+ #pragma omp for ordered
+ for (i = 0; i < 8; i += n)
+ {
+ #pragma omp ordered doacross(sink:omp_cur_iteration + 1) /* { dg-error "'omp_cur_iteration' undeclared \\\(first use in this function\\\)" "" { target c } } */
+ } /* { dg-error "'omp_cur_iteration' has not been declared" "" { target c++ } .-1 } */
+}
+
+void
+qux (int n)
+{
+ int i;
+ #pragma omp for ordered
+ for (i = 0; i < 8; i += n)
+ {
+ #pragma omp ordered doacross(sink:omp_cur_iteration - (2 - 1)) /* { dg-error "'omp_cur_iteration' undeclared \\\(first use in this function\\\)" "" { target c } } */
+ } /* { dg-error "expected integer before '\\\(' token" "" { target *-*-* } .-1 } */
+} /* { dg-error "'omp_cur_iteration' has not been declared" "" { target c++ } .-2 } */
+ /* { dg-error "expected '\\\)' before '\\\(' token" "" { target c++ } .-3 } */
+void
+corge (int n)
+{
+ int i;
+ #pragma omp for ordered
+ for (i = 0; i < 8; i += n)
+ {
+ #pragma omp ordered doacross(sink:omp_cur_iteration - 1LL) /* { dg-error "'omp_cur_iteration' undeclared \\\(first use in this function\\\)" "" { target c } } */
+ } /* { dg-error "'omp_cur_iteration' has not been declared" "" { target c++ } .-1 } */
+}
@@ -160,7 +160,14 @@ foo (void)
for (i = 0; i < 64; i++)
#pragma omp parallel
{
- #pragma omp ordered depend(source) /* { dg-error ".ordered. construct with .depend. clause must be closely nested inside a loop with .ordered. clause with a parameter" } */
- #pragma omp ordered depend(sink: i - 1) /* { dg-error ".ordered. construct with .depend. clause must be closely nested inside a loop with .ordered. clause with a parameter" } */
+ #pragma omp ordered depend(source) /* { dg-error ".ordered. construct with .depend. clause must be closely nested inside a loop with .ordered. clause" } */
+ #pragma omp ordered depend(sink: i - 1) /* { dg-error ".ordered. construct with .depend. clause must be closely nested inside a loop with .ordered. clause" } */
+ }
+ #pragma omp for ordered(1)
+ for (i = 0; i < 64; i++)
+ #pragma omp parallel
+ {
+ #pragma omp ordered doacross(source:) /* { dg-error ".ordered. construct with .doacross. clause must be closely nested inside a loop with .ordered. clause" } */
+ #pragma omp ordered doacross(sink: i - 1) /* { dg-error ".ordered. construct with .doacross. clause must be closely nested inside a loop with .ordered. clause" } */
}
}
@@ -47,29 +47,53 @@ foo (void)
#pragma omp ordered threads, simd, threads, simd /* { dg-error "too many .threads. clauses" } */
; /* { dg-error "too many .simd. clauses" "" { target *-*-* } .-1 } */
}
- #pragma omp for simd ordered(1) /* { dg-error ".ordered. clause with parameter may not be specified on .#pragma omp for simd. construct" } */
+ #pragma omp for simd ordered(1)
for (i = 0; i < 64; i++)
{
- #pragma omp ordered depend(sink: i - 1) /* { dg-error "clause must be closely nested inside a loop with .ordered. clause with a parameter" } */
- #pragma omp ordered depend(source) /* { dg-error "clause must be closely nested inside a loop with .ordered. clause with a parameter" } */
+ #pragma omp ordered depend(sink: i - 1) /* { dg-error "clause must be closely nested inside a loop with .ordered. clause" } */
+ #pragma omp ordered depend(source) /* { dg-error "clause must be closely nested inside a loop with .ordered. clause" } */
}
- #pragma omp parallel for simd ordered(1) /* { dg-error ".ordered. clause with parameter may not be specified on .#pragma omp parallel for simd. construct" } */
+ #pragma omp for simd ordered(1)
for (i = 0; i < 64; i++)
{
- #pragma omp ordered depend(sink: i - 1) /* { dg-error "clause must be closely nested inside a loop with .ordered. clause with a parameter" } */
- #pragma omp ordered depend(source) /* { dg-error "clause must be closely nested inside a loop with .ordered. clause with a parameter" } */
+ #pragma omp ordered doacross(sink: i - 1) /* { dg-error "clause must be closely nested inside a loop with .ordered. clause" } */
+ #pragma omp ordered doacross(source:omp_cur_iteration) /* { dg-error "clause must be closely nested inside a loop with .ordered. clause" } */
+ }
+ #pragma omp parallel for simd ordered(1)
+ for (i = 0; i < 64; i++)
+ {
+ #pragma omp ordered depend(sink: i - 1) /* { dg-error "clause must be closely nested inside a loop with .ordered. clause" } */
+ #pragma omp ordered depend(source) /* { dg-error "clause must be closely nested inside a loop with .ordered. clause" } */
+ }
+ #pragma omp parallel for simd ordered(1)
+ for (i = 0; i < 64; i++)
+ {
+ #pragma omp ordered doacross(sink: i - 1) /* { dg-error "clause must be closely nested inside a loop with .ordered. clause" } */
+ #pragma omp ordered doacross(source:) /* { dg-error "clause must be closely nested inside a loop with .ordered. clause" } */
+ }
+ #pragma omp parallel for ordered
+ for (i = 0; i < 64; i++)
+ {
+ #pragma omp ordered depend(sink: i - 1)
+ #pragma omp ordered depend(source)
}
#pragma omp parallel for ordered
for (i = 0; i < 64; i++)
{
- #pragma omp ordered depend(sink: i - 1) /* { dg-error "clause must be closely nested inside a loop with .ordered. clause with a parameter" } */
- #pragma omp ordered depend(source) /* { dg-error "clause must be closely nested inside a loop with .ordered. clause with a parameter" } */
+ #pragma omp ordered doacross(sink: i - 1)
+ #pragma omp ordered doacross(source:)
+ }
+ #pragma omp parallel for
+ for (i = 0; i < 64; i++)
+ {
+ #pragma omp ordered depend(sink: i - 1) /* { dg-error "clause must be closely nested inside a loop with .ordered. clause" } */
+ #pragma omp ordered depend(source) /* { dg-error "clause must be closely nested inside a loop with .ordered. clause" } */
}
#pragma omp parallel for
for (i = 0; i < 64; i++)
{
- #pragma omp ordered depend(sink: i - 1) /* { dg-error "clause must be closely nested inside a loop with .ordered. clause with a parameter" } */
- #pragma omp ordered depend(source) /* { dg-error "clause must be closely nested inside a loop with .ordered. clause with a parameter" } */
+ #pragma omp ordered doacross(sink: i - 1) /* { dg-error "clause must be closely nested inside a loop with .ordered. clause" } */
+ #pragma omp ordered doacross(source:) /* { dg-error "clause must be closely nested inside a loop with .ordered. clause" } */
}
}
@@ -14,7 +14,7 @@ foo ()
for (i=0; i < 100; ++i)
{
#pragma omp ordered depend(sink:poo-1,paa+1) /* { dg-error "poo.*declared.*paa.*declared" } */
- bar(&i); /* { dg-error "may not be closely nested" "" { target *-*-* } .-1 } */
+ bar(&i); /* { dg-error "must not have the same binding region" "" { target *-*-* } .-1 } */
#pragma omp ordered depend(source)
}
}
@@ -158,8 +158,8 @@ subroutine foo
!$omp do ordered(1)
do i = 0, 63
!$omp parallel
- !$omp ordered depend(source) ! { dg-error ".ordered. construct with .depend. clause must be closely nested inside a loop with .ordered. clause with a parameter" }
- !$omp ordered depend(sink: i - 1) ! { dg-error ".ordered. construct with .depend. clause must be closely nested inside a loop with .ordered. clause with a parameter" }
+ !$omp ordered depend(source) ! { dg-error ".ordered. construct with .depend. clause must be closely nested inside a loop with .ordered. clause" }
+ !$omp ordered depend(sink: i - 1) ! { dg-error ".ordered. construct with .depend. clause must be closely nested inside a loop with .ordered. clause" }
!$omp end parallel
end do
end