diff mbox

[gomp4.5] Support for monotonic and nonmonotonic schedule modifiers

Message ID 20151014154437.GA478@tucnak.redhat.com
State New
Headers show

Commit Message

Jakub Jelinek Oct. 14, 2015, 3:44 p.m. UTC
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  <jakub@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.


	Jakub
diff mbox

Patch

--- 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"