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  <ja...@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

Reply via email to