This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[gomp5] Support OpenMP loops with != condition


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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]