Hi! I've created gomp-4_5-branch in svn, where further OpenMP 4.5 development will happen.
The following patch which I've committed there (and after a while plan to merge to trunk together with other smaller changes) adds support for monotonic and nonmonotonic schedule modifiers. The older versions of the standard can be read either way for dynamic and guided schedules, whether the chunks must be given in order or randomly; all current OpenMP implementations (including libgomp) have monotonic behavior, but for better scalability at least of dynamic scheduling allowing random order of the chunks is desirable, so that work-stealing can be used. On the library side, this patch right now just adds aliases which make it clear whether user wants monotonic or nonmonotonic, static kind as well as ordered clause force monotonic, and for now we treat lack of nonmonotonic as monotonic (which is going to change in 5.0). Once we have a work-stealing implementation, we can just change the library side. 2015-10-14 Jakub Jelinek <ja...@redhat.com> * tree-core.h (enum omp_clause_schedule_kind): Add OMP_CLAUSE_SCHEDULE_MASK, OMP_CLAUSE_SCHEDULE_MONOTONIC, OMP_CLAUSE_SCHEDULE_NONMONOTONIC and change OMP_CLAUSE_SCHEDULE_LAST value. * omp-builtins.def (BUILT_IN_GOMP_LOOP_NONMONOTONIC_DYNAMIC_START, BUILT_IN_GOMP_LOOP_NONMONOTONIC_GUIDED_START, BUILT_IN_GOMP_LOOP_NONMONOTONIC_DYNAMIC_NEXT, BUILT_IN_GOMP_LOOP_NONMONOTONIC_GUIDED_NEXT, BUILT_IN_GOMP_LOOP_ULL_NONMONOTONIC_DYNAMIC_START, BUILT_IN_GOMP_LOOP_ULL_NONMONOTONIC_GUIDED_START, BUILT_IN_GOMP_LOOP_ULL_NONMONOTONIC_DYNAMIC_NEXT, BUILT_IN_GOMP_LOOP_ULL_NONMONOTONIC_GUIDED_NEXT, BUILT_IN_GOMP_PARALLEL_LOOP_NONMONOTONIC_DYNAMIC, BUILT_IN_GOMP_PARALLEL_LOOP_NONMONOTONIC_GUIDED): New built-ins. * omp-low.c (struct omp_region): Add sched_modifiers field. (struct omp_for_data): Likewise. (extract_omp_for_data): Fill in sched_modifiers, and mask out OMP_CLAUSE_SCHEDULE_KIND bits outside of OMP_CLAUSE_SCHEDULE_MASK from sched_kind. (determine_parallel_type): Use only OMP_CLAUSE_SCHEDULE_MASK bits of OMP_CLAUSE_SCHED_KIND. (expand_parallel_call): Use nonmonotonic entrypoints for nonmonotonic: dynamic/guided. (expand_omp_for): Likewise. Initialize region->sched_modifiers. * tree-pretty-print.c (dump_omp_clause): Print schedule clause modifiers. gcc/c/ * c-parser.c (c_parser_omp_clause_schedule): Parse schedule modifiers, diagnose monotonic together with nonmonotonic. * c-typeck.c (c_finish_omp_clauses): Diagnose nonmonotonic modifier on kinds other than dynamic or guided or nonmonotonic modifier together with ordered clause. gcc/cp/ * parser.c (cp_parser_omp_clause_schedule): Parse schedule modifiers, diagnose monotonic together with nonmonotonic. * semantics.c (finish_omp_clauses): Diagnose nonmonotonic modifier on kinds other than dynamic or guided or nonmonotonic modifier together with ordered clause. gcc/testsuite/ * c-c++-common/gomp/schedule-modifiers-1.c: New test. * gcc.dg/gomp/for-20.c: New test. * gcc.dg/gomp/for-21.c: New test. * gcc.dg/gomp/for-22.c: New test. * gcc.dg/gomp/for-23.c: New test. * gcc.dg/gomp/for-24.c: New test. libgomp/ * libgomp.map (GOMP_4.5): Export 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 and GOMP_parallel_loop_nonmonotonic_guided. * libgomp_g.h (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): New prototypes. * loop.c (GOMP_parallel_loop_nonmonotonic_dynamic, GOMP_parallel_loop_nonmonotonic_guided, GOMP_loop_nonmonotonic_dynamic_start, GOMP_loop_nonmonotonic_guided_start, GOMP_loop_nonmonotonic_dynamic_next, GOMP_loop_nonmonotonic_guided_next): New aliases or functions. * loop_ull.c (GOMP_loop_ull_nonmonotonic_dynamic_start, GOMP_loop_ull_nonmonotonic_guided_start, GOMP_loop_ull_nonmonotonic_dynamic_next, GOMP_loop_ull_nonmonotonic_guided_next): Likewise. * testsuite/libgomp.c/monotonic-1.c: New test. * testsuite/libgomp.c/monotonic-2.c: New test. * testsuite/libgomp.c/nonmonotonic-1.c: New test. * testsuite/libgomp.c/nonmonotonic-2.c: New test. * testsuite/libgomp.c++/monotonic-1.C: New test. * testsuite/libgomp.c++/monotonic-2.C: New test. * testsuite/libgomp.c++/nonmonotonic-1.C: New test. * testsuite/libgomp.c++/nonmonotonic-2.C: New test. --- gcc/tree-core.h.jj 2015-10-14 10:25:50.000000000 +0200 +++ gcc/tree-core.h 2015-10-14 13:12:30.482312906 +0200 @@ -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 { --- gcc/omp-builtins.def.jj 2015-10-14 10:25:50.000000000 +0200 +++ gcc/omp-builtins.def 2015-10-14 11:53:08.092506700 +0200 @@ -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", --- gcc/omp-low.c.jj 2015-10-14 10:24:56.000000000 +0200 +++ gcc/omp-low.c 2015-10-14 17:05:48.903095117 +0200 @@ -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 --- gcc/tree-pretty-print.c.jj 2015-10-14 10:24:54.000000000 +0200 +++ gcc/tree-pretty-print.c 2015-10-14 11:29:06.251053393 +0200 @@ -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"); --- gcc/c/c-parser.c.jj 2015-10-14 10:24:55.078533855 +0200 +++ gcc/c/c-parser.c 2015-10-14 11:12:49.866631975 +0200 @@ -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; --- gcc/c/c-typeck.c.jj 2015-10-14 10:24:55.000000000 +0200 +++ gcc/c/c-typeck.c 2015-10-14 13:29:30.821056080 +0200 @@ -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; } --- gcc/cp/parser.c.jj 2015-10-14 10:25:31.345991462 +0200 +++ gcc/cp/parser.c 2015-10-14 17:13:56.594931158 +0200 @@ -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; --- gcc/cp/semantics.c.jj 2015-10-14 10:25:31.343991492 +0200 +++ gcc/cp/semantics.c 2015-10-14 17:14:13.191687359 +0200 @@ -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) { --- gcc/testsuite/c-c++-common/gomp/schedule-modifiers-1.c.jj 2015-10-14 14:20:35.167455646 +0200 +++ gcc/testsuite/c-c++-common/gomp/schedule-modifiers-1.c 2015-10-14 13:34:18.000000000 +0200 @@ -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++) + ; +} --- gcc/testsuite/gcc.dg/gomp/for-20.c.jj 2015-10-14 17:07:11.291884865 +0200 +++ gcc/testsuite/gcc.dg/gomp/for-20.c 2015-10-14 17:07:52.276282824 +0200 @@ -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" } } */ --- gcc/testsuite/gcc.dg/gomp/for-21.c.jj 2015-10-14 17:08:00.749158361 +0200 +++ gcc/testsuite/gcc.dg/gomp/for-21.c 2015-10-14 17:08:28.241754508 +0200 @@ -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" } } */ --- gcc/testsuite/gcc.dg/gomp/for-22.c.jj 2015-10-14 17:08:36.267636612 +0200 +++ gcc/testsuite/gcc.dg/gomp/for-22.c 2015-10-14 17:09:06.696189631 +0200 @@ -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" } } */ --- gcc/testsuite/gcc.dg/gomp/for-23.c.jj 2015-10-14 17:09:14.119080593 +0200 +++ gcc/testsuite/gcc.dg/gomp/for-23.c 2015-10-14 17:09:33.620794122 +0200 @@ -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" } } */ --- gcc/testsuite/gcc.dg/gomp/for-24.c.jj 2015-10-14 17:09:40.458693676 +0200 +++ gcc/testsuite/gcc.dg/gomp/for-24.c 2015-10-14 17:13:33.347272655 +0200 @@ -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" } } */ --- libgomp/libgomp.map.jj 2015-10-14 10:24:10.000000000 +0200 +++ libgomp/libgomp.map 2015-10-14 13:41:18.884479760 +0200 @@ -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 { --- libgomp/libgomp_g.h.jj 2015-10-14 10:24:10.000000000 +0200 +++ libgomp/libgomp_g.h 2015-10-14 13:53:33.612536779 +0200 @@ -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 *); --- libgomp/loop.c.jj 2015-10-14 10:24:10.000000000 +0200 +++ libgomp/loop.c 2015-10-14 17:17:08.222116246 +0200 @@ -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) --- libgomp/loop_ull.c.jj 2015-10-14 10:24:10.000000000 +0200 +++ libgomp/loop_ull.c 2015-10-14 14:20:13.407778934 +0200 @@ -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) --- libgomp/testsuite/libgomp.c/monotonic-1.c.jj 2015-10-14 15:28:48.994453338 +0200 +++ libgomp/testsuite/libgomp.c/monotonic-1.c 2015-10-14 16:35:01.819006691 +0200 @@ -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; +} --- libgomp/testsuite/libgomp.c/monotonic-2.c.jj 2015-10-14 16:14:45.915822535 +0200 +++ libgomp/testsuite/libgomp.c/monotonic-2.c 2015-10-14 16:35:21.661717802 +0200 @@ -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" --- libgomp/testsuite/libgomp.c/nonmonotonic-1.c.jj 2015-10-14 16:27:17.141788027 +0200 +++ libgomp/testsuite/libgomp.c/nonmonotonic-1.c 2015-10-14 16:36:03.585107442 +0200 @@ -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; +} --- libgomp/testsuite/libgomp.c/nonmonotonic-2.c.jj 2015-10-14 16:27:20.100744564 +0200 +++ libgomp/testsuite/libgomp.c/nonmonotonic-2.c 2015-10-14 16:36:18.458890895 +0200 @@ -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" --- libgomp/testsuite/libgomp.c++/monotonic-1.C.jj 2015-10-14 17:17:43.902592117 +0200 +++ libgomp/testsuite/libgomp.c++/monotonic-1.C 2015-10-14 17:17:57.630390463 +0200 @@ -0,0 +1,3 @@ +// { dg-do run } + +#include "../libgomp.c/monotonic-1.c" --- libgomp/testsuite/libgomp.c++/monotonic-2.C.jj 2015-10-14 17:18:24.648993572 +0200 +++ libgomp/testsuite/libgomp.c++/monotonic-2.C 2015-10-14 17:18:29.796917952 +0200 @@ -0,0 +1,3 @@ +// { dg-do run } + +#include "../libgomp.c/monotonic-2.c" --- libgomp/testsuite/libgomp.c++/nonmonotonic-1.C.jj 2015-10-14 17:18:24.651993528 +0200 +++ libgomp/testsuite/libgomp.c++/nonmonotonic-1.C 2015-10-14 17:18:36.958812747 +0200 @@ -0,0 +1,3 @@ +// { dg-do run } + +#include "../libgomp.c/nonmonotonic-1.c" --- libgomp/testsuite/libgomp.c++/nonmonotonic-2.C.jj 2015-10-14 17:18:24.654993484 +0200 +++ libgomp/testsuite/libgomp.c++/nonmonotonic-2.C 2015-10-14 17:18:44.448702724 +0200 @@ -0,0 +1,3 @@ +// { dg-do run } + +#include "../libgomp.c/nonmonotonic-2.c" Jakub