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] Handle 'if' and 'num_threads' clauses


Adds handling for 'if' and 'num_threads' and some basic error
checking.  The new test in gcc.dg/gomp should start passing once
rth fixes the DEFAULT_CFLAGS problem.



	* c-parser.c (c_parser_pragma_omp_clause): Fix dangling if().
	(c_parser_pragma_omp_clause_if): Remove printf.
	Check that only one clause 'if' is specified.
	Call add_new_clause.
	(c_parser_pragma_omp_clause_num_threads): Remove printf.
	Check that only one clause 'num_threads' is specified.
	Call add_new_clause.
	* gimple-low.c (emit_num_threads_setup_code): New.
	(lower_gomp_parallel): Call it.
	Add new argument DATA.  Modify all callers.
	* tree-pretty-print.c (dump_generic_node): Handle
	GOMP_CLAUSE_IF and GOMP_CLAUSE_NUM_THREADS.
	* tree.def (GOMP_CLAUSE_IF, GOMP_CLAUSE_NUM_THREADS): Define.
	* tree.h (GOMP_IF_EXPR, GOMP_NUM_THREADS_EXPR): Define.


testsuite/

	* gcc.dg/gomp/omp-parallel-if.c: New test.

libgomp/

	* testsuite/libgomp.dg/omp-parallel-if.c: New test.

Index: gcc/c-parser.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-parser.c,v
retrieving revision 2.17.4.13
diff -d -u -p -r2.17.4.13 c-parser.c
--- gcc/c-parser.c	23 Sep 2005 04:32:19 -0000	2.17.4.13
+++ gcc/c-parser.c	23 Sep 2005 05:32:26 -0000
@@ -6801,7 +6801,7 @@ c_parser_pragma_omp_clause (c_parser *pa
     {
       result = PRAGMA_OMP_CLAUSE_IF;
     }
-  if (c_parser_next_token_is_keyword (parser, RID_DEFAULT))
+  else if (c_parser_next_token_is_keyword (parser, RID_DEFAULT))
     {
       result = PRAGMA_OMP_CLAUSE_DEFAULT;
     }
@@ -6992,13 +6992,18 @@ c_parser_pragma_omp_clause_firstprivate 
 static void
 c_parser_pragma_omp_clause_if (c_parser *parser)
 {
-  printf ("if: ");
-
   if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
     {
       tree t = c_parser_paren_condition (parser);
-      print_generic_expr (stdout, t, 0);
-      printf ("\n");
+      tree c;
+
+      /* At most one 'if' clause may appear in the directive.  */
+      for (c = curr_clause_set; c; c = TREE_CHAIN (c))
+	if (TREE_CODE (TREE_VALUE (c)) == GOMP_CLAUSE_IF)
+	  error ("at most one %<if%> clause may appear in a parallel "
+	         "directive");
+
+      add_new_clause (build (GOMP_CLAUSE_IF, NULL_TREE, t));
     }
   else
     {
@@ -7035,23 +7040,27 @@ c_parser_pragma_omp_clause_nowait (c_par
 static void
 c_parser_pragma_omp_clause_num_threads (c_parser *parser)
 {
-  printf ("num_threads: ");
-
   if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
     {
       tree t = c_parser_expression (parser).value;
 
-      if (TREE_CODE (TREE_TYPE (t)) == INTEGER_TYPE)
-	{
-	  print_generic_expr (stdout, t, 0);
-	}
+      if (!INTEGRAL_TYPE_P (TREE_TYPE (t)))
+	c_parser_error (parser, "expected integer expression");
       else
 	{
-	  c_parser_error (parser, "expected integer expression");
+	  tree c;
+
+	  /* At most one 'num_threads' clause may appear in the directive.  */
+	  for (c = curr_clause_set; c; c = TREE_CHAIN (c))
+	    if (TREE_CODE (TREE_VALUE (c)) == GOMP_CLAUSE_NUM_THREADS)
+	      error ("at most one %<num_threads%> clause may appear "
+		     "in a parallel directive");
+
+	  add_new_clause (build (GOMP_CLAUSE_NUM_THREADS, TREE_TYPE (t), t));
 	}
+
       c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
     }
-  printf ("\n");
 }
 
 /* OpenMP 2.5:
Index: gcc/gimple-low.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/gimple-low.c,v
retrieving revision 2.24.4.9
diff -d -u -p -r2.24.4.9 gimple-low.c
--- gcc/gimple-low.c	22 Sep 2005 14:30:48 -0000	2.24.4.9
+++ gcc/gimple-low.c	23 Sep 2005 05:32:26 -0000
@@ -683,12 +683,98 @@ emit_gomp_data_setup_code (tree_stmt_ite
 }
 
 
+/* Static emit code to specify the number of threads to use in the
+   runtime.
+
+   TSI points to where the code should be emitted.
+
+   RI_P points to the remap structure holding clause information.
+
+   DATA points to GIMPLE lowering information.
+
+   Returns the argument that should be passed to GOMP_parallel_start.  */
+
+static tree
+emit_num_threads_setup_code (tree_stmt_iterator *tsi, struct remap_info_d *ri_p,
+			     struct lower_data *data)
+{
+  tree val, cond, c;
+  tree clauses = ri_p->clauses;
+
+  /* By default, the value of NUM_THREADS is zero (selected at run
+     time) and there is no conditional.  */
+  cond = NULL_TREE;
+  val = integer_zero_node;
+
+  for (c = clauses; c; c = TREE_CHAIN (c))
+    {
+      tree clause = TREE_VALUE (c);
+
+      if (TREE_CODE (clause) == GOMP_CLAUSE_IF)
+	cond = GOMP_IF_EXPR (clause);
+      else if (TREE_CODE (clause) == GOMP_CLAUSE_NUM_THREADS)
+	val = GOMP_NUM_THREADS_EXPR (clause);
+    }
+
+  /* If we found either of 'if (expr)' or 'num_threads (expr)',
+     create a local variable and prepare a list of statements to be
+     inserted.  */
+  if (cond || val != integer_zero_node)
+    {
+      tree t;
+      tree num_threads = create_tmp_var (unsigned_type_node, ".num_threads");
+      tree stmt_list = alloc_stmt_list ();
+
+      if (cond)
+	{
+	  /* If we found the clause 'if (cond)', build the
+	     conditional:
+
+	     	if (cond)
+		  .num_threads = val
+		else
+		  .num_threads = 1  */
+	  t = build (COND_EXPR, void_type_node, cond, 
+		     build (MODIFY_EXPR, void_type_node, num_threads, val),
+		     build (MODIFY_EXPR, void_type_node, num_threads,
+			    integer_one_node));
+	  append_to_statement_list (t, &stmt_list);
+	}
+      else
+	{
+	  gcc_assert (val != integer_zero_node);
+
+	  /* Otherwise, if we found a num_threads clause with anything
+	     other than zero, assign that value to .num_threads:
+	     .num_threads = val  */
+	  t = build (MODIFY_EXPR, unsigned_type_node, num_threads, val);
+	  append_to_statement_list (t, &stmt_list);
+	}
+
+      /* Gimplify and lower the emitted code.  This is necessary
+	 mostly for COND and VAL, which can be arbitrary expressions.  */
+      push_gimplify_context ();
+      gimplify_stmt (&stmt_list);
+      pop_gimplify_context (NULL);
+      lower_stmt_body (stmt_list, data);
+
+      tsi_link_after (tsi, stmt_list, TSI_CONTINUE_LINKING);
+
+      return num_threads;
+    }
+
+  /* Otherwise, just return zero to specify that the number of threads
+     should be selected at runtime.  */
+  return integer_zero_node;
+}
+
+
 /* Lower the OpenMP parallel directive pointed by TSI.  Build a new
    function with the body of the pragma and emit the appropriate
    runtime call.  DATA contains locus and scope information for TSI.  */
 
 static void
-lower_gomp_parallel (tree_stmt_iterator *tsi)
+lower_gomp_parallel (tree_stmt_iterator *tsi, struct lower_data *data)
 {
   tree par_stmt, fn, call, args, num_threads, addr_data_arg;
   tree_stmt_iterator orig_tsi;
@@ -738,10 +824,12 @@ lower_gomp_parallel (tree_stmt_iterator 
   else
     addr_data_arg = null_pointer_node;
 
-  /* Emit GOMP_parallel_start (__gomp_fn.XXXX ...) to PRE_P.  FIXME,
-     num_threads should only be integer_zero_node if the clause
-     num_threads is not present.  */
-  num_threads = integer_zero_node;
+  /* Emit code to set up the number of threads to use according to the
+     IF and NUM_THREADS clauses.  If both are missing, set it to 0 so
+     that it is dynamically selected by the runtime.  */
+  num_threads = emit_num_threads_setup_code (tsi, ri_p, data);
+
+  /* Emit GOMP_parallel_start (__gomp_fn.XXXX ...).  */
   call = create_gomp_parallel_start (fn, addr_data_arg, num_threads);
   tsi_link_after (tsi, call, TSI_CONTINUE_LINKING);
 
@@ -1062,7 +1150,7 @@ lower_stmt (tree_stmt_iterator *tsi, str
       break;
 
     case GOMP_PARALLEL:
-      lower_gomp_parallel (tsi);
+      lower_gomp_parallel (tsi, data);
       break;
 
     case GOMP_FOR:
Index: tree-pretty-print.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-pretty-print.c,v
retrieving revision 2.61.4.6
diff -d -u -p -r2.61.4.6 tree-pretty-print.c
--- tree-pretty-print.c	20 Sep 2005 21:19:24 -0000	2.61.4.6
+++ tree-pretty-print.c	23 Sep 2005 05:51:58 -0000
@@ -1598,6 +1598,19 @@ dump_generic_node (pretty_printer *buffe
       pp_string (buffer, ")");
       break;
 
+    case GOMP_CLAUSE_IF:
+      pp_string (buffer, "if (");
+      dump_generic_node (buffer, GOMP_IF_EXPR (node), spc, flags, false);
+      pp_string (buffer, ")");
+      break;
+
+    case GOMP_CLAUSE_NUM_THREADS:
+      pp_string (buffer, "num_threads (");
+      dump_generic_node (buffer, GOMP_NUM_THREADS_EXPR (node), spc, flags,
+			 false);
+      pp_string (buffer, ")");
+      break;
+
     case REDUC_MAX_EXPR:
       pp_string (buffer, " REDUC_MAX_EXPR < ");
       dump_generic_node (buffer, TREE_OPERAND (node, 0), spc, flags, false);
Index: gcc/tree.def
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree.def,v
retrieving revision 1.116.4.7
diff -d -u -p -r1.116.4.7 tree.def
--- gcc/tree.def	20 Sep 2005 21:19:25 -0000	1.116.4.7
+++ gcc/tree.def	23 Sep 2005 05:32:27 -0000
@@ -1021,6 +1021,12 @@ DEFTREECODE (GOMP_CLAUSE_COPYIN, "copyin
 /* OpenMP clause: copyprivate (variable_list).  */
 DEFTREECODE (GOMP_CLAUSE_COPYPRIVATE, "copyprivate", tcc_expression, 1)
 
+/* OpenMP clause: if (scalar-expression).  */
+DEFTREECODE (GOMP_CLAUSE_IF, "if", tcc_expression, 1)
+
+/* OpenMP clause: num_threads (integer-expression).  */
+DEFTREECODE (GOMP_CLAUSE_NUM_THREADS, "num_threads", tcc_expression, 1)
+
 /* Reduction operations. 
    Operations that take a vector of elements and "reduce" it to a scalar
    result (e.g. summing the elements of the vector, finding the minimum over
Index: gcc/tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree.h,v
retrieving revision 1.735.4.8
diff -d -u -p -r1.735.4.8 tree.h
--- gcc/tree.h	22 Sep 2005 14:30:49 -0000	1.735.4.8
+++ gcc/tree.h	23 Sep 2005 05:32:27 -0000
@@ -1412,6 +1412,10 @@ struct tree_constructor GTY(())
   		TREE_OPERAND (GOMP_CLAUSE_COPYIN_CHECK (NODE), 0)
 #define GOMP_COPYPRIVATE_VARS(NODE)	\
   		TREE_OPERAND (GOMP_CLAUSE_COPYPRIVATE_CHECK (NODE), 0)
+#define GOMP_IF_EXPR(NODE)		\
+  		TREE_OPERAND (GOMP_CLAUSE_IF_CHECK (NODE), 0)
+#define GOMP_NUM_THREADS_EXPR(NODE)	\
+  		TREE_OPERAND (GOMP_CLAUSE_NUM_THREADS_CHECK (NODE), 0)
 
 
 struct tree_exp GTY(())
Index: gcc/testsuite/gcc.dg/gomp/omp-parallel-if.c
===================================================================
RCS file: gcc/testsuite/gcc.dg/gomp/omp-parallel-if.c
diff -N gcc/testsuite/gcc.dg/gomp/omp-parallel-if.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gcc/testsuite/gcc.dg/gomp/omp-parallel-if.c	23 Sep 2005 05:32:30 -0000
@@ -0,0 +1,31 @@
+/* { dg-do compile } */
+
+#include <omp.h>
+
+int
+foo (void)
+{
+  return 10;
+}
+
+main ()
+{
+  int A = 0;
+
+  /* Malformed uses of 'if' and 'num_threads'.  */
+  #pragma omp parallel if (foo () > 10) shared (A) if (foo () == 3)	/* { dg-error "at most one 'if'" } */
+    {
+      A = omp_get_num_threads ();
+    }
+
+  #pragma omp parallel if (foo () == 10) num_threads (3) shared (A) num_threads (20)	/* { dg-error "at most one 'num_threads'" } */
+    {
+      A = omp_get_num_threads ();
+    }
+
+  /* Valid uses of 'if' and 'num_threads'.  */
+  #pragma omp parallel if (foo () == 10) num_threads (foo ()) shared (A)
+    {
+      A = omp_get_num_threads ();
+    }
+}
Index: libgomp/testsuite/libgomp.dg/omp-parallel-if.c
===================================================================
RCS file: libgomp/testsuite/libgomp.dg/omp-parallel-if.c
diff -N libgomp/testsuite/libgomp.dg/omp-parallel-if.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ libgomp/testsuite/libgomp.dg/omp-parallel-if.c	23 Sep 2005 05:32:30 -0000
@@ -0,0 +1,40 @@
+#include <omp.h>
+
+extern void abort (void);
+
+int
+foo (void)
+{
+  return 10;
+}
+
+main ()
+{
+  int A = 0;
+
+  #pragma omp parallel if (foo () > 10) shared (A)
+    {
+      A = omp_get_num_threads ();
+    }
+
+  if (A != 1)
+    abort ();
+
+  #pragma omp parallel if (foo () == 10) num_threads (3) shared (A)
+    {
+      A = omp_get_num_threads ();
+    }
+
+  if (A != 3)
+    abort ();
+
+  #pragma omp parallel if (foo () == 10) num_threads (foo ()) shared (A)
+    {
+      A = omp_get_num_threads ();
+    }
+
+  if (A != 10)
+    abort ();
+
+  return 0;
+}


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