@@ -450,7 +450,10 @@ enum omp_clause_schedule_kind {
OMP_CLAUSE_SCHEDULE_AUTO,
OMP_CLAUSE_SCHEDULE_RUNTIME,
OMP_CLAUSE_SCHEDULE_CILKFOR,
- OMP_CLAUSE_SCHEDULE_LAST
+ OMP_CLAUSE_SCHEDULE_MASK = (1 << 3) - 1,
+ OMP_CLAUSE_SCHEDULE_MONOTONIC = (1 << 3),
+ OMP_CLAUSE_SCHEDULE_NONMONOTONIC = (1 << 4),
+ OMP_CLAUSE_SCHEDULE_LAST = 2 * OMP_CLAUSE_SCHEDULE_NONMONOTONIC - 1
};
enum omp_clause_default_kind {
@@ -113,6 +113,14 @@ DEF_GOMP_BUILTIN (BUILT_IN_GOMP_LOOP_RUN
"GOMP_loop_runtime_start",
BT_FN_BOOL_LONG_LONG_LONG_LONGPTR_LONGPTR,
ATTR_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_LOOP_NONMONOTONIC_DYNAMIC_START,
+ "GOMP_loop_nonmonotonic_dynamic_start",
+ BT_FN_BOOL_LONG_LONG_LONG_LONG_LONGPTR_LONGPTR,
+ ATTR_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_LOOP_NONMONOTONIC_GUIDED_START,
+ "GOMP_loop_nonmonotonic_guided_start",
+ BT_FN_BOOL_LONG_LONG_LONG_LONG_LONGPTR_LONGPTR,
+ ATTR_NOTHROW_LEAF_LIST)
DEF_GOMP_BUILTIN (BUILT_IN_GOMP_LOOP_ORDERED_STATIC_START,
"GOMP_loop_ordered_static_start",
BT_FN_BOOL_LONG_LONG_LONG_LONG_LONGPTR_LONGPTR,
@@ -153,6 +161,12 @@ DEF_GOMP_BUILTIN (BUILT_IN_GOMP_LOOP_GUI
BT_FN_BOOL_LONGPTR_LONGPTR, ATTR_NOTHROW_LEAF_LIST)
DEF_GOMP_BUILTIN (BUILT_IN_GOMP_LOOP_RUNTIME_NEXT, "GOMP_loop_runtime_next",
BT_FN_BOOL_LONGPTR_LONGPTR, ATTR_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_LOOP_NONMONOTONIC_DYNAMIC_NEXT,
+ "GOMP_loop_nonmonotonic_dynamic_next",
+ BT_FN_BOOL_LONGPTR_LONGPTR, ATTR_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_LOOP_NONMONOTONIC_GUIDED_NEXT,
+ "GOMP_loop_nonmonotonic_guided_next",
+ BT_FN_BOOL_LONGPTR_LONGPTR, ATTR_NOTHROW_LEAF_LIST)
DEF_GOMP_BUILTIN (BUILT_IN_GOMP_LOOP_ORDERED_STATIC_NEXT,
"GOMP_loop_ordered_static_next",
BT_FN_BOOL_LONGPTR_LONGPTR, ATTR_NOTHROW_LEAF_LIST)
@@ -181,6 +195,14 @@ DEF_GOMP_BUILTIN (BUILT_IN_GOMP_LOOP_ULL
"GOMP_loop_ull_runtime_start",
BT_FN_BOOL_BOOL_ULL_ULL_ULL_ULLPTR_ULLPTR,
ATTR_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_LOOP_ULL_NONMONOTONIC_DYNAMIC_START,
+ "GOMP_loop_ull_nonmonotonic_dynamic_start",
+ BT_FN_BOOL_BOOL_ULL_ULL_ULL_ULL_ULLPTR_ULLPTR,
+ ATTR_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_LOOP_ULL_NONMONOTONIC_GUIDED_START,
+ "GOMP_loop_ull_nonmonotonic_guided_start",
+ BT_FN_BOOL_BOOL_ULL_ULL_ULL_ULL_ULLPTR_ULLPTR,
+ ATTR_NOTHROW_LEAF_LIST)
DEF_GOMP_BUILTIN (BUILT_IN_GOMP_LOOP_ULL_ORDERED_STATIC_START,
"GOMP_loop_ull_ordered_static_start",
BT_FN_BOOL_BOOL_ULL_ULL_ULL_ULL_ULLPTR_ULLPTR,
@@ -213,13 +235,23 @@ DEF_GOMP_BUILTIN (BUILT_IN_GOMP_LOOP_ULL
"GOMP_loop_ull_doacross_runtime_start",
BT_FN_BOOL_UINT_ULLPTR_ULLPTR_ULLPTR,
ATTR_NOTHROW_LEAF_LIST)
-DEF_GOMP_BUILTIN (BUILT_IN_GOMP_LOOP_ULL_STATIC_NEXT, "GOMP_loop_ull_static_next",
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_LOOP_ULL_STATIC_NEXT,
+ "GOMP_loop_ull_static_next",
+ BT_FN_BOOL_ULONGLONGPTR_ULONGLONGPTR, ATTR_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_LOOP_ULL_DYNAMIC_NEXT,
+ "GOMP_loop_ull_dynamic_next",
+ BT_FN_BOOL_ULONGLONGPTR_ULONGLONGPTR, ATTR_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_LOOP_ULL_GUIDED_NEXT,
+ "GOMP_loop_ull_guided_next",
BT_FN_BOOL_ULONGLONGPTR_ULONGLONGPTR, ATTR_NOTHROW_LEAF_LIST)
-DEF_GOMP_BUILTIN (BUILT_IN_GOMP_LOOP_ULL_DYNAMIC_NEXT, "GOMP_loop_ull_dynamic_next",
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_LOOP_ULL_RUNTIME_NEXT,
+ "GOMP_loop_ull_runtime_next",
BT_FN_BOOL_ULONGLONGPTR_ULONGLONGPTR, ATTR_NOTHROW_LEAF_LIST)
-DEF_GOMP_BUILTIN (BUILT_IN_GOMP_LOOP_ULL_GUIDED_NEXT, "GOMP_loop_ull_guided_next",
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_LOOP_ULL_NONMONOTONIC_DYNAMIC_NEXT,
+ "GOMP_loop_ull_nonmonotonic_dynamic_next",
BT_FN_BOOL_ULONGLONGPTR_ULONGLONGPTR, ATTR_NOTHROW_LEAF_LIST)
-DEF_GOMP_BUILTIN (BUILT_IN_GOMP_LOOP_ULL_RUNTIME_NEXT, "GOMP_loop_ull_runtime_next",
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_LOOP_ULL_NONMONOTONIC_GUIDED_NEXT,
+ "GOMP_loop_ull_nonmonotonic_guided_next",
BT_FN_BOOL_ULONGLONGPTR_ULONGLONGPTR, ATTR_NOTHROW_LEAF_LIST)
DEF_GOMP_BUILTIN (BUILT_IN_GOMP_LOOP_ULL_ORDERED_STATIC_NEXT,
"GOMP_loop_ull_ordered_static_next",
@@ -252,6 +284,14 @@ DEF_GOMP_BUILTIN (BUILT_IN_GOMP_PARALLEL
"GOMP_parallel_loop_runtime",
BT_FN_VOID_OMPFN_PTR_UINT_LONG_LONG_LONG_UINT,
ATTR_NOTHROW_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_PARALLEL_LOOP_NONMONOTONIC_DYNAMIC,
+ "GOMP_parallel_loop_nonmonotonic_dynamic",
+ BT_FN_VOID_OMPFN_PTR_UINT_LONG_LONG_LONG_LONG_UINT,
+ ATTR_NOTHROW_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_PARALLEL_LOOP_NONMONOTONIC_GUIDED,
+ "GOMP_parallel_loop_nonmonotonic_guided",
+ BT_FN_VOID_OMPFN_PTR_UINT_LONG_LONG_LONG_LONG_UINT,
+ ATTR_NOTHROW_LIST)
DEF_GOMP_BUILTIN (BUILT_IN_GOMP_LOOP_END, "GOMP_loop_end",
BT_FN_VOID, ATTR_NOTHROW_LEAF_LIST)
DEF_GOMP_BUILTIN (BUILT_IN_GOMP_LOOP_END_CANCEL, "GOMP_loop_end_cancel",
@@ -128,6 +128,9 @@ struct omp_region
/* Schedule kind, only used for GIMPLE_OMP_FOR type regions. */
enum omp_clause_schedule_kind sched_kind;
+ /* Schedule modifiers. */
+ unsigned char sched_modifiers;
+
/* True if this is a combined parallel+workshare region. */
bool is_combined_parallel;
@@ -229,6 +232,7 @@ struct omp_for_data
int collapse;
int ordered;
bool have_nowait, have_ordered, simd_schedule;
+ unsigned char sched_modifiers;
enum omp_clause_schedule_kind sched_kind;
struct omp_for_data_loop *loops;
};
@@ -493,6 +497,7 @@ extract_omp_for_data (gomp_for *for_stmt
fd->collapse = 1;
fd->ordered = 0;
fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
+ fd->sched_modifiers = 0;
fd->chunk_size = NULL_TREE;
fd->simd_schedule = false;
if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_CILKFOR)
@@ -513,7 +518,11 @@ extract_omp_for_data (gomp_for *for_stmt
break;
case OMP_CLAUSE_SCHEDULE:
gcc_assert (!distribute && !taskloop);
- fd->sched_kind = OMP_CLAUSE_SCHEDULE_KIND (t);
+ fd->sched_kind
+ = (enum omp_clause_schedule_kind)
+ (OMP_CLAUSE_SCHEDULE_KIND (t) & OMP_CLAUSE_SCHEDULE_MASK);
+ fd->sched_modifiers = (OMP_CLAUSE_SCHEDULE_KIND (t)
+ & ~OMP_CLAUSE_SCHEDULE_MASK);
fd->chunk_size = OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (t);
fd->simd_schedule = OMP_CLAUSE_SCHEDULE_SIMD (t);
break;
@@ -1011,7 +1020,8 @@ determine_parallel_type (struct omp_regi
tree clauses = gimple_omp_for_clauses (ws_stmt);
tree c = find_omp_clause (clauses, OMP_CLAUSE_SCHEDULE);
if (c == NULL
- || OMP_CLAUSE_SCHEDULE_KIND (c) == OMP_CLAUSE_SCHEDULE_STATIC
+ || ((OMP_CLAUSE_SCHEDULE_KIND (c) & OMP_CLAUSE_SCHEDULE_MASK)
+ == OMP_CLAUSE_SCHEDULE_STATIC)
|| find_omp_clause (clauses, OMP_CLAUSE_ORDERED))
{
region->is_combined_parallel = false;
@@ -5817,11 +5827,26 @@ expand_parallel_call (struct omp_region
{
case GIMPLE_OMP_FOR:
gcc_assert (region->inner->sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
- start_ix2 = ((int)BUILT_IN_GOMP_PARALLEL_LOOP_STATIC
- + (region->inner->sched_kind
- == OMP_CLAUSE_SCHEDULE_RUNTIME
- ? 3 : region->inner->sched_kind));
- start_ix = (enum built_in_function)start_ix2;
+ switch (region->inner->sched_kind)
+ {
+ case OMP_CLAUSE_SCHEDULE_RUNTIME:
+ start_ix2 = 3;
+ break;
+ case OMP_CLAUSE_SCHEDULE_DYNAMIC:
+ case OMP_CLAUSE_SCHEDULE_GUIDED:
+ if (region->inner->sched_modifiers
+ & OMP_CLAUSE_SCHEDULE_NONMONOTONIC)
+ {
+ start_ix2 = 3 + region->inner->sched_kind;
+ break;
+ }
+ /* FALLTHRU */
+ default:
+ start_ix2 = region->inner->sched_kind;
+ break;
+ }
+ start_ix2 += (int) BUILT_IN_GOMP_PARALLEL_LOOP_STATIC;
+ start_ix = (enum built_in_function) start_ix2;
break;
case GIMPLE_OMP_SECTIONS:
start_ix = BUILT_IN_GOMP_PARALLEL_SECTIONS;
@@ -10225,6 +10250,7 @@ expand_omp_for (struct omp_region *regio
extract_omp_for_data (as_a <gomp_for *> (last_stmt (region->entry)),
&fd, loops);
region->sched_kind = fd.sched_kind;
+ region->sched_modifiers = fd.sched_modifiers;
gcc_assert (EDGE_COUNT (region->entry->succs) == 2);
BRANCH_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
@@ -10270,10 +10296,27 @@ expand_omp_for (struct omp_region *regio
&& fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
fd.chunk_size = integer_zero_node;
gcc_assert (fd.sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
- fn_index = (fd.sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
- ? 3 : fd.sched_kind;
+ switch (fd.sched_kind)
+ {
+ case OMP_CLAUSE_SCHEDULE_RUNTIME:
+ fn_index = 3;
+ break;
+ case OMP_CLAUSE_SCHEDULE_DYNAMIC:
+ case OMP_CLAUSE_SCHEDULE_GUIDED:
+ if ((fd.sched_modifiers & OMP_CLAUSE_SCHEDULE_NONMONOTONIC)
+ && !fd.ordered
+ && !fd.have_ordered)
+ {
+ fn_index = 3 + fd.sched_kind;
+ break;
+ }
+ /* FALLTHRU */
+ default:
+ fn_index = fd.sched_kind;
+ break;
+ }
if (!fd.ordered)
- fn_index += fd.have_ordered * 4;
+ fn_index += fd.have_ordered * 6;
if (fd.ordered)
start_ix = ((int)BUILT_IN_GOMP_LOOP_DOACROSS_STATIC_START) + fn_index;
else
@@ -447,9 +447,24 @@ dump_omp_clause (pretty_printer *pp, tre
case OMP_CLAUSE_SCHEDULE:
pp_string (pp, "schedule(");
+ if (OMP_CLAUSE_SCHEDULE_KIND (clause)
+ & (OMP_CLAUSE_SCHEDULE_MONOTONIC
+ | OMP_CLAUSE_SCHEDULE_NONMONOTONIC))
+ {
+ if (OMP_CLAUSE_SCHEDULE_KIND (clause)
+ & OMP_CLAUSE_SCHEDULE_MONOTONIC)
+ pp_string (pp, "monotonic");
+ else
+ pp_string (pp, "nonmonotonic");
+ if (OMP_CLAUSE_SCHEDULE_SIMD (clause))
+ pp_comma (pp);
+ else
+ pp_colon (pp);
+ }
if (OMP_CLAUSE_SCHEDULE_SIMD (clause))
pp_string (pp, "simd:");
- switch (OMP_CLAUSE_SCHEDULE_KIND (clause))
+
+ switch (OMP_CLAUSE_SCHEDULE_KIND (clause) & OMP_CLAUSE_SCHEDULE_MASK)
{
case OMP_CLAUSE_SCHEDULE_STATIC:
pp_string (pp, "static");
@@ -11417,35 +11417,58 @@ c_parser_omp_clause_reduction (c_parser
OpenMP 4.5:
schedule ( schedule-modifier : schedule-kind )
- schedule ( schedule-modifier : schedule-kind , expression )
+ schedule ( schedule-modifier [ , schedule-modifier ] : schedule-kind , expression )
schedule-modifier:
- simd */
+ simd
+ monotonic
+ nonmonotonic */
static tree
c_parser_omp_clause_schedule (c_parser *parser, tree list)
{
tree c, t;
location_t loc = c_parser_peek_token (parser)->location;
+ int modifiers = 0, nmodifiers = 0;
if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
return list;
c = build_omp_clause (loc, OMP_CLAUSE_SCHEDULE);
- if (c_parser_next_token_is (parser, CPP_NAME))
+ while (c_parser_next_token_is (parser, CPP_NAME))
{
tree kind = c_parser_peek_token (parser)->value;
const char *p = IDENTIFIER_POINTER (kind);
- if (strcmp ("simd", p) == 0
- && c_parser_peek_2nd_token (parser)->type == CPP_COLON)
+ if (strcmp ("simd", p) == 0)
+ OMP_CLAUSE_SCHEDULE_SIMD (c) = 1;
+ else if (strcmp ("monotonic", p) == 0)
+ modifiers |= OMP_CLAUSE_SCHEDULE_MONOTONIC;
+ else if (strcmp ("nonmonotonic", p) == 0)
+ modifiers |= OMP_CLAUSE_SCHEDULE_NONMONOTONIC;
+ else
+ break;
+ c_parser_consume_token (parser);
+ if (nmodifiers++ == 0
+ && c_parser_next_token_is (parser, CPP_COMMA))
+ c_parser_consume_token (parser);
+ else
{
- OMP_CLAUSE_SCHEDULE_SIMD (c) = 1;
- c_parser_consume_token (parser);
- c_parser_consume_token (parser);
+ c_parser_require (parser, CPP_COLON, "expected %<:%>");
+ break;
}
}
+ if ((modifiers & (OMP_CLAUSE_SCHEDULE_MONOTONIC
+ | OMP_CLAUSE_SCHEDULE_NONMONOTONIC))
+ == (OMP_CLAUSE_SCHEDULE_MONOTONIC
+ | OMP_CLAUSE_SCHEDULE_NONMONOTONIC))
+ {
+ error_at (loc, "both %<monotonic%> and %<nonmonotonic%> modifiers "
+ "specified");
+ modifiers = 0;
+ }
+
if (c_parser_next_token_is (parser, CPP_NAME))
{
tree kind = c_parser_peek_token (parser)->value;
@@ -11511,6 +11534,10 @@ c_parser_omp_clause_schedule (c_parser *
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
"expected %<,%> or %<)%>");
+ OMP_CLAUSE_SCHEDULE_KIND (c)
+ = (enum omp_clause_schedule_kind)
+ (OMP_CLAUSE_SCHEDULE_KIND (c) | modifiers);
+
check_no_duplicate_clause (list, OMP_CLAUSE_SCHEDULE, "schedule");
OMP_CLAUSE_CHAIN (c) = list;
return c;
@@ -12235,6 +12235,8 @@ c_finish_omp_clauses (tree clauses, bool
bool branch_seen = false;
bool copyprivate_seen = false;
tree *nowait_clause = NULL;
+ bool ordered_seen = false;
+ tree schedule_clause = NULL_TREE;
bitmap_obstack_initialize (NULL);
bitmap_initialize (&generic_head, &bitmap_default_obstack);
@@ -12909,8 +12911,6 @@ c_finish_omp_clauses (tree clauses, bool
case OMP_CLAUSE_NUM_THREADS:
case OMP_CLAUSE_NUM_TEAMS:
case OMP_CLAUSE_THREAD_LIMIT:
- case OMP_CLAUSE_SCHEDULE:
- case OMP_CLAUSE_ORDERED:
case OMP_CLAUSE_DEFAULT:
case OMP_CLAUSE_UNTIED:
case OMP_CLAUSE_COLLAPSE:
@@ -12945,6 +12945,39 @@ c_finish_omp_clauses (tree clauses, bool
pc = &OMP_CLAUSE_CHAIN (c);
continue;
+ case OMP_CLAUSE_SCHEDULE:
+ if (OMP_CLAUSE_SCHEDULE_KIND (c) & OMP_CLAUSE_SCHEDULE_NONMONOTONIC)
+ {
+ const char *p = NULL;
+ switch (OMP_CLAUSE_SCHEDULE_KIND (c) & OMP_CLAUSE_SCHEDULE_MASK)
+ {
+ case OMP_CLAUSE_SCHEDULE_STATIC: p = "static"; break;
+ case OMP_CLAUSE_SCHEDULE_DYNAMIC: break;
+ case OMP_CLAUSE_SCHEDULE_GUIDED: break;
+ case OMP_CLAUSE_SCHEDULE_AUTO: p = "auto"; break;
+ case OMP_CLAUSE_SCHEDULE_RUNTIME: p = "runtime"; break;
+ default: gcc_unreachable ();
+ }
+ if (p)
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%<nonmonotonic%> modifier specified for %qs "
+ "schedule kind", p);
+ OMP_CLAUSE_SCHEDULE_KIND (c)
+ = (enum omp_clause_schedule_kind)
+ (OMP_CLAUSE_SCHEDULE_KIND (c)
+ & ~OMP_CLAUSE_SCHEDULE_NONMONOTONIC);
+ }
+ }
+ schedule_clause = c;
+ pc = &OMP_CLAUSE_CHAIN (c);
+ continue;
+
+ case OMP_CLAUSE_ORDERED:
+ ordered_seen = true;
+ pc = &OMP_CLAUSE_CHAIN (c);
+ continue;
+
case OMP_CLAUSE_SAFELEN:
safelen = c;
pc = &OMP_CLAUSE_CHAIN (c);
@@ -13035,6 +13068,20 @@ c_finish_omp_clauses (tree clauses, bool
= OMP_CLAUSE_SAFELEN_EXPR (safelen);
}
+ if (ordered_seen
+ && schedule_clause
+ && (OMP_CLAUSE_SCHEDULE_KIND (schedule_clause)
+ & OMP_CLAUSE_SCHEDULE_NONMONOTONIC))
+ {
+ error_at (OMP_CLAUSE_LOCATION (schedule_clause),
+ "%<nonmonotonic%> schedule modifier specified together "
+ "with %<ordered%> clause");
+ OMP_CLAUSE_SCHEDULE_KIND (schedule_clause)
+ = (enum omp_clause_schedule_kind)
+ (OMP_CLAUSE_SCHEDULE_KIND (schedule_clause)
+ & ~OMP_CLAUSE_SCHEDULE_NONMONOTONIC);
+ }
+
bitmap_obstack_release (NULL);
return clauses;
}
@@ -30440,31 +30440,44 @@ cp_parser_omp_clause_reduction (cp_parse
OpenMP 4.5:
schedule ( schedule-modifier : schedule-kind )
- schedule ( schedule-modifier : schedule-kind , expression )
+ schedule ( schedule-modifier [ , schedule-modifier ] : schedule-kind , expression )
schedule-modifier:
- simd */
+ simd
+ monotonic
+ nonmonotonic */
static tree
cp_parser_omp_clause_schedule (cp_parser *parser, tree list, location_t location)
{
tree c, t;
+ int modifiers = 0, nmodifiers = 0;
if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
return list;
c = build_omp_clause (location, OMP_CLAUSE_SCHEDULE);
- if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
+ while (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
{
tree id = cp_lexer_peek_token (parser->lexer)->u.value;
const char *p = IDENTIFIER_POINTER (id);
- if (strcmp ("simd", p) == 0
- && cp_lexer_nth_token_is (parser->lexer, 2, CPP_COLON))
+ if (strcmp ("simd", p) == 0)
+ OMP_CLAUSE_SCHEDULE_SIMD (c) = 1;
+ else if (strcmp ("monotonic", p) == 0)
+ modifiers |= OMP_CLAUSE_SCHEDULE_MONOTONIC;
+ else if (strcmp ("nonmonotonic", p) == 0)
+ modifiers |= OMP_CLAUSE_SCHEDULE_NONMONOTONIC;
+ else
+ break;
+ cp_lexer_consume_token (parser->lexer);
+ if (nmodifiers++ == 0
+ && cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
+ cp_lexer_consume_token (parser->lexer);
+ else
{
- OMP_CLAUSE_SCHEDULE_SIMD (c) = 1;
- cp_lexer_consume_token (parser->lexer);
- cp_lexer_consume_token (parser->lexer);
+ cp_parser_require (parser, CPP_COLON, RT_COLON);
+ break;
}
}
@@ -30505,6 +30518,16 @@ cp_parser_omp_clause_schedule (cp_parser
goto invalid_kind;
cp_lexer_consume_token (parser->lexer);
+ if ((modifiers & (OMP_CLAUSE_SCHEDULE_MONOTONIC
+ | OMP_CLAUSE_SCHEDULE_NONMONOTONIC))
+ == (OMP_CLAUSE_SCHEDULE_MONOTONIC
+ | OMP_CLAUSE_SCHEDULE_NONMONOTONIC))
+ {
+ error_at (location, "both %<monotonic%> and %<nonmonotonic%> modifiers "
+ "specified");
+ modifiers = 0;
+ }
+
if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
{
cp_token *token;
@@ -30530,6 +30553,10 @@ cp_parser_omp_clause_schedule (cp_parser
else if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_COMMA_CLOSE_PAREN))
goto resync_fail;
+ OMP_CLAUSE_SCHEDULE_KIND (c)
+ = (enum omp_clause_schedule_kind)
+ (OMP_CLAUSE_SCHEDULE_KIND (c) | modifiers);
+
check_no_duplicate_clause (list, OMP_CLAUSE_SCHEDULE, "schedule", location);
OMP_CLAUSE_CHAIN (c) = list;
return c;
@@ -5652,6 +5652,7 @@ finish_omp_clauses (tree clauses, bool a
tree safelen = NULL_TREE;
bool branch_seen = false;
bool copyprivate_seen = false;
+ bool ordered_seen = false;
bitmap_obstack_initialize (NULL);
bitmap_initialize (&generic_head, &bitmap_default_obstack);
@@ -5988,6 +5989,30 @@ finish_omp_clauses (tree clauses, bool a
break;
case OMP_CLAUSE_SCHEDULE:
+ if (OMP_CLAUSE_SCHEDULE_KIND (c) & OMP_CLAUSE_SCHEDULE_NONMONOTONIC)
+ {
+ const char *p = NULL;
+ switch (OMP_CLAUSE_SCHEDULE_KIND (c) & OMP_CLAUSE_SCHEDULE_MASK)
+ {
+ case OMP_CLAUSE_SCHEDULE_STATIC: p = "static"; break;
+ case OMP_CLAUSE_SCHEDULE_DYNAMIC: break;
+ case OMP_CLAUSE_SCHEDULE_GUIDED: break;
+ case OMP_CLAUSE_SCHEDULE_AUTO: p = "auto"; break;
+ case OMP_CLAUSE_SCHEDULE_RUNTIME: p = "runtime"; break;
+ default: gcc_unreachable ();
+ }
+ if (p)
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%<nonmonotonic%> modifier specified for %qs "
+ "schedule kind", p);
+ OMP_CLAUSE_SCHEDULE_KIND (c)
+ = (enum omp_clause_schedule_kind)
+ (OMP_CLAUSE_SCHEDULE_KIND (c)
+ & ~OMP_CLAUSE_SCHEDULE_NONMONOTONIC);
+ }
+ }
+
t = OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (c);
if (t == NULL)
;
@@ -6672,7 +6697,6 @@ finish_omp_clauses (tree clauses, bool a
goto check_dup_generic;
case OMP_CLAUSE_NOWAIT:
- case OMP_CLAUSE_ORDERED:
case OMP_CLAUSE_DEFAULT:
case OMP_CLAUSE_UNTIED:
case OMP_CLAUSE_COLLAPSE:
@@ -6689,6 +6713,10 @@ finish_omp_clauses (tree clauses, bool a
case OMP_CLAUSE__CILK_FOR_COUNT_:
break;
+ case OMP_CLAUSE_ORDERED:
+ ordered_seen = true;
+ break;
+
case OMP_CLAUSE_INBRANCH:
case OMP_CLAUSE_NOTINBRANCH:
if (branch_seen)
@@ -6771,6 +6799,21 @@ finish_omp_clauses (tree clauses, bool a
}
pc = &OMP_CLAUSE_CHAIN (c);
continue;
+ case OMP_CLAUSE_SCHEDULE:
+ if (ordered_seen
+ && (OMP_CLAUSE_SCHEDULE_KIND (c)
+ & OMP_CLAUSE_SCHEDULE_NONMONOTONIC))
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%<nonmonotonic%> schedule modifier specified "
+ "together with %<ordered%> clause");
+ OMP_CLAUSE_SCHEDULE_KIND (c)
+ = (enum omp_clause_schedule_kind)
+ (OMP_CLAUSE_SCHEDULE_KIND (c)
+ & ~OMP_CLAUSE_SCHEDULE_NONMONOTONIC);
+ }
+ pc = &OMP_CLAUSE_CHAIN (c);
+ continue;
case OMP_CLAUSE_NOWAIT:
if (copyprivate_seen)
{
@@ -0,0 +1,109 @@
+/* { dg-do compile } */
+/* { dg-options "-fopenmp" } */
+
+void
+foo (void)
+{
+ int i;
+ #pragma omp for simd schedule (simd, simd: static, 5)
+ for (i = 0; i < 64; i++)
+ ;
+ #pragma omp for simd schedule (monotonic, simd: static)
+ for (i = 0; i < 64; i++)
+ ;
+ #pragma omp for simd schedule (simd , monotonic : static, 6)
+ for (i = 0; i < 64; i++)
+ ;
+ #pragma omp for schedule (monotonic, monotonic : static, 7)
+ for (i = 0; i < 64; i++)
+ ;
+ #pragma omp for schedule (nonmonotonic, nonmonotonic : dynamic)
+ for (i = 0; i < 64; i++)
+ ;
+ #pragma omp for simd schedule (nonmonotonic , simd : dynamic, 3)
+ for (i = 0; i < 64; i++)
+ ;
+ #pragma omp for simd schedule (nonmonotonic,simd:guided,4)
+ for (i = 0; i < 64; i++)
+ ;
+ #pragma omp for schedule (monotonic: static, 2)
+ for (i = 0; i < 64; i++)
+ ;
+ #pragma omp for schedule (monotonic : static)
+ for (i = 0; i < 64; i++)
+ ;
+ #pragma omp for schedule (monotonic : dynamic)
+ for (i = 0; i < 64; i++)
+ ;
+ #pragma omp for schedule (monotonic : dynamic, 3)
+ for (i = 0; i < 64; i++)
+ ;
+ #pragma omp for schedule (monotonic : guided)
+ for (i = 0; i < 64; i++)
+ ;
+ #pragma omp for schedule (monotonic : guided, 7)
+ for (i = 0; i < 64; i++)
+ ;
+ #pragma omp for schedule (monotonic : runtime)
+ for (i = 0; i < 64; i++)
+ ;
+ #pragma omp for schedule (monotonic : auto)
+ for (i = 0; i < 64; i++)
+ ;
+ #pragma omp for schedule (nonmonotonic : dynamic)
+ for (i = 0; i < 64; i++)
+ ;
+ #pragma omp for schedule (nonmonotonic : dynamic, 3)
+ for (i = 0; i < 64; i++)
+ ;
+ #pragma omp for schedule (nonmonotonic : guided)
+ for (i = 0; i < 64; i++)
+ ;
+ #pragma omp for schedule (nonmonotonic : guided, 7)
+ for (i = 0; i < 64; i++)
+ ;
+}
+
+void
+bar (void)
+{
+ int i;
+ #pragma omp for schedule (nonmonotonic: static, 2) /* { dg-error ".nonmonotonic. modifier specified for .static. schedule kind" } */
+ for (i = 0; i < 64; i++)
+ ;
+ #pragma omp for schedule (nonmonotonic : static) /* { dg-error ".nonmonotonic. modifier specified for .static. schedule kind" } */
+ for (i = 0; i < 64; i++)
+ ;
+ #pragma omp for schedule (nonmonotonic : runtime) /* { dg-error ".nonmonotonic. modifier specified for .runtime. schedule kind" } */
+ for (i = 0; i < 64; i++)
+ ;
+ #pragma omp for schedule (nonmonotonic : auto) /* { dg-error ".nonmonotonic. modifier specified for .auto. schedule kind" } */
+ for (i = 0; i < 64; i++)
+ ;
+ #pragma omp for schedule (nonmonotonic, dynamic) ordered /* { dg-error ".nonmonotonic. schedule modifier specified together with .ordered. clause" } */
+ for (i = 0; i < 64; i++)
+ #pragma omp ordered
+ ;
+ #pragma omp for ordered schedule(nonmonotonic, dynamic, 5) /* { dg-error ".nonmonotonic. schedule modifier specified together with .ordered. clause" } */
+ for (i = 0; i < 64; i++)
+ #pragma omp ordered
+ ;
+ #pragma omp for schedule (nonmonotonic, guided) ordered(1) /* { dg-error ".nonmonotonic. schedule modifier specified together with .ordered. clause" } */
+ for (i = 0; i < 64; i++)
+ {
+ #pragma omp ordered depend(sink: i - 1)
+ #pragma omp ordered depend(source)
+ }
+ #pragma omp for ordered(1) schedule(nonmonotonic, guided, 2) /* { dg-error ".nonmonotonic. schedule modifier specified together with .ordered. clause" } */
+ for (i = 0; i < 64; i++)
+ {
+ #pragma omp ordered depend(source)
+ #pragma omp ordered depend(sink: i - 1)
+ }
+ #pragma omp for schedule (nonmonotonic , monotonic : dynamic) /* { dg-error "both .monotonic. and .nonmonotonic. modifiers specified" } */
+ for (i = 0; i < 64; i++)
+ ;
+ #pragma omp for schedule (monotonic,nonmonotonic:dynamic) /* { dg-error "both .monotonic. and .nonmonotonic. modifiers specified" } */
+ for (i = 0; i < 64; i++)
+ ;
+}
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-options "-fopenmp -fdump-tree-ompexp" } */
+
+extern void bar(int);
+
+void foo (int n)
+{
+ int i;
+
+ #pragma omp for schedule(nonmonotonic:guided)
+ for (i = 0; i < n; ++i)
+ bar(i);
+}
+
+/* { dg-final { scan-tree-dump-times "GOMP_loop_nonmonotonic_guided_start" 1 "ompexp" } } */
+/* { dg-final { scan-tree-dump-times "GOMP_loop_nonmonotonic_guided_next" 1 "ompexp" } } */
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-options "-fopenmp -fdump-tree-ompexp" } */
+
+extern void bar(int);
+
+void foo (int n)
+{
+ int i;
+
+ #pragma omp for schedule(nonmonotonic:dynamic, 2)
+ for (i = 0; i < n; ++i)
+ bar(i);
+}
+
+/* { dg-final { scan-tree-dump-times "GOMP_loop_nonmonotonic_dynamic_start" 1 "ompexp" } } */
+/* { dg-final { scan-tree-dump-times "GOMP_loop_nonmonotonic_dynamic_next" 1 "ompexp" } } */
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-options "-fopenmp -fdump-tree-ompexp" } */
+
+extern void bar(unsigned long long);
+
+void foo (unsigned long long n)
+{
+ unsigned long long i;
+
+ #pragma omp for schedule(nonmonotonic:guided, 7)
+ for (i = 0; i < n; ++i)
+ bar(i);
+}
+
+/* { dg-final { scan-tree-dump-times "GOMP_loop_ull_nonmonotonic_guided_start" 1 "ompexp" } } */
+/* { dg-final { scan-tree-dump-times "GOMP_loop_ull_nonmonotonic_guided_next" 1 "ompexp" } } */
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-options "-fopenmp -fdump-tree-ompexp" } */
+
+extern void bar(unsigned long long);
+
+void foo (unsigned long long n)
+{
+ unsigned long long i;
+
+ #pragma omp for schedule (nonmonotonic : dynamic)
+ for (i = 0; i < n; ++i)
+ bar(i);
+}
+
+/* { dg-final { scan-tree-dump-times "GOMP_loop_ull_nonmonotonic_dynamic_start" 1 "ompexp" } } */
+/* { dg-final { scan-tree-dump-times "GOMP_loop_ull_nonmonotonic_dynamic_next" 1 "ompexp" } } */
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fopenmp -fdump-tree-ssa" } */
+
+extern void bar(int);
+
+void foo (void)
+{
+ int i;
+
+ #pragma omp parallel for schedule (nonmonotonic : dynamic, 4)
+ for (i = 0; i < 37; ++i)
+ bar(i);
+}
+
+/* { dg-final { scan-tree-dump-times "GOMP_parallel_loop_nonmonotonic_dynamic" 1 "ssa" } } */
+/* { dg-final { scan-tree-dump-times "GOMP_loop_nonmonotonic_dynamic_start" 0 "ssa" } } */
+/* { dg-final { scan-tree-dump-times "GOMP_loop_nonmonotonic_dynamic_next" 2 "ssa" } } */
@@ -286,6 +286,16 @@ GOMP_4.5 {
GOMP_loop_ull_doacross_static_start;
GOMP_doacross_ull_post;
GOMP_doacross_ull_wait;
+ GOMP_loop_nonmonotonic_dynamic_next;
+ GOMP_loop_nonmonotonic_dynamic_start;
+ GOMP_loop_nonmonotonic_guided_next;
+ GOMP_loop_nonmonotonic_guided_start;
+ GOMP_loop_ull_nonmonotonic_dynamic_next;
+ GOMP_loop_ull_nonmonotonic_dynamic_start;
+ GOMP_loop_ull_nonmonotonic_guided_next;
+ GOMP_loop_ull_nonmonotonic_guided_start;
+ GOMP_parallel_loop_nonmonotonic_dynamic;
+ GOMP_parallel_loop_nonmonotonic_guided;
} GOMP_4.0.1;
OACC_2.0 {
@@ -52,6 +52,10 @@ extern bool GOMP_loop_static_start (long
extern bool GOMP_loop_dynamic_start (long, long, long, long, long *, long *);
extern bool GOMP_loop_guided_start (long, long, long, long, long *, long *);
extern bool GOMP_loop_runtime_start (long, long, long, long *, long *);
+extern bool GOMP_loop_nonmonotonic_dynamic_start (long, long, long, long,
+ long *, long *);
+extern bool GOMP_loop_nonmonotonic_guided_start (long, long, long, long,
+ long *, long *);
extern bool GOMP_loop_ordered_static_start (long, long, long, long,
long *, long *);
@@ -65,6 +69,8 @@ extern bool GOMP_loop_static_next (long
extern bool GOMP_loop_dynamic_next (long *, long *);
extern bool GOMP_loop_guided_next (long *, long *);
extern bool GOMP_loop_runtime_next (long *, long *);
+extern bool GOMP_loop_nonmonotonic_dynamic_next (long *, long *);
+extern bool GOMP_loop_nonmonotonic_guided_next (long *, long *);
extern bool GOMP_loop_ordered_static_next (long *, long *);
extern bool GOMP_loop_ordered_dynamic_next (long *, long *);
@@ -100,6 +106,12 @@ extern void GOMP_parallel_loop_guided (v
extern void GOMP_parallel_loop_runtime (void (*)(void *), void *,
unsigned, long, long, long,
unsigned);
+extern void GOMP_parallel_loop_nonmonotonic_dynamic (void (*)(void *), void *,
+ unsigned, long, long,
+ long, long, unsigned);
+extern void GOMP_parallel_loop_nonmonotonic_guided (void (*)(void *), void *,
+ unsigned, long, long,
+ long, long, unsigned);
extern void GOMP_loop_end (void);
extern void GOMP_loop_end_nowait (void);
@@ -130,6 +142,18 @@ extern bool GOMP_loop_ull_runtime_start
unsigned long long,
unsigned long long *,
unsigned long long *);
+extern bool GOMP_loop_ull_nonmonotonic_dynamic_start (bool, unsigned long long,
+ unsigned long long,
+ unsigned long long,
+ unsigned long long,
+ unsigned long long *,
+ unsigned long long *);
+extern bool GOMP_loop_ull_nonmonotonic_guided_start (bool, unsigned long long,
+ unsigned long long,
+ unsigned long long,
+ unsigned long long,
+ unsigned long long *,
+ unsigned long long *);
extern bool GOMP_loop_ull_ordered_static_start (bool, unsigned long long,
unsigned long long,
@@ -163,6 +187,10 @@ extern bool GOMP_loop_ull_guided_next (u
unsigned long long *);
extern bool GOMP_loop_ull_runtime_next (unsigned long long *,
unsigned long long *);
+extern bool GOMP_loop_ull_nonmonotonic_dynamic_next (unsigned long long *,
+ unsigned long long *);
+extern bool GOMP_loop_ull_nonmonotonic_guided_next (unsigned long long *,
+ unsigned long long *);
extern bool GOMP_loop_ull_ordered_static_next (unsigned long long *,
unsigned long long *);
@@ -111,6 +111,11 @@ gomp_loop_static_start (long start, long
return !gomp_iter_static_next (istart, iend);
}
+/* The current dynamic implementation is always monotonic. The
+ entrypoints without nonmonotonic in them have to be always monotonic,
+ but the nonmonotonic ones could be changed to use work-stealing for
+ improved scalability. */
+
static bool
gomp_loop_dynamic_start (long start, long end, long incr, long chunk_size,
long *istart, long *iend)
@@ -136,6 +141,9 @@ gomp_loop_dynamic_start (long start, lon
return ret;
}
+/* Similarly as for dynamic, though the question is how can the chunk sizes
+ be decreased without a central locking or atomics. */
+
static bool
gomp_loop_guided_start (long start, long end, long incr, long chunk_size,
long *istart, long *iend)
@@ -630,6 +638,37 @@ GOMP_parallel_loop_guided (void (*fn) (v
GOMP_parallel_end ();
}
+#ifdef HAVE_ATTRIBUTE_ALIAS
+extern __typeof(GOMP_parallel_loop_dynamic) GOMP_parallel_loop_nonmonotonic_dynamic
+ __attribute__((alias ("GOMP_parallel_loop_dynamic")));
+extern __typeof(GOMP_parallel_loop_guided) GOMP_parallel_loop_nonmonotonic_guided
+ __attribute__((alias ("GOMP_parallel_loop_guided")));
+#else
+void
+GOMP_parallel_loop_nonmonotonic_dynamic (void (*fn) (void *), void *data,
+ unsigned num_threads, long start,
+ long end, long incr, long chunk_size,
+ unsigned flags)
+{
+ gomp_parallel_loop_start (fn, data, num_threads, start, end, incr,
+ GFS_DYNAMIC, chunk_size, flags);
+ fn (data);
+ GOMP_parallel_end ();
+}
+
+void
+GOMP_parallel_loop_nonmonotonic_guided (void (*fn) (void *), void *data,
+ unsigned num_threads, long start,
+ long end, long incr, long chunk_size,
+ unsigned flags)
+{
+ gomp_parallel_loop_start (fn, data, num_threads, start, end, incr,
+ GFS_GUIDED, chunk_size, flags);
+ fn (data);
+ GOMP_parallel_end ();
+}
+#endif
+
void
GOMP_parallel_loop_runtime (void (*fn) (void *), void *data,
unsigned num_threads, long start, long end,
@@ -678,6 +717,10 @@ extern __typeof(gomp_loop_dynamic_start)
__attribute__((alias ("gomp_loop_dynamic_start")));
extern __typeof(gomp_loop_guided_start) GOMP_loop_guided_start
__attribute__((alias ("gomp_loop_guided_start")));
+extern __typeof(gomp_loop_dynamic_start) GOMP_loop_nonmonotonic_dynamic_start
+ __attribute__((alias ("gomp_loop_dynamic_start")));
+extern __typeof(gomp_loop_guided_start) GOMP_loop_nonmonotonic_guided_start
+ __attribute__((alias ("gomp_loop_guided_start")));
extern __typeof(gomp_loop_ordered_static_start) GOMP_loop_ordered_static_start
__attribute__((alias ("gomp_loop_ordered_static_start")));
@@ -699,6 +742,10 @@ extern __typeof(gomp_loop_dynamic_next)
__attribute__((alias ("gomp_loop_dynamic_next")));
extern __typeof(gomp_loop_guided_next) GOMP_loop_guided_next
__attribute__((alias ("gomp_loop_guided_next")));
+extern __typeof(gomp_loop_dynamic_next) GOMP_loop_nonmonotonic_dynamic_next
+ __attribute__((alias ("gomp_loop_dynamic_next")));
+extern __typeof(gomp_loop_guided_next) GOMP_loop_nonmonotonic_guided_next
+ __attribute__((alias ("gomp_loop_guided_next")));
extern __typeof(gomp_loop_ordered_static_next) GOMP_loop_ordered_static_next
__attribute__((alias ("gomp_loop_ordered_static_next")));
@@ -729,6 +776,21 @@ GOMP_loop_guided_start (long start, long
}
bool
+GOMP_loop_nonmonotonic_dynamic_start (long start, long end, long incr,
+ long chunk_size, long *istart,
+ long *iend)
+{
+ return gomp_loop_dynamic_start (start, end, incr, chunk_size, istart, iend);
+}
+
+bool
+GOMP_loop_nonmonotonic_guided_start (long start, long end, long incr,
+ long chunk_size, long *istart, long *iend)
+{
+ return gomp_loop_guided_start (start, end, incr, chunk_size, istart, iend);
+}
+
+bool
GOMP_loop_ordered_static_start (long start, long end, long incr,
long chunk_size, long *istart, long *iend)
{
@@ -793,6 +855,18 @@ GOMP_loop_guided_next (long *istart, lon
{
return gomp_loop_guided_next (istart, iend);
}
+
+bool
+GOMP_loop_nonmonotonic_dynamic_next (long *istart, long *iend)
+{
+ return gomp_loop_dynamic_next (istart, iend);
+}
+
+bool
+GOMP_loop_nonmonotonic_guided_next (long *istart, long *iend)
+{
+ return gomp_loop_guided_next (istart, iend);
+}
bool
GOMP_loop_ordered_static_next (long *istart, long *iend)
@@ -566,6 +566,10 @@ extern __typeof(gomp_loop_ull_dynamic_st
__attribute__((alias ("gomp_loop_ull_dynamic_start")));
extern __typeof(gomp_loop_ull_guided_start) GOMP_loop_ull_guided_start
__attribute__((alias ("gomp_loop_ull_guided_start")));
+extern __typeof(gomp_loop_ull_dynamic_start) GOMP_loop_ull_nonmonotonic_dynamic_start
+ __attribute__((alias ("gomp_loop_ull_dynamic_start")));
+extern __typeof(gomp_loop_ull_guided_start) GOMP_loop_ull_nonmonotonic_guided_start
+ __attribute__((alias ("gomp_loop_ull_guided_start")));
extern __typeof(gomp_loop_ull_ordered_static_start) GOMP_loop_ull_ordered_static_start
__attribute__((alias ("gomp_loop_ull_ordered_static_start")));
@@ -587,6 +591,10 @@ extern __typeof(gomp_loop_ull_dynamic_ne
__attribute__((alias ("gomp_loop_ull_dynamic_next")));
extern __typeof(gomp_loop_ull_guided_next) GOMP_loop_ull_guided_next
__attribute__((alias ("gomp_loop_ull_guided_next")));
+extern __typeof(gomp_loop_ull_dynamic_next) GOMP_loop_ull_nonmonotonic_dynamic_next
+ __attribute__((alias ("gomp_loop_ull_dynamic_next")));
+extern __typeof(gomp_loop_ull_guided_next) GOMP_loop_ull_nonmonotonic_guided_next
+ __attribute__((alias ("gomp_loop_ull_guided_next")));
extern __typeof(gomp_loop_ull_ordered_static_next) GOMP_loop_ull_ordered_static_next
__attribute__((alias ("gomp_loop_ull_ordered_static_next")));
@@ -623,6 +631,25 @@ GOMP_loop_ull_guided_start (bool up, gom
}
bool
+GOMP_loop_ull_nonmonotonic_dynamic_start (bool up, gomp_ull start,
+ gomp_ull end, gomp_ull incr,
+ gomp_ull chunk_size,
+ gomp_ull *istart, gomp_ull *iend)
+{
+ return gomp_loop_ull_dynamic_start (up, start, end, incr, chunk_size, istart,
+ iend);
+}
+
+bool
+GOMP_loop_ull_nonmonotonic_guided_start (bool up, gomp_ull start, gomp_ull end,
+ gomp_ull incr, gomp_ull chunk_size,
+ gomp_ull *istart, gomp_ull *iend)
+{
+ return gomp_loop_ull_guided_start (up, start, end, incr, chunk_size, istart,
+ iend);
+}
+
+bool
GOMP_loop_ull_ordered_static_start (bool up, gomp_ull start, gomp_ull end,
gomp_ull incr, gomp_ull chunk_size,
gomp_ull *istart, gomp_ull *iend)
@@ -693,6 +720,18 @@ GOMP_loop_ull_guided_next (gomp_ull *ist
{
return gomp_loop_ull_guided_next (istart, iend);
}
+
+bool
+GOMP_loop_ull_nonmonotonic_dynamic_next (gomp_ull *istart, gomp_ull *iend)
+{
+ return gomp_loop_ull_dynamic_next (istart, iend);
+}
+
+bool
+GOMP_loop_ull_nonmonotonic_guided_next (gomp_ull *istart, gomp_ull *iend)
+{
+ return gomp_loop_ull_guided_next (istart, iend);
+}
bool
GOMP_loop_ull_ordered_static_next (gomp_ull *istart, gomp_ull *iend)
@@ -0,0 +1,303 @@
+/* { dg-do run } */
+
+#ifndef MONOTONIC_TYPE
+#include <omp.h>
+#include <stdlib.h>
+#define MONOTONIC_TYPE int
+#define MONOTONIC_UNDEF -1
+#define MONOTONIC_END(n) n
+#endif
+
+int
+main ()
+{
+ MONOTONIC_TYPE i;
+ #pragma omp parallel
+ {
+ int cnt = omp_get_num_threads ();
+ int thr = omp_get_thread_num ();
+ MONOTONIC_TYPE l = MONOTONIC_UNDEF;
+ int c = 0;
+ int n = 0;
+ #pragma omp for nowait schedule(static, 5)
+ for (i = 0; i < MONOTONIC_END (73); i++)
+ {
+ if (l == MONOTONIC_UNDEF)
+ {
+ n = 1;
+ c++;
+ }
+ else if (l == i - 1)
+ n++;
+ else
+ {
+ if (l >= i)
+ abort ();
+ if (cnt == 1)
+ abort ();
+ if (n != 5)
+ abort ();
+ n = 1;
+ c++;
+ }
+ if (n == 1)
+ {
+ if ((i % 5) != 0)
+ abort ();
+ if ((i / 5) % cnt != thr)
+ abort ();
+ }
+ l = i;
+ }
+ if (cnt == 1)
+ {
+ if (n != 73 || l != 73 - 1 || c != 1)
+ abort ();
+ }
+ else if (thr > 73 / 5)
+ {
+ if (l != MONOTONIC_UNDEF || c != 0 || n != 0)
+ abort ();
+ }
+ else if (thr == 73 / 5)
+ {
+ if (l != 73 - 1 || c != 1 || n != 73 % 5)
+ abort ();
+ }
+ else if (c == 0)
+ abort ();
+ else if (l == 73 - 1)
+ {
+ if (thr != (73 / 5) % cnt || n != 73 % 5)
+ abort ();
+ }
+ else if ((n % 5) != 0)
+ abort ();
+ l = MONOTONIC_UNDEF;
+ c = 0;
+ n = 0;
+ #pragma omp for schedule( monotonic: static, 7) nowait
+ for (i = 0; i < MONOTONIC_END (73); i++)
+ {
+ if (l == MONOTONIC_UNDEF)
+ {
+ n = 1;
+ c++;
+ }
+ else if (l == i - 1)
+ n++;
+ else
+ {
+ if (l >= i)
+ abort ();
+ if (cnt == 1)
+ abort ();
+ if (n != 7)
+ abort ();
+ n = 1;
+ c++;
+ }
+ if (n == 1)
+ {
+ if ((i % 7) != 0)
+ abort ();
+ if ((i / 7) % cnt != thr)
+ abort ();
+ }
+ l = i;
+ }
+ if (cnt == 1)
+ {
+ if (n != 73 || l != 73 - 1 || c != 1)
+ abort ();
+ }
+ else if (thr > 73 / 7)
+ {
+ if (l != MONOTONIC_UNDEF || c != 0 || n != 0)
+ abort ();
+ }
+ else if (thr == 73 / 7)
+ {
+ if (l != 73 - 1 || c != 1 || n != 73 % 7)
+ abort ();
+ }
+ else if (c == 0)
+ abort ();
+ else if (l == 73 - 1)
+ {
+ if (thr != (73 / 7) % cnt || n != 73 % 7)
+ abort ();
+ }
+ else if ((n % 7) != 0)
+ abort ();
+ l = MONOTONIC_UNDEF;
+ c = 0;
+ n = 0;
+ #pragma omp for nowait schedule(static)
+ for (i = 0; i < MONOTONIC_END (73); i++)
+ {
+ if (l == MONOTONIC_UNDEF)
+ {
+ n = 1;
+ c++;
+ }
+ else if (l == i - 1)
+ n++;
+ else
+ abort ();
+ l = i;
+ }
+ if (c > 1)
+ abort ();
+ l = MONOTONIC_UNDEF;
+ c = 0;
+ n = 0;
+ #pragma omp for nowait schedule(monotonic,simd:static)
+ for (i = 0; i < MONOTONIC_END (73); i++)
+ {
+ if (l == MONOTONIC_UNDEF)
+ {
+ n = 1;
+ c++;
+ }
+ else if (l == i - 1)
+ n++;
+ else
+ abort ();
+ l = i;
+ }
+ if (c > 1)
+ abort ();
+ l = MONOTONIC_UNDEF;
+ c = 0;
+ n = 0;
+ #pragma omp for schedule(monotonic : dynamic, 5) nowait
+ for (i = 0; i < MONOTONIC_END (73); i++)
+ {
+ if (l == MONOTONIC_UNDEF)
+ {
+ n = 1;
+ c++;
+ }
+ else if (l == i - 1)
+ n++;
+ else
+ {
+ if (l >= i)
+ abort ();
+ if ((n % 5) != 0 || n == 0)
+ abort ();
+ n = 1;
+ c++;
+ }
+ l = i;
+ }
+ if (l == 73 - 1)
+ {
+ if (n % 5 != 73 % 5)
+ abort ();
+ }
+ else if (l == MONOTONIC_UNDEF)
+ {
+ if (n != 0 || c != 0)
+ abort ();
+ }
+ else if ((n % 5) != 0 || n == 0)
+ abort ();
+ l = MONOTONIC_UNDEF;
+ c = 0;
+ n = 0;
+ #pragma omp for nowait schedule(dynamic, 7) ordered(1)
+ for (i = 0; i < MONOTONIC_END (73); i++)
+ {
+ if (l == MONOTONIC_UNDEF)
+ {
+ n = 1;
+ c++;
+ }
+ else if (l == i - 1)
+ n++;
+ else
+ {
+ if (l >= i)
+ abort ();
+ if ((n % 7) != 0 || n == 0)
+ abort ();
+ n = 1;
+ c++;
+ }
+ #pragma omp ordered depend(source)
+ if (MONOTONIC_UNDEF > 0)
+ {
+ #pragma omp ordered depend(sink: i)
+ }
+ else
+ {
+ #pragma omp ordered depend(sink: i - 1)
+ }
+ l = i;
+ }
+ if (l == 73 - 1)
+ {
+ if (n % 7 != 73 % 7)
+ abort ();
+ }
+ else if (l == MONOTONIC_UNDEF)
+ {
+ if (n != 0 || c != 0)
+ abort ();
+ }
+ else if ((n % 7) != 0 || n == 0)
+ abort ();
+ l = MONOTONIC_UNDEF;
+ c = 0;
+ n = 0;
+ #pragma omp for schedule (monotonic :guided , 7) nowait
+ for (i = 0; i < MONOTONIC_END (73); i++)
+ {
+ if (l == MONOTONIC_UNDEF)
+ {
+ n = 1;
+ c++;
+ }
+ else if (l == i - 1)
+ n++;
+ else
+ {
+ if (l >= i)
+ abort ();
+ if (n < 7)
+ abort ();
+ n = 1;
+ c++;
+ }
+ l = i;
+ }
+ l = MONOTONIC_UNDEF;
+ c = 0;
+ n = 0;
+ #pragma omp for nowait schedule(guided, 7) ordered
+ for (i = 0; i < MONOTONIC_END (73); i++)
+ {
+ if (l == MONOTONIC_UNDEF)
+ {
+ n = 1;
+ c++;
+ }
+ else if (l == i - 1)
+ n++;
+ else
+ {
+ if (l >= i)
+ abort ();
+ if (n < 7)
+ abort ();
+ n = 1;
+ c++;
+ }
+ #pragma omp ordered
+ l = i;
+ }
+ }
+ return 0;
+}
@@ -0,0 +1,11 @@
+/* { dg-do run } */
+
+#include <omp.h>
+#include <stdlib.h>
+#define MONOTONIC_TYPE unsigned long long
+#define MONOTONIC_UNDEF -1ULL
+#define MONOTONIC_END(n) n + v
+
+volatile int v;
+
+#include "monotonic-1.c"
@@ -0,0 +1,53 @@
+/* { dg-do run } */
+
+#ifndef NONMONOTONIC_TYPE
+#include <omp.h>
+#include <stdlib.h>
+#define NONMONOTONIC_TYPE int
+#define NONMONOTONIC_END(n) n
+#endif
+
+int a[73];
+
+int
+main ()
+{
+ NONMONOTONIC_TYPE i;
+ #pragma omp parallel for schedule(nonmonotonic: dynamic)
+ for (i = 0; i < NONMONOTONIC_END (73); i++)
+ a[i]++;
+ #pragma omp parallel for schedule(nonmonotonic: dynamic, 5)
+ for (i = 0; i < NONMONOTONIC_END (73); i++)
+ a[i]++;
+ #pragma omp parallel for schedule(nonmonotonic: guided)
+ for (i = 0; i < NONMONOTONIC_END (73); i++)
+ a[i]++;
+ #pragma omp parallel for schedule(nonmonotonic: guided, 7)
+ for (i = 0; i < NONMONOTONIC_END (73); i++)
+ a[i]++;
+ #pragma omp parallel
+ {
+ int cnt = omp_get_num_threads ();
+ int thr = omp_get_thread_num ();
+ if (thr < 73)
+ a[thr]++;
+ #pragma omp barrier
+ #pragma omp for schedule(nonmonotonic: dynamic)
+ for (i = 0; i < NONMONOTONIC_END (73); i++)
+ a[i]++;
+ #pragma omp for schedule(nonmonotonic: dynamic, 7)
+ for (i = 0; i < NONMONOTONIC_END (73); i++)
+ a[i]++;
+ #pragma omp for schedule(nonmonotonic: guided)
+ for (i = 0; i < NONMONOTONIC_END (73); i++)
+ a[i]++;
+ #pragma omp for schedule(nonmonotonic: guided, 5)
+ for (i = 0; i < NONMONOTONIC_END (73); i++)
+ a[i]++;
+ #pragma omp single private (i)
+ for (i = 0; i < 73; i++)
+ if (a[i] != 8 + (i < cnt))
+ abort ();
+ }
+ return 0;
+}
@@ -0,0 +1,10 @@
+/* { dg-do run } */
+
+#include <omp.h>
+#include <stdlib.h>
+#define NONMONOTONIC_TYPE unsigned long long
+#define NONMONOTONIC_END(n) n + v
+
+volatile int v;
+
+#include "nonmonotonic-1.c"
@@ -0,0 +1,3 @@
+// { dg-do run }
+
+#include "../libgomp.c/monotonic-1.c"
@@ -0,0 +1,3 @@
+// { dg-do run }
+
+#include "../libgomp.c/monotonic-2.c"
@@ -0,0 +1,3 @@
+// { dg-do run }
+
+#include "../libgomp.c/nonmonotonic-1.c"
@@ -0,0 +1,3 @@
+// { dg-do run }
+
+#include "../libgomp.c/nonmonotonic-2.c"