From c5cdb03fb9e13c384901671a424555550ed098f1 Mon Sep 17 00:00:00 2001
From: Jakub Jelinek <jakub@redhat.com>
Date: Mon, 23 Mar 2009 22:05:30 +0100
Subject: [PATCH] re PR c/39495 (OMP parallel loop w/ unsigned index var
 rejected)

	PR c/39495
	* c-parser.c (c_parser_omp_for_loop): Call c_parser_binary_expression
	instead of c_parser_expression_conv, if original_code isn't one of the
	4 allowed comparison codes, fail.

	* semantics.c (handle_omp_for_class_iterator): Swap cond operands and
	code if iter is the second operand.
	* parser.c (cp_parser_binary_expression): Add no_toplevel_fold_p
	argument.  If it is set, don't build the toplevel expression with
	build_x_binary_op, but build2.
	(cp_parser_assignment_expression,  cp_parser_omp_for_incr): Adjust
	callers.
	(cp_parser_omp_for_cond): Don't assume the first operand of the
	comparison must be decl.

	* gcc.dg/gomp/pr39495-2.c: Remove xfails.

	* testsuite/libgomp.c/loop-12.c: New test.
	* testsuite/libgomp.c/loop-11.c: New test.
	* testsuite/libgomp.c++/loop-11.C: New test.
	* testsuite/libgomp.c++/loop-12.C: New test.
	* testsuite/libgomp.c++/for-8.C: New test.

From-SVN: r145014
---
 gcc/ChangeLog                           |   7 +
 gcc/c-parser.c                          |  16 +-
 gcc/cp/ChangeLog                        |  13 +
 gcc/cp/parser.c                         |  59 ++--
 gcc/cp/semantics.c                      |   3 +
 gcc/testsuite/ChangeLog                 |   5 +
 gcc/testsuite/gcc.dg/gomp/pr39495-2.c   |   8 +-
 libgomp/ChangeLog                       |   9 +
 libgomp/testsuite/libgomp.c++/for-8.C   | 291 ++++++++++++++++++
 libgomp/testsuite/libgomp.c++/loop-11.C | 276 +++++++++++++++++
 libgomp/testsuite/libgomp.c++/loop-12.C | 387 ++++++++++++++++++++++++
 libgomp/testsuite/libgomp.c/loop-11.c   | 276 +++++++++++++++++
 libgomp/testsuite/libgomp.c/loop-12.c   | 387 ++++++++++++++++++++++++
 13 files changed, 1706 insertions(+), 31 deletions(-)
 create mode 100644 libgomp/testsuite/libgomp.c++/for-8.C
 create mode 100644 libgomp/testsuite/libgomp.c++/loop-11.C
 create mode 100644 libgomp/testsuite/libgomp.c++/loop-12.C
 create mode 100644 libgomp/testsuite/libgomp.c/loop-11.c
 create mode 100644 libgomp/testsuite/libgomp.c/loop-12.c

diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 00290b54fa56..c1f7e6f01297 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,10 @@
+2009-03-23  Jakub Jelinek  <jakub@redhat.com>
+
+	PR c/39495
+	* c-parser.c (c_parser_omp_for_loop): Call c_parser_binary_expression
+	instead of c_parser_expression_conv, if original_code isn't one of the
+	4 allowed comparison codes, fail.
+
 2009-03-23  Richard Guenther  <rguenther@suse.de>
 
 	* cgraph.h (struct cgraph_node): Reorder fields for 64-bit hosts.
diff --git a/gcc/c-parser.c b/gcc/c-parser.c
index 6dfcb6015972..ea0036c0ba24 100644
--- a/gcc/c-parser.c
+++ b/gcc/c-parser.c
@@ -7652,9 +7652,23 @@ c_parser_omp_for_loop (c_parser *parser, tree clauses, tree *par_clauses)
       if (c_parser_next_token_is_not (parser, CPP_SEMICOLON))
 	{
 	  location_t cond_loc = c_parser_peek_token (parser)->location;
+	  struct c_expr cond_expr = c_parser_binary_expression (parser, NULL);
 
-	  cond = c_parser_expression_conv (parser).value;
+	  cond = cond_expr.value;
 	  cond = c_objc_common_truthvalue_conversion (cond_loc, cond);
+	  switch (cond_expr.original_code)
+	    {
+	    case GT_EXPR:
+	    case GE_EXPR:
+	    case LT_EXPR:
+	    case LE_EXPR:
+	      break;
+	    default:
+	      /* Can't be cond = error_mark_node, because we want to preserve
+		 the location until c_finish_omp_for.  */
+	      cond = build1 (NOP_EXPR, boolean_type_node, error_mark_node);
+	      break;
+	    }
 	  protected_set_expr_location (cond, cond_loc);
 	}
       c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index e9e424d28fcc..3f1017477776 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,16 @@
+2009-03-23  Jakub Jelinek  <jakub@redhat.com>
+
+	PR c/39495
+	* semantics.c (handle_omp_for_class_iterator): Swap cond operands and
+	code if iter is the second operand.
+	* parser.c (cp_parser_binary_expression): Add no_toplevel_fold_p
+	argument.  If it is set, don't build the toplevel expression with
+	build_x_binary_op, but build2.
+	(cp_parser_assignment_expression,  cp_parser_omp_for_incr): Adjust
+	callers.
+	(cp_parser_omp_for_cond): Don't assume the first operand of the
+	comparison must be decl.
+
 2009-03-23  Jason Merrill  <jason@redhat.com>
 
 	* pt.c (make_fnparm_pack): Split out from...
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index d3343aa60978..02a96ccc4a4e 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -1615,7 +1615,7 @@ static tree cp_parser_delete_expression
 static tree cp_parser_cast_expression
   (cp_parser *, bool, bool, cp_id_kind *);
 static tree cp_parser_binary_expression
-  (cp_parser *, bool, enum cp_parser_prec, cp_id_kind *);
+  (cp_parser *, bool, bool, enum cp_parser_prec, cp_id_kind *);
 static tree cp_parser_question_colon_clause
   (cp_parser *, tree);
 static tree cp_parser_assignment_expression
@@ -6215,6 +6215,7 @@ cp_parser_cast_expression (cp_parser *parser, bool address_p, bool cast_p,
 
 static tree
 cp_parser_binary_expression (cp_parser* parser, bool cast_p,
+			     bool no_toplevel_fold_p,
 			     enum cp_parser_prec prec,
 			     cp_id_kind * pidk)
 {
@@ -6297,6 +6298,7 @@ cp_parser_binary_expression (cp_parser* parser, bool cast_p,
 	  goto get_rhs;
 
 	 pop:
+	  lookahead_prec = new_prec;
 	  /* If the stack is not empty, we have parsed into LHS the right side
 	     (`4' in the example above) of an expression we had suspended.
 	     We can use the information on the stack to recover the LHS (`3')
@@ -6321,8 +6323,14 @@ cp_parser_binary_expression (cp_parser* parser, bool cast_p,
 	 pass the correct tree_code unless the unary expression was
 	 surrounded by parentheses.
       */
-      lhs = build_x_binary_op (tree_type, lhs, lhs_type, rhs, rhs_type,
-			       &overloaded_p, tf_warning_or_error);
+      if (no_toplevel_fold_p
+	  && lookahead_prec <= prec
+	  && sp == stack
+	  && TREE_CODE_CLASS (tree_type) == tcc_comparison)
+	lhs = build2 (tree_type, boolean_type_node, lhs, rhs);
+      else
+	lhs = build_x_binary_op (tree_type, lhs, lhs_type, rhs, rhs_type,
+				 &overloaded_p, tf_warning_or_error);
       lhs_type = tree_type;
 
       /* If the binary operator required the use of an overloaded operator,
@@ -6408,7 +6416,8 @@ cp_parser_assignment_expression (cp_parser* parser, bool cast_p,
   else
     {
       /* Parse the binary expressions (logical-or-expression).  */
-      expr = cp_parser_binary_expression (parser, cast_p, PREC_NOT_OPERATOR, pidk);
+      expr = cp_parser_binary_expression (parser, cast_p, false,
+					  PREC_NOT_OPERATOR, pidk);
       /* If the next token is a `?' then we're actually looking at a
 	 conditional-expression.  */
       if (cp_lexer_next_token_is (parser->lexer, CPP_QUERY))
@@ -21015,41 +21024,39 @@ cp_parser_omp_flush (cp_parser *parser, cp_token *pragma_tok)
 static tree
 cp_parser_omp_for_cond (cp_parser *parser, tree decl)
 {
-  tree lhs = cp_parser_cast_expression (parser, false, false, NULL), rhs;
-  enum tree_code op;
-  cp_token *token;
+  tree cond = cp_parser_binary_expression (parser, false, true,
+					   PREC_NOT_OPERATOR, NULL);
+  bool overloaded_p;
 
-  if (decl && lhs != decl)
+  if (cond == error_mark_node
+      || cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
     {
       cp_parser_skip_to_end_of_statement (parser);
       return error_mark_node;
     }
 
-  token = cp_lexer_peek_token (parser->lexer);
-  op = binops_by_token [token->type].tree_type;
-  switch (op)
+  switch (TREE_CODE (cond))
     {
-    case LT_EXPR:
-    case LE_EXPR:
     case GT_EXPR:
     case GE_EXPR:
+    case LT_EXPR:
+    case LE_EXPR:
       break;
     default:
-      cp_parser_skip_to_end_of_statement (parser);
       return error_mark_node;
     }
 
-  cp_lexer_consume_token (parser->lexer);
-  rhs = cp_parser_binary_expression (parser, false,
-				     PREC_RELATIONAL_EXPRESSION, NULL);
-  if (rhs == error_mark_node
-      || cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
-    {
-      cp_parser_skip_to_end_of_statement (parser);
-      return error_mark_node;
-    }
+  /* If decl is an iterator, preserve LHS and RHS of the relational
+     expr until finish_omp_for.  */
+  if (decl
+      && (type_dependent_expression_p (decl)
+	  || CLASS_TYPE_P (TREE_TYPE (decl))))
+    return cond;
 
-  return build2 (op, boolean_type_node, lhs, rhs);
+  return build_x_binary_op (TREE_CODE (cond),
+			    TREE_OPERAND (cond, 0), ERROR_MARK,
+			    TREE_OPERAND (cond, 1), ERROR_MARK,
+			    &overloaded_p, tf_warning_or_error);
 }
 
 /* Helper function, to parse omp for increment expression.  */
@@ -21098,7 +21105,7 @@ cp_parser_omp_for_incr (cp_parser *parser, tree decl)
       return build2 (MODIFY_EXPR, TREE_TYPE (decl), decl, rhs);
     }
 
-  lhs = cp_parser_binary_expression (parser, false,
+  lhs = cp_parser_binary_expression (parser, false, false,
 				     PREC_ADDITIVE_EXPRESSION, NULL);
   token = cp_lexer_peek_token (parser->lexer);
   decl_first = lhs == decl;
@@ -21112,7 +21119,7 @@ cp_parser_omp_for_incr (cp_parser *parser, tree decl)
     {
       op = token->type == CPP_PLUS ? PLUS_EXPR : MINUS_EXPR;
       cp_lexer_consume_token (parser->lexer);
-      rhs = cp_parser_binary_expression (parser, false,
+      rhs = cp_parser_binary_expression (parser, false, false,
 					 PREC_ADDITIVE_EXPRESSION, NULL);
       token = cp_lexer_peek_token (parser->lexer);
       if (token->type == CPP_PLUS || token->type == CPP_MINUS || decl_first)
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index c72897007284..71fc43e855a3 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -3921,6 +3921,9 @@ handle_omp_for_class_iterator (int i, location_t locus, tree declv, tree initv,
     case GE_EXPR:
     case LT_EXPR:
     case LE_EXPR:
+      if (TREE_OPERAND (cond, 1) == iter)
+	cond = build2 (swap_tree_comparison (TREE_CODE (cond)),
+		       TREE_TYPE (cond), iter, TREE_OPERAND (cond, 0));
       if (TREE_OPERAND (cond, 0) != iter)
 	cond = error_mark_node;
       else
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 40205fa7dae0..cced718e4218 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2009-03-23  Jakub Jelinek  <jakub@redhat.com>
+
+	PR c/39495
+	* gcc.dg/gomp/pr39495-2.c: Remove xfails.
+
 2009-03-23  Jason Merrill  <jason@redhat.com>
 
 	* g++.dg/cpp0x/auto12.C: Add variadic test.
diff --git a/gcc/testsuite/gcc.dg/gomp/pr39495-2.c b/gcc/testsuite/gcc.dg/gomp/pr39495-2.c
index e46369637b75..a276c24ed982 100644
--- a/gcc/testsuite/gcc.dg/gomp/pr39495-2.c
+++ b/gcc/testsuite/gcc.dg/gomp/pr39495-2.c
@@ -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" "" { xfail *-*-* } } */
+  for (i = INT_MIN + 6; i != INT_MIN; i--)	/* { dg-error "invalid controlling predicate" } */
     ;
 #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" "" { xfail *-*-* }  } */
+  for (i = INT_MAX - 6; i != INT_MAX; i++)	/* { dg-error "invalid controlling predicate" } */
     ;
 #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" "" { xfail *-*-* }  } */
+  for (u = 6; u != 0; u--)			/* { dg-error "invalid controlling predicate" } */
     ;
 #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" "" { xfail *-*-* }  } */
+  for (u = UINT_MAX - 6; u != UINT_MAX; u++)	/* { dg-error "invalid controlling predicate" } */
     ;
 #pragma omp for
   for (u = UINT_MAX - 6; u == UINT_MAX; u++)	/* { dg-error "invalid controlling predicate" } */
diff --git a/libgomp/ChangeLog b/libgomp/ChangeLog
index 26b6457ff23e..205bcceaaee4 100644
--- a/libgomp/ChangeLog
+++ b/libgomp/ChangeLog
@@ -1,3 +1,12 @@
+2009-03-23  Jakub Jelinek  <jakub@redhat.com>
+
+	PR c/39495
+	* testsuite/libgomp.c/loop-12.c: New test.
+	* testsuite/libgomp.c/loop-11.c: New test.
+	* testsuite/libgomp.c++/loop-11.C: New test.
+	* testsuite/libgomp.c++/loop-12.C: New test.
+	* testsuite/libgomp.c++/for-8.C: New test.
+
 2009-03-01  Ralf Wildenhues  <Ralf.Wildenhues@gmx.de>
 
 	* configure: Regenerate.
diff --git a/libgomp/testsuite/libgomp.c++/for-8.C b/libgomp/testsuite/libgomp.c++/for-8.C
new file mode 100644
index 000000000000..918de7cc8517
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/for-8.C
@@ -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; y >= i; i += 6)
+    baz (i);
+}
+
+void
+f2 (const I<int> &x, const I<int> &y)
+{
+  I<int> i;
+#pragma omp parallel for private(i)
+  for (i = x; y - 1 > i; i = 1 - 6 + 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; y >= i; 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; y + 10 < i; --i)
+    baz (i);
+}
+
+void
+f5 (const I<int> &x, const I<int> &y)
+{
+#pragma omp parallel for
+  for (I<int> i = x + 2000 - 64; y + 10 < i; i -= 10)
+    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; y + 10 < i; i = i - 12 + 2)
+    {
+      I<int> j = i + N;
+      baz (j);
+    }
+}
+
+template <int N>
+void
+f7 (I<int> i, const I<int> &x, const I<int> &y)
+{
+#pragma omp parallel for
+  for (i = x - 10; y + 10 >= i; i += N)
+    baz (i);
+}
+
+template <int N>
+void
+f8 (J<int> j)
+{
+  I<int> i;
+#pragma omp parallel for
+  for (i = j.begin (); j.end () + N >= i; i += 2)
+    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; y >= i; 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; y < i; 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; y >= i; i += 3)
+      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; y < i; --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; y + N >= i; 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 && (i - 10) % 6 == 0);
+  f2 (&a[0], &a[1999]);
+  check (i < 1998 && (i & 1) == 0);
+  f3<char> (&a[20], &a[1837]);
+  check (i >= 20 && i <= 1837);
+  f4<int> (&a[0], &a[30]);
+  check (i > 40 && i <= 2000 - 64);
+  f5 (&a[0], &a[100]);
+  check (i >= 116 && i <= 2000 - 64 && (i - 116) % 10 == 0);
+  f6<-10> (&a[10], &a[110]);
+  check (i >= 116 && i <= 2000 - 64 && (i - 116) % 10 == 0);
+  f7<6> (I<int> (), &a[12], &a[1800]);
+  check (i >= 2 && i <= 1808 && (i - 2) % 6 == 0);
+  f8<121> (J<int> (&a[14], &a[1803]));
+  check (i >= 14 && i <= 1924 && (i & 1) == 0);
+  f9<int, 7> (&a[33], &a[1967]);
+  check (i >= 33 && i <= 1967 && (i - 33) % 7 == 0);
+  f10<int, -7> (&a[1939], &a[17]);
+  check (i >= 21 && i <= 1939 && (i - 21) % 7 == 0);
+  f11<I<int> > (&a[16], &a[1981]);
+  check (i >= 16 && i <= 1984 && (i - 16) % 3 == 0);
+  f12<I<int> > (&a[1761], &a[37]);
+  check (i > 37 && i <= 1761);
+  K<5>::f13<I<int> > (&a[1], &a[1935]);
+  check (i >= 1 && i <= 1936 && (i - 1) % 5 == 0);
+  f9<long, 7> (&b[33], &b[1967]);
+  check (i >= 33 && i <= 1967 && (i - 33) % 7 == 0);
+  f10<long, -7> (&b[1939], &b[17]);
+  check (i >= 21 && i <= 1939 && (i - 21) % 7 == 0);
+  f11<I<long> > (&b[16], &b[1981]);
+  check (i >= 16 && i <= 1984 && (i - 16) % 3 == 0);
+  f12<I<long> > (&b[1761], &b[37]);
+  check (i > 37 && i <= 1761);
+  K<5>::f13<I<long> > (&b[1], &b[1935]);
+  check (i >= 1 && i <= 1936 && (i - 1) % 5 == 0);
+}
diff --git a/libgomp/testsuite/libgomp.c++/loop-11.C b/libgomp/testsuite/libgomp.c++/loop-11.C
new file mode 100644
index 000000000000..7775b86b8182
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/loop-11.C
@@ -0,0 +1,276 @@
+#include <omp.h>
+#include <stdlib.h>
+#include <string.h>
+
+int
+test1 ()
+{
+  short int buf[64], *p;
+  int i;
+  memset (buf, '\0', sizeof (buf));
+#pragma omp parallel for
+  for (p = &buf[10]; &buf[54] > p; p++)
+    *p = 5;
+  for (i = 0; i < 64; i++)
+    if (buf[i] != 5 * (i >= 10 && i < 54))
+      abort ();
+  memset (buf, '\0', sizeof (buf));
+#pragma omp parallel for
+  for (p = &buf[3]; &buf[63] >= p; p += 2)
+    p[-2] = 6;
+  for (i = 0; i < 64; i++)
+    if (buf[i] != 6 * ((i & 1) && i <= 61))
+      abort ();
+  memset (buf, '\0', sizeof (buf));
+#pragma omp parallel for
+  for (p = &buf[16]; &buf[51] > p; p = 4 + p)
+    p[2] = 7;
+  for (i = 0; i < 64; i++)
+    if (buf[i] != 7 * ((i & 3) == 2 && i >= 18 && i < 53))
+      abort ();
+  memset (buf, '\0', sizeof (buf));
+#pragma omp parallel for
+  for (p = &buf[16]; &buf[40] >= p; p = p + 4ULL)
+    p[2] = -7;
+  for (i = 0; i < 64; i++)
+    if (buf[i] != -7 * ((i & 3) == 2 && i >= 18 && i <= 42))
+      abort ();
+  memset (buf, '\0', sizeof (buf));
+#pragma omp parallel for
+  for (p = &buf[53]; &buf[9] < p; --p)
+    *p = 5;
+  for (i = 0; i < 64; i++)
+    if (buf[i] != 5 * (i >= 10 && i < 54))
+      abort ();
+  memset (buf, '\0', sizeof (buf));
+#pragma omp parallel for
+  for (p = &buf[63]; &buf[3] <= p; p -= 2)
+    p[-2] = 6;
+  for (i = 0; i < 64; i++)
+    if (buf[i] != 6 * ((i & 1) && i <= 61))
+      abort ();
+  memset (buf, '\0', sizeof (buf));
+#pragma omp parallel for
+  for (p = &buf[48]; &buf[15] < p; p = -4 + p)
+    p[2] = 7;
+  for (i = 0; i < 64; i++)
+    if (buf[i] != 7 * ((i & 3) == 2 && i >= 18 && i < 53))
+      abort ();
+  memset (buf, '\0', sizeof (buf));
+#pragma omp parallel for
+  for (p = &buf[40]; &buf[16] <= p; p = p - 4ULL)
+    p[2] = -7;
+  for (i = 0; i < 64; i++)
+    if (buf[i] != -7 * ((i & 3) == 2 && i >= 18 && i <= 42))
+      abort ();
+  return 0;
+}
+
+int
+test2 ()
+{
+  int buf[64], *p;
+  int i;
+  memset (buf, '\0', sizeof (buf));
+#pragma omp parallel for schedule (static, 3)
+  for (p = &buf[10]; &buf[54] > p; p++)
+    *p = 5;
+  for (i = 0; i < 64; i++)
+    if (buf[i] != 5 * (i >= 10 && i < 54))
+      abort ();
+  memset (buf, '\0', sizeof (buf));
+#pragma omp parallel for schedule (static, 3)
+  for (p = &buf[3]; &buf[63] >= p; p += 2)
+    p[-2] = 6;
+  for (i = 0; i < 64; i++)
+    if (buf[i] != 6 * ((i & 1) && i <= 61))
+      abort ();
+  memset (buf, '\0', sizeof (buf));
+#pragma omp parallel for schedule (static, 3)
+  for (p = &buf[16]; &buf[51] > p; p = 4 + p)
+    p[2] = 7;
+  for (i = 0; i < 64; i++)
+    if (buf[i] != 7 * ((i & 3) == 2 && i >= 18 && i < 53))
+      abort ();
+  memset (buf, '\0', sizeof (buf));
+#pragma omp parallel for schedule (static, 3)
+  for (p = &buf[16]; &buf[40] >= p; p = p + 4ULL)
+    p[2] = -7;
+  for (i = 0; i < 64; i++)
+    if (buf[i] != -7 * ((i & 3) == 2 && i >= 18 && i <= 42))
+      abort ();
+  memset (buf, '\0', sizeof (buf));
+#pragma omp parallel for schedule (static, 3)
+  for (p = &buf[53]; &buf[9] < p; --p)
+    *p = 5;
+  for (i = 0; i < 64; i++)
+    if (buf[i] != 5 * (i >= 10 && i < 54))
+      abort ();
+  memset (buf, '\0', sizeof (buf));
+#pragma omp parallel for schedule (static, 3)
+  for (p = &buf[63]; &buf[3] <= p; p -= 2)
+    p[-2] = 6;
+  for (i = 0; i < 64; i++)
+    if (buf[i] != 6 * ((i & 1) && i <= 61))
+      abort ();
+  memset (buf, '\0', sizeof (buf));
+#pragma omp parallel for schedule (static, 3)
+  for (p = &buf[48]; &buf[15] < p; p = -4 + p)
+    p[2] = 7;
+  for (i = 0; i < 64; i++)
+    if (buf[i] != 7 * ((i & 3) == 2 && i >= 18 && i < 53))
+      abort ();
+  memset (buf, '\0', sizeof (buf));
+#pragma omp parallel for schedule (static, 3)
+  for (p = &buf[40]; &buf[16] <= p; p = p - 4ULL)
+    p[2] = -7;
+  for (i = 0; i < 64; i++)
+    if (buf[i] != -7 * ((i & 3) == 2 && i >= 18 && i <= 42))
+      abort ();
+  return 0;
+}
+
+int
+test3 ()
+{
+  int buf[64], *p;
+  int i;
+  memset (buf, '\0', sizeof (buf));
+#pragma omp parallel for schedule (dynamic, 3)
+  for (p = &buf[10]; &buf[54] > p; p++)
+    *p = 5;
+  for (i = 0; i < 64; i++)
+    if (buf[i] != 5 * (i >= 10 && i < 54))
+      abort ();
+  memset (buf, '\0', sizeof (buf));
+#pragma omp parallel for schedule (dynamic, 3)
+  for (p = &buf[3]; &buf[63] >= p; p += 2)
+    p[-2] = 6;
+  for (i = 0; i < 64; i++)
+    if (buf[i] != 6 * ((i & 1) && i <= 61))
+      abort ();
+  memset (buf, '\0', sizeof (buf));
+#pragma omp parallel for schedule (dynamic, 3)
+  for (p = &buf[16]; &buf[51] > p; p = 4 + p)
+    p[2] = 7;
+  for (i = 0; i < 64; i++)
+    if (buf[i] != 7 * ((i & 3) == 2 && i >= 18 && i < 53))
+      abort ();
+  memset (buf, '\0', sizeof (buf));
+#pragma omp parallel for schedule (dynamic, 3)
+  for (p = &buf[16]; &buf[40] >= p; p = p + 4ULL)
+    p[2] = -7;
+  for (i = 0; i < 64; i++)
+    if (buf[i] != -7 * ((i & 3) == 2 && i >= 18 && i <= 42))
+      abort ();
+  memset (buf, '\0', sizeof (buf));
+#pragma omp parallel for schedule (dynamic, 3)
+  for (p = &buf[53]; &buf[9] < p; --p)
+    *p = 5;
+  for (i = 0; i < 64; i++)
+    if (buf[i] != 5 * (i >= 10 && i < 54))
+      abort ();
+  memset (buf, '\0', sizeof (buf));
+#pragma omp parallel for schedule (dynamic, 3)
+  for (p = &buf[63]; &buf[3] <= p; p -= 2)
+    p[-2] = 6;
+  for (i = 0; i < 64; i++)
+    if (buf[i] != 6 * ((i & 1) && i <= 61))
+      abort ();
+  memset (buf, '\0', sizeof (buf));
+#pragma omp parallel for schedule (dynamic, 3)
+  for (p = &buf[48]; &buf[15] < p; p = -4 + p)
+    p[2] = 7;
+  for (i = 0; i < 64; i++)
+    if (buf[i] != 7 * ((i & 3) == 2 && i >= 18 && i < 53))
+      abort ();
+  memset (buf, '\0', sizeof (buf));
+#pragma omp parallel for schedule (dynamic, 3)
+  for (p = &buf[40]; &buf[16] <= p; p = p - 4ULL)
+    p[2] = -7;
+  for (i = 0; i < 64; i++)
+    if (buf[i] != -7 * ((i & 3) == 2 && i >= 18 && i <= 42))
+      abort ();
+  return 0;
+}
+
+int
+test4 ()
+{
+  int buf[64], *p;
+  int i;
+  memset (buf, '\0', sizeof (buf));
+#pragma omp parallel for schedule (runtime)
+  for (p = &buf[10]; &buf[54] > p; p++)
+    *p = 5;
+  for (i = 0; i < 64; i++)
+    if (buf[i] != 5 * (i >= 10 && i < 54))
+      abort ();
+  memset (buf, '\0', sizeof (buf));
+#pragma omp parallel for schedule (runtime)
+  for (p = &buf[3]; &buf[63] >= p; p += 2)
+    p[-2] = 6;
+  for (i = 0; i < 64; i++)
+    if (buf[i] != 6 * ((i & 1) && i <= 61))
+      abort ();
+  memset (buf, '\0', sizeof (buf));
+#pragma omp parallel for schedule (runtime)
+  for (p = &buf[16]; &buf[51] > p; p = 4 + p)
+    p[2] = 7;
+  for (i = 0; i < 64; i++)
+    if (buf[i] != 7 * ((i & 3) == 2 && i >= 18 && i < 53))
+      abort ();
+  memset (buf, '\0', sizeof (buf));
+#pragma omp parallel for schedule (runtime)
+  for (p = &buf[16]; &buf[40] >= p; p = p + 4ULL)
+    p[2] = -7;
+  for (i = 0; i < 64; i++)
+    if (buf[i] != -7 * ((i & 3) == 2 && i >= 18 && i <= 42))
+      abort ();
+  memset (buf, '\0', sizeof (buf));
+#pragma omp parallel for schedule (runtime)
+  for (p = &buf[53]; &buf[9] < p; --p)
+    *p = 5;
+  for (i = 0; i < 64; i++)
+    if (buf[i] != 5 * (i >= 10 && i < 54))
+      abort ();
+  memset (buf, '\0', sizeof (buf));
+#pragma omp parallel for schedule (runtime)
+  for (p = &buf[63]; &buf[3] <= p; p -= 2)
+    p[-2] = 6;
+  for (i = 0; i < 64; i++)
+    if (buf[i] != 6 * ((i & 1) && i <= 61))
+      abort ();
+  memset (buf, '\0', sizeof (buf));
+#pragma omp parallel for schedule (runtime)
+  for (p = &buf[48]; &buf[15] < p; p = -4 + p)
+    p[2] = 7;
+  for (i = 0; i < 64; i++)
+    if (buf[i] != 7 * ((i & 3) == 2 && i >= 18 && i < 53))
+      abort ();
+  memset (buf, '\0', sizeof (buf));
+#pragma omp parallel for schedule (runtime)
+  for (p = &buf[40]; &buf[16] <= p; p = p - 4ULL)
+    p[2] = -7;
+  for (i = 0; i < 64; i++)
+    if (buf[i] != -7 * ((i & 3) == 2 && i >= 18 && i <= 42))
+      abort ();
+  return 0;
+}
+
+int
+main ()
+{
+  test1 ();
+  test2 ();
+  test3 ();
+  omp_set_schedule (omp_sched_static, 0);
+  test4 ();
+  omp_set_schedule (omp_sched_static, 3);
+  test4 ();
+  omp_set_schedule (omp_sched_dynamic, 5);
+  test4 ();
+  omp_set_schedule (omp_sched_guided, 2);
+  test4 ();
+  return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c++/loop-12.C b/libgomp/testsuite/libgomp.c++/loop-12.C
new file mode 100644
index 000000000000..f8aca92b8aee
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/loop-12.C
@@ -0,0 +1,387 @@
+// { dg-do run }
+
+#include <omp.h>
+
+extern "C" void abort ();
+
+#define LLONG_MAX __LONG_LONG_MAX__
+#define ULLONG_MAX (LLONG_MAX * 2ULL + 1)
+#define INT_MAX __INT_MAX__
+
+int arr[6 * 5];
+
+void
+set (int loopidx, int idx)
+{
+#pragma omp atomic
+  arr[loopidx * 5 + idx]++;
+}
+
+#define check(var, val, loopidx, idx) \
+  if (var == (val)) set (loopidx, idx); else
+#define test(loopidx, count) \
+  for (idx = 0; idx < 5; idx++) \
+    if (arr[loopidx * 5 + idx] != idx < count) \
+      abort (); \
+    else \
+      arr[loopidx * 5 + idx] = 0
+
+int
+test1 ()
+{
+  int e = 0, idx;
+
+#pragma omp parallel reduction(+:e)
+  {
+    long long i;
+    unsigned long long j;
+    #pragma omp for schedule(dynamic,1) nowait
+    for (i = LLONG_MAX - 30001; LLONG_MAX - 10001 >= i; i += 10000)
+      {
+	check (i, LLONG_MAX - 30001, 0, 0)
+	check (i, LLONG_MAX - 20001, 0, 1)
+	check (i, LLONG_MAX - 10001, 0, 2)
+	e = 1;
+      }
+    #pragma omp for schedule(dynamic,1) nowait
+    for (i = -LLONG_MAX + 30000; -LLONG_MAX + 10000 <= i; i -= 10000)
+      {
+	check (i, -LLONG_MAX + 30000, 1, 0)
+	check (i, -LLONG_MAX + 20000, 1, 1)
+	check (i, -LLONG_MAX + 10000, 1, 2)
+	e = 1;
+      }
+    #pragma omp for schedule(dynamic,1) nowait
+    for (j = 20; LLONG_MAX - 70 >= j; j += LLONG_MAX + 50ULL)
+      {
+	check (j, 20, 2, 0)
+	e = 1;
+      }
+    #pragma omp for schedule(dynamic,1) nowait
+    for (j = ULLONG_MAX - 3; LLONG_MAX + 70ULL <= j; j -= LLONG_MAX + 50ULL)
+      {
+	check (j, ULLONG_MAX - 3, 3, 0)
+	e = 1;
+      }
+    #pragma omp for schedule(dynamic,1) nowait
+    for (j = LLONG_MAX - 20000ULL; LLONG_MAX + 10000ULL >= j; j += 10000ULL)
+      {
+	check (j, LLONG_MAX - 20000ULL, 4, 0)
+	check (j, LLONG_MAX - 10000ULL, 4, 1)
+	check (j, LLONG_MAX, 4, 2)
+	check (j, LLONG_MAX + 10000ULL, 4, 3)
+	e = 1;
+      }
+    #pragma omp for schedule(dynamic,1) nowait
+    for (i = -3LL * INT_MAX - 20000LL; INT_MAX + 10000LL >= i; i += INT_MAX + 200LL)
+      {
+	check (i, -3LL * INT_MAX - 20000LL, 5, 0)
+	check (i, -2LL * INT_MAX - 20000LL + 200LL, 5, 1)
+	check (i, -INT_MAX - 20000LL + 400LL, 5, 2)
+	check (i, -20000LL + 600LL, 5, 3)
+	check (i, INT_MAX - 20000LL + 800LL, 5, 4)
+	e = 1;
+      }
+  }
+  if (e)
+    abort ();
+  test (0, 3);
+  test (1, 3);
+  test (2, 1);
+  test (3, 1);
+  test (4, 4);
+  test (5, 5);
+  return 0;
+}
+
+int
+test2 ()
+{
+  int e = 0, idx;
+
+#pragma omp parallel reduction(+:e)
+  {
+    long long i;
+    unsigned long long j;
+    #pragma omp for schedule(guided,1) nowait
+    for (i = LLONG_MAX - 30001; LLONG_MAX - 10001 >= i; i += 10000)
+      {
+	check (i, LLONG_MAX - 30001, 0, 0)
+	check (i, LLONG_MAX - 20001, 0, 1)
+	check (i, LLONG_MAX - 10001, 0, 2)
+	e = 1;
+      }
+    #pragma omp for schedule(guided,1) nowait
+    for (i = -LLONG_MAX + 30000; -LLONG_MAX + 10000 <= i; i -= 10000)
+      {
+	check (i, -LLONG_MAX + 30000, 1, 0)
+	check (i, -LLONG_MAX + 20000, 1, 1)
+	check (i, -LLONG_MAX + 10000, 1, 2)
+	e = 1;
+      }
+    #pragma omp for schedule(guided,1) nowait
+    for (j = 20; LLONG_MAX - 70 >= j; j += LLONG_MAX + 50ULL)
+      {
+	check (j, 20, 2, 0)
+	e = 1;
+      }
+    #pragma omp for schedule(guided,1) nowait
+    for (j = ULLONG_MAX - 3; LLONG_MAX + 70ULL <= j; j -= LLONG_MAX + 50ULL)
+      {
+	check (j, ULLONG_MAX - 3, 3, 0)
+	e = 1;
+      }
+    #pragma omp for schedule(guided,1) nowait
+    for (j = LLONG_MAX - 20000ULL; LLONG_MAX + 10000ULL >= j; j += 10000ULL)
+      {
+	check (j, LLONG_MAX - 20000ULL, 4, 0)
+	check (j, LLONG_MAX - 10000ULL, 4, 1)
+	check (j, LLONG_MAX, 4, 2)
+	check (j, LLONG_MAX + 10000ULL, 4, 3)
+	e = 1;
+      }
+    #pragma omp for schedule(guided,1) nowait
+    for (i = -3LL * INT_MAX - 20000LL; INT_MAX + 10000LL >= i; i += INT_MAX + 200LL)
+      {
+	check (i, -3LL * INT_MAX - 20000LL, 5, 0)
+	check (i, -2LL * INT_MAX - 20000LL + 200LL, 5, 1)
+	check (i, -INT_MAX - 20000LL + 400LL, 5, 2)
+	check (i, -20000LL + 600LL, 5, 3)
+	check (i, INT_MAX - 20000LL + 800LL, 5, 4)
+	e = 1;
+      }
+  }
+  if (e)
+    abort ();
+  test (0, 3);
+  test (1, 3);
+  test (2, 1);
+  test (3, 1);
+  test (4, 4);
+  test (5, 5);
+  return 0;
+}
+
+int
+test3 ()
+{
+  int e = 0, idx;
+
+#pragma omp parallel reduction(+:e)
+  {
+    long long i;
+    unsigned long long j;
+    #pragma omp for schedule(static) nowait
+    for (i = LLONG_MAX - 30001; LLONG_MAX - 10001 >= i; i += 10000)
+      {
+	check (i, LLONG_MAX - 30001, 0, 0)
+	check (i, LLONG_MAX - 20001, 0, 1)
+	check (i, LLONG_MAX - 10001, 0, 2)
+	e = 1;
+      }
+    #pragma omp for schedule(static) nowait
+    for (i = -LLONG_MAX + 30000; -LLONG_MAX + 10000 <= i; i -= 10000)
+      {
+	check (i, -LLONG_MAX + 30000, 1, 0)
+	check (i, -LLONG_MAX + 20000, 1, 1)
+	check (i, -LLONG_MAX + 10000, 1, 2)
+	e = 1;
+      }
+    #pragma omp for schedule(static) nowait
+    for (j = 20; LLONG_MAX - 70 >= j; j += LLONG_MAX + 50ULL)
+      {
+	check (j, 20, 2, 0)
+	e = 1;
+      }
+    #pragma omp for schedule(static) nowait
+    for (j = ULLONG_MAX - 3; LLONG_MAX + 70ULL <= j; j -= LLONG_MAX + 50ULL)
+      {
+	check (j, ULLONG_MAX - 3, 3, 0)
+	e = 1;
+      }
+    #pragma omp for schedule(static) nowait
+    for (j = LLONG_MAX - 20000ULL; LLONG_MAX + 10000ULL >= j; j += 10000ULL)
+      {
+	check (j, LLONG_MAX - 20000ULL, 4, 0)
+	check (j, LLONG_MAX - 10000ULL, 4, 1)
+	check (j, LLONG_MAX, 4, 2)
+	check (j, LLONG_MAX + 10000ULL, 4, 3)
+	e = 1;
+      }
+    #pragma omp for schedule(static) nowait
+    for (i = -3LL * INT_MAX - 20000LL; INT_MAX + 10000LL >= i; i += INT_MAX + 200LL)
+      {
+	check (i, -3LL * INT_MAX - 20000LL, 5, 0)
+	check (i, -2LL * INT_MAX - 20000LL + 200LL, 5, 1)
+	check (i, -INT_MAX - 20000LL + 400LL, 5, 2)
+	check (i, -20000LL + 600LL, 5, 3)
+	check (i, INT_MAX - 20000LL + 800LL, 5, 4)
+	e = 1;
+      }
+  }
+  if (e)
+    abort ();
+  test (0, 3);
+  test (1, 3);
+  test (2, 1);
+  test (3, 1);
+  test (4, 4);
+  test (5, 5);
+  return 0;
+}
+
+int
+test4 ()
+{
+  int e = 0, idx;
+
+#pragma omp parallel reduction(+:e)
+  {
+    long long i;
+    unsigned long long j;
+    #pragma omp for schedule(static,1) nowait
+    for (i = LLONG_MAX - 30001; LLONG_MAX - 10001 >= i; i += 10000)
+      {
+	check (i, LLONG_MAX - 30001, 0, 0)
+	check (i, LLONG_MAX - 20001, 0, 1)
+	check (i, LLONG_MAX - 10001, 0, 2)
+	e = 1;
+      }
+    #pragma omp for schedule(static,1) nowait
+    for (i = -LLONG_MAX + 30000; -LLONG_MAX + 10000 <= i; i -= 10000)
+      {
+	check (i, -LLONG_MAX + 30000, 1, 0)
+	check (i, -LLONG_MAX + 20000, 1, 1)
+	check (i, -LLONG_MAX + 10000, 1, 2)
+	e = 1;
+      }
+    #pragma omp for schedule(static,1) nowait
+    for (j = 20; LLONG_MAX - 70 >= j; j += LLONG_MAX + 50ULL)
+      {
+	check (j, 20, 2, 0)
+	e = 1;
+      }
+    #pragma omp for schedule(static,1) nowait
+    for (j = ULLONG_MAX - 3; LLONG_MAX + 70ULL <= j; j -= LLONG_MAX + 50ULL)
+      {
+	check (j, ULLONG_MAX - 3, 3, 0)
+	e = 1;
+      }
+    #pragma omp for schedule(static,1) nowait
+    for (j = LLONG_MAX - 20000ULL; LLONG_MAX + 10000ULL >= j; j += 10000ULL)
+      {
+	check (j, LLONG_MAX - 20000ULL, 4, 0)
+	check (j, LLONG_MAX - 10000ULL, 4, 1)
+	check (j, LLONG_MAX, 4, 2)
+	check (j, LLONG_MAX + 10000ULL, 4, 3)
+	e = 1;
+      }
+    #pragma omp for schedule(static,1) nowait
+    for (i = -3LL * INT_MAX - 20000LL; INT_MAX + 10000LL >= i; i += INT_MAX + 200LL)
+      {
+	check (i, -3LL * INT_MAX - 20000LL, 5, 0)
+	check (i, -2LL * INT_MAX - 20000LL + 200LL, 5, 1)
+	check (i, -INT_MAX - 20000LL + 400LL, 5, 2)
+	check (i, -20000LL + 600LL, 5, 3)
+	check (i, INT_MAX - 20000LL + 800LL, 5, 4)
+	e = 1;
+      }
+  }
+  if (e)
+    abort ();
+  test (0, 3);
+  test (1, 3);
+  test (2, 1);
+  test (3, 1);
+  test (4, 4);
+  test (5, 5);
+  return 0;
+}
+
+int
+test5 ()
+{
+  int e = 0, idx;
+
+#pragma omp parallel reduction(+:e)
+  {
+    long long i;
+    unsigned long long j;
+    #pragma omp for schedule(runtime) nowait
+    for (i = LLONG_MAX - 30001; LLONG_MAX - 10001 >= i; i += 10000)
+      {
+	check (i, LLONG_MAX - 30001, 0, 0)
+	check (i, LLONG_MAX - 20001, 0, 1)
+	check (i, LLONG_MAX - 10001, 0, 2)
+	e = 1;
+      }
+    #pragma omp for schedule(runtime) nowait
+    for (i = -LLONG_MAX + 30000; -LLONG_MAX + 10000 <= i; i -= 10000)
+      {
+	check (i, -LLONG_MAX + 30000, 1, 0)
+	check (i, -LLONG_MAX + 20000, 1, 1)
+	check (i, -LLONG_MAX + 10000, 1, 2)
+	e = 1;
+      }
+    #pragma omp for schedule(runtime) nowait
+    for (j = 20; LLONG_MAX - 70 >= j; j += LLONG_MAX + 50ULL)
+      {
+	check (j, 20, 2, 0)
+	e = 1;
+      }
+    #pragma omp for schedule(runtime) nowait
+    for (j = ULLONG_MAX - 3; LLONG_MAX + 70ULL <= j; j -= LLONG_MAX + 50ULL)
+      {
+	check (j, ULLONG_MAX - 3, 3, 0)
+	e = 1;
+      }
+    #pragma omp for schedule(runtime) nowait
+    for (j = LLONG_MAX - 20000ULL; LLONG_MAX + 10000ULL >= j; j += 10000ULL)
+      {
+	check (j, LLONG_MAX - 20000ULL, 4, 0)
+	check (j, LLONG_MAX - 10000ULL, 4, 1)
+	check (j, LLONG_MAX, 4, 2)
+	check (j, LLONG_MAX + 10000ULL, 4, 3)
+	e = 1;
+      }
+    #pragma omp for schedule(runtime) nowait
+    for (i = -3LL * INT_MAX - 20000LL; INT_MAX + 10000LL >= i; i += INT_MAX + 200LL)
+      {
+	check (i, -3LL * INT_MAX - 20000LL, 5, 0)
+	check (i, -2LL * INT_MAX - 20000LL + 200LL, 5, 1)
+	check (i, -INT_MAX - 20000LL + 400LL, 5, 2)
+	check (i, -20000LL + 600LL, 5, 3)
+	check (i, INT_MAX - 20000LL + 800LL, 5, 4)
+	e = 1;
+      }
+  }
+  if (e)
+    abort ();
+  test (0, 3);
+  test (1, 3);
+  test (2, 1);
+  test (3, 1);
+  test (4, 4);
+  test (5, 5);
+  return 0;
+}
+
+int
+main ()
+{
+  if (2 * sizeof (int) != sizeof (long long))
+    return 0;
+  test1 ();
+  test2 ();
+  test3 ();
+  test4 ();
+  omp_set_schedule (omp_sched_static, 0);
+  test5 ();
+  omp_set_schedule (omp_sched_static, 3);
+  test5 ();
+  omp_set_schedule (omp_sched_dynamic, 5);
+  test5 ();
+  omp_set_schedule (omp_sched_guided, 2);
+  test5 ();
+  return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c/loop-11.c b/libgomp/testsuite/libgomp.c/loop-11.c
new file mode 100644
index 000000000000..c5ac3c4348a8
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c/loop-11.c
@@ -0,0 +1,276 @@
+#include <omp.h>
+#include <stdlib.h>
+#include <string.h>
+
+int
+test1 (void)
+{
+  short int buf[64], *p;
+  int i;
+  memset (buf, '\0', sizeof (buf));
+#pragma omp parallel for
+  for (p = &buf[10]; &buf[54] > p; p++)
+    *p = 5;
+  for (i = 0; i < 64; i++)
+    if (buf[i] != 5 * (i >= 10 && i < 54))
+      abort ();
+  memset (buf, '\0', sizeof (buf));
+#pragma omp parallel for
+  for (p = &buf[3]; &buf[63] >= p; p += 2)
+    p[-2] = 6;
+  for (i = 0; i < 64; i++)
+    if (buf[i] != 6 * ((i & 1) && i <= 61))
+      abort ();
+  memset (buf, '\0', sizeof (buf));
+#pragma omp parallel for
+  for (p = &buf[16]; &buf[51] > p; p = 4 + p)
+    p[2] = 7;
+  for (i = 0; i < 64; i++)
+    if (buf[i] != 7 * ((i & 3) == 2 && i >= 18 && i < 53))
+      abort ();
+  memset (buf, '\0', sizeof (buf));
+#pragma omp parallel for
+  for (p = &buf[16]; &buf[40] >= p; p = p + 4ULL)
+    p[2] = -7;
+  for (i = 0; i < 64; i++)
+    if (buf[i] != -7 * ((i & 3) == 2 && i >= 18 && i <= 42))
+      abort ();
+  memset (buf, '\0', sizeof (buf));
+#pragma omp parallel for
+  for (p = &buf[53]; &buf[9] < p; --p)
+    *p = 5;
+  for (i = 0; i < 64; i++)
+    if (buf[i] != 5 * (i >= 10 && i < 54))
+      abort ();
+  memset (buf, '\0', sizeof (buf));
+#pragma omp parallel for
+  for (p = &buf[63]; &buf[3] <= p; p -= 2)
+    p[-2] = 6;
+  for (i = 0; i < 64; i++)
+    if (buf[i] != 6 * ((i & 1) && i <= 61))
+      abort ();
+  memset (buf, '\0', sizeof (buf));
+#pragma omp parallel for
+  for (p = &buf[48]; &buf[15] < p; p = -4 + p)
+    p[2] = 7;
+  for (i = 0; i < 64; i++)
+    if (buf[i] != 7 * ((i & 3) == 2 && i >= 18 && i < 53))
+      abort ();
+  memset (buf, '\0', sizeof (buf));
+#pragma omp parallel for
+  for (p = &buf[40]; &buf[16] <= p; p = p - 4ULL)
+    p[2] = -7;
+  for (i = 0; i < 64; i++)
+    if (buf[i] != -7 * ((i & 3) == 2 && i >= 18 && i <= 42))
+      abort ();
+  return 0;
+}
+
+int
+test2 (void)
+{
+  int buf[64], *p;
+  int i;
+  memset (buf, '\0', sizeof (buf));
+#pragma omp parallel for schedule (static, 3)
+  for (p = &buf[10]; &buf[54] > p; p++)
+    *p = 5;
+  for (i = 0; i < 64; i++)
+    if (buf[i] != 5 * (i >= 10 && i < 54))
+      abort ();
+  memset (buf, '\0', sizeof (buf));
+#pragma omp parallel for schedule (static, 3)
+  for (p = &buf[3]; &buf[63] >= p; p += 2)
+    p[-2] = 6;
+  for (i = 0; i < 64; i++)
+    if (buf[i] != 6 * ((i & 1) && i <= 61))
+      abort ();
+  memset (buf, '\0', sizeof (buf));
+#pragma omp parallel for schedule (static, 3)
+  for (p = &buf[16]; &buf[51] > p; p = 4 + p)
+    p[2] = 7;
+  for (i = 0; i < 64; i++)
+    if (buf[i] != 7 * ((i & 3) == 2 && i >= 18 && i < 53))
+      abort ();
+  memset (buf, '\0', sizeof (buf));
+#pragma omp parallel for schedule (static, 3)
+  for (p = &buf[16]; &buf[40] >= p; p = p + 4ULL)
+    p[2] = -7;
+  for (i = 0; i < 64; i++)
+    if (buf[i] != -7 * ((i & 3) == 2 && i >= 18 && i <= 42))
+      abort ();
+  memset (buf, '\0', sizeof (buf));
+#pragma omp parallel for schedule (static, 3)
+  for (p = &buf[53]; &buf[9] < p; --p)
+    *p = 5;
+  for (i = 0; i < 64; i++)
+    if (buf[i] != 5 * (i >= 10 && i < 54))
+      abort ();
+  memset (buf, '\0', sizeof (buf));
+#pragma omp parallel for schedule (static, 3)
+  for (p = &buf[63]; &buf[3] <= p; p -= 2)
+    p[-2] = 6;
+  for (i = 0; i < 64; i++)
+    if (buf[i] != 6 * ((i & 1) && i <= 61))
+      abort ();
+  memset (buf, '\0', sizeof (buf));
+#pragma omp parallel for schedule (static, 3)
+  for (p = &buf[48]; &buf[15] < p; p = -4 + p)
+    p[2] = 7;
+  for (i = 0; i < 64; i++)
+    if (buf[i] != 7 * ((i & 3) == 2 && i >= 18 && i < 53))
+      abort ();
+  memset (buf, '\0', sizeof (buf));
+#pragma omp parallel for schedule (static, 3)
+  for (p = &buf[40]; &buf[16] <= p; p = p - 4ULL)
+    p[2] = -7;
+  for (i = 0; i < 64; i++)
+    if (buf[i] != -7 * ((i & 3) == 2 && i >= 18 && i <= 42))
+      abort ();
+  return 0;
+}
+
+int
+test3 (void)
+{
+  int buf[64], *p;
+  int i;
+  memset (buf, '\0', sizeof (buf));
+#pragma omp parallel for schedule (dynamic, 3)
+  for (p = &buf[10]; &buf[54] > p; p++)
+    *p = 5;
+  for (i = 0; i < 64; i++)
+    if (buf[i] != 5 * (i >= 10 && i < 54))
+      abort ();
+  memset (buf, '\0', sizeof (buf));
+#pragma omp parallel for schedule (dynamic, 3)
+  for (p = &buf[3]; &buf[63] >= p; p += 2)
+    p[-2] = 6;
+  for (i = 0; i < 64; i++)
+    if (buf[i] != 6 * ((i & 1) && i <= 61))
+      abort ();
+  memset (buf, '\0', sizeof (buf));
+#pragma omp parallel for schedule (dynamic, 3)
+  for (p = &buf[16]; &buf[51] > p; p = 4 + p)
+    p[2] = 7;
+  for (i = 0; i < 64; i++)
+    if (buf[i] != 7 * ((i & 3) == 2 && i >= 18 && i < 53))
+      abort ();
+  memset (buf, '\0', sizeof (buf));
+#pragma omp parallel for schedule (dynamic, 3)
+  for (p = &buf[16]; &buf[40] >= p; p = p + 4ULL)
+    p[2] = -7;
+  for (i = 0; i < 64; i++)
+    if (buf[i] != -7 * ((i & 3) == 2 && i >= 18 && i <= 42))
+      abort ();
+  memset (buf, '\0', sizeof (buf));
+#pragma omp parallel for schedule (dynamic, 3)
+  for (p = &buf[53]; &buf[9] < p; --p)
+    *p = 5;
+  for (i = 0; i < 64; i++)
+    if (buf[i] != 5 * (i >= 10 && i < 54))
+      abort ();
+  memset (buf, '\0', sizeof (buf));
+#pragma omp parallel for schedule (dynamic, 3)
+  for (p = &buf[63]; &buf[3] <= p; p -= 2)
+    p[-2] = 6;
+  for (i = 0; i < 64; i++)
+    if (buf[i] != 6 * ((i & 1) && i <= 61))
+      abort ();
+  memset (buf, '\0', sizeof (buf));
+#pragma omp parallel for schedule (dynamic, 3)
+  for (p = &buf[48]; &buf[15] < p; p = -4 + p)
+    p[2] = 7;
+  for (i = 0; i < 64; i++)
+    if (buf[i] != 7 * ((i & 3) == 2 && i >= 18 && i < 53))
+      abort ();
+  memset (buf, '\0', sizeof (buf));
+#pragma omp parallel for schedule (dynamic, 3)
+  for (p = &buf[40]; &buf[16] <= p; p = p - 4ULL)
+    p[2] = -7;
+  for (i = 0; i < 64; i++)
+    if (buf[i] != -7 * ((i & 3) == 2 && i >= 18 && i <= 42))
+      abort ();
+  return 0;
+}
+
+int
+test4 (void)
+{
+  int buf[64], *p;
+  int i;
+  memset (buf, '\0', sizeof (buf));
+#pragma omp parallel for schedule (runtime)
+  for (p = &buf[10]; &buf[54] > p; p++)
+    *p = 5;
+  for (i = 0; i < 64; i++)
+    if (buf[i] != 5 * (i >= 10 && i < 54))
+      abort ();
+  memset (buf, '\0', sizeof (buf));
+#pragma omp parallel for schedule (runtime)
+  for (p = &buf[3]; &buf[63] >= p; p += 2)
+    p[-2] = 6;
+  for (i = 0; i < 64; i++)
+    if (buf[i] != 6 * ((i & 1) && i <= 61))
+      abort ();
+  memset (buf, '\0', sizeof (buf));
+#pragma omp parallel for schedule (runtime)
+  for (p = &buf[16]; &buf[51] > p; p = 4 + p)
+    p[2] = 7;
+  for (i = 0; i < 64; i++)
+    if (buf[i] != 7 * ((i & 3) == 2 && i >= 18 && i < 53))
+      abort ();
+  memset (buf, '\0', sizeof (buf));
+#pragma omp parallel for schedule (runtime)
+  for (p = &buf[16]; &buf[40] >= p; p = p + 4ULL)
+    p[2] = -7;
+  for (i = 0; i < 64; i++)
+    if (buf[i] != -7 * ((i & 3) == 2 && i >= 18 && i <= 42))
+      abort ();
+  memset (buf, '\0', sizeof (buf));
+#pragma omp parallel for schedule (runtime)
+  for (p = &buf[53]; &buf[9] < p; --p)
+    *p = 5;
+  for (i = 0; i < 64; i++)
+    if (buf[i] != 5 * (i >= 10 && i < 54))
+      abort ();
+  memset (buf, '\0', sizeof (buf));
+#pragma omp parallel for schedule (runtime)
+  for (p = &buf[63]; &buf[3] <= p; p -= 2)
+    p[-2] = 6;
+  for (i = 0; i < 64; i++)
+    if (buf[i] != 6 * ((i & 1) && i <= 61))
+      abort ();
+  memset (buf, '\0', sizeof (buf));
+#pragma omp parallel for schedule (runtime)
+  for (p = &buf[48]; &buf[15] < p; p = -4 + p)
+    p[2] = 7;
+  for (i = 0; i < 64; i++)
+    if (buf[i] != 7 * ((i & 3) == 2 && i >= 18 && i < 53))
+      abort ();
+  memset (buf, '\0', sizeof (buf));
+#pragma omp parallel for schedule (runtime)
+  for (p = &buf[40]; &buf[16] <= p; p = p - 4ULL)
+    p[2] = -7;
+  for (i = 0; i < 64; i++)
+    if (buf[i] != -7 * ((i & 3) == 2 && i >= 18 && i <= 42))
+      abort ();
+  return 0;
+}
+
+int
+main (void)
+{
+  test1 ();
+  test2 ();
+  test3 ();
+  omp_set_schedule (omp_sched_static, 0);
+  test4 ();
+  omp_set_schedule (omp_sched_static, 3);
+  test4 ();
+  omp_set_schedule (omp_sched_dynamic, 5);
+  test4 ();
+  omp_set_schedule (omp_sched_guided, 2);
+  test4 ();
+  return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c/loop-12.c b/libgomp/testsuite/libgomp.c/loop-12.c
new file mode 100644
index 000000000000..395da363e489
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c/loop-12.c
@@ -0,0 +1,387 @@
+/* { dg-do run } */
+
+#include <omp.h>
+
+extern void abort (void);
+
+#define LLONG_MAX __LONG_LONG_MAX__
+#define ULLONG_MAX (LLONG_MAX * 2ULL + 1)
+#define INT_MAX __INT_MAX__
+
+int arr[6 * 5];
+
+void
+set (int loopidx, int idx)
+{
+#pragma omp atomic
+  arr[loopidx * 5 + idx]++;
+}
+
+#define check(var, val, loopidx, idx) \
+  if (var == (val)) set (loopidx, idx); else
+#define test(loopidx, count) \
+  for (idx = 0; idx < 5; idx++) \
+    if (arr[loopidx * 5 + idx] != idx < count) \
+      abort (); \
+    else \
+      arr[loopidx * 5 + idx] = 0
+
+int
+test1 (void)
+{
+  int e = 0, idx;
+
+#pragma omp parallel reduction(+:e)
+  {
+    long long i;
+    unsigned long long j;
+    #pragma omp for schedule(dynamic,1) nowait
+    for (i = LLONG_MAX - 30001; LLONG_MAX - 10001 >= i; i += 10000)
+      {
+	check (i, LLONG_MAX - 30001, 0, 0)
+	check (i, LLONG_MAX - 20001, 0, 1)
+	check (i, LLONG_MAX - 10001, 0, 2)
+	e = 1;
+      }
+    #pragma omp for schedule(dynamic,1) nowait
+    for (i = -LLONG_MAX + 30000; -LLONG_MAX + 10000 <= i; i -= 10000)
+      {
+	check (i, -LLONG_MAX + 30000, 1, 0)
+	check (i, -LLONG_MAX + 20000, 1, 1)
+	check (i, -LLONG_MAX + 10000, 1, 2)
+	e = 1;
+      }
+    #pragma omp for schedule(dynamic,1) nowait
+    for (j = 20; LLONG_MAX - 70 >= j; j += LLONG_MAX + 50ULL)
+      {
+	check (j, 20, 2, 0)
+	e = 1;
+      }
+    #pragma omp for schedule(dynamic,1) nowait
+    for (j = ULLONG_MAX - 3; LLONG_MAX + 70ULL <= j; j -= LLONG_MAX + 50ULL)
+      {
+	check (j, ULLONG_MAX - 3, 3, 0)
+	e = 1;
+      }
+    #pragma omp for schedule(dynamic,1) nowait
+    for (j = LLONG_MAX - 20000ULL; LLONG_MAX + 10000ULL >= j; j += 10000ULL)
+      {
+	check (j, LLONG_MAX - 20000ULL, 4, 0)
+	check (j, LLONG_MAX - 10000ULL, 4, 1)
+	check (j, LLONG_MAX, 4, 2)
+	check (j, LLONG_MAX + 10000ULL, 4, 3)
+	e = 1;
+      }
+    #pragma omp for schedule(dynamic,1) nowait
+    for (i = -3LL * INT_MAX - 20000LL; INT_MAX + 10000LL >= i; i += INT_MAX + 200LL)
+      {
+	check (i, -3LL * INT_MAX - 20000LL, 5, 0)
+	check (i, -2LL * INT_MAX - 20000LL + 200LL, 5, 1)
+	check (i, -INT_MAX - 20000LL + 400LL, 5, 2)
+	check (i, -20000LL + 600LL, 5, 3)
+	check (i, INT_MAX - 20000LL + 800LL, 5, 4)
+	e = 1;
+      }
+  }
+  if (e)
+    abort ();
+  test (0, 3);
+  test (1, 3);
+  test (2, 1);
+  test (3, 1);
+  test (4, 4);
+  test (5, 5);
+  return 0;
+}
+
+int
+test2 (void)
+{
+  int e = 0, idx;
+
+#pragma omp parallel reduction(+:e)
+  {
+    long long i;
+    unsigned long long j;
+    #pragma omp for schedule(guided,1) nowait
+    for (i = LLONG_MAX - 30001; LLONG_MAX - 10001 >= i; i += 10000)
+      {
+	check (i, LLONG_MAX - 30001, 0, 0)
+	check (i, LLONG_MAX - 20001, 0, 1)
+	check (i, LLONG_MAX - 10001, 0, 2)
+	e = 1;
+      }
+    #pragma omp for schedule(guided,1) nowait
+    for (i = -LLONG_MAX + 30000; -LLONG_MAX + 10000 <= i; i -= 10000)
+      {
+	check (i, -LLONG_MAX + 30000, 1, 0)
+	check (i, -LLONG_MAX + 20000, 1, 1)
+	check (i, -LLONG_MAX + 10000, 1, 2)
+	e = 1;
+      }
+    #pragma omp for schedule(guided,1) nowait
+    for (j = 20; LLONG_MAX - 70 >= j; j += LLONG_MAX + 50ULL)
+      {
+	check (j, 20, 2, 0)
+	e = 1;
+      }
+    #pragma omp for schedule(guided,1) nowait
+    for (j = ULLONG_MAX - 3; LLONG_MAX + 70ULL <= j; j -= LLONG_MAX + 50ULL)
+      {
+	check (j, ULLONG_MAX - 3, 3, 0)
+	e = 1;
+      }
+    #pragma omp for schedule(guided,1) nowait
+    for (j = LLONG_MAX - 20000ULL; LLONG_MAX + 10000ULL >= j; j += 10000ULL)
+      {
+	check (j, LLONG_MAX - 20000ULL, 4, 0)
+	check (j, LLONG_MAX - 10000ULL, 4, 1)
+	check (j, LLONG_MAX, 4, 2)
+	check (j, LLONG_MAX + 10000ULL, 4, 3)
+	e = 1;
+      }
+    #pragma omp for schedule(guided,1) nowait
+    for (i = -3LL * INT_MAX - 20000LL; INT_MAX + 10000LL >= i; i += INT_MAX + 200LL)
+      {
+	check (i, -3LL * INT_MAX - 20000LL, 5, 0)
+	check (i, -2LL * INT_MAX - 20000LL + 200LL, 5, 1)
+	check (i, -INT_MAX - 20000LL + 400LL, 5, 2)
+	check (i, -20000LL + 600LL, 5, 3)
+	check (i, INT_MAX - 20000LL + 800LL, 5, 4)
+	e = 1;
+      }
+  }
+  if (e)
+    abort ();
+  test (0, 3);
+  test (1, 3);
+  test (2, 1);
+  test (3, 1);
+  test (4, 4);
+  test (5, 5);
+  return 0;
+}
+
+int
+test3 (void)
+{
+  int e = 0, idx;
+
+#pragma omp parallel reduction(+:e)
+  {
+    long long i;
+    unsigned long long j;
+    #pragma omp for schedule(static) nowait
+    for (i = LLONG_MAX - 30001; LLONG_MAX - 10001 >= i; i += 10000)
+      {
+	check (i, LLONG_MAX - 30001, 0, 0)
+	check (i, LLONG_MAX - 20001, 0, 1)
+	check (i, LLONG_MAX - 10001, 0, 2)
+	e = 1;
+      }
+    #pragma omp for schedule(static) nowait
+    for (i = -LLONG_MAX + 30000; -LLONG_MAX + 10000 <= i; i -= 10000)
+      {
+	check (i, -LLONG_MAX + 30000, 1, 0)
+	check (i, -LLONG_MAX + 20000, 1, 1)
+	check (i, -LLONG_MAX + 10000, 1, 2)
+	e = 1;
+      }
+    #pragma omp for schedule(static) nowait
+    for (j = 20; LLONG_MAX - 70 >= j; j += LLONG_MAX + 50ULL)
+      {
+	check (j, 20, 2, 0)
+	e = 1;
+      }
+    #pragma omp for schedule(static) nowait
+    for (j = ULLONG_MAX - 3; LLONG_MAX + 70ULL <= j; j -= LLONG_MAX + 50ULL)
+      {
+	check (j, ULLONG_MAX - 3, 3, 0)
+	e = 1;
+      }
+    #pragma omp for schedule(static) nowait
+    for (j = LLONG_MAX - 20000ULL; LLONG_MAX + 10000ULL >= j; j += 10000ULL)
+      {
+	check (j, LLONG_MAX - 20000ULL, 4, 0)
+	check (j, LLONG_MAX - 10000ULL, 4, 1)
+	check (j, LLONG_MAX, 4, 2)
+	check (j, LLONG_MAX + 10000ULL, 4, 3)
+	e = 1;
+      }
+    #pragma omp for schedule(static) nowait
+    for (i = -3LL * INT_MAX - 20000LL; INT_MAX + 10000LL >= i; i += INT_MAX + 200LL)
+      {
+	check (i, -3LL * INT_MAX - 20000LL, 5, 0)
+	check (i, -2LL * INT_MAX - 20000LL + 200LL, 5, 1)
+	check (i, -INT_MAX - 20000LL + 400LL, 5, 2)
+	check (i, -20000LL + 600LL, 5, 3)
+	check (i, INT_MAX - 20000LL + 800LL, 5, 4)
+	e = 1;
+      }
+  }
+  if (e)
+    abort ();
+  test (0, 3);
+  test (1, 3);
+  test (2, 1);
+  test (3, 1);
+  test (4, 4);
+  test (5, 5);
+  return 0;
+}
+
+int
+test4 (void)
+{
+  int e = 0, idx;
+
+#pragma omp parallel reduction(+:e)
+  {
+    long long i;
+    unsigned long long j;
+    #pragma omp for schedule(static,1) nowait
+    for (i = LLONG_MAX - 30001; LLONG_MAX - 10001 >= i; i += 10000)
+      {
+	check (i, LLONG_MAX - 30001, 0, 0)
+	check (i, LLONG_MAX - 20001, 0, 1)
+	check (i, LLONG_MAX - 10001, 0, 2)
+	e = 1;
+      }
+    #pragma omp for schedule(static,1) nowait
+    for (i = -LLONG_MAX + 30000; -LLONG_MAX + 10000 <= i; i -= 10000)
+      {
+	check (i, -LLONG_MAX + 30000, 1, 0)
+	check (i, -LLONG_MAX + 20000, 1, 1)
+	check (i, -LLONG_MAX + 10000, 1, 2)
+	e = 1;
+      }
+    #pragma omp for schedule(static,1) nowait
+    for (j = 20; LLONG_MAX - 70 >= j; j += LLONG_MAX + 50ULL)
+      {
+	check (j, 20, 2, 0)
+	e = 1;
+      }
+    #pragma omp for schedule(static,1) nowait
+    for (j = ULLONG_MAX - 3; LLONG_MAX + 70ULL <= j; j -= LLONG_MAX + 50ULL)
+      {
+	check (j, ULLONG_MAX - 3, 3, 0)
+	e = 1;
+      }
+    #pragma omp for schedule(static,1) nowait
+    for (j = LLONG_MAX - 20000ULL; LLONG_MAX + 10000ULL >= j; j += 10000ULL)
+      {
+	check (j, LLONG_MAX - 20000ULL, 4, 0)
+	check (j, LLONG_MAX - 10000ULL, 4, 1)
+	check (j, LLONG_MAX, 4, 2)
+	check (j, LLONG_MAX + 10000ULL, 4, 3)
+	e = 1;
+      }
+    #pragma omp for schedule(static,1) nowait
+    for (i = -3LL * INT_MAX - 20000LL; INT_MAX + 10000LL >= i; i += INT_MAX + 200LL)
+      {
+	check (i, -3LL * INT_MAX - 20000LL, 5, 0)
+	check (i, -2LL * INT_MAX - 20000LL + 200LL, 5, 1)
+	check (i, -INT_MAX - 20000LL + 400LL, 5, 2)
+	check (i, -20000LL + 600LL, 5, 3)
+	check (i, INT_MAX - 20000LL + 800LL, 5, 4)
+	e = 1;
+      }
+  }
+  if (e)
+    abort ();
+  test (0, 3);
+  test (1, 3);
+  test (2, 1);
+  test (3, 1);
+  test (4, 4);
+  test (5, 5);
+  return 0;
+}
+
+int
+test5 (void)
+{
+  int e = 0, idx;
+
+#pragma omp parallel reduction(+:e)
+  {
+    long long i;
+    unsigned long long j;
+    #pragma omp for schedule(runtime) nowait
+    for (i = LLONG_MAX - 30001; LLONG_MAX - 10001 >= i; i += 10000)
+      {
+	check (i, LLONG_MAX - 30001, 0, 0)
+	check (i, LLONG_MAX - 20001, 0, 1)
+	check (i, LLONG_MAX - 10001, 0, 2)
+	e = 1;
+      }
+    #pragma omp for schedule(runtime) nowait
+    for (i = -LLONG_MAX + 30000; -LLONG_MAX + 10000 <= i; i -= 10000)
+      {
+	check (i, -LLONG_MAX + 30000, 1, 0)
+	check (i, -LLONG_MAX + 20000, 1, 1)
+	check (i, -LLONG_MAX + 10000, 1, 2)
+	e = 1;
+      }
+    #pragma omp for schedule(runtime) nowait
+    for (j = 20; LLONG_MAX - 70 >= j; j += LLONG_MAX + 50ULL)
+      {
+	check (j, 20, 2, 0)
+	e = 1;
+      }
+    #pragma omp for schedule(runtime) nowait
+    for (j = ULLONG_MAX - 3; LLONG_MAX + 70ULL <= j; j -= LLONG_MAX + 50ULL)
+      {
+	check (j, ULLONG_MAX - 3, 3, 0)
+	e = 1;
+      }
+    #pragma omp for schedule(runtime) nowait
+    for (j = LLONG_MAX - 20000ULL; LLONG_MAX + 10000ULL >= j; j += 10000ULL)
+      {
+	check (j, LLONG_MAX - 20000ULL, 4, 0)
+	check (j, LLONG_MAX - 10000ULL, 4, 1)
+	check (j, LLONG_MAX, 4, 2)
+	check (j, LLONG_MAX + 10000ULL, 4, 3)
+	e = 1;
+      }
+    #pragma omp for schedule(runtime) nowait
+    for (i = -3LL * INT_MAX - 20000LL; INT_MAX + 10000LL >= i; i += INT_MAX + 200LL)
+      {
+	check (i, -3LL * INT_MAX - 20000LL, 5, 0)
+	check (i, -2LL * INT_MAX - 20000LL + 200LL, 5, 1)
+	check (i, -INT_MAX - 20000LL + 400LL, 5, 2)
+	check (i, -20000LL + 600LL, 5, 3)
+	check (i, INT_MAX - 20000LL + 800LL, 5, 4)
+	e = 1;
+      }
+  }
+  if (e)
+    abort ();
+  test (0, 3);
+  test (1, 3);
+  test (2, 1);
+  test (3, 1);
+  test (4, 4);
+  test (5, 5);
+  return 0;
+}
+
+int
+main (void)
+{
+  if (2 * sizeof (int) != sizeof (long long))
+    return 0;
+  test1 ();
+  test2 ();
+  test3 ();
+  test4 ();
+  omp_set_schedule (omp_sched_static, 0);
+  test5 ();
+  omp_set_schedule (omp_sched_static, 3);
+  test5 ();
+  omp_set_schedule (omp_sched_dynamic, 5);
+  test5 ();
+  omp_set_schedule (omp_sched_guided, 2);
+  test5 ();
+  return 0;
+}
-- 
GitLab