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


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

[gomp] Add some diagnostics


Now that I could fix all the merge problems that had rth
chuckling to himself, I can commit some minor diagnostics for
parallel loops.

I have no idea whether the messages we are emitting are properly
formatted or follow the accepted style for error messages.  Could
one of the FE folks take a look?  The recovery is to emit a
sequential loop if we see a malformed parallel loop, otherwise we
get confused down the line if we end up with a half finished loop
structure.

This also adds a small test with valid and malformed parallel
loops.



	* c-tree.h (c_finish_gomp_for): Declare
	* c-typeck.c (c_finish_gomp_for): New.
	* c-parser.c (c_parser_for_statement): Call it.  If the
	parallel loop was malformed, call c_finish_loop to emit a
	sequential loop.

testsuite/ChangeLog.gomp:

	* gcc.dg/gomp/omp-for-1.c: New test.

Index: c-parser.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-parser.c,v
retrieving revision 2.17.4.8
diff -d -u -p -r2.17.4.8 c-parser.c
--- c-parser.c	21 Sep 2005 23:44:45 -0000	2.17.4.8
+++ c-parser.c	22 Sep 2005 14:05:12 -0000
@@ -4174,8 +4174,14 @@ c_parser_for_statement (c_parser *parser
   if (!is_omp_for)
     c_finish_loop (loc, cond, incr, body, c_break_label, c_cont_label, true);
   else
-    add_stmt (build (GOMP_FOR, void_type_node, pop_omp_clauses (), init, cond,
-	             incr, body));
+    {
+      tree t = c_finish_gomp_for (init, cond, incr, body, pop_omp_clauses ());
+      if (t)
+	add_stmt (t);
+      else
+	c_finish_loop (loc, cond, incr, body, c_break_label, c_cont_label,
+		       true);
+    }
   add_stmt (c_end_compound_stmt (block, flag_isoc99));
   c_break_label = save_break;
   c_cont_label = save_cont;
Index: c-tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-tree.h,v
retrieving revision 1.203.4.3
diff -d -u -p -r1.203.4.3 c-tree.h
--- c-tree.h	21 Sep 2005 23:44:46 -0000	1.203.4.3
+++ c-tree.h	22 Sep 2005 14:05:12 -0000
@@ -574,6 +574,7 @@ extern tree c_finish_goto_ptr (tree);
 extern void c_begin_vm_scope (unsigned int);
 extern void c_end_vm_scope (unsigned int);
 extern tree c_expr_to_decl (tree, bool *, bool *, bool *);
+extern tree c_finish_gomp_for (tree, tree, tree, tree, tree);
 
 /* Set to 0 at beginning of a function definition, set to 1 if
    a return statement that specifies a return value is seen.  */
Index: c-typeck.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-typeck.c,v
retrieving revision 1.450.4.4
diff -d -u -p -r1.450.4.4 c-typeck.c
--- c-typeck.c	14 Sep 2005 12:43:07 -0000	1.450.4.4
+++ c-typeck.c	22 Sep 2005 14:05:14 -0000
@@ -8257,3 +8257,173 @@ c_expr_to_decl (tree expr, bool *tc ATTR
   else
     return expr;
 }
+
+
+/* Validate and emit code for the OpenMP directive #pragma omp for.
+   INIT, COND, INCR and BODY are the four basic elements of the loop
+   (initialization expression, controlling predicate, increment
+   expression and body of the loop).  CLAUSES is the set of data
+   sharing and copying clauses found at the start of the directive.  */
+
+tree
+c_finish_gomp_for (tree init, tree cond, tree incr, tree body, tree clauses)
+{
+  bool found;
+  tree t, loop_ix = NULL_TREE;
+
+  /* Validate the form of the loop.  It must be of the form (OpenMP
+     Public Draft v2.5)
+
+     	for (init-expr; var relop b; incr-expr)
+
+	init-expr	One of the following
+				var = lb
+				integer-type var = lb
+
+	incr-expr	One of the following
+				++var
+				var++
+				--var
+				var--
+				var += incr
+				var -= incr
+				var = var + incr
+				var = incr + var
+				var = var - incr
+
+	var		A signed integer variable.  If it was shared, 
+			it is implicitly made private.  It may only be
+			modified inside incr-expr.  After the loop its
+			value is indeterminate, unles it is marked
+			lastprivate.
+
+	relop		One of <, <=, > or >=
+
+	lb, b, incr	Loop invariant integer expressions.  There is
+			no synchronization during the evaluation of
+			these expressions.  Th order, frequency and
+			side-effects of these expressions are
+			unspecified.  */
+  if (cond == NULL_TREE)
+    {
+      error ("missing controlling predicate in %<omp for%> loop");
+      return NULL_TREE;
+    }
+  else
+    {
+      bool cond_ok = false;
+
+      if (TREE_CODE (cond) == LT_EXPR
+	  || TREE_CODE (cond) == LE_EXPR
+	  || TREE_CODE (cond) == GT_EXPR
+	  || TREE_CODE (cond) == GE_EXPR)
+	{
+	  loop_ix = TREE_OPERAND (cond, 0);
+	  if (DECL_P (loop_ix))
+	    cond_ok = true;
+	}
+
+      if (!cond_ok)
+	{
+	  error ("invalid controlling predicate in %<omp for%> loop");
+	  return NULL_TREE;
+	}
+    }
+
+  /* If we got to this point, we must have a loop index variable.  */
+  gcc_assert (loop_ix);
+
+  if (incr == NULL_TREE)
+    {
+      error ("missing increment expression in %<omp for%> loop");
+      return NULL_TREE;
+    }
+  else
+    {
+      bool incr_ok = false;
+      enum tree_code code = TREE_CODE (incr);
+
+      /* Check all the valid increment expressions: v++, v--, ++v, --v,
+	 v = v + incr, v = incr + v and v = v - incr.  */
+      if ((code == POSTINCREMENT_EXPR && TREE_OPERAND (incr, 0) == loop_ix)
+	  || (code == PREINCREMENT_EXPR && TREE_OPERAND (incr, 0) == loop_ix)
+	  || (code == POSTDECREMENT_EXPR && TREE_OPERAND (incr, 0) == loop_ix)
+	  || (code == PREDECREMENT_EXPR && TREE_OPERAND (incr, 0) == loop_ix)
+	  || (code == MODIFY_EXPR
+	      && TREE_CODE (TREE_OPERAND (incr, 1)) == PLUS_EXPR
+	      && (TREE_OPERAND (TREE_OPERAND (incr, 1), 0) == loop_ix
+		  || TREE_OPERAND (TREE_OPERAND (incr, 1), 1) == loop_ix))
+	  || (code == MODIFY_EXPR
+	      && TREE_CODE (TREE_OPERAND (incr, 1)) == MINUS_EXPR
+	      && TREE_OPERAND (TREE_OPERAND (incr, 1), 0) == loop_ix))
+	incr_ok = true;
+
+      if (!incr_ok)
+	{
+	  error ("invalid increment expression in %<omp for%> loop");
+	  return NULL_TREE;
+	}
+    }
+
+  if (init == NULL_TREE)
+    {
+      if (flag_isoc99)
+	{
+	  /* Only in C99 may the init expression be empty.  If the
+	     loop index variable has a DECL_INITIAL expression, use it
+	     to build the GOMP_FOR_INIT operand.  */
+	  if (DECL_INITIAL (loop_ix))
+	    init = build (MODIFY_EXPR, TREE_TYPE (loop_ix),
+			  loop_ix, DECL_INITIAL (loop_ix));
+	}
+
+      if (init == NULL_TREE)
+	{
+	  error ("missing initialization expression in %<omp for%> loop");
+	  return NULL_TREE;
+	}
+    }
+
+  /* The loop controlling variable is always private.  Add it to the
+     list of private clauses.  */
+  found = false;
+  for (t = clauses; t; t = TREE_CHAIN (t))
+    {
+      tree clause = TREE_VALUE (t);
+
+      if (TREE_CODE (clause) == GOMP_CLAUSE_PRIVATE)
+	{
+	  tree n;
+
+	  for (n = GOMP_PRIVATE_VARS (clause); n; n = TREE_CHAIN (n))
+	    {
+	      tree v = TREE_VALUE (n);
+	      if (v == loop_ix)
+		{
+		  found = true;
+		  break;
+		}
+	    }
+
+	  /* If LOOP_IX is not mentioned in a private clause, add it.  */
+	  if (!found)
+	    {
+	      GOMP_PRIVATE_VARS (clause) = 
+		tree_cons (NULL_TREE, loop_ix, GOMP_PRIVATE_VARS (clause));
+	      found = true;
+	      break;
+	    }
+	}
+    }
+
+  /* If we did not even have a private clause, add one.  */
+  if (!found)
+    clauses = tree_cons (NULL_TREE,
+			 build (GOMP_CLAUSE_PRIVATE,
+				NULL_TREE,
+				tree_cons (NULL_TREE, loop_ix, NULL_TREE)),
+			 clauses);
+
+  /* Build and return a GOMP_FOR tree.  */
+  return (build (GOMP_FOR, void_type_node, clauses, init, cond, incr, body));
+}
Index: testsuite/gcc.dg/gomp/omp-for-1.c
===================================================================
RCS file: testsuite/gcc.dg/gomp/omp-for-1.c
diff -N testsuite/gcc.dg/gomp/omp-for-1.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ testsuite/gcc.dg/gomp/omp-for-1.c	22 Sep 2005 14:05:17 -0000
@@ -0,0 +1,48 @@
+/* { dg-do compile } */
+
+void foo (int j, int k)
+{
+  int i;
+
+  /* Valid loops.  */
+  #pragma omp for
+  for (i = 0; i < 10; i++)
+    baz (i);
+
+  #pragma omp for
+  for (i = j; i <= 10; i+=4)
+    baz (i);
+
+  #pragma omp for
+  for (i = j; i > 0; i = i - 1)
+    baz (j);
+
+  #pragma omp for
+  for (i = j; i >= k; i--)
+    baz (i);
+
+  /* Malformed parallel loops.  */
+  #pragma omp for
+  i = 0;		/* { dg-error "for statement expected" } */
+  for ( ; i < 10; )
+    {
+      baz (i);
+      i++;
+    }
+
+  #pragma omp for
+  for (i = 0; ; i--)
+    {
+      if (i >= 10)
+	break;
+      baz (i);
+    }			/* { dg-error "missing controlling predicate" } */
+
+  #pragma omp for
+  for (i = 0; i < 10 && j > 4; i-=3)
+    baz (i);		/* { dg-error "invalid controlling predicate" } */
+
+  #pragma omp for
+  for (i = 0; i < 10; i-=3, j+=2)
+    baz (i);		/* { dg-error "invalid increment expression" } */
+}


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