[gomp4.1] Taskloop C++ random access iterator support

Jakub Jelinek jakub@redhat.com
Tue Jun 23 14:40:00 GMT 2015


Hi!

I've committed following patch to add support for C++ random access
iterators in taskloop constructs.

2015-06-23  Jakub Jelinek  <jakub@redhat.com>

	* tree.h (OMP_CLAUSE_PRIVATE_TASKLOOP_IV,
	OMP_CLAUSE_LASTPRIVATE_TASKLOOP_IV): Define.
	* gimplify.c (gimplify_omp_for): Handle gimplification of
	OMP_TASKLOOP with C++ random access iterator clauses.
	* omp-low.c (scan_sharing_clauses): Ignore
	OMP_CLAUSE_SHARED with OMP_CLAUSE_SHARED_FIRSTPRIVATE if
	it is a global var outside of the outer taskloop for.
	(lower_lastprivate_clauses): Handle
	OMP_CLAUSE_LASTPRIVATE_TASKLOOP_IV lastprivate if the
	decl is global outside of outer taskloop for.
	(lower_send_clauses): Look beyond the outer taskloop for.
gcc/cp/
	* semantics.c (handle_omp_for_class_iterator): Handle
	OMP_TASKLOOP class iterators.
	(finish_omp_for): Adjust handle_omp_for_class_iterator
	caller.
libgomp/
	* testsuite/libgomp.c++/taskloop-6.C: New test.
	* testsuite/libgomp.c++/taskloop-7.C: New test.
	* testsuite/libgomp.c++/taskloop-8.C: New test.
	* testsuite/libgomp.c++/taskloop-9.C: New test.

--- gcc/tree.h.jj	2015-06-17 21:02:00.000000000 +0200
+++ gcc/tree.h	2015-06-22 15:19:37.501110534 +0200
@@ -1356,6 +1356,12 @@ extern void protected_set_expr_location
 #define OMP_CLAUSE_PRIVATE_OUTER_REF(NODE) \
   TREE_PRIVATE (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_PRIVATE))
 
+/* True if a PRIVATE clause is for a C++ class IV on taskloop construct
+   (thus should be private on the outer taskloop and firstprivate on
+   task).  */
+#define OMP_CLAUSE_PRIVATE_TASKLOOP_IV(NODE) \
+  TREE_PROTECTED (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_PRIVATE))
+
 /* True on a LASTPRIVATE clause if a FIRSTPRIVATE clause for the same
    decl is present in the chain.  */
 #define OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE(NODE) \
@@ -1367,6 +1373,12 @@ extern void protected_set_expr_location
 #define OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ(NODE) \
   (OMP_CLAUSE_CHECK (NODE))->omp_clause.gimple_reduction_init
 
+/* True if a LASTPRIVATE clause is for a C++ class IV on taskloop construct
+   (thus should be lastprivate on the outer taskloop and firstprivate on
+   task).  */
+#define OMP_CLAUSE_LASTPRIVATE_TASKLOOP_IV(NODE) \
+  TREE_PROTECTED (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_LASTPRIVATE))
+
 /* True on a SHARED clause if a FIRSTPRIVATE clause for the same
    decl is present in the chain (this can happen only for taskloop
    with FIRSTPRIVATE/LASTPRIVATE on it originally.  */
--- gcc/gimplify.c.jj	2015-06-18 15:16:18.000000000 +0200
+++ gcc/gimplify.c	2015-06-23 10:03:28.908079507 +0200
@@ -7230,7 +7230,8 @@ gimplify_omp_for (tree *expr_p, gimple_s
 	    {
 	      TREE_OPERAND (t, 1)
 		= get_initialized_tmp_var (TREE_OPERAND (t, 1),
-					   pre_p, NULL);
+					   gimple_seq_empty_p (for_pre_body)
+					   ? pre_p : &for_pre_body, NULL);
 	      tree c = build_omp_clause (input_location,
 					 OMP_CLAUSE_FIRSTPRIVATE);
 	      OMP_CLAUSE_DECL (c) = TREE_OPERAND (t, 1);
@@ -7250,7 +7251,9 @@ gimplify_omp_for (tree *expr_p, gimple_s
 
 	      if (!is_gimple_constant (*tp))
 		{
-		  *tp = get_initialized_tmp_var (*tp, pre_p, NULL);
+		  gimple_seq *seq = gimple_seq_empty_p (for_pre_body)
+				    ? pre_p : &for_pre_body;
+		  *tp = get_initialized_tmp_var (*tp, seq, NULL);
 		  tree c = build_omp_clause (input_location,
 					     OMP_CLAUSE_FIRSTPRIVATE);
 		  OMP_CLAUSE_DECL (c) = *tp;
@@ -7683,7 +7686,6 @@ gimplify_omp_for (tree *expr_p, gimple_s
 	  {
 	  /* These clauses are allowed on task, move them there.  */
 	  case OMP_CLAUSE_SHARED:
-	  case OMP_CLAUSE_PRIVATE:
 	  case OMP_CLAUSE_FIRSTPRIVATE:
 	  case OMP_CLAUSE_DEFAULT:
 	  case OMP_CLAUSE_IF:
@@ -7694,6 +7696,26 @@ gimplify_omp_for (tree *expr_p, gimple_s
 	    *gtask_clauses_ptr = c;
 	    gtask_clauses_ptr = &OMP_CLAUSE_CHAIN (c);
 	    break;
+	  case OMP_CLAUSE_PRIVATE:
+	    if (OMP_CLAUSE_PRIVATE_TASKLOOP_IV (c))
+	      {
+		/* We want private on outer for and firstprivate
+		   on task.  */
+		*gtask_clauses_ptr
+		  = build_omp_clause (OMP_CLAUSE_LOCATION (c),
+				      OMP_CLAUSE_FIRSTPRIVATE);
+		OMP_CLAUSE_DECL (*gtask_clauses_ptr) = OMP_CLAUSE_DECL (c);
+		lang_hooks.decls.omp_finish_clause (*gtask_clauses_ptr, NULL);
+		gtask_clauses_ptr = &OMP_CLAUSE_CHAIN (*gtask_clauses_ptr);
+		*gforo_clauses_ptr = c;
+		gforo_clauses_ptr = &OMP_CLAUSE_CHAIN (c);
+	      }
+	    else
+	      {
+		*gtask_clauses_ptr = c;
+		gtask_clauses_ptr = &OMP_CLAUSE_CHAIN (c);
+	      }
+	    break;
 	  /* These clauses go into outer taskloop clauses.  */
 	  case OMP_CLAUSE_GRAINSIZE:
 	  case OMP_CLAUSE_NUM_TASKS:
@@ -7712,6 +7734,26 @@ gimplify_omp_for (tree *expr_p, gimple_s
 	     a shared clause on task.  If the same decl is also firstprivate,
 	     add also firstprivate clause on the inner taskloop.  */
 	  case OMP_CLAUSE_LASTPRIVATE:
+	    if (OMP_CLAUSE_LASTPRIVATE_TASKLOOP_IV (c))
+	      {
+		/* For taskloop C++ lastprivate IVs, we want:
+		   1) private on outer taskloop
+		   2) firstprivate and shared on task
+		   3) lastprivate on inner taskloop  */
+		*gtask_clauses_ptr
+		  = build_omp_clause (OMP_CLAUSE_LOCATION (c),
+				      OMP_CLAUSE_FIRSTPRIVATE);
+		OMP_CLAUSE_DECL (*gtask_clauses_ptr) = OMP_CLAUSE_DECL (c);
+		lang_hooks.decls.omp_finish_clause (*gtask_clauses_ptr, NULL);
+		gtask_clauses_ptr = &OMP_CLAUSE_CHAIN (*gtask_clauses_ptr);
+		OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c) = 1;
+		*gforo_clauses_ptr = build_omp_clause (OMP_CLAUSE_LOCATION (c),
+						       OMP_CLAUSE_PRIVATE);
+		OMP_CLAUSE_DECL (*gforo_clauses_ptr) = OMP_CLAUSE_DECL (c);
+		OMP_CLAUSE_PRIVATE_TASKLOOP_IV (*gforo_clauses_ptr) = 1;
+		TREE_TYPE (*gforo_clauses_ptr) = TREE_TYPE (c);
+		gforo_clauses_ptr = &OMP_CLAUSE_CHAIN (*gforo_clauses_ptr);
+	      }
 	    *gfor_clauses_ptr = c;
 	    gfor_clauses_ptr = &OMP_CLAUSE_CHAIN (c);
 	    *gtask_clauses_ptr
@@ -7735,7 +7777,9 @@ gimplify_omp_for (tree *expr_p, gimple_s
       g = gimple_build_bind (NULL_TREE, g, NULL_TREE);
       gomp_for *gforo
 	= gimple_build_omp_for (g, GF_OMP_FOR_KIND_TASKLOOP, outer_for_clauses,
-				gimple_omp_for_collapse (gfor), NULL);
+				gimple_omp_for_collapse (gfor),
+				gimple_omp_for_pre_body (gfor));
+      gimple_omp_for_set_pre_body (gfor, NULL);
       gimple_omp_for_set_combined_p (gforo, true);
       gimple_omp_for_set_combined_into_p (gfor, true);
       for (i = 0; i < (int) gimple_omp_for_collapse (gfor); i++)
--- gcc/omp-low.c.jj	2015-06-22 11:17:39.000000000 +0200
+++ gcc/omp-low.c	2015-06-23 14:19:13.466669690 +0200
@@ -2169,6 +2169,9 @@ scan_sharing_clauses (tree clauses, omp_
 	    break;
 	  if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
 	    {
+	      if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl,
+								 ctx->outer)))
+		break;
 	      bool by_ref = use_pointer_for_field (decl, ctx);
 	      install_var_field (decl, by_ref, 11, ctx);
 	      break;
@@ -4965,7 +4968,18 @@ lower_lastprivate_clauses (tree clauses,
 	      OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c) = NULL;
 	    }
 
-	  x = build_outer_var_ref (var, ctx, true);
+	  x = NULL_TREE;
+	  if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
+	      && OMP_CLAUSE_LASTPRIVATE_TASKLOOP_IV (c))
+	    {
+	      gcc_checking_assert (is_taskloop_ctx (ctx));
+	      tree ovar = maybe_lookup_decl_in_outer_ctx (var,
+							  ctx->outer->outer);
+	      if (is_global_var (ovar))
+		x = ovar;
+	    }
+	  if (!x)
+	    x = build_outer_var_ref (var, ctx, true);
 	  if (is_reference (var))
 	    new_var = build_simple_mem_ref_loc (clause_loc, new_var);
 	  x = lang_hooks.decls.omp_clause_assign_op (c, x, new_var);
@@ -5326,11 +5340,15 @@ lower_send_clauses (tree clauses, gimple
 {
   tree c, t;
   int ignored_looptemp = 0;
+  bool is_taskloop = false;
 
   /* For taskloop, ignore first two _looptemp_ clauses, those are initialized
      by GOMP_taskloop.  */
   if (is_task_ctx (ctx) && gimple_omp_task_taskloop_p (ctx->stmt))
-    ignored_looptemp = 2;
+    {
+      ignored_looptemp = 2;
+      is_taskloop = true;
+    }
 
   for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
     {
@@ -5375,7 +5393,16 @@ lower_send_clauses (tree clauses, gimple
 	  if (is_variable_sized (val))
 	    continue;
 	}
-      var = lookup_decl_in_outer_ctx (val, ctx);
+
+      /* For OMP_CLAUSE_SHARED_FIRSTPRIVATE, look beyond the
+	 outer taskloop region.  */
+      omp_context *ctx_for_o = ctx;
+      if (is_taskloop
+	  && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
+	  && OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
+	ctx_for_o = ctx->outer;
+
+      var = lookup_decl_in_outer_ctx (val, ctx_for_o);
 
       if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYIN
 	  && is_global_var (var))
@@ -5385,7 +5412,7 @@ lower_send_clauses (tree clauses, gimple
       if (t)
 	{
 	  var = DECL_VALUE_EXPR (var);
-	  tree o = maybe_lookup_decl_in_outer_ctx (t, ctx);
+	  tree o = maybe_lookup_decl_in_outer_ctx (t, ctx_for_o);
 	  if (o != t)
 	    var = unshare_and_remap (var, t, o);
 	  else
--- gcc/cp/semantics.c.jj	2015-06-22 11:17:39.000000000 +0200
+++ gcc/cp/semantics.c	2015-06-23 10:12:08.618129457 +0200
@@ -6791,9 +6791,10 @@ finish_omp_task (tree clauses, tree body
    into integral iterator.  Return FALSE if successful.  */
 
 static bool
-handle_omp_for_class_iterator (int i, location_t locus, tree declv, tree initv,
-			       tree condv, tree incrv, tree *body,
-			       tree *pre_body, tree clauses, tree *lastp)
+handle_omp_for_class_iterator (int i, location_t locus, enum tree_code code,
+			       tree declv, tree initv, tree condv, tree incrv,
+			       tree *body, tree *pre_body, tree &clauses,
+			       tree *lastp)
 {
   tree diff, iter_init, iter_incr = NULL, last;
   tree incr_var = NULL, orig_pre_body, orig_body, c;
@@ -6951,10 +6952,25 @@ handle_omp_for_class_iterator (int i, lo
     }
 
   incr = cp_convert (TREE_TYPE (diff), incr, tf_warning_or_error);
+  bool taskloop_iv_seen = false;
   for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
     if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
 	&& OMP_CLAUSE_DECL (c) == iter)
-      break;
+      {
+	if (code == OMP_TASKLOOP)
+	  {
+	    taskloop_iv_seen = true;
+	    OMP_CLAUSE_LASTPRIVATE_TASKLOOP_IV (c) = 1;
+	  }
+	break;
+      }
+    else if (code == OMP_TASKLOOP
+	     && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_PRIVATE
+	     && OMP_CLAUSE_DECL (c) == iter)
+      {
+	taskloop_iv_seen = true;
+	OMP_CLAUSE_PRIVATE_TASKLOOP_IV (c) = 1;
+      }
 
   decl = create_temporary_var (TREE_TYPE (diff));
   pushdecl (decl);
@@ -6962,13 +6978,32 @@ handle_omp_for_class_iterator (int i, lo
   last = create_temporary_var (TREE_TYPE (diff));
   pushdecl (last);
   add_decl_expr (last);
-  if (c && iter_incr == NULL)
+  if (c && iter_incr == NULL && TREE_CODE (incr) != INTEGER_CST)
     {
       incr_var = create_temporary_var (TREE_TYPE (diff));
       pushdecl (incr_var);
       add_decl_expr (incr_var);
     }
   gcc_assert (stmts_are_full_exprs_p ());
+  tree diffvar = NULL_TREE;
+  if (code == OMP_TASKLOOP)
+    {
+      if (!taskloop_iv_seen)
+	{
+	  tree ivc = build_omp_clause (locus, OMP_CLAUSE_FIRSTPRIVATE);
+	  OMP_CLAUSE_DECL (ivc) = iter;
+	  cxx_omp_finish_clause (ivc, NULL);
+	  OMP_CLAUSE_CHAIN (ivc) = clauses;
+	  clauses = ivc;
+	}
+      tree lvc = build_omp_clause (locus, OMP_CLAUSE_FIRSTPRIVATE);
+      OMP_CLAUSE_DECL (lvc) = last;
+      OMP_CLAUSE_CHAIN (lvc) = clauses;
+      clauses = lvc;
+      diffvar = create_temporary_var (TREE_TYPE (diff));
+      pushdecl (diffvar);
+      add_decl_expr (diffvar);
+    }
 
   orig_pre_body = *pre_body;
   *pre_body = push_stmt_list ();
@@ -6981,10 +7016,13 @@ handle_omp_for_class_iterator (int i, lo
   init = build_int_cst (TREE_TYPE (diff), 0);
   if (c && iter_incr == NULL)
     {
-      finish_expr_stmt (build_x_modify_expr (elocus,
-					     incr_var, NOP_EXPR,
-					     incr, tf_warning_or_error));
-      incr = incr_var;
+      if (incr_var)
+	{
+	  finish_expr_stmt (build_x_modify_expr (elocus,
+						 incr_var, NOP_EXPR,
+						 incr, tf_warning_or_error));
+	  incr = incr_var;
+	}
       iter_incr = build_x_modify_expr (elocus,
 				       iter, PLUS_EXPR, incr,
 				       tf_warning_or_error);
@@ -6992,6 +7030,13 @@ handle_omp_for_class_iterator (int i, lo
   finish_expr_stmt (build_x_modify_expr (elocus,
 					 last, NOP_EXPR, init,
 					 tf_warning_or_error));
+  if (diffvar)
+    {
+      finish_expr_stmt (build_x_modify_expr (elocus,
+					     diffvar, NOP_EXPR,
+					     diff, tf_warning_or_error));
+      diff = diffvar;
+    }
   *pre_body = pop_stmt_list (*pre_body);
 
   cond = cp_build_binary_op (elocus,
@@ -7176,8 +7221,8 @@ finish_omp_for (location_t locus, enum t
 	    }
 	  if (code == CILK_FOR && i == 0)
 	    orig_decl = decl;
-	  if (handle_omp_for_class_iterator (i, locus, declv, initv, condv,
-					     incrv, &body, &pre_body,
+	  if (handle_omp_for_class_iterator (i, locus, code, declv, initv,
+					     condv, incrv, &body, &pre_body,
 					     clauses, &last))
 	    return NULL;
 	  continue;
--- libgomp/testsuite/libgomp.c++/taskloop-6.C.jj	2015-06-23 14:25:31.717932978 +0200
+++ libgomp/testsuite/libgomp.c++/taskloop-6.C	2015-06-23 15:56:31.022700214 +0200
@@ -0,0 +1,442 @@
+// { dg-do run }
+
+typedef __PTRDIFF_TYPE__ ptrdiff_t;
+extern "C" void abort ();
+
+template <typename T>
+class I
+{
+public:
+  typedef ptrdiff_t difference_type;
+  I ();
+  ~I ();
+  I (T *);
+  I (const I &);
+  T &operator * ();
+  T *operator -> ();
+  T &operator [] (const difference_type &) const;
+  I &operator = (const I &);
+  I &operator ++ ();
+  I operator ++ (int);
+  I &operator -- ();
+  I operator -- (int);
+  I &operator += (const difference_type &);
+  I &operator -= (const difference_type &);
+  I operator + (const difference_type &) const;
+  I operator - (const difference_type &) const;
+  template <typename S> friend bool operator == (I<S> &, I<S> &);
+  template <typename S> friend bool operator == (const I<S> &, const I<S> &);
+  template <typename S> friend bool operator < (I<S> &, I<S> &);
+  template <typename S> friend bool operator < (const I<S> &, const I<S> &);
+  template <typename S> friend bool operator <= (I<S> &, I<S> &);
+  template <typename S> friend bool operator <= (const I<S> &, const I<S> &);
+  template <typename S> friend bool operator > (I<S> &, I<S> &);
+  template <typename S> friend bool operator > (const I<S> &, const I<S> &);
+  template <typename S> friend bool operator >= (I<S> &, I<S> &);
+  template <typename S> friend bool operator >= (const I<S> &, const I<S> &);
+  template <typename S> friend typename I<S>::difference_type operator - (I<S> &, I<S> &);
+  template <typename S> friend typename I<S>::difference_type operator - (const I<S> &, const I<S> &);
+  template <typename S> friend I<S> operator + (typename I<S>::difference_type , const I<S> &);
+private:
+  T *p;
+};
+template <typename T> I<T>::I () : p (0) {}
+template <typename T> I<T>::~I () {}
+template <typename T> I<T>::I (T *x) : p (x) {}
+template <typename T> I<T>::I (const I &x) : p (x.p) {}
+template <typename T> T &I<T>::operator * () { return *p; }
+template <typename T> T *I<T>::operator -> () { return p; }
+template <typename T> T &I<T>::operator [] (const difference_type &x) const { return p[x]; }
+template <typename T> I<T> &I<T>::operator = (const I &x) { p = x.p; return *this; }
+template <typename T> I<T> &I<T>::operator ++ () { ++p; return *this; }
+template <typename T> I<T> I<T>::operator ++ (int) { return I (p++); }
+template <typename T> I<T> &I<T>::operator -- () { --p; return *this; }
+template <typename T> I<T> I<T>::operator -- (int) { return I (p--); }
+template <typename T> I<T> &I<T>::operator += (const difference_type &x) { p += x; return *this; }
+template <typename T> I<T> &I<T>::operator -= (const difference_type &x) { p -= x; return *this; }
+template <typename T> I<T> I<T>::operator + (const difference_type &x) const { return I (p + x); }
+template <typename T> I<T> I<T>::operator - (const difference_type &x) const { return I (p - x); }
+template <typename T> bool operator == (I<T> &x, I<T> &y) { return x.p == y.p; }
+template <typename T> bool operator == (const I<T> &x, const I<T> &y) { return x.p == y.p; }
+template <typename T> bool operator != (I<T> &x, I<T> &y) { return !(x == y); }
+template <typename T> bool operator != (const I<T> &x, const I<T> &y) { return !(x == y); }
+template <typename T> bool operator < (I<T> &x, I<T> &y) { return x.p < y.p; }
+template <typename T> bool operator < (const I<T> &x, const I<T> &y) { return x.p < y.p; }
+template <typename T> bool operator <= (I<T> &x, I<T> &y) { return x.p <= y.p; }
+template <typename T> bool operator <= (const I<T> &x, const I<T> &y) { return x.p <= y.p; }
+template <typename T> bool operator > (I<T> &x, I<T> &y) { return x.p > y.p; }
+template <typename T> bool operator > (const I<T> &x, const I<T> &y) { return x.p > y.p; }
+template <typename T> bool operator >= (I<T> &x, I<T> &y) { return x.p >= y.p; }
+template <typename T> bool operator >= (const I<T> &x, const I<T> &y) { return x.p >= y.p; }
+template <typename T> typename I<T>::difference_type operator - (I<T> &x, I<T> &y) { return x.p - y.p; }
+template <typename T> typename I<T>::difference_type operator - (const I<T> &x, const I<T> &y) { return x.p - y.p; }
+template <typename T> I<T> operator + (typename I<T>::difference_type x, const I<T> &y) { return I<T> (x + y.p); }
+
+template <typename T>
+class J
+{
+public:
+  J(const I<T> &x, const I<T> &y) : b (x), e (y) {}
+  const I<T> &begin ();
+  const I<T> &end ();
+private:
+  I<T> b, e;
+};
+
+template <typename T> const I<T> &J<T>::begin () { return b; }
+template <typename T> const I<T> &J<T>::end () { return e; }
+
+int results[2000];
+
+template <typename T>
+void
+baz (I<T> &i)
+{
+  if (*i < 0 || *i >= 2000)
+    abort ();
+  results[*i]++;
+}
+
+void
+f1 (const I<int> &x, const I<int> &y)
+{
+#pragma omp parallel
+#pragma omp single
+#pragma omp taskloop num_tasks(22)
+  for (I<int> i = x; i <= y; i += 6)
+    baz (i);
+}
+
+void
+f2 (const I<int> &x, const I<int> &y)
+{
+  I<int> i;
+#pragma omp parallel
+#pragma omp single
+#pragma omp taskloop grainsize(384) private(i)
+  for (i = x; i < y - 1; i = 1 - 6 + 7 + i)
+    baz (i);
+}
+
+template <typename T>
+void
+f3 (const I<int> &x, const I<int> &y)
+{
+#pragma omp parallel
+#pragma omp single
+#pragma omp taskloop default(none) firstprivate (x, y)
+  for (I<int> i = x; i <= y; i = i + 9 - 8)
+    baz (i);
+}
+
+template <typename T>
+void
+f4 (const I<int> &x, const I<int> &y)
+{
+  I<int> i;
+#pragma omp parallel
+#pragma omp single
+#pragma omp taskloop lastprivate(i)
+  for (i = x + 2000 - 64; i > y + 10; --i)
+    baz (i);
+}
+
+void
+f5 (const I<int> &x, const I<int> &y)
+{
+#pragma omp parallel
+#pragma omp single
+#pragma omp taskloop
+  for (I<int> i = x + 2000 - 64; i > y + 10; i -= 10)
+    baz (i);
+}
+
+template <int N>
+void
+f6 (const I<int> &x, const I<int> &y)
+{
+#pragma omp parallel
+#pragma omp single
+#pragma omp taskloop
+  for (I<int> i = x + 2000 - 64; i > y + 10; i = i - 12 + 2)
+    {
+      I<int> j = i + N;
+      baz (j);
+    }
+}
+
+template <int N>
+void
+f7 (I<int> i, const I<int> &x, const I<int> &y)
+{
+#pragma omp parallel
+#pragma omp single
+#pragma omp taskloop default(none) firstprivate (x, y)
+  for (i = x - 10; i <= y + 10; i += N)
+    baz (i);
+}
+
+template <int N>
+void
+f8 (J<int> j)
+{
+  I<int> i;
+#pragma omp parallel
+#pragma omp single
+#pragma omp taskloop default(none) num_tasks(*I<int> (j.begin ())) firstprivate (j)
+  for (i = j.begin (); i <= j.end () + N; i += 2)
+    baz (i);
+}
+
+template <typename T, int N>
+void
+f9 (const I<T> &x, const I<T> &y)
+{
+#pragma omp parallel
+#pragma omp single
+#pragma omp taskloop grainsize(163)
+  for (I<T> i = x; i <= y; i = i + N)
+    baz (i);
+}
+
+template <typename T, int N>
+void
+f10 (const I<T> &x, const I<T> &y)
+{
+  I<T> i;
+#pragma omp parallel
+#pragma omp single
+#pragma omp taskloop
+  for (i = x; i > y; i = i + N)
+    baz (i);
+}
+
+template <typename T>
+void
+f11 (const T &x, const T &y)
+{
+#pragma omp parallel
+  {
+#pragma omp single nowait
+#pragma omp taskloop nogroup
+    for (T i = x; i <= y; i += 3)
+      baz (i);
+#pragma omp single nowait
+    {
+      T j = y + 3;
+      baz (j);
+    }
+  }
+}
+
+template <typename T>
+void
+f12 (const T &x, const T &y)
+{
+  T i;
+#pragma omp parallel
+#pragma omp single
+#pragma omp taskloop
+  for (i = x; i > y; --i)
+    baz (i);
+}
+
+template <int N>
+struct K
+{
+  template <typename T>
+  static void
+  f13 (const T &x, const T &y)
+  {
+#pragma omp parallel
+#pragma omp single
+#pragma omp taskloop
+    for (T i = x; i <= y + N; i += N)
+      baz (i);
+  }
+};
+
+I<int>
+f14 (const I<int> &x, const I<int> &y)
+{
+  I<int> i;
+#pragma omp parallel
+#pragma omp single
+#pragma omp taskloop lastprivate(i)
+  for (i = x; i < y - 1; i = 1 - 6 + 7 + i)
+    baz (i);
+  return i;
+}
+
+template <typename T>
+I<int>
+f15 (const I<int> &x, const I<int> &y)
+{
+  I<int> i;
+#pragma omp parallel
+#pragma omp single
+#pragma omp taskloop lastprivate(i)
+  for (i = x + 2000 - 64; i > y + 10; --i)
+    baz (i);
+  return i;
+}
+
+template <int N>
+I<int>
+f16 (I<int> i, const I<int> &x, const I<int> &y)
+{
+#pragma omp parallel
+#pragma omp single
+#pragma omp taskloop lastprivate(i)
+  for (i = x - 10; i <= y + 10; i += N)
+    baz (i);
+  return i;
+}
+
+template <int N>
+I<int>
+f17 (J<int> j)
+{
+  static I<int> i;
+#pragma omp parallel
+#pragma omp single
+#pragma omp taskloop lastprivate(i)
+  for (i = j.begin (); i <= j.end () + N; i += 2)
+    baz (i);
+  return i;
+}
+
+template <typename T, int N>
+I<T>
+f18 (const I<T> &x, const I<T> &y)
+{
+  static I<T> i;
+#pragma omp parallel
+#pragma omp single
+#pragma omp taskloop lastprivate(i)
+  for (i = x; i > y; i = i + N)
+    baz (i);
+  return i;
+}
+
+template <typename T>
+T
+f19 (const T &x, const T &y)
+{
+  T i;
+#pragma omp parallel
+  {
+#pragma omp single nowait
+#pragma omp taskloop nogroup lastprivate(i)
+    for (i = x; i <= y; i += 3)
+      baz (i);
+#pragma omp single nowait
+    {
+      T j = y + 3;
+      baz (j);
+    }
+  }
+  return i;
+}
+
+template <typename T>
+T
+f20 (const T &x, const T &y)
+{
+  T i;
+#pragma omp parallel
+#pragma omp single
+#pragma omp taskloop lastprivate(i)
+  for (i = x; i > y; --i)
+    baz (i);
+  return i;
+}
+
+#define check(expr) \
+  for (int i = 0; i < 2000; i++)			\
+    if (expr)						\
+      {							\
+	if (results[i] != 1)				\
+	  abort ();					\
+	results[i] = 0;					\
+      }							\
+    else if (results[i])				\
+      abort ()
+
+int
+main ()
+{
+  int a[2000];
+  long b[2000];
+  for (int i = 0; i < 2000; i++)
+    {
+      a[i] = i;
+      b[i] = i;
+    }
+  f1 (&a[10], &a[1990]);
+  check (i >= 10 && i <= 1990 && (i - 10) % 6 == 0);
+  f2 (&a[0], &a[1999]);
+  check (i < 1998 && (i & 1) == 0);
+  f3<char> (&a[20], &a[1837]);
+  check (i >= 20 && i <= 1837);
+  f4<int> (&a[0], &a[30]);
+  check (i > 40 && i <= 2000 - 64);
+  f5 (&a[0], &a[100]);
+  check (i >= 116 && i <= 2000 - 64 && (i - 116) % 10 == 0);
+  f6<-10> (&a[10], &a[110]);
+  check (i >= 116 && i <= 2000 - 64 && (i - 116) % 10 == 0);
+  f7<6> (I<int> (), &a[12], &a[1800]);
+  check (i >= 2 && i <= 1808 && (i - 2) % 6 == 0);
+  f8<121> (J<int> (&a[14], &a[1803]));
+  check (i >= 14 && i <= 1924 && (i & 1) == 0);
+  f9<int, 7> (&a[33], &a[1967]);
+  check (i >= 33 && i <= 1967 && (i - 33) % 7 == 0);
+  f10<int, -7> (&a[1939], &a[17]);
+  check (i >= 21 && i <= 1939 && (i - 21) % 7 == 0);
+  f11<I<int> > (&a[16], &a[1981]);
+  check (i >= 16 && i <= 1984 && (i - 16) % 3 == 0);
+  f12<I<int> > (&a[1761], &a[37]);
+  check (i > 37 && i <= 1761);
+  K<5>::f13<I<int> > (&a[1], &a[1935]);
+  check (i >= 1 && i <= 1936 && (i - 1) % 5 == 0);
+  if (f14 (&a[0], &a[1999]) != I<int>(&a[1998]))
+    abort ();
+  check (i < 1998 && (i & 1) == 0);
+  if (f15<int> (&a[0], &a[30]) != I<int>(&a[40]))
+    abort ();
+  check (i > 40 && i <= 2000 - 64);
+  if (f16<6> (I<int> (), &a[12], &a[1800]) != I<int>(&a[1814]))
+    abort ();
+  check (i >= 2 && i <= 1808 && (i - 2) % 6 == 0);
+  if (f17<121> (J<int> (&a[14], &a[1803])) != I<int>(&a[1926]))
+    abort ();
+  check (i >= 14 && i <= 1924 && (i & 1) == 0);
+  if (f18<int, -7> (&a[1939], &a[17]) != I<int>(&a[14]))
+    abort ();
+  check (i >= 21 && i <= 1939 && (i - 21) % 7 == 0);
+  if (f19<I<int> > (&a[16], &a[1981]) != I<int>(&a[1984]))
+    abort ();
+  check (i >= 16 && i <= 1984 && (i - 16) % 3 == 0);
+  if (f20<I<int> > (&a[1761], &a[37]) != I<int>(&a[37]))
+    abort ();
+  check (i > 37 && i <= 1761);
+  f9<long, 7> (&b[33], &b[1967]);
+  check (i >= 33 && i <= 1967 && (i - 33) % 7 == 0);
+  f10<long, -7> (&b[1939], &b[17]);
+  check (i >= 21 && i <= 1939 && (i - 21) % 7 == 0);
+  f11<I<long> > (&b[16], &b[1981]);
+  check (i >= 16 && i <= 1984 && (i - 16) % 3 == 0);
+  f12<I<long> > (&b[1761], &b[37]);
+  check (i > 37 && i <= 1761);
+  K<5>::f13<I<long> > (&b[1], &b[1935]);
+  check (i >= 1 && i <= 1936 && (i - 1) % 5 == 0);
+  if (f18<long, -7> (&b[1939], &b[17]) != I<long>(&b[14]))
+    abort ();
+  check (i >= 21 && i <= 1939 && (i - 21) % 7 == 0);
+  if (f19<I<long> > (&b[16], &b[1981]) != I<long>(&b[1984]))
+    abort ();
+  check (i >= 16 && i <= 1984 && (i - 16) % 3 == 0);
+  if (f20<I<long> > (&b[1761], &b[37]) != I<long>(&b[37]))
+    abort ();
+  check (i > 37 && i <= 1761);
+}
--- libgomp/testsuite/libgomp.c++/taskloop-7.C.jj	2015-06-23 14:36:24.771027568 +0200
+++ libgomp/testsuite/libgomp.c++/taskloop-7.C	2015-06-23 15:34:09.847959682 +0200
@@ -0,0 +1,400 @@
+// { dg-do run }
+
+#include <vector>
+#include <cstdlib>
+
+template <typename T>
+class J
+{
+public:
+  typedef typename std::vector<T>::const_iterator const_iterator;
+  J(const const_iterator &x, const const_iterator &y) : b (x), e (y) {}
+  const const_iterator &begin ();
+  const const_iterator &end ();
+private:
+  const_iterator b, e;
+};
+
+template <typename T>
+const typename std::vector<T>::const_iterator &J<T>::begin () { return b; }
+template <typename T>
+const typename std::vector<T>::const_iterator &J<T>::end () { return e; }
+
+int results[2000];
+
+template <typename T>
+void
+baz (T &i)
+{
+  if (*i < 0 || *i >= 2000)
+    std::abort ();
+  results[*i]++;
+}
+
+void
+f1 (const std::vector<int>::const_iterator &x,
+    const std::vector<int>::const_iterator &y)
+{
+#pragma omp parallel
+#pragma omp single
+#pragma omp taskloop
+  for (std::vector<int>::const_iterator i = x; i <= y; i += 6)
+    baz (i);
+}
+
+void
+f2 (const std::vector<int>::const_iterator &x,
+    const std::vector<int>::const_iterator &y)
+{
+  std::vector<int>::const_iterator i;
+#pragma omp parallel
+#pragma omp single
+#pragma omp taskloop private(i)
+  for (i = x; i < y - 1; i = 1 - 6 + 7 + i)
+    baz (i);
+}
+
+template <typename T>
+void
+f3 (const std::vector<int>::const_iterator &x,
+    const std::vector<int>::const_iterator &y)
+{
+#pragma omp parallel
+#pragma omp single
+#pragma omp taskloop
+  for (std::vector<int>::const_iterator i = x; i <= y; i = i + 9 - 8)
+    baz (i);
+}
+
+template <typename T>
+void
+f4 (const std::vector<int>::const_iterator &x,
+    const std::vector<int>::const_iterator &y)
+{
+  std::vector<int>::const_iterator i;
+#pragma omp parallel
+#pragma omp single
+#pragma omp taskloop lastprivate(i)
+  for (i = x + 2000 - 64; i > y + 10; --i)
+    baz (i);
+}
+
+void
+f5 (const std::vector<int>::const_iterator &x,
+    const std::vector<int>::const_iterator &y)
+{
+#pragma omp parallel
+#pragma omp single
+#pragma omp taskloop
+  for (std::vector<int>::const_iterator i = x + 2000 - 64; i > y + 10; i -= 10)
+    baz (i);
+}
+
+template <int N>
+void
+f6 (const std::vector<int>::const_iterator &x,
+    const std::vector<int>::const_iterator &y)
+{
+#pragma omp parallel
+#pragma omp single
+#pragma omp taskloop
+  for (std::vector<int>::const_iterator i = x + 2000 - 64;
+       i > y + 10; i = i - 12 + 2)
+    {
+      std::vector<int>::const_iterator j = i + N;
+      baz (j);
+    }
+}
+
+template <int N>
+void
+f7 (std::vector<int>::const_iterator i,
+    const std::vector<int>::const_iterator &x,
+    const std::vector<int>::const_iterator &y)
+{
+#pragma omp parallel
+#pragma omp single
+#pragma omp taskloop
+  for (i = x - 10; i <= y + 10; i += N)
+    baz (i);
+}
+
+template <int N>
+void
+f8 (J<int> j)
+{
+  std::vector<int>::const_iterator i;
+#pragma omp parallel
+#pragma omp single
+#pragma omp taskloop
+  for (i = j.begin (); i <= j.end () + N; i += 2)
+    baz (i);
+}
+
+template <typename T, int N>
+void
+f9 (const typename std::vector<T>::const_iterator &x,
+    const typename std::vector<T>::const_iterator &y)
+{
+#pragma omp parallel
+#pragma omp single
+#pragma omp taskloop
+  for (typename std::vector<T>::const_iterator i = x; i <= y; i = i + N)
+    baz (i);
+}
+
+template <typename T, int N>
+void
+f10 (const typename std::vector<T>::const_iterator &x,
+     const typename std::vector<T>::const_iterator &y)
+{
+  typename std::vector<T>::const_iterator i;
+#pragma omp parallel
+#pragma omp single
+#pragma omp taskloop
+  for (i = x; i > y; i = i + N)
+    baz (i);
+}
+
+template <typename T>
+void
+f11 (const T &x, const T &y)
+{
+#pragma omp parallel
+  {
+#pragma omp single nowait
+#pragma omp taskloop nogroup
+    for (T i = x; i <= y; i += 3)
+      baz (i);
+#pragma omp single nowait
+    {
+      T j = y + 3;
+      baz (j);
+    }
+  }
+}
+
+template <typename T>
+void
+f12 (const T &x, const T &y)
+{
+  T i;
+#pragma omp parallel
+#pragma omp single
+#pragma omp taskloop
+  for (i = x; i > y; --i)
+    baz (i);
+}
+
+template <int N>
+struct K
+{
+  template <typename T>
+  static void
+  f13 (const T &x, const T &y)
+  {
+#pragma omp parallel
+#pragma omp single
+#pragma omp taskloop
+    for (T i = x; i <= y + N; i += N)
+      baz (i);
+  }
+};
+
+std::vector<int>::const_iterator
+f14 (const std::vector<int>::const_iterator &x,
+     const std::vector<int>::const_iterator &y)
+{
+  std::vector<int>::const_iterator i;
+#pragma omp parallel
+#pragma omp single
+#pragma omp taskloop lastprivate(i)
+  for (i = x; i < y - 1; i = 1 - 6 + 7 + i)
+    baz (i);
+  return i;
+}
+
+template <typename T>
+std::vector<int>::const_iterator
+f15 (const std::vector<int>::const_iterator &x,
+     const std::vector<int>::const_iterator &y)
+{
+  std::vector<int>::const_iterator i;
+#pragma omp parallel
+#pragma omp single
+#pragma omp taskloop lastprivate(i)
+  for (i = x + 2000 - 64; i > y + 10; --i)
+    baz (i);
+  return i;
+}
+
+template <int N>
+std::vector<int>::const_iterator
+f16 (std::vector<int>::const_iterator i,
+     const std::vector<int>::const_iterator &x,
+     const std::vector<int>::const_iterator &y)
+{
+#pragma omp parallel
+#pragma omp single
+#pragma omp taskloop lastprivate(i)
+  for (i = x - 10; i <= y + 10; i += N)
+    baz (i);
+  return i;
+}
+
+template <int N>
+std::vector<int>::const_iterator
+f17 (J<int> j)
+{
+  static std::vector<int>::const_iterator i;
+#pragma omp parallel
+#pragma omp single
+#pragma omp taskloop lastprivate(i)
+  for (i = j.begin (); i <= j.end () + N; i += 2)
+    baz (i);
+  return i;
+}
+
+template <typename T, int N>
+typename std::vector<T>::const_iterator
+f18 (const typename std::vector<T>::const_iterator &x,
+     const typename std::vector<T>::const_iterator &y)
+{
+  static typename std::vector<T>::const_iterator i;
+#pragma omp parallel
+#pragma omp single
+#pragma omp taskloop lastprivate(i)
+  for (i = x; i > y; i = i + N)
+    baz (i);
+  return i;
+}
+
+template <typename T>
+T
+f19 (const T &x, const T &y)
+{
+  T i;
+#pragma omp parallel
+  {
+#pragma omp single nowait
+#pragma omp taskloop nogroup lastprivate(i)
+    for (i = x; i <= y; i += 3)
+      baz (i);
+#pragma omp single nowait
+    {
+      T j = y + 3;
+      baz (j);
+    }
+  }
+  return i;
+}
+
+template <typename T>
+T
+f20 (const T &x, const T &y)
+{
+  T i;
+#pragma omp parallel
+#pragma omp single
+#pragma omp taskloop lastprivate(i)
+  for (i = x; i > y; --i)
+    baz (i);
+  return i;
+}
+
+#define check(expr) \
+  for (int i = 0; i < 2000; i++)			\
+    if (expr)						\
+      {							\
+	if (results[i] != 1)				\
+	  std::abort ();				\
+	results[i] = 0;					\
+      }							\
+    else if (results[i])				\
+      std::abort ()
+
+int
+main ()
+{
+  std::vector<int> a(2000);
+  std::vector<long> b(2000);
+  for (int i = 0; i < 2000; i++)
+    {
+      a[i] = i;
+      b[i] = i;
+    }
+  f1 (a.begin () + 10, a.begin () + 1990);
+  check (i >= 10 && i <= 1990 && (i - 10) % 6 == 0);
+  f2 (a.begin () + 0, a.begin () + 1999);
+  check (i < 1998 && (i & 1) == 0);
+  f3<char> (a.begin () + 20, a.begin () + 1837);
+  check (i >= 20 && i <= 1837);
+  f4<int> (a.begin () + 0, a.begin () + 30);
+  check (i > 40 && i <= 2000 - 64);
+  f5 (a.begin () + 0, a.begin () + 100);
+  check (i >= 116 && i <= 2000 - 64 && (i - 116) % 10 == 0);
+  f6<-10> (a.begin () + 10, a.begin () + 110);
+  check (i >= 116 && i <= 2000 - 64 && (i - 116) % 10 == 0);
+  f7<6> (std::vector<int>::const_iterator (), a.begin () + 12,
+	 a.begin () + 1800);
+  check (i >= 2 && i <= 1808 && (i - 2) % 6 == 0);
+  f8<121> (J<int> (a.begin () + 14, a.begin () + 1803));
+  check (i >= 14 && i <= 1924 && (i & 1) == 0);
+  f9<int, 7> (a.begin () + 33, a.begin () + 1967);
+  check (i >= 33 && i <= 1967 && (i - 33) % 7 == 0);
+  f10<int, -7> (a.begin () + 1939, a.begin () + 17);
+  check (i >= 21 && i <= 1939 && (i - 21) % 7 == 0);
+  f11<std::vector<int>::const_iterator > (a.begin () + 16, a.begin () + 1981);
+  check (i >= 16 && i <= 1984 && (i - 16) % 3 == 0);
+  f12<std::vector<int>::const_iterator > (a.begin () + 1761, a.begin () + 37);
+  check (i > 37 && i <= 1761);
+  K<5>::f13<std::vector<int>::const_iterator > (a.begin () + 1,
+						a.begin () + 1935);
+  check (i >= 1 && i <= 1936 && (i - 1) % 5 == 0);
+  if (f14 (a.begin () + 0, a.begin () + 1999) != a.begin () + 1998)
+    std::abort ();
+  check (i < 1998 && (i & 1) == 0);
+  if (f15<int> (a.begin () + 0, a.begin () + 30) != a.begin () + 40)
+    std::abort ();
+  check (i > 40 && i <= 2000 - 64);
+  if (f16<6> (std::vector<int>::const_iterator (), a.begin () + 12,
+	      a.begin () + 1800) != a.begin () + 1814)
+    std::abort ();
+  check (i >= 2 && i <= 1808 && (i - 2) % 6 == 0);
+  if (f17<121> (J<int> (a.begin () + 14, a.begin () + 1803)) != a.begin () + 1926)
+    std::abort ();
+  check (i >= 14 && i <= 1924 && (i & 1) == 0);
+  if (f18<int, -7> (a.begin () + 1939, a.begin () + 17) != a.begin () + 14)
+    std::abort ();
+  check (i >= 21 && i <= 1939 && (i - 21) % 7 == 0);
+  if (f19<std::vector<int>::const_iterator > (a.begin () + 16, a.begin () + 1981)
+      != a.begin () + 1984)
+    std::abort ();
+  check (i >= 16 && i <= 1984 && (i - 16) % 3 == 0);
+  if (f20<std::vector<int>::const_iterator > (a.begin () + 1761, a.begin () + 37)
+      != a.begin () + 37)
+    std::abort ();
+  check (i > 37 && i <= 1761);
+  f9<long, 7> (b.begin () + 33, b.begin () + 1967);
+  check (i >= 33 && i <= 1967 && (i - 33) % 7 == 0);
+  f10<long, -7> (b.begin () + 1939, b.begin () + 17);
+  check (i >= 21 && i <= 1939 && (i - 21) % 7 == 0);
+  f11<std::vector<long>::const_iterator > (b.begin () + 16, b.begin () + 1981);
+  check (i >= 16 && i <= 1984 && (i - 16) % 3 == 0);
+  f12<std::vector<long>::const_iterator > (b.begin () + 1761, b.begin () + 37);
+  check (i > 37 && i <= 1761);
+  K<5>::f13<std::vector<long>::const_iterator > (b.begin () + 1,
+						 b.begin () + 1935);
+  check (i >= 1 && i <= 1936 && (i - 1) % 5 == 0);
+  if (f18<long, -7> (b.begin () + 1939, b.begin () + 17) != b.begin () + 14)
+    std::abort ();
+  check (i >= 21 && i <= 1939 && (i - 21) % 7 == 0);
+  if (f19<std::vector<long>::const_iterator > (b.begin () + 16, b.begin () + 1981)
+      != b.begin () + 1984)
+    std::abort ();
+  check (i >= 16 && i <= 1984 && (i - 16) % 3 == 0);
+  if (f20<std::vector<long>::const_iterator > (b.begin () + 1761, b.begin () + 37)
+      != b.begin () + 37)
+    std::abort ();
+  check (i > 37 && i <= 1761);
+}
--- libgomp/testsuite/libgomp.c++/taskloop-8.C.jj	2015-06-23 15:38:19.107160655 +0200
+++ libgomp/testsuite/libgomp.c++/taskloop-8.C	2015-06-23 15:40:44.694941712 +0200
@@ -0,0 +1,250 @@
+// { dg-do run }
+
+#include <string>
+#include <cstdlib>
+
+template <typename T>
+class J
+{
+public:
+  typedef typename std::basic_string<T>::iterator iterator;
+  J(const iterator &x, const iterator &y) : b (x), e (y) {}
+  const iterator &begin ();
+  const iterator &end ();
+private:
+  iterator b, e;
+};
+
+template <typename T>
+const typename std::basic_string<T>::iterator &J<T>::begin () { return b; }
+template <typename T>
+const typename std::basic_string<T>::iterator &J<T>::end () { return e; }
+
+template <typename T>
+void
+baz (T &i)
+{
+  if (*i < L'a' || *i >= L'a' + 2000)
+    std::abort ();
+  (*i)++;
+}
+
+void
+f1 (const std::basic_string<wchar_t>::iterator &x,
+    const std::basic_string<wchar_t>::iterator &y)
+{
+#pragma omp parallel
+#pragma omp single
+#pragma omp taskloop
+  for (std::basic_string<wchar_t>::iterator i = x; i <= y; i += 6)
+    baz (i);
+}
+
+void
+f2 (const std::basic_string<wchar_t>::iterator &x,
+    const std::basic_string<wchar_t>::iterator &y)
+{
+  std::basic_string<wchar_t>::iterator i;
+#pragma omp parallel
+#pragma omp single
+#pragma omp taskloop private(i)
+  for (i = x; i < y - 1; i = 1 - 6 + 7 + i)
+    baz (i);
+}
+
+template <typename T>
+void
+f3 (const std::basic_string<wchar_t>::iterator &x,
+    const std::basic_string<wchar_t>::iterator &y)
+{
+#pragma omp parallel
+#pragma omp single
+#pragma omp taskloop
+  for (std::basic_string<wchar_t>::iterator i = x; i <= y; i = i + 9 - 8)
+    baz (i);
+}
+
+template <typename T>
+void
+f4 (const std::basic_string<wchar_t>::iterator &x,
+    const std::basic_string<wchar_t>::iterator &y)
+{
+  std::basic_string<wchar_t>::iterator i;
+#pragma omp parallel
+#pragma omp single
+#pragma omp taskloop lastprivate(i)
+  for (i = x + 2000 - 64; i > y + 10; --i)
+    baz (i);
+}
+
+void
+f5 (const std::basic_string<wchar_t>::iterator &x,
+    const std::basic_string<wchar_t>::iterator &y)
+{
+#pragma omp parallel
+#pragma omp single
+#pragma omp taskloop
+  for (std::basic_string<wchar_t>::iterator i = x + 2000 - 64;
+       i > y + 10; i -= 10)
+    baz (i);
+}
+
+template <int N>
+void
+f6 (const std::basic_string<wchar_t>::iterator &x,
+    const std::basic_string<wchar_t>::iterator &y)
+{
+#pragma omp parallel
+#pragma omp single
+#pragma omp taskloop
+  for (std::basic_string<wchar_t>::iterator i = x + 2000 - 64;
+       i > y + 10; i = i - 12 + 2)
+    {
+      std::basic_string<wchar_t>::iterator j = i + N;
+      baz (j);
+    }
+}
+
+template <int N>
+void
+f7 (std::basic_string<wchar_t>::iterator i,
+    const std::basic_string<wchar_t>::iterator &x,
+    const std::basic_string<wchar_t>::iterator &y)
+{
+#pragma omp parallel
+#pragma omp single
+#pragma omp taskloop
+  for (i = x - 10; i <= y + 10; i += N)
+    baz (i);
+}
+
+template <wchar_t N>
+void
+f8 (J<wchar_t> j)
+{
+  std::basic_string<wchar_t>::iterator i;
+#pragma omp parallel
+#pragma omp single
+#pragma omp taskloop
+  for (i = j.begin (); i <= j.end () + N; i += 2)
+    baz (i);
+}
+
+template <typename T, int N>
+void
+f9 (const typename std::basic_string<T>::iterator &x,
+    const typename std::basic_string<T>::iterator &y)
+{
+#pragma omp parallel
+#pragma omp single
+#pragma omp taskloop
+  for (typename std::basic_string<T>::iterator i = x; i <= y; i = i + N)
+    baz (i);
+}
+
+template <typename T, int N>
+void
+f10 (const typename std::basic_string<T>::iterator &x,
+     const typename std::basic_string<T>::iterator &y)
+{
+  typename std::basic_string<T>::iterator i;
+#pragma omp parallel
+#pragma omp single
+#pragma omp taskloop
+  for (i = x; i > y; i = i + N)
+    baz (i);
+}
+
+template <typename T>
+void
+f11 (const T &x, const T &y)
+{
+#pragma omp parallel
+  {
+#pragma omp single nowait
+#pragma omp taskloop nogroup
+    for (T i = x; i <= y; i += 3)
+      baz (i);
+#pragma omp single nowait
+    {
+      T j = y + 3;
+      baz (j);
+    }
+  }
+}
+
+template <typename T>
+void
+f12 (const T &x, const T &y)
+{
+  T i;
+#pragma omp parallel
+#pragma omp single
+#pragma omp taskloop private(i)
+  for (i = x; i > y; --i)
+    baz (i);
+}
+
+template <int N>
+struct K
+{
+  template <typename T>
+  static void
+  f13 (const T &x, const T &y)
+  {
+#pragma omp parallel
+#pragma omp single
+#pragma omp taskloop
+    for (T i = x; i <= y + N; i += N)
+      baz (i);
+  }
+};
+
+#define check(expr) \
+  for (int i = 0; i < 2000; i++)			\
+    if (expr)						\
+      {							\
+	if (a[i] != L'a' + i + 1)			\
+	  std::abort ();				\
+	a[i] = L'a' + i;				\
+      }							\
+    else if (a[i] != L'a' + i)				\
+      std::abort ()
+
+int
+main ()
+{
+  std::basic_string<wchar_t> a = L"";
+  for (int i = 0; i < 2000; i++)
+    a += L'a' + i;
+  f1 (a.begin () + 10, a.begin () + 1990);
+  check (i >= 10 && i <= 1990 && (i - 10) % 6 == 0);
+  f2 (a.begin () + 0, a.begin () + 1999);
+  check (i < 1998 && (i & 1) == 0);
+  f3<char> (a.begin () + 20, a.begin () + 1837);
+  check (i >= 20 && i <= 1837);
+  f4<int> (a.begin () + 0, a.begin () + 30);
+  check (i > 40 && i <= 2000 - 64);
+  f5 (a.begin () + 0, a.begin () + 100);
+  check (i >= 116 && i <= 2000 - 64 && (i - 116) % 10 == 0);
+  f6<-10> (a.begin () + 10, a.begin () + 110);
+  check (i >= 116 && i <= 2000 - 64 && (i - 116) % 10 == 0);
+  f7<6> (std::basic_string<wchar_t>::iterator (), a.begin () + 12,
+	 a.begin () + 1800);
+  check (i >= 2 && i <= 1808 && (i - 2) % 6 == 0);
+  f8<121> (J<wchar_t> (a.begin () + 14, a.begin () + 1803));
+  check (i >= 14 && i <= 1924 && (i & 1) == 0);
+  f9<wchar_t, 7> (a.begin () + 33, a.begin () + 1967);
+  check (i >= 33 && i <= 1967 && (i - 33) % 7 == 0);
+  f10<wchar_t, -7> (a.begin () + 1939, a.begin () + 17);
+  check (i >= 21 && i <= 1939 && (i - 21) % 7 == 0);
+  f11<std::basic_string<wchar_t>::iterator > (a.begin () + 16,
+					      a.begin () + 1981);
+  check (i >= 16 && i <= 1984 && (i - 16) % 3 == 0);
+  f12<std::basic_string<wchar_t>::iterator > (a.begin () + 1761,
+					      a.begin () + 37);
+  check (i > 37 && i <= 1761);
+  K<5>::f13<std::basic_string<wchar_t>::iterator > (a.begin () + 1,
+						    a.begin () + 1935);
+  check (i >= 1 && i <= 1936 && (i - 1) % 5 == 0);
+}
--- libgomp/testsuite/libgomp.c++/taskloop-9.C.jj	2015-06-23 15:41:50.575937601 +0200
+++ libgomp/testsuite/libgomp.c++/taskloop-9.C	2015-06-23 15:47:27.416900471 +0200
@@ -0,0 +1,323 @@
+// { dg-do run }
+
+typedef __PTRDIFF_TYPE__ ptrdiff_t;
+extern "C" void abort ();
+
+template <typename T>
+class I
+{
+public:
+  typedef ptrdiff_t difference_type;
+  I ();
+  ~I ();
+  I (T *);
+  I (const I &);
+  T &operator * ();
+  T *operator -> ();
+  T &operator [] (const difference_type &) const;
+  I &operator = (const I &);
+  I &operator ++ ();
+  I operator ++ (int);
+  I &operator -- ();
+  I operator -- (int);
+  I &operator += (const difference_type &);
+  I &operator -= (const difference_type &);
+  I operator + (const difference_type &) const;
+  I operator - (const difference_type &) const;
+  template <typename S> friend bool operator == (I<S> &, I<S> &);
+  template <typename S> friend bool operator == (const I<S> &, const I<S> &);
+  template <typename S> friend bool operator < (I<S> &, I<S> &);
+  template <typename S> friend bool operator < (const I<S> &, const I<S> &);
+  template <typename S> friend bool operator <= (I<S> &, I<S> &);
+  template <typename S> friend bool operator <= (const I<S> &, const I<S> &);
+  template <typename S> friend bool operator > (I<S> &, I<S> &);
+  template <typename S> friend bool operator > (const I<S> &, const I<S> &);
+  template <typename S> friend bool operator >= (I<S> &, I<S> &);
+  template <typename S> friend bool operator >= (const I<S> &, const I<S> &);
+  template <typename S> friend typename I<S>::difference_type operator - (I<S> &, I<S> &);
+  template <typename S> friend typename I<S>::difference_type operator - (const I<S> &, const I<S> &);
+  template <typename S> friend I<S> operator + (typename I<S>::difference_type , const I<S> &);
+private:
+  T *p;
+};
+template <typename T> I<T>::I () : p (0) {}
+template <typename T> I<T>::~I () { p = (T *) 0; }
+template <typename T> I<T>::I (T *x) : p (x) {}
+template <typename T> I<T>::I (const I &x) : p (x.p) {}
+template <typename T> T &I<T>::operator * () { return *p; }
+template <typename T> T *I<T>::operator -> () { return p; }
+template <typename T> T &I<T>::operator [] (const difference_type &x) const { return p[x]; }
+template <typename T> I<T> &I<T>::operator = (const I &x) { p = x.p; return *this; }
+template <typename T> I<T> &I<T>::operator ++ () { ++p; return *this; }
+template <typename T> I<T> I<T>::operator ++ (int) { return I (p++); }
+template <typename T> I<T> &I<T>::operator -- () { --p; return *this; }
+template <typename T> I<T> I<T>::operator -- (int) { return I (p--); }
+template <typename T> I<T> &I<T>::operator += (const difference_type &x) { p += x; return *this; }
+template <typename T> I<T> &I<T>::operator -= (const difference_type &x) { p -= x; return *this; }
+template <typename T> I<T> I<T>::operator + (const difference_type &x) const { return I (p + x); }
+template <typename T> I<T> I<T>::operator - (const difference_type &x) const { return I (p - x); }
+template <typename T> bool operator == (I<T> &x, I<T> &y) { return x.p == y.p; }
+template <typename T> bool operator == (const I<T> &x, const I<T> &y) { return x.p == y.p; }
+template <typename T> bool operator != (I<T> &x, I<T> &y) { return !(x == y); }
+template <typename T> bool operator != (const I<T> &x, const I<T> &y) { return !(x == y); }
+template <typename T> bool operator < (I<T> &x, I<T> &y) { return x.p < y.p; }
+template <typename T> bool operator < (const I<T> &x, const I<T> &y) { return x.p < y.p; }
+template <typename T> bool operator <= (I<T> &x, I<T> &y) { return x.p <= y.p; }
+template <typename T> bool operator <= (const I<T> &x, const I<T> &y) { return x.p <= y.p; }
+template <typename T> bool operator > (I<T> &x, I<T> &y) { return x.p > y.p; }
+template <typename T> bool operator > (const I<T> &x, const I<T> &y) { return x.p > y.p; }
+template <typename T> bool operator >= (I<T> &x, I<T> &y) { return x.p >= y.p; }
+template <typename T> bool operator >= (const I<T> &x, const I<T> &y) { return x.p >= y.p; }
+template <typename T> typename I<T>::difference_type operator - (I<T> &x, I<T> &y) { return x.p - y.p; }
+template <typename T> typename I<T>::difference_type operator - (const I<T> &x, const I<T> &y) { return x.p - y.p; }
+template <typename T> I<T> operator + (typename I<T>::difference_type x, const I<T> &y) { return I<T> (x + y.p); }
+
+template <typename T>
+class J
+{
+public:
+  J(const I<T> &x, const I<T> &y) : b (x), e (y) {}
+  const I<T> &begin ();
+  const I<T> &end ();
+private:
+  I<T> b, e;
+};
+
+template <typename T> const I<T> &J<T>::begin () { return b; }
+template <typename T> const I<T> &J<T>::end () { return e; }
+
+int results[2000];
+
+template <typename T>
+void
+baz (I<T> &i)
+{
+  if (*i < 0 || *i >= 2000)
+    abort ();
+  results[*i]++;
+}
+
+I<int>
+f1 (const I<int> &x, const I<int> &y)
+{
+  I<int> i;
+#pragma omp parallel shared (i)
+  {
+  #pragma omp single
+  #pragma omp taskloop lastprivate (i)
+    for (i = x; i < y - 1; ++i)
+      baz (i);
+  #pragma omp single
+    i += 3;
+  }
+  return I<int> (i);
+}
+
+I<int>
+f2 (const I<int> &x, const I<int> &y)
+{
+  I<int> i;
+#pragma omp parallel
+#pragma omp single
+#pragma omp taskloop lastprivate (i)
+  for (i = x; i < y - 1; i = 1 - 6 + 7 + i)
+    baz (i);
+  return I<int> (i);
+}
+
+template <typename T>
+I<int>
+f3 (const I<int> &x, const I<int> &y)
+{
+  I<int> i;
+#pragma omp parallel
+#pragma omp single
+#pragma omp taskloop lastprivate (i)
+    for (i = x + 1000 - 64; i <= y - 10; i++)
+      baz (i);
+  return i;
+}
+
+template <typename T>
+I<int>
+f4 (const I<int> &x, const I<int> &y)
+{
+  I<int> i;
+#pragma omp parallel
+#pragma omp single
+#pragma omp taskloop lastprivate (i)
+  for (i = x + 2000 - 64; i > y + 10; --i)
+    baz (i);
+  return I<int> (i);
+}
+
+template <typename T>
+I<int>
+f5 (const I<int> &x, const I<int> &y)
+{
+  I<int> i;
+#pragma omp parallel
+#pragma omp single
+#pragma omp taskloop lastprivate (i)
+  for (i = x; i > y + T (6); i--)
+    baz (i);
+  return i;
+}
+
+template <typename T>
+I<int>
+f6 (const I<int> &x, const I<int> &y)
+{
+  I<int> i;
+#pragma omp parallel
+#pragma omp single
+#pragma omp taskloop lastprivate (i)
+  for (i = x - T (7); i > y; i -= T (2))
+    baz (i);
+  return I<int> (i);
+}
+
+template <int N>
+I<int>
+f7 (I<int> i, const I<int> &x, const I<int> &y)
+{
+#pragma omp parallel
+#pragma omp single
+#pragma omp taskloop lastprivate (i)
+  for (i = x - 10; i <= y + 10; i += N)
+    baz (i);
+  return I<int> (i);
+}
+
+template <int N>
+I<int>
+f8 (J<int> j)
+{
+  I<int> i;
+#pragma omp parallel shared (i)
+  #pragma omp single
+  #pragma omp taskloop lastprivate (i)
+    for (i = j.begin (); i <= j.end () + N; i += 2)
+      baz (i);
+  return i;
+}
+
+I<int> i9;
+
+template <long N>
+I<int> &
+f9 (J<int> j)
+{
+#pragma omp parallel
+#pragma omp single
+#pragma omp taskloop lastprivate (i9)
+  for (i9 = j.begin () + N; i9 <= j.end () - N; i9 = i9 - N)
+    baz (i9);
+  return i9;
+}
+
+template <typename T, int N>
+I<T>
+f10 (const I<T> &x, const I<T> &y)
+{
+  I<T> i;
+#pragma omp parallel
+#pragma omp single
+#pragma omp taskloop lastprivate (i)
+  for (i = x; i > y; i = i + N)
+    baz (i);
+  return i;
+}
+
+template <typename T, typename U>
+T
+f11 (T i, const T &x, const T &y)
+{
+#pragma omp parallel
+  #pragma omp single
+  #pragma omp taskloop lastprivate (i)
+  for (i = x + U (2); i <= y + U (1); i = U (2) + U (3) + i)
+    baz (i);
+  return T (i);
+}
+
+template <typename T>
+T
+f12 (const T &x, const T &y)
+{
+  T i;
+#pragma omp parallel
+#pragma omp single
+#pragma omp taskloop lastprivate (i)
+  for (i = x; i > y; --i)
+    baz (i);
+  return i;
+}
+
+#define check(expr) \
+  for (int i = 0; i < 2000; i++)			\
+    if (expr)						\
+      {							\
+	if (results[i] != 1)				\
+	  abort ();					\
+	results[i] = 0;					\
+      }							\
+    else if (results[i])				\
+      abort ()
+
+int
+main ()
+{
+  int a[2000];
+  long b[2000];
+  for (int i = 0; i < 2000; i++)
+    {
+      a[i] = i;
+      b[i] = i;
+    }
+  if (*f1 (&a[10], &a[1873]) != 1875)
+    abort ();
+  check (i >= 10 && i < 1872);
+  if (*f2 (&a[0], &a[1998]) != 1998)
+    abort ();
+  check (i < 1997 && (i & 1) == 0);
+  if (*f3<int> (&a[10], &a[1971]) != 1962)
+    abort ();
+  check (i >= 946 && i <= 1961);
+  if (*f4<int> (&a[0], &a[30]) != 40)
+    abort ();
+  check (i > 40 && i <= 2000 - 64);
+  if (*f5<short> (&a[1931], &a[17]) != 23)
+    abort ();
+  check (i > 23 && i <= 1931);
+  if (*f6<long> (&a[1931], &a[17]) != 16)
+    abort ();
+  check (i > 17 && i <= 1924 && (i & 1) == 0);
+  if (*f7<6> (I<int> (), &a[12], &a[1800]) != 1814)
+    abort ();
+  check (i >= 2 && i <= 1808 && (i - 2) % 6 == 0);
+  if (*f8<121> (J<int> (&a[14], &a[1803])) != 1926)
+    abort ();
+  check (i >= 14 && i <= 1924 && (i & 1) == 0);
+  if (*f9<-3L> (J<int> (&a[27], &a[1761])) != 1767)
+    abort ();
+  check (i >= 24 && i <= 1764 && (i % 3) == 0);
+  if (*f10<int, -7> (&a[1939], &a[17]) != 14)
+    abort ();
+  check (i >= 21 && i <= 1939 && i % 7 == 0);
+  if (*f11<I<int>, short> (I<int> (), &a[71], &a[1941]) != 1943)
+    abort ();
+  check (i >= 73 && i <= 1938 && (i - 73) % 5 == 0);
+  if (*f12<I<int> > (&a[1761], &a[37]) != 37)
+    abort ();
+  check (i > 37 && i <= 1761);
+  if (*f10<long, -7> (&b[1939], &b[17]) != 14)
+    abort ();
+  check (i >= 21 && i <= 1939 && i % 7 == 0);
+  if (*f11<I<long>, short> (I<long> (), &b[71], &b[1941]) != 1943)
+    abort ();
+  check (i >= 73 && i <= 1938 && (i - 73) % 5 == 0);
+  if (*f12<I<long> > (&b[1761], &b[37]) != 37)
+    abort ();
+  check (i > 37 && i <= 1761);
+}

	Jakub



More information about the Gcc-patches mailing list