This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[gomp5] Support OpenMP loops with != condition
- From: Jakub Jelinek <jakub at redhat dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Thu, 29 Jun 2017 10:48:00 +0200
- Subject: [gomp5] Support OpenMP loops with != condition
- Authentication-results: sourceware.org; auth=none
- Authentication-results: ext-mx10.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com
- Authentication-results: ext-mx10.extmail.prod.ext.phx2.redhat.com; spf=pass smtp.mailfrom=jakub at redhat dot com
- Dkim-filter: OpenDKIM Filter v2.11.0 mx1.redhat.com 28F965F795
- Dmarc-filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 28F965F795
- Reply-to: Jakub Jelinek <jakub at redhat dot com>
Hi!
OpenMP 5.0 is going to support loops where condition is not just
</<=/>/>= comparison, but also !=, with the requirement that the
increment has to be constant expression of 1 or -1 in that case
(and no overflow even for unsigned iterators).
The following patch implements it, tested on x86_64-linux, committed to
gomp-5_0-branch.
2017-06-29 Jakub Jelinek <jakub@redhat.com>
gcc/
* omp-general.c (omp_extract_for_data): Allow NE_EXPR
even in OpenMP loops, transform them into LT_EXPR or
GT_EXPR loops depending on incr sign. Formatting fixes.
gcc/c-family/
* c-common.h (c_finish_omp_for): Add FINAL_P argument.
* c-omp.c (check_omp_for_incr_expr): Formatting fixes.
(c_finish_omp_for): Add FINAL_P argument. Allow NE_EXPR
even in OpenMP loops, diagnose if NE_EXPR and incr expression
is not constant expression 1 or -1. Transform NE_EXPR loops
with iterators pointers to VLA into LT_EXPR or GT_EXPR loops.
gcc/c/
* c-parser.c (c_parser_omp_for_loop): Allow NE_EXPR even in
OpenMP loops, adjust c_finish_omp_for caller.
gcc/cp/
* parser.c (cp_parser_omp_for_cond): Allow NE_EXPR even in OpenMP
loops.
* pt.c (dependent_omp_for_p): Return true if class type iterator
does not have INTEGER_CST increment.
* semantics.c (handle_omp_for_class_iterator): Call cp_fully_fold
on incr.
(finish_omp_for): Adjust c_finish_omp_for caller.
gcc/testsuite/
* c-c++-common/gomp/for-1.c: New test.
* c-c++-common/gomp/for-2.c: New test.
* c-c++-common/gomp/for-3.c: New test.
* c-c++-common/gomp/for-4.c: New test.
* c-c++-common/gomp/for-5.c: New test.
* gcc.dg/gomp/pr39495-2.c (foo): Don't expect errors on !=.
* g++.dg/gomp/pr39495-2.C (foo): Likewise.
* g++.dg/gomp/loop-4.C: New test.
libgomp/
* testsuite/libgomp.c/for-2.h: If CONDNE macro is defined, define
a different N(test), don't define N(f0) to N(f14), but instead define
N(f20) to N(f34) using != comparisons.
* testsuite/libgomp.c/for-4.c: Use dg-additional-options.
* testsuite/libgomp.c/for-7.c: New test.
* testsuite/libgomp.c/for-8.c: New test.
* testsuite/libgomp.c/for-9.c: New test.
* testsuite/libgomp.c/for-10.c: New test.
* testsuite/libgomp.c/for-11.c: New test.
* testsuite/libgomp.c/for-12.c: New test.
* testsuite/libgomp.c/for-13.c: New test.
* testsuite/libgomp.c++/for-12.C: Remove dg-options.
* testsuite/libgomp.c++/for-15.C: New test.
* testsuite/libgomp.c++/for-16.C: New test.
* testsuite/libgomp.c++/for-17.C: New test.
* testsuite/libgomp.c++/for-18.C: New test.
* testsuite/libgomp.c++/for-19.C: New test.
* testsuite/libgomp.c++/for-20.C: New test.
* testsuite/libgomp.c++/for-21.C: New test.
* testsuite/libgomp.c++/for-22.C: New test.
* testsuite/libgomp.c++/for-23.C: New test.
--- gcc/omp-general.c.jj 2017-05-24 11:48:18.881013651 +0200
+++ gcc/omp-general.c 2017-06-23 15:05:12.655397129 +0200
@@ -252,14 +252,45 @@ omp_extract_for_data (gomp_for *for_stmt
loop->cond_code = gimple_omp_for_cond (for_stmt, i);
loop->n2 = gimple_omp_for_final (for_stmt, i);
gcc_assert (loop->cond_code != NE_EXPR
- || gimple_omp_for_kind (for_stmt) == GF_OMP_FOR_KIND_CILKSIMD
- || gimple_omp_for_kind (for_stmt) == GF_OMP_FOR_KIND_CILKFOR);
- omp_adjust_for_condition (loc, &loop->cond_code, &loop->n2);
-
+ || (gimple_omp_for_kind (for_stmt)
+ != GF_OMP_FOR_KIND_OACC_LOOP));
t = gimple_omp_for_incr (for_stmt, i);
gcc_assert (TREE_OPERAND (t, 0) == var);
loop->step = omp_get_for_step_from_incr (loc, t);
+ if (loop->cond_code == NE_EXPR
+ && fd->sched_kind != OMP_CLAUSE_SCHEDULE_CILKFOR
+ && (!simd || (gimple_omp_for_kind (for_stmt)
+ != GF_OMP_FOR_KIND_CILKSIMD)))
+ {
+ gcc_assert (TREE_CODE (loop->step) == INTEGER_CST);
+ if (TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE)
+ {
+ if (integer_onep (loop->step))
+ loop->cond_code = LT_EXPR;
+ else
+ {
+ gcc_assert (integer_minus_onep (loop->step));
+ loop->cond_code = GT_EXPR;
+ }
+ }
+ else
+ {
+ tree unit = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (loop->v)));
+ gcc_assert (TREE_CODE (unit) == INTEGER_CST);
+ if (tree_int_cst_equal (unit, loop->step))
+ loop->cond_code = LT_EXPR;
+ else
+ {
+ gcc_assert (wi::neg (wi::to_widest (unit))
+ == wi::to_widest (loop->step));
+ loop->cond_code = GT_EXPR;
+ }
+ }
+ }
+
+ omp_adjust_for_condition (loc, &loop->cond_code, &loop->n2);
+
if (simd
|| (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
&& !fd->have_ordered))
@@ -284,9 +315,8 @@ omp_extract_for_data (gomp_for *for_stmt
tree n;
if (loop->cond_code == LT_EXPR)
- n = fold_build2_loc (loc,
- PLUS_EXPR, TREE_TYPE (loop->v),
- loop->n2, loop->step);
+ n = fold_build2_loc (loc, PLUS_EXPR, TREE_TYPE (loop->v),
+ loop->n2, loop->step);
else
n = loop->n1;
if (TREE_CODE (n) != INTEGER_CST
@@ -301,15 +331,13 @@ omp_extract_for_data (gomp_for *for_stmt
if (loop->cond_code == LT_EXPR)
{
n1 = loop->n1;
- n2 = fold_build2_loc (loc,
- PLUS_EXPR, TREE_TYPE (loop->v),
- loop->n2, loop->step);
+ n2 = fold_build2_loc (loc, PLUS_EXPR, TREE_TYPE (loop->v),
+ loop->n2, loop->step);
}
else
{
- n1 = fold_build2_loc (loc,
- MINUS_EXPR, TREE_TYPE (loop->v),
- loop->n2, loop->step);
+ n1 = fold_build2_loc (loc, MINUS_EXPR, TREE_TYPE (loop->v),
+ loop->n2, loop->step);
n2 = loop->n1;
}
if (TREE_CODE (n1) != INTEGER_CST
@@ -341,27 +369,31 @@ omp_extract_for_data (gomp_for *for_stmt
if (POINTER_TYPE_P (itype))
itype = signed_type_for (itype);
t = build_int_cst (itype, (loop->cond_code == LT_EXPR ? -1 : 1));
- t = fold_build2_loc (loc,
- PLUS_EXPR, itype,
- fold_convert_loc (loc, itype, loop->step), t);
+ t = fold_build2_loc (loc, PLUS_EXPR, itype,
+ fold_convert_loc (loc, itype, loop->step),
+ t);
t = fold_build2_loc (loc, PLUS_EXPR, itype, t,
- fold_convert_loc (loc, itype, loop->n2));
+ fold_convert_loc (loc, itype, loop->n2));
t = fold_build2_loc (loc, MINUS_EXPR, itype, t,
- fold_convert_loc (loc, itype, loop->n1));
+ fold_convert_loc (loc, itype, loop->n1));
if (TYPE_UNSIGNED (itype) && loop->cond_code == GT_EXPR)
- t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype,
- fold_build1_loc (loc, NEGATE_EXPR, itype, t),
- fold_build1_loc (loc, NEGATE_EXPR, itype,
- fold_convert_loc (loc, itype,
- loop->step)));
+ {
+ tree step = fold_convert_loc (loc, itype, loop->step);
+ t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype,
+ fold_build1_loc (loc, NEGATE_EXPR,
+ itype, t),
+ fold_build1_loc (loc, NEGATE_EXPR,
+ itype, step));
+ }
else
t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype, t,
- fold_convert_loc (loc, itype, loop->step));
+ fold_convert_loc (loc, itype,
+ loop->step));
t = fold_convert_loc (loc, long_long_unsigned_type_node, t);
if (count != NULL_TREE)
- count = fold_build2_loc (loc,
- MULT_EXPR, long_long_unsigned_type_node,
- count, t);
+ count = fold_build2_loc (loc, MULT_EXPR,
+ long_long_unsigned_type_node,
+ count, t);
else
count = t;
if (TREE_CODE (count) != INTEGER_CST)
--- gcc/c-family/c-common.h.jj 2017-05-24 11:56:00.000000000 +0200
+++ gcc/c-family/c-common.h 2017-06-27 14:58:35.049139137 +0200
@@ -1291,7 +1291,7 @@ extern void c_finish_omp_flush (location
extern void c_finish_omp_taskwait (location_t);
extern void c_finish_omp_taskyield (location_t);
extern tree c_finish_omp_for (location_t, enum tree_code, tree, tree, tree,
- tree, tree, tree, tree);
+ tree, tree, tree, tree, bool);
extern bool c_omp_check_loop_iv (tree, tree, walk_tree_lh);
extern bool c_omp_check_loop_iv_exprs (location_t, tree, tree, tree, tree,
walk_tree_lh);
--- gcc/c-family/c-omp.c.jj 2017-05-24 11:56:00.119183052 +0200
+++ gcc/c-family/c-omp.c 2017-06-28 18:30:29.130040052 +0200
@@ -381,17 +381,17 @@ check_omp_for_incr_expr (location_t loc,
t = check_omp_for_incr_expr (loc, TREE_OPERAND (exp, 0), decl);
if (t != error_mark_node)
return fold_build2_loc (loc, MINUS_EXPR,
- TREE_TYPE (exp), t, TREE_OPERAND (exp, 1));
+ TREE_TYPE (exp), t, TREE_OPERAND (exp, 1));
break;
case PLUS_EXPR:
t = check_omp_for_incr_expr (loc, TREE_OPERAND (exp, 0), decl);
if (t != error_mark_node)
return fold_build2_loc (loc, PLUS_EXPR,
- TREE_TYPE (exp), t, TREE_OPERAND (exp, 1));
+ TREE_TYPE (exp), t, TREE_OPERAND (exp, 1));
t = check_omp_for_incr_expr (loc, TREE_OPERAND (exp, 1), decl);
if (t != error_mark_node)
return fold_build2_loc (loc, PLUS_EXPR,
- TREE_TYPE (exp), TREE_OPERAND (exp, 0), t);
+ TREE_TYPE (exp), TREE_OPERAND (exp, 0), t);
break;
case COMPOUND_EXPR:
{
@@ -457,7 +457,7 @@ c_omp_for_incr_canonicalize_ptr (locatio
tree
c_finish_omp_for (location_t locus, enum tree_code code, tree declv,
tree orig_declv, tree initv, tree condv, tree incrv,
- tree body, tree pre_body)
+ tree body, tree pre_body, bool final_p)
{
location_t elocus;
bool fail = false;
@@ -592,7 +592,8 @@ c_finish_omp_for (location_t locus, enum
{
if (!INTEGRAL_TYPE_P (TREE_TYPE (decl)))
{
- if (code != CILK_SIMD && code != CILK_FOR)
+ if (code != CILK_SIMD && code != CILK_FOR
+ && (code == OACC_LOOP || TREE_CODE (cond) == EQ_EXPR))
cond_ok = false;
}
else if (operand_equal_p (TREE_OPERAND (cond, 1),
@@ -605,7 +606,9 @@ c_finish_omp_for (location_t locus, enum
0))
TREE_SET_CODE (cond, TREE_CODE (cond) == NE_EXPR
? LT_EXPR : GE_EXPR);
- else if (code != CILK_SIMD && code != CILK_FOR)
+ else if (code != CILK_SIMD && code != CILK_FOR
+ && (code == OACC_LOOP
+ || TREE_CODE (cond) == EQ_EXPR))
cond_ok = false;
}
}
@@ -641,6 +644,23 @@ c_finish_omp_for (location_t locus, enum
break;
incr_ok = true;
+ if (!fail
+ && TREE_CODE (cond) == NE_EXPR
+ && TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE
+ && code != CILK_SIMD
+ && code != CILK_FOR
+ && TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (decl)))
+ && (TREE_CODE (TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (decl))))
+ != INTEGER_CST))
+ {
+ /* For pointer to VLA, transform != into < or >
+ depending on whether incr is increment or decrement. */
+ if (TREE_CODE (incr) == PREINCREMENT_EXPR
+ || TREE_CODE (incr) == POSTINCREMENT_EXPR)
+ TREE_SET_CODE (cond, LT_EXPR);
+ else
+ TREE_SET_CODE (cond, GT_EXPR);
+ }
incr = c_omp_for_incr_canonicalize_ptr (elocus, decl, incr);
break;
@@ -676,6 +696,60 @@ c_finish_omp_for (location_t locus, enum
incr = build2 (MODIFY_EXPR, void_type_node, decl, t);
}
}
+ if (!fail
+ && incr_ok
+ && TREE_CODE (cond) == NE_EXPR
+ && code != CILK_SIMD
+ && code != CILK_FOR)
+ {
+ tree i = TREE_OPERAND (incr, 1);
+ i = TREE_OPERAND (i, TREE_OPERAND (i, 0) == decl);
+ i = c_fully_fold (i, false, NULL);
+ if (!final_p
+ && TREE_CODE (i) != INTEGER_CST)
+ ;
+ else if (TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE)
+ {
+ tree unit
+ = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (decl)));
+ if (unit)
+ {
+ enum tree_code ccode = GT_EXPR;
+ unit = c_fully_fold (unit, false, NULL);
+ i = fold_convert (TREE_TYPE (unit), i);
+ if (operand_equal_p (unit, i, 0))
+ ccode = LT_EXPR;
+ if (ccode == GT_EXPR)
+ {
+ i = fold_unary (NEGATE_EXPR, TREE_TYPE (i), i);
+ if (i == NULL_TREE
+ || !operand_equal_p (unit, i, 0))
+ {
+ error_at (elocus,
+ "increment is not constant 1 or "
+ "-1 for != condition");
+ fail = true;
+ }
+ }
+ if (TREE_CODE (unit) != INTEGER_CST)
+ /* For pointer to VLA, transform != into < or >
+ depending on whether the pointer is
+ incremented or decremented in each
+ iteration. */
+ TREE_SET_CODE (cond, ccode);
+ }
+ }
+ else
+ {
+ if (!integer_onep (i) && !integer_minus_onep (i))
+ {
+ error_at (elocus,
+ "increment is not constant 1 or -1 for"
+ " != condition");
+ fail = true;
+ }
+ }
+ }
break;
default:
--- gcc/c/c-parser.c.jj 2017-05-24 11:56:00.111183154 +0200
+++ gcc/c/c-parser.c 2017-06-27 15:02:58.601006059 +0200
@@ -15136,7 +15136,7 @@ c_parser_omp_for_loop (location_t loc, c
case LE_EXPR:
break;
case NE_EXPR:
- if (code == CILK_SIMD || code == CILK_FOR)
+ if (code != OACC_LOOP)
break;
/* FALLTHRU. */
default:
@@ -15273,7 +15273,7 @@ c_parser_omp_for_loop (location_t loc, c
if (!fail)
{
stmt = c_finish_omp_for (loc, code, declv, NULL, initv, condv,
- incrv, body, pre_body);
+ incrv, body, pre_body, true);
/* Check for iterators appearing in lb, b or incr expressions. */
if (stmt && !c_omp_check_loop_iv (stmt, declv, NULL))
--- gcc/cp/parser.c.jj 2017-05-24 11:56:00.000000000 +0200
+++ gcc/cp/parser.c 2017-06-23 11:00:52.811115577 +0200
@@ -34196,9 +34196,8 @@ cp_parser_omp_for_cond (cp_parser *parse
case LE_EXPR:
break;
case NE_EXPR:
- if (code == CILK_SIMD || code == CILK_FOR)
+ if (code != OACC_LOOP)
break;
- /* Fall through: OpenMP disallows NE_EXPR. */
gcc_fallthrough ();
default:
return error_mark_node;
--- gcc/cp/pt.c.jj 2017-05-24 11:56:00.000000000 +0200
+++ gcc/cp/pt.c 2017-06-28 16:24:09.654377250 +0200
@@ -24468,6 +24468,20 @@ dependent_omp_for_p (tree declv, tree in
if (type_dependent_expression_p (TREE_OPERAND (t, 0))
|| type_dependent_expression_p (TREE_OPERAND (t, 1)))
return true;
+
+ /* If this loop has a class iterator with != comparison
+ with increment other than i++/++i/i--/--i, make sure the
+ increment is constant. */
+ if (CLASS_TYPE_P (TREE_TYPE (decl))
+ && TREE_CODE (cond) == NE_EXPR)
+ {
+ if (TREE_OPERAND (t, 0) == decl)
+ t = TREE_OPERAND (t, 1);
+ else
+ t = TREE_OPERAND (t, 0);
+ if (TREE_CODE (t) != INTEGER_CST)
+ return true;
+ }
}
}
}
--- gcc/cp/semantics.c.jj 2017-05-24 11:56:00.000000000 +0200
+++ gcc/cp/semantics.c 2017-06-28 15:53:59.303706277 +0200
@@ -7891,6 +7891,7 @@ handle_omp_for_class_iterator (int i, lo
}
incr = cp_convert (TREE_TYPE (diff), incr, tf_warning_or_error);
+ incr = cp_fully_fold (incr);
bool taskloop_iv_seen = false;
for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
@@ -8277,7 +8278,8 @@ finish_omp_for (location_t locus, enum t
block = push_stmt_list ();
omp_for = c_finish_omp_for (locus, code, declv, orig_declv, initv, condv,
- incrv, body, pre_body);
+ incrv, body, pre_body,
+ !processing_template_decl);
/* Check for iterators appearing in lb, b or incr expressions. */
if (omp_for && !c_omp_check_loop_iv (omp_for, orig_declv, cp_walk_subtrees))
--- gcc/testsuite/c-c++-common/gomp/for-1.c.jj 2017-06-28 18:06:50.461763313 +0200
+++ gcc/testsuite/c-c++-common/gomp/for-1.c 2017-06-28 17:56:03.000000000 +0200
@@ -0,0 +1,60 @@
+void bar (int);
+
+int a[256];
+
+void
+foo (void)
+{
+ int i;
+ #pragma omp for
+ for (i = 0; i != 64; i++)
+ bar (i);
+ #pragma omp for
+ for (i = 128; i != 64; i--)
+ bar (i);
+ #pragma omp for
+ for (i = 0; i != 64; i = i + 1)
+ bar (i);
+ #pragma omp for
+ for (i = 128; i != 64; i = i - 1)
+ bar (i);
+ #pragma omp for
+ for (i = 0; i != 64; i = 1 + i)
+ bar (i);
+ #pragma omp for
+ for (i = 128; i != 64; i = -1 + i)
+ bar (i);
+ #pragma omp for
+ for (i = 0; i != 64; i += 1)
+ bar (i);
+ #pragma omp for
+ for (i = 128; i != 64; i -= 1)
+ bar (i);
+ #pragma omp single
+ {
+ #pragma omp simd
+ for (i = 0; i != 64; i++)
+ a[i] = a[i] + 1;
+ #pragma omp simd
+ for (i = 128; i != 64; i--)
+ a[i] = a[i] + 1;
+ #pragma omp simd
+ for (i = 0; i != 64; i = i + 1)
+ a[i] = a[i] + 1;
+ #pragma omp simd
+ for (i = 128; i != 64; i = i - 1)
+ a[i] = a[i] + 1;
+ #pragma omp simd
+ for (i = 0; i != 64; i = 1 + i)
+ a[i] = a[i] + 1;
+ #pragma omp simd
+ for (i = 128; i != 64; i = -1 + i)
+ a[i] = a[i] + 1;
+ #pragma omp simd
+ for (i = 0; i != 64; i += 1)
+ a[i] = a[i] + 1;
+ #pragma omp simd
+ for (i = 128; i != 64; i -= 1)
+ a[i] = a[i] + 1;
+ }
+}
--- gcc/testsuite/c-c++-common/gomp/for-2.c.jj 2017-06-28 18:06:53.597726264 +0200
+++ gcc/testsuite/c-c++-common/gomp/for-2.c 2017-06-12 11:32:36.000000000 +0200
@@ -0,0 +1,31 @@
+void bar (short *);
+
+void
+foo (short *q, short *r, short *s)
+{
+ short *p;
+ #pragma omp for
+ for (p = q; p != r; p++)
+ bar (p);
+ #pragma omp for
+ for (p = s; p != r; p--)
+ bar (p);
+ #pragma omp for
+ for (p = q; p != r; p = p + 1)
+ bar (p);
+ #pragma omp for
+ for (p = s; p != r; p = p - 1)
+ bar (p);
+ #pragma omp for
+ for (p = q; p != r; p = 1 + p)
+ bar (p);
+ #pragma omp for
+ for (p = s; p != r; p = -1 + p)
+ bar (p);
+ #pragma omp for
+ for (p = q; p != r; p += 1)
+ bar (p);
+ #pragma omp for
+ for (p = s; p != r; p -= 1)
+ bar (p);
+}
--- gcc/testsuite/c-c++-common/gomp/for-3.c.jj 2017-06-28 18:07:24.625359692 +0200
+++ gcc/testsuite/c-c++-common/gomp/for-3.c 2017-06-28 18:14:54.211048119 +0200
@@ -0,0 +1,48 @@
+void bar (int);
+
+int a[256];
+
+void
+foo (int j)
+{
+ int i;
+ #pragma omp for
+ for (i = 0; i != 64; i = i + 4) /* { dg-error "increment is not constant 1 or -1" } */
+ bar (i);
+ #pragma omp for
+ for (i = 128; i != 64; i = i - 4) /* { dg-error "increment is not constant 1 or -1" } */
+ bar (i);
+ #pragma omp for
+ for (i = 0; i != 64; i = j + i) /* { dg-error "increment is not constant 1 or -1" } */
+ bar (i);
+ #pragma omp for
+ for (i = 128; i != 64; i = -16 + i) /* { dg-error "increment is not constant 1 or -1" } */
+ bar (i);
+ #pragma omp for
+ for (i = 0; i != 64; i += j) /* { dg-error "increment is not constant 1 or -1" } */
+ bar (i);
+ #pragma omp for
+ for (i = 128; i != 64; i -= 8) /* { dg-error "increment is not constant 1 or -1" } */
+ bar (i);
+ #pragma omp single
+ {
+ #pragma omp simd
+ for (i = 0; i != 64; i = i + 16) /* { dg-error "increment is not constant 1 or -1" } */
+ a[i] = a[i] + 1;
+ #pragma omp simd
+ for (i = 128; i != 64; i = i - 2) /* { dg-error "increment is not constant 1 or -1" } */
+ a[i] = a[i] + 1;
+ #pragma omp simd
+ for (i = 0; i != 64; i = j + i) /* { dg-error "increment is not constant 1 or -1" } */
+ a[i] = a[i] + 1;
+ #pragma omp simd
+ for (i = 128; i != 64; i = -j + i) /* { dg-error "increment is not constant 1 or -1" } */
+ a[i] = a[i] + 1;
+ #pragma omp simd
+ for (i = 0; i != 64; i += 8) /* { dg-error "increment is not constant 1 or -1" } */
+ a[i] = a[i] + 1;
+ #pragma omp simd
+ for (i = 128; i != 64; i -= j) /* { dg-error "increment is not constant 1 or -1" } */
+ a[i] = a[i] + 1;
+ }
+}
--- gcc/testsuite/c-c++-common/gomp/for-4.c.jj 2017-06-28 18:15:20.800733979 +0200
+++ gcc/testsuite/c-c++-common/gomp/for-4.c 2017-06-28 18:16:28.669932147 +0200
@@ -0,0 +1,25 @@
+void bar (short *);
+
+void
+foo (short *q, short *r, short *s, long t)
+{
+ short *p;
+ #pragma omp for
+ for (p = q; p != r; p = p + 5) /* { dg-error "increment is not constant 1 or -1" } */
+ bar (p);
+ #pragma omp for
+ for (p = s; p != r; p = p - 2) /* { dg-error "increment is not constant 1 or -1" } */
+ bar (p);
+ #pragma omp for
+ for (p = q; p != r; p = t + p) /* { dg-error "increment is not constant 1 or -1" } */
+ bar (p);
+ #pragma omp for
+ for (p = s; p != r; p = -t + p) /* { dg-error "increment is not constant 1 or -1" } */
+ bar (p);
+ #pragma omp for
+ for (p = q; p != r; p += t) /* { dg-error "increment is not constant 1 or -1" } */
+ bar (p);
+ #pragma omp for
+ for (p = s; p != r; p -= 7) /* { dg-error "increment is not constant 1 or -1" } */
+ bar (p);
+}
--- gcc/testsuite/c-c++-common/gomp/for-5.c.jj 2017-06-28 19:30:19.008831921 +0200
+++ gcc/testsuite/c-c++-common/gomp/for-5.c 2017-06-28 19:34:54.093593473 +0200
@@ -0,0 +1,50 @@
+// { dg-options "-fopenmp" }
+
+void bar (void *);
+
+__attribute__((noinline, noclone)) void
+foo (void *qx, void *rx, void *sx, int n)
+{
+ unsigned short (*q)[n], (*r)[n], (*s)[n], (*p)[n];
+ q = (typeof (q)) qx;
+ r = (typeof (r)) rx;
+ s = (typeof (s)) sx;
+ int t = 1;
+ int o = -1;
+ #pragma omp for
+ for (p = q; p != r; p += t) /* { dg-error "increment is not constant 1 or -1" } */
+ bar (p);
+ #pragma omp for
+ for (p = s; p != r; p += o) /* { dg-error "increment is not constant 1 or -1" } */
+ bar (p);
+ #pragma omp for
+ for (p = q; p != r; p = p + t) /* { dg-error "increment is not constant 1 or -1" } */
+ bar (p);
+ #pragma omp for
+ for (p = s; p != r; p = p + o) /* { dg-error "increment is not constant 1 or -1" } */
+ bar (p);
+ #pragma omp for
+ for (p = q; p != r; p = t + p) /* { dg-error "increment is not constant 1 or -1" } */
+ bar (p);
+ #pragma omp for
+ for (p = s; p != r; p = o + p) /* { dg-error "increment is not constant 1 or -1" } */
+ bar (p);
+ #pragma omp for
+ for (p = q; p != r; p += 2) /* { dg-error "increment is not constant 1 or -1" } */
+ bar (p);
+ #pragma omp for
+ for (p = s; p != r; p -= 2) /* { dg-error "increment is not constant 1 or -1" } */
+ bar (p);
+ #pragma omp for
+ for (p = q; p != r; p = p + 3) /* { dg-error "increment is not constant 1 or -1" } */
+ bar (p);
+ #pragma omp for
+ for (p = s; p != r; p = p - 3) /* { dg-error "increment is not constant 1 or -1" } */
+ bar (p);
+ #pragma omp for
+ for (p = q; p != r; p = 4 + p) /* { dg-error "increment is not constant 1 or -1" } */
+ bar (p);
+ #pragma omp for
+ for (p = s; p != r; p = -5 + p) /* { dg-error "increment is not constant 1 or -1" } */
+ bar (p);
+}
--- gcc/testsuite/gcc.dg/gomp/pr39495-2.c.jj 2017-05-04 15:05:34.757845532 +0200
+++ gcc/testsuite/gcc.dg/gomp/pr39495-2.c 2017-06-28 15:11:28.703710328 +0200
@@ -13,25 +13,25 @@ foo (void)
unsigned int u;
#pragma omp for
- for (i = INT_MIN + 6; i != INT_MIN; i--) /* { dg-error "invalid controlling predicate" } */
+ for (i = INT_MIN + 6; i != INT_MIN; i--)
;
#pragma omp for
for (i = INT_MIN + 6; i == INT_MIN; i--) /* { dg-error "invalid controlling predicate" } */
;
#pragma omp for
- for (i = INT_MAX - 6; i != INT_MAX; i++) /* { dg-error "invalid controlling predicate" } */
+ for (i = INT_MAX - 6; i != INT_MAX; i++)
;
#pragma omp for
for (i = INT_MAX - 6; i == INT_MAX; i++) /* { dg-error "invalid controlling predicate" } */
;
#pragma omp for
- for (u = 6; u != 0; u--) /* { dg-error "invalid controlling predicate" } */
+ for (u = 6; u != 0; u--)
;
#pragma omp for
for (u = 6; u == 0; u--) /* { dg-error "invalid controlling predicate" } */
;
#pragma omp for
- for (u = UINT_MAX - 6; u != UINT_MAX; u++) /* { dg-error "invalid controlling predicate" } */
+ for (u = UINT_MAX - 6; u != UINT_MAX; u++)
;
#pragma omp for
for (u = UINT_MAX - 6; u == UINT_MAX; u++) /* { dg-error "invalid controlling predicate" } */
--- gcc/testsuite/g++.dg/gomp/pr39495-2.C.jj 2017-05-04 15:05:46.000000000 +0200
+++ gcc/testsuite/g++.dg/gomp/pr39495-2.C 2017-06-28 15:18:01.041022936 +0200
@@ -13,25 +13,25 @@ foo (void)
unsigned int u;
#pragma omp for
- for (i = INT_MIN + 6; i != INT_MIN; i--) // { dg-error "invalid controlling predicate" }
+ for (i = INT_MIN + 6; i != INT_MIN; i--)
;
#pragma omp for
for (i = INT_MIN + 6; i == INT_MIN; i--) // { dg-error "invalid controlling predicate" }
;
#pragma omp for
- for (i = INT_MAX - 6; i != INT_MAX; i++) // { dg-error "invalid controlling predicate" }
+ for (i = INT_MAX - 6; i != INT_MAX; i++)
;
#pragma omp for
for (i = INT_MAX - 6; i == INT_MAX; i++) // { dg-error "invalid controlling predicate" }
;
#pragma omp for
- for (u = 6; u != 0; u--) // { dg-error "invalid controlling predicate" }
+ for (u = 6; u != 0; u--)
;
#pragma omp for
for (u = 6; u == 0; u--) // { dg-error "invalid controlling predicate" }
;
#pragma omp for
- for (u = UINT_MAX - 6; u != UINT_MAX; u++) // { dg-error "invalid controlling predicate" }
+ for (u = UINT_MAX - 6; u != UINT_MAX; u++)
;
#pragma omp for
for (u = UINT_MAX - 6; u == UINT_MAX; u++) // { dg-error "invalid controlling predicate" }
--- gcc/testsuite/g++.dg/gomp/loop-4.C.jj 2017-06-28 19:06:22.035756688 +0200
+++ gcc/testsuite/g++.dg/gomp/loop-4.C 2017-06-28 19:19:07.440742612 +0200
@@ -0,0 +1,227 @@
+typedef __PTRDIFF_TYPE__ ptrdiff_t;
+
+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> bool operator == (I<T> &, I<T> &);
+template <typename T> bool operator == (const I<T> &, const I<T> &);
+template <typename T> bool operator != (I<T> &, I<T> &);
+template <typename T> bool operator != (const I<T> &, const I<T> &);
+template <typename T> bool operator < (I<T> &, I<T> &);
+template <typename T> bool operator < (const I<T> &, const I<T> &);
+template <typename T> bool operator <= (I<T> &, I<T> &);
+template <typename T> bool operator <= (const I<T> &, const I<T> &);
+template <typename T> bool operator > (I<T> &, I<T> &);
+template <typename T> bool operator > (const I<T> &, const I<T> &);
+template <typename T> bool operator >= (I<T> &, I<T> &);
+template <typename T> bool operator >= (const I<T> &, const I<T> &);
+template <typename T> typename I<T>::difference_type operator - (I<T> &, I<T> &);
+template <typename T> typename I<T>::difference_type operator - (const I<T> &, const I<T> &);
+template <typename T> I<T> operator + (typename I<T>::difference_type, const I<T> &);
+
+ptrdiff_t foo (I<int> &);
+I<int> &bar (I<int> &);
+I<int> &baz (I<int> *);
+
+void
+f0 ()
+{
+ int i;
+ const int j = 1;
+ const int k = -1;
+ const int m = 2;
+ const int n = -7;
+ int o = 1;
+ int p = -1;
+ #pragma omp for
+ for (i = 0; i != 64; i += j)
+ ;
+ #pragma omp for
+ for (i = 64; i != 0; i -= j)
+ ;
+ #pragma omp for
+ for (i = 0; i != 64; i -= k)
+ ;
+ #pragma omp for
+ for (i = 64; i != 0; i += k)
+ ;
+ #pragma omp for
+ for (i = 0; i != 64; i += m) // { dg-error "increment is not constant 1 or -1 for != condition" }
+ ;
+ #pragma omp for
+ for (i = 64; i != 0; i -= m) // { dg-error "increment is not constant 1 or -1 for != condition" }
+ ;
+ #pragma omp for
+ for (i = 0; i != 64; i -= n) // { dg-error "increment is not constant 1 or -1 for != condition" }
+ ;
+ #pragma omp for
+ for (i = 64; i != 0; i += n) // { dg-error "increment is not constant 1 or -1 for != condition" }
+ ;
+ #pragma omp for
+ for (i = 0; i != 64; i += o) // { dg-error "increment is not constant 1 or -1 for != condition" }
+ ;
+ #pragma omp for
+ for (i = 64; i != 0; i -= o) // { dg-error "increment is not constant 1 or -1 for != condition" }
+ ;
+ #pragma omp for
+ for (i = 0; i != 64; i -= p) // { dg-error "increment is not constant 1 or -1 for != condition" }
+ ;
+ #pragma omp for
+ for (i = 64; i != 0; i += p) // { dg-error "increment is not constant 1 or -1 for != condition" }
+ ;
+}
+
+void
+f1 (I<int> &x, I<int> &y, I<int> &u, I<int> &v)
+{
+ I<int> i, j;
+ const int k = 1;
+ const int l = -1;
+ const int m = 2;
+ const int n = -7;
+ int o = 1;
+ int p = -1;
+ #pragma omp for
+ for (i = x; i != y; i++)
+ ;
+ #pragma omp for
+ for (i = x; y != i; ++i)
+ ;
+ #pragma omp for
+ for (i = x; i != y; i = i + 1)
+ ;
+ #pragma omp for
+ for (i = x; i != y; i = 1 + i)
+ ;
+ #pragma omp for
+ for (i = y; i != x; i--)
+ ;
+ #pragma omp for
+ for (i = y; x != i; --i)
+ ;
+ #pragma omp for
+ for (i = y; i != x; i = i - 1)
+ ;
+ #pragma omp for
+ for (i = y; i != x; i = -1 + i)
+ ;
+ #pragma omp for
+ for (i = x; i != y; i = i + k)
+ ;
+ #pragma omp for
+ for (i = x; i != y; i = k + i)
+ ;
+ #pragma omp for
+ for (i = y; i != x; i = i - k)
+ ;
+ #pragma omp for
+ for (i = y; i != x; i = -k + i)
+ ;
+ #pragma omp for
+ for (i = x; i != y; i = i - l)
+ ;
+ #pragma omp for
+ for (i = x; i != y; i = -l + i)
+ ;
+ #pragma omp for
+ for (i = y; i != x; i = i + l)
+ ;
+ #pragma omp for
+ for (i = y; i != x; i = l + i)
+ ;
+ #pragma omp for
+ for (i = x; i != y; i = i + 2) // { dg-error "increment is not constant 1 or -1 for != condition" }
+ ;
+ #pragma omp for
+ for (i = x; i != y; i = 7 + i) // { dg-error "increment is not constant 1 or -1 for != condition" }
+ ;
+ #pragma omp for
+ for (i = y; i != x; i = i - 2) // { dg-error "increment is not constant 1 or -1 for != condition" }
+ ;
+ #pragma omp for
+ for (i = y; i != x; i = -7 + i) // { dg-error "increment is not constant 1 or -1 for != condition" }
+ ;
+ #pragma omp for
+ for (i = x; i != y; i = i + m) // { dg-error "increment is not constant 1 or -1 for != condition" }
+ ;
+ #pragma omp for
+ for (i = x; i != y; i = m + i) // { dg-error "increment is not constant 1 or -1 for != condition" }
+ ;
+ #pragma omp for
+ for (i = y; i != x; i = i - m) // { dg-error "increment is not constant 1 or -1 for != condition" }
+ ;
+ #pragma omp for
+ for (i = y; i != x; i = -m + i) // { dg-error "increment is not constant 1 or -1 for != condition" }
+ ;
+ #pragma omp for
+ for (i = x; i != y; i = i - n) // { dg-error "increment is not constant 1 or -1 for != condition" }
+ ;
+ #pragma omp for
+ for (i = x; i != y; i = -n + i) // { dg-error "increment is not constant 1 or -1 for != condition" }
+ ;
+ #pragma omp for
+ for (i = y; i != x; i = i + n) // { dg-error "increment is not constant 1 or -1 for != condition" }
+ ;
+ #pragma omp for
+ for (i = y; i != x; i = n + i) // { dg-error "increment is not constant 1 or -1 for != condition" }
+ ;
+ #pragma omp for
+ for (i = x; i != y; i = i + o) // { dg-error "increment is not constant 1 or -1 for != condition" }
+ ;
+ #pragma omp for
+ for (i = x; i != y; i = o + i) // { dg-error "increment is not constant 1 or -1 for != condition" }
+ ;
+ #pragma omp for
+ for (i = y; i != x; i = i - o) // { dg-error "increment is not constant 1 or -1 for != condition" }
+ ;
+ #pragma omp for
+ for (i = y; i != x; i = -o + i) // { dg-error "increment is not constant 1 or -1 for != condition" }
+ ;
+ #pragma omp for
+ for (i = x; i != y; i = i - p) // { dg-error "increment is not constant 1 or -1 for != condition" }
+ ;
+ #pragma omp for
+ for (i = x; i != y; i = -p + i) // { dg-error "increment is not constant 1 or -1 for != condition" }
+ ;
+ #pragma omp for
+ for (i = y; i != x; i = i + p) // { dg-error "increment is not constant 1 or -1 for != condition" }
+ ;
+ #pragma omp for
+ for (i = y; i != x; i = p + i) // { dg-error "increment is not constant 1 or -1 for != condition" }
+ ;
+}
--- libgomp/testsuite/libgomp.c/for-2.h.jj 2017-05-04 15:04:53.000000000 +0200
+++ libgomp/testsuite/libgomp.c/for-2.h 2017-06-23 19:35:12.101928314 +0200
@@ -21,6 +21,7 @@ noreturn (void)
#define OMPFROM(v) do {} while (0)
#endif
+#ifndef CONDNE
__attribute__((noinline, noclone)) void
N(f0) (void)
{
@@ -311,3 +312,292 @@ N(test) (void)
return 1;
return 0;
}
+
+#else
+
+__attribute__((noinline, noclone)) void
+N(f20) (void)
+{
+ int i;
+ OMPTGT
+#pragma omp F S
+ for (i = 0; i != 1500; i++)
+ a[i] += 2;
+}
+
+__attribute__((noinline, noclone)) void
+N(f21) (void)
+{
+ OMPTGT
+#pragma omp F S
+ for (unsigned int i = __INT_MAX__; i < 1500U + __INT_MAX__; i += 2 - 1)
+ a[(i - __INT_MAX__)] -= 2;
+}
+
+__attribute__((noinline, noclone)) void
+N(f22) (void)
+{
+ unsigned long long i;
+ OMPTGT
+#pragma omp F S
+ for (i = __LONG_LONG_MAX__ + 1500ULL - 27;
+ i != __LONG_LONG_MAX__ - 27ULL; i -= 3 - 2)
+ a[i + 26LL - __LONG_LONG_MAX__] -= 4;
+}
+
+__attribute__((noinline, noclone)) void
+N(f23) (long long n1, long long n2)
+{
+ OMPTGT
+#pragma omp F S
+ for (long long i = n1 + 23; i != n2 - 25; --i)
+ a[i + 48] += 7;
+}
+
+__attribute__((noinline, noclone)) void
+N(f24) (void)
+{
+ unsigned int i;
+ OMPTGT
+#pragma omp F S
+ for (i = 30; i != 30; i += 1)
+ a[i] += 10;
+}
+
+__attribute__((noinline, noclone)) void
+N(f25) (int n11, int n12, int n21, int n22, int n31, int n32,
+ int s2)
+{
+ SC int v1, v2, v3;
+ OMPTGT
+#pragma omp F S collapse(3)
+ for (v1 = n11; v1 != n12; v1 += 17 - 19 + 3)
+ for (v2 = n21; v2 < n22; v2 += s2)
+ for (v3 = n31; v3 != n32; ++v3)
+ b[v1][v2][v3] += 2.5;
+}
+
+__attribute__((noinline, noclone)) void
+N(f26) (int n11, int n12, int n21, int n22, long long n31, long long n32,
+ int s2)
+{
+ SC int v1, v2;
+ SC long long v3;
+ OMPTGT
+#pragma omp F S collapse(3)
+ for (v1 = n11; v1 != n12; v1 += -1)
+ for (v2 = n21; v2 > n22; v2 += s2)
+ for (v3 = n31; v3 != n32; v3 --)
+ b[v1][v2 / 2][v3] -= 4.5;
+}
+
+__attribute__((noinline, noclone)) void
+N(f27) (void)
+{
+ SC unsigned int v1, v3;
+ SC unsigned long long v2;
+ OMPTGT
+#pragma omp F S collapse(3)
+ for (v1 = 0; v1 < 20; v1 += 2)
+ for (v2 = __LONG_LONG_MAX__ + 11ULL;
+ v2 != __LONG_LONG_MAX__ - 4ULL; -- v2)
+ for (v3 = 10; v3 != 0; v3--)
+ b[v1 >> 1][v2 - __LONG_LONG_MAX__ + 3][v3 - 1] += 5.5;
+}
+
+__attribute__((noinline, noclone)) void
+N(f28) (void)
+{
+ SC long long v1, v2, v3;
+ OMPTGT
+#pragma omp F S collapse(3)
+ for (v1 = 0; v1 != 20; v1 -= 17 - 18)
+ for (v2 = 30; v2 < 20; v2++)
+ for (v3 = 10; v3 < 0; v3--)
+ b[v1][v2][v3] += 5.5;
+}
+
+__attribute__((noinline, noclone)) void
+N(f29) (void)
+{
+ int i;
+ OMPTGT
+#pragma omp F S
+ for (i = 20; i != 20; i++)
+ {
+ a[i] += 2;
+ noreturn ();
+ a[i] -= 4;
+ }
+}
+
+__attribute__((noinline, noclone)) void
+N(f30) (void)
+{
+ SC int i;
+ OMPTGT
+#pragma omp F S collapse(3)
+ for (i = 0; i != 10; i++)
+ for (int j = 10; j < 8; j++)
+ for (long k = -10; k != 10; k++)
+ {
+ b[i][j][k] += 4;
+ noreturn ();
+ b[i][j][k] -= 8;
+ }
+}
+
+__attribute__((noinline, noclone)) void
+N(f31) (int n)
+{
+ int i;
+ OMPTGT
+#pragma omp F S
+ for (i = 20; i != n; i++)
+ {
+ a[i] += 8;
+ noreturn ();
+ a[i] -= 16;
+ }
+}
+
+__attribute__((noinline, noclone)) void
+N(f32) (int n)
+{
+ SC int i;
+ OMPTGT
+#pragma omp F S collapse(3)
+ for (i = 0; i != 10; i++)
+ for (int j = n; j != 12; j++)
+ for (long k = -10; k != 10; k++)
+ {
+ b[i][j][k] += 16;
+ noreturn ();
+ b[i][j][k] -= 32;
+ }
+}
+
+__attribute__((noinline, noclone)) void
+N(f33) (void)
+{
+ int *i;
+ OMPTGT
+#pragma omp F S
+ for (i = a; i != &a[1500]; i++)
+ i[0] += 2;
+}
+
+__attribute__((noinline, noclone)) void
+N(f34) (void)
+{
+ SC float *i;
+ OMPTGT
+#pragma omp F S collapse(3)
+ for (i = &b[0][0][0]; i != &b[0][0][10]; i++)
+ for (float *j = &b[0][15][0]; j > &b[0][0][0]; j -= 10)
+ for (float *k = &b[0][0][10]; k != &b[0][0][0]; --k)
+ b[i - &b[0][0][0]][(j - &b[0][0][0]) / 10 - 1][(k - &b[0][0][0]) - 1]
+ -= 3.5;
+}
+
+__attribute__((noinline, noclone)) int
+N(test) (void)
+{
+ int i, j, k;
+ for (i = 0; i < 1500; i++)
+ a[i] = i - 25;
+ OMPTO (a);
+ N(f20) ();
+ OMPFROM (a);
+ for (i = 0; i < 1500; i++)
+ if (a[i] != i - 23)
+ return 1;
+ N(f21) ();
+ OMPFROM (a);
+ for (i = 0; i < 1500; i++)
+ if (a[i] != i - 25)
+ return 1;
+ N(f22) ();
+ OMPFROM (a);
+ for (i = 0; i < 1500; i++)
+ if (a[i] != i - 29)
+ return 1;
+ N(f23) (1500LL - 1 - 23 - 48, -1LL + 25 - 48);
+ OMPFROM (a);
+ for (i = 0; i < 1500; i++)
+ if (a[i] != i - 22)
+ return 1;
+ N(f24) ();
+ OMPFROM (a);
+ for (i = 0; i < 1500; i++)
+ if (a[i] != i - 22)
+ return 1;
+ for (i = 0; i < 10; i++)
+ for (j = 0; j < 15; j++)
+ for (k = 0; k < 10; k++)
+ b[i][j][k] = i - 2.5 + 1.5 * j - 1.5 * k;
+ OMPTO (b);
+ N(f25) (0, 10, 0, 15, 0, 10, 1);
+ OMPFROM (b);
+ for (i = 0; i < 10; i++)
+ for (j = 0; j < 15; j++)
+ for (k = 0; k < 10; k++)
+ if (b[i][j][k] != i + 1.5 * j - 1.5 * k)
+ return 1;
+ N(f25) (0, 10, 30, 15, 0, 10, 5);
+ OMPFROM (b);
+ for (i = 0; i < 10; i++)
+ for (j = 0; j < 15; j++)
+ for (k = 0; k < 10; k++)
+ if (b[i][j][k] != i + 1.5 * j - 1.5 * k)
+ return 1;
+ N(f26) (9, -1, 29, 0, 9, -1, -2);
+ OMPFROM (b);
+ for (i = 0; i < 10; i++)
+ for (j = 0; j < 15; j++)
+ for (k = 0; k < 10; k++)
+ if (b[i][j][k] != i - 4.5 + 1.5 * j - 1.5 * k)
+ return 1;
+ N(f27) ();
+ OMPFROM (b);
+ for (i = 0; i < 10; i++)
+ for (j = 0; j < 15; j++)
+ for (k = 0; k < 10; k++)
+ if (b[i][j][k] != i + 1.0 + 1.5 * j - 1.5 * k)
+ return 1;
+ N(f28) ();
+ OMPFROM (b);
+ for (i = 0; i < 10; i++)
+ for (j = 0; j < 15; j++)
+ for (k = 0; k < 10; k++)
+ if (b[i][j][k] != i + 1.0 + 1.5 * j - 1.5 * k)
+ return 1;
+ N(f29) ();
+ N(f30) ();
+ N(f31) (20);
+ N(f32) (12);
+ OMPFROM (a);
+ OMPFROM (b);
+ for (i = 0; i < 1500; i++)
+ if (a[i] != i - 22)
+ return 1;
+ for (i = 0; i < 10; i++)
+ for (j = 0; j < 15; j++)
+ for (k = 0; k < 10; k++)
+ if (b[i][j][k] != i + 1.0 + 1.5 * j - 1.5 * k)
+ return 1;
+ N(f33) ();
+ N(f34) ();
+ OMPFROM (a);
+ OMPFROM (b);
+ for (i = 0; i < 1500; i++)
+ if (a[i] != i - 20)
+ return 1;
+ for (i = 0; i < 10; i++)
+ for (j = 0; j < 15; j++)
+ for (k = 0; k < 10; k++)
+ if (b[i][j][k] != i - 2.5 + 1.5 * j - 1.5 * k)
+ return 1;
+ return 0;
+}
+#endif
--- libgomp/testsuite/libgomp.c/for-4.c.jj 2017-05-04 15:04:53.000000000 +0200
+++ libgomp/testsuite/libgomp.c/for-4.c 2017-06-23 19:40:29.718234544 +0200
@@ -1,4 +1,4 @@
-/* { dg-options "-std=gnu99 -fopenmp" } */
+/* { dg-additional-options "-std=gnu99" } */
extern void abort (void);
--- libgomp/testsuite/libgomp.c/for-7.c.jj 2017-06-23 18:20:35.568048702 +0200
+++ libgomp/testsuite/libgomp.c/for-7.c 2017-06-23 18:20:29.160122759 +0200
@@ -0,0 +1,4 @@
+/* { dg-additional-options "-std=gnu99" } */
+
+#define CONDNE
+#include "for-1.c"
--- libgomp/testsuite/libgomp.c/for-8.c.jj 2017-06-23 19:35:36.707642158 +0200
+++ libgomp/testsuite/libgomp.c/for-8.c 2017-06-23 19:35:41.010592116 +0200
@@ -0,0 +1,4 @@
+/* { dg-additional-options "-std=gnu99" } */
+
+#define CONDNE
+#include "for-2.c"
--- libgomp/testsuite/libgomp.c/for-9.c.jj 2017-06-23 19:35:51.670468145 +0200
+++ libgomp/testsuite/libgomp.c/for-9.c 2017-06-23 19:35:59.094381807 +0200
@@ -0,0 +1,4 @@
+/* { dg-additional-options "-std=gnu99" } */
+
+#define CONDNE
+#include "for-3.c"
--- libgomp/testsuite/libgomp.c/for-10.c.jj 2017-06-23 19:40:46.635037807 +0200
+++ libgomp/testsuite/libgomp.c/for-10.c 2017-06-23 19:40:51.662979334 +0200
@@ -0,0 +1,4 @@
+/* { dg-additional-options "-std=gnu99" } */
+
+#define CONDNE
+#include "for-4.c"
--- libgomp/testsuite/libgomp.c/for-11.c.jj 2017-06-23 19:40:59.187891822 +0200
+++ libgomp/testsuite/libgomp.c/for-11.c 2017-06-23 19:41:04.809826441 +0200
@@ -0,0 +1,4 @@
+/* { dg-additional-options "-std=gnu99" } */
+
+#define CONDNE
+#include "for-5.c"
--- libgomp/testsuite/libgomp.c/for-12.c.jj 2017-06-23 19:41:13.072730346 +0200
+++ libgomp/testsuite/libgomp.c/for-12.c 2017-06-23 19:41:18.414668221 +0200
@@ -0,0 +1,4 @@
+/* { dg-additional-options "-std=gnu99" } */
+
+#define CONDNE
+#include "for-6.c"
--- libgomp/testsuite/libgomp.c/for-13.c.jj 2017-06-28 18:56:28.138745794 +0200
+++ libgomp/testsuite/libgomp.c/for-13.c 2017-06-28 19:02:32.231461074 +0200
@@ -0,0 +1,99 @@
+unsigned short a[256];
+
+__attribute__((noinline, noclone)) void
+bar (void *x, unsigned short z)
+{
+ unsigned short *y = (unsigned short *) x;
+ if (y < &a[5] || y > &a[222] || y == &a[124])
+ __builtin_abort ();
+ *y += z;
+}
+
+__attribute__((noinline, noclone)) void
+foo (void *qx, void *rx, void *sx, int n)
+{
+ unsigned short (*q)[n], (*r)[n], (*s)[n], (*p)[n];
+ q = (typeof (q)) qx;
+ r = (typeof (r)) rx;
+ s = (typeof (s)) sx;
+ #pragma omp for
+ for (p = q; p != r; p++)
+ bar (p, 1);
+ #pragma omp for
+ for (p = s; p != r; p--)
+ bar (p, 2);
+ #pragma omp for
+ for (p = q; p != r; p = p + 1)
+ bar (p, 4);
+ #pragma omp for
+ for (p = s; p != r; p = p - 1)
+ bar (p, 8);
+ #pragma omp for
+ for (p = q; p != r; p = 1 + p)
+ bar (p, 16);
+ #pragma omp for
+ for (p = s; p != r; p = -1 + p)
+ bar (p, 32);
+ #pragma omp for
+ for (p = q; p != r; p += 1)
+ bar (p, 64);
+ #pragma omp for
+ for (p = s; p != r; p -= 1)
+ bar (p, 128);
+}
+
+__attribute__((noinline, noclone)) void
+baz (void *qx, void *rx, void *sx, int n)
+{
+ unsigned short (*q)[n], (*r)[n], (*s)[n], (*p)[n];
+ q = (typeof (q)) qx;
+ r = (typeof (r)) rx;
+ s = (typeof (s)) sx;
+ #pragma omp for
+ for (p = q; p < r; p++)
+ bar (p, 256);
+ #pragma omp for
+ for (p = s; p > r; p--)
+ bar (p, 512);
+ #pragma omp for
+ for (p = q; p < r; p = p + 1)
+ bar (p, 1024);
+ #pragma omp for
+ for (p = s; p > r; p = p - 1)
+ bar (p, 2048);
+ #pragma omp for
+ for (p = q; p < r; p = 1 + p)
+ bar (p, 4096);
+ #pragma omp for
+ for (p = s; p > r; p = -1 + p)
+ bar (p, 8192);
+ #pragma omp for
+ for (p = q; p < r; p += 1)
+ bar (p, 16384);
+ #pragma omp for
+ for (p = s; p > r; p -= 1)
+ bar (p, 32768U);
+}
+
+int
+main ()
+{
+ int i;
+ volatile int j = 7;
+#pragma omp parallel
+ {
+ foo (&a[5 + (j - 7)], &a[124 + (j - 7)], &a[222 + (j - 7)], j);
+ baz (&a[5 + (j - 7)], &a[124 + (j - 7)], &a[222 + (j - 7)], j);
+ }
+ for (i = 0; i < 256; i++)
+ if (i < 5 || i > 222 || i == 124 || ((i - 5) % 7) != 0)
+ {
+ if (a[i])
+ __builtin_abort ();
+ }
+ else if (i < 124 && a[i] != 1 + 4 + 16 + 64 + 256 + 1024 + 4096 + 16384)
+ __builtin_abort ();
+ else if (i > 124 && a[i] != 2 + 8 + 32 + 128 + 512 + 2048 + 8192 + 32768U)
+ __builtin_abort ();
+ return 0;
+}
--- libgomp/testsuite/libgomp.c++/for-12.C.jj 2017-05-04 15:04:52.000000000 +0200
+++ libgomp/testsuite/libgomp.c++/for-12.C 2017-06-23 19:48:16.502805999 +0200
@@ -1,5 +1,3 @@
-/* { dg-options "-fopenmp" } */
-
extern "C" void abort (void);
#define M(x, y, z) O(x, y, z)
--- libgomp/testsuite/libgomp.c++/for-15.C.jj 2017-06-23 19:50:00.023518987 +0200
+++ libgomp/testsuite/libgomp.c++/for-15.C 2017-06-23 19:48:49.000428062 +0200
@@ -0,0 +1,2 @@
+#define CONDNE
+#include "for-9.C"
--- libgomp/testsuite/libgomp.c++/for-16.C.jj 2017-06-23 19:50:00.025518959 +0200
+++ libgomp/testsuite/libgomp.c++/for-16.C 2017-06-23 19:49:18.494085061 +0200
@@ -0,0 +1,2 @@
+#define CONDNE
+#include "for-10.C"
--- libgomp/testsuite/libgomp.c++/for-17.C.jj 2017-06-23 19:50:00.026518944 +0200
+++ libgomp/testsuite/libgomp.c++/for-17.C 2017-06-23 19:49:22.896033868 +0200
@@ -0,0 +1,2 @@
+#define CONDNE
+#include "for-11.C"
--- libgomp/testsuite/libgomp.c++/for-18.C.jj 2017-06-23 19:50:00.028518916 +0200
+++ libgomp/testsuite/libgomp.c++/for-18.C 2017-06-23 19:49:27.952973698 +0200
@@ -0,0 +1,2 @@
+#define CONDNE
+#include "for-12.C"
--- libgomp/testsuite/libgomp.c++/for-19.C.jj 2017-06-23 19:50:00.029518902 +0200
+++ libgomp/testsuite/libgomp.c++/for-19.C 2017-06-23 19:49:31.990916447 +0200
@@ -0,0 +1,2 @@
+#define CONDNE
+#include "for-13.C"
--- libgomp/testsuite/libgomp.c++/for-20.C.jj 2017-06-23 19:50:00.031518873 +0200
+++ libgomp/testsuite/libgomp.c++/for-20.C 2017-06-23 19:49:36.853847498 +0200
@@ -0,0 +1,2 @@
+#define CONDNE
+#include "for-14.C"
--- libgomp/testsuite/libgomp.c++/for-21.C.jj 2017-06-28 14:27:29.617173520 +0200
+++ libgomp/testsuite/libgomp.c++/for-21.C 2017-06-28 14:21:53.000000000 +0200
@@ -0,0 +1,291 @@
+// { 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 for
+ for (I<int> i = x; i != y; i++)
+ baz (i);
+}
+
+void
+f2 (const I<int> &x, const I<int> &y)
+{
+ I<int> i;
+#pragma omp parallel for private(i)
+ for (i = x; i != y - 1; i = 2 - 8 + 7 + i)
+ baz (i);
+}
+
+template <typename T>
+void
+f3 (const I<int> &x, const I<int> &y)
+{
+#pragma omp parallel for
+ 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 for 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 for
+ for (I<int> i = x + 2000 - 64; i != y + 10; i--)
+ baz (i);
+}
+
+template <int N>
+void
+f6 (const I<int> &x, const I<int> &y)
+{
+#pragma omp parallel for
+ for (I<int> i = x + 2000 - 64; i != y + 10; i = i - 12 + 11)
+ {
+ 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 for
+ 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 for
+ for (i = j.begin (); i != j.end () + N; i += 1)
+ baz (i);
+}
+
+template <typename T, int N>
+void
+f9 (const I<T> &x, const I<T> &y)
+{
+#pragma omp parallel for
+ 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 for
+ 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 for nowait
+ for (T i = x; i != y; i++)
+ baz (i);
+#pragma omp single
+ {
+ T j = y + 3;
+ baz (j);
+ }
+ }
+}
+
+template <typename T>
+void
+f12 (const T &x, const T &y)
+{
+ T i;
+#pragma omp parallel for
+ 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 for
+ for (T i = x; i != y + N; i += N)
+ baz (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);
+ f2 (&a[0], &a[1999]);
+ check (i < 1998);
+ 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 > 110 && i <= 2000 - 64);
+ f6<-10> (&a[10], &a[110]);
+ check (i > 110 && i <= 2000 - 64);
+ f7<1> (I<int> (), &a[12], &a[1800]);
+ check (i >= 2 && i < 1810);
+ f8<121> (J<int> (&a[14], &a[1803]));
+ check (i >= 14 && i < 1924);
+ f9<int, -1> (&a[33], &a[1967]);
+ check (i >= 33 && i < 1967);
+ f10<int, -1> (&a[1939], &a[17]);
+ check (i > 17 && i <= 1939);
+ f11<I<int> > (&a[16], &a[1981]);
+ check ((i >= 16 && i < 1981) || i == 1984);
+ f12<I<int> > (&a[1761], &a[37]);
+ check (i > 37 && i <= 1761);
+ K<1>::f13<I<int> > (&a[1], &a[1935]);
+ check (i >= 1 && i < 1936);
+ f9<long, 1 - 2> (&b[33], &b[1967]);
+ check (i >= 33 && i < 1967);
+ f10<long, -1> (&b[1939], &b[17]);
+ check (i > 17 && i <= 1939);
+ f11<I<long> > (&b[16], &b[1981]);
+ check ((i >= 16 && i < 1981) || i == 1984);
+ f12<I<long> > (&b[1761], &b[37]);
+ check (i > 37 && i <= 1761);
+ K<1>::f13<I<long> > (&b[1], &b[1935]);
+ check (i >= 1 && i < 1936);
+}
--- libgomp/testsuite/libgomp.c++/for-22.C.jj 2017-06-28 17:40:33.432216053 +0200
+++ libgomp/testsuite/libgomp.c++/for-22.C 2017-06-28 17:40:24.000000000 +0200
@@ -0,0 +1,314 @@
+// { 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 for lastprivate (i) schedule(runtime)
+ for (i = x; i != y; 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 for lastprivate(i)
+ for (i = x; i != y - 1; i = 2 - 8 + 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 for lastprivate (i)
+ for (i = x; i != y; i = i + 9 - 8)
+ baz (i);
+ return i;
+}
+
+template <typename T>
+I<int>
+f4 (const I<int> &x, const I<int> &y)
+{
+ I<int> i;
+#pragma omp parallel for 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 for lastprivate(i)
+ for (i = x + 2000 - 64; i != y + T (10); 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 for lastprivate (i)
+ for (i = x + 2000 - 64; i != y + 10; i = i - T (12) + T (11))
+ {
+ I<int> j = i + -10;
+ baz (j);
+ }
+ return I<int> (i);
+}
+
+template <int N>
+I<int>
+f7 (I<int> i, const I<int> &x, const I<int> &y)
+{
+#pragma omp parallel for 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 for lastprivate (i)
+ for (i = j.begin (); i != j.end () + N; i += 1)
+ baz (i);
+ return i;
+}
+
+I<int> i9;
+
+template <long N>
+I<int> &
+f9 (J<int> j)
+{
+#pragma omp parallel for lastprivate(i9)
+ for (i9 = j.begin (); 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 for 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 for lastprivate (i)
+ for (i = x + U (0); i != y + U (2 - 2); i = U(3) + U(-2) + i)
+ baz (i);
+#pragma omp single
+ {
+ T j = y + 3;
+ baz (j);
+ }
+ }
+ return i;
+}
+
+template <typename T>
+T
+f12 (const T &x, const T &y)
+{
+ T i;
+#pragma omp parallel for 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[1990]) != 1993)
+ abort ();
+ check (i >= 10 && i < 1990);
+ if (*f2 (&a[0], &a[1999]) != 1998)
+ abort ();
+ check (i < 1998);
+ if (*f3<char> (&a[20], &a[1837]) != 1837)
+ abort ();
+ check (i >= 20 && i < 1837);
+ if (*f4<int> (&a[0], &a[30]) != 40)
+ abort ();
+ check (i > 40 && i <= 2000 - 64);
+ if (*f5<int> (&a[0], &a[100]) != 110)
+ abort ();
+ check (i > 110 && i <= 2000 - 64);
+ if (*f6<int> (&a[10], &a[110]) != 120)
+ abort ();
+ check (i > 110 && i <= 2000 - 64);
+ if (*f7<1> (I<int> (), &a[12], &a[1800]) != 1810)
+ abort ();
+ check (i >= 2 && i < 1810);
+ if (*f8<121> (J<int> (&a[14], &a[1803])) != 1924)
+ abort ();
+ check (i >= 14 && i < 1924);
+ if (*f9<-1> (J<int> (&a[33], &a[1967])) != 1968)
+ abort ();
+ check (i >= 33 && i <= 1967);
+ if (*f10<int, -1> (&a[1939], &a[17]) != 17)
+ abort ();
+ check (i > 17 && i <= 1939);
+ if (*f11<I<int>, int> (I<int> (), &a[16], &a[1981]) != 1981)
+ abort ();
+ check ((i >= 16 && i < 1981) || i == 1984);
+ if (*f12<I<int> > (&a[1761], &a[37]) != 37)
+ abort ();
+ check (i > 37 && i <= 1761);
+ if (*f10<long, -1> (&b[1939], &b[17]) != 17)
+ abort ();
+ check (i > 17 && i <= 1939);
+ if (*f11<I<long>, long> (I<long> (), &b[16], &b[1981]) != 1981)
+ abort ();
+ check ((i >= 16 && i < 1981) || i == 1984);
+ if (*f12<I<long> > (&b[1761], &b[37]) != 37)
+ abort ();
+ check (i > 37 && i <= 1761);
+}
--- libgomp/testsuite/libgomp.c++/for-23.C.jj 2017-06-28 18:57:08.017276495 +0200
+++ libgomp/testsuite/libgomp.c++/for-23.C 2017-06-28 18:57:02.836337466 +0200
@@ -0,0 +1 @@
+#include "../libgomp.c/for-13.c"
Jakub