[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