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] Some more progress on OMP_TASK support


Hi!

The following patch allows us to generate simple #pragma omp task
constructs.  Data sharing rules are for the time being the same as for
#pragma omp parallel, which in many cases is the same, but some things
are firstprivate for tasks while shared for parallels by default, will do
that later.

The added testcase shows a problem with ICVs, the failing test is commented
out so far.  To fix that I believe GOMP_parallel_start* should create
a new task always and GOMP_parallel_end free it.

Tested on x86_64-linux, committed to gomp-3_0-branch.

2007-11-30  Jakub Jelinek  <jakub@redhat.com>

	* builtin-types.def (BT_FN_VOID_OMPFN_PTR_BOOL_BOOL): New.
	* omp-builtins.def (BUILT_IN_GOMP_TASK): New builtin.
	* gimplify.c (omp_region_type): New enum.
	(struct gimplify_omp_ctx): Remove is_parallel and is_combined_parallel
	fields, add region_type.
	(new_omp_context): Take region_type as argument instead of is_parallel
	and is_combined_parallel.
	(gimple_add_tmp_var, omp_firstprivatize_variable, omp_notice_variable,
	omp_is_private, omp_check_private): Adjust ctx->is_parallel and
	ctx->is_combined_parallel checks.
	(gimplify_scan_omp_clauses): Take region_type as last argument instead
	of in_parallel and in_combined_parallel.
	(gimplify_omp_parallel, gimplify_omp_for, gimplify_omp_workshare): Adjust
	callers.
	(gimplify_omp_task): New function.
	(gimplify_expr): Handle OMP_TASK.
	* tree-inline.c (estimate_num_insns_1): Handle OMP_TASK.
	* tree.h (OMP_TASKREG_CHECK, OMP_TASKREG_BODY, OMP_TASKREG_CLAUSES,
	OMP_TASKREG_FN, OMP_TASKREG_DATA_ARG): Define.
	* omp-low.c (parallel_nesting_level): Rename to...
	(taskreg_nesting_level): ... this.
	(is_taskreg_ctx): New function.
	(build_outer_var_ref, omp_copy_decl, scan_sharing_clauses,
	scan_sharing_clauses): Use is_taskreg_ctx instead of is_parallel_ctx.
	(scan_omp_parallel, execute_lower_omp): Rename parallel_nesting_level to
	taskreg_nesting_level.
	(scan_omp_1): Likewise.  Handle OMP_TASK.
	(scan_omp_task): New function.
	(expand_task_call): New function.
	(expand_omp_parallel): Rename to...
	(expand_omp_taskreg): ... this.  Use OMP_TASKREG_* macros where needed.
	Call omp_task_call for OMP_TASK regions.
	(expand_omp): Adjust caller, handle OMP_TASK.
	(lower_omp_parallel): Rename to...
	(lower_omp_taskreg): ... this.  Use OMP_TASKREG_* macros where needed.
	(lower_omp_1): Adjust caller, handle OMP_TASK.
	(diagnose_sb_1, diagnose_sb_2): Handle OMP_TASK.
	* tree-cfg.c (make_edges): Handle OMP_TASK.
fortran/
	* types.def (BT_FN_VOID_OMPFN_PTR_BOOL_BOOL): New.
libgomp/
	* testsuite/libgomp.c/icv-1.c: New test.

--- gcc/fortran/types.def.jj	2007-11-14 12:41:21.000000000 +0100
+++ gcc/fortran/types.def	2007-11-30 09:45:34.000000000 +0100
@@ -116,6 +116,8 @@ DEF_FUNCTION_TYPE_4 (BT_FN_VOID_OMPFN_PT
                      BT_VOID, BT_PTR_FN_VOID_PTR, BT_PTR, BT_UINT, BT_UINT)
 DEF_FUNCTION_TYPE_4 (BT_FN_VOID_PTR_WORD_WORD_PTR,
 		     BT_VOID, BT_PTR, BT_WORD, BT_WORD, BT_PTR)
+DEF_FUNCTION_TYPE_4 (BT_FN_VOID_OMPFN_PTR_BOOL_BOOL, BT_VOID,
+		     BT_PTR_FN_VOID_PTR, BT_PTR, BT_BOOL, BT_BOOL)
 
 DEF_FUNCTION_TYPE_5 (BT_FN_BOOL_LONG_LONG_LONG_LONGPTR_LONGPTR,
                      BT_BOOL, BT_LONG, BT_LONG, BT_LONG,
--- gcc/builtin-types.def.jj	2007-11-14 12:47:19.000000000 +0100
+++ gcc/builtin-types.def	2007-11-30 09:08:22.000000000 +0100
@@ -393,6 +393,8 @@ DEF_FUNCTION_TYPE_4 (BT_FN_VOID_OMPFN_PT
 		     BT_VOID, BT_PTR_FN_VOID_PTR, BT_PTR, BT_UINT, BT_UINT)
 DEF_FUNCTION_TYPE_4 (BT_FN_VOID_PTR_WORD_WORD_PTR,
 		     BT_VOID, BT_PTR, BT_WORD, BT_WORD, BT_PTR)
+DEF_FUNCTION_TYPE_4 (BT_FN_VOID_OMPFN_PTR_BOOL_BOOL, BT_VOID, BT_PTR_FN_VOID_PTR,
+		     BT_PTR, BT_BOOL, BT_BOOL)
 
 DEF_FUNCTION_TYPE_5 (BT_FN_INT_STRING_INT_SIZE_CONST_STRING_VALIST_ARG,
 		     BT_INT, BT_STRING, BT_INT, BT_SIZE, BT_CONST_STRING,
--- gcc/omp-builtins.def.jj	2007-11-14 16:02:08.000000000 +0100
+++ gcc/omp-builtins.def	2007-11-30 09:42:58.000000000 +0100
@@ -150,6 +150,8 @@ DEF_GOMP_BUILTIN (BUILT_IN_GOMP_PARALLEL
 		  BT_FN_VOID_OMPFN_PTR_UINT, ATTR_NOTHROW_LIST)
 DEF_GOMP_BUILTIN (BUILT_IN_GOMP_PARALLEL_END, "GOMP_parallel_end",
 		  BT_FN_VOID, ATTR_NOTHROW_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_TASK, "GOMP_task",
+		  BT_FN_VOID_OMPFN_PTR_BOOL_BOOL, ATTR_NOTHROW_LIST)
 DEF_GOMP_BUILTIN (BUILT_IN_GOMP_SECTIONS_START, "GOMP_sections_start",
 		  BT_FN_UINT_UINT, ATTR_NOTHROW_LIST)
 DEF_GOMP_BUILTIN (BUILT_IN_GOMP_SECTIONS_NEXT, "GOMP_sections_next",
--- gcc/gimplify.c.jj	2007-11-14 17:33:47.000000000 +0100
+++ gcc/gimplify.c	2007-11-30 09:02:16.000000000 +0100
@@ -66,6 +66,14 @@ enum gimplify_omp_var_data
 			   | GOVD_LASTPRIVATE | GOVD_REDUCTION | GOVD_LOCAL)
 };
 
+enum omp_region_type
+{
+  ORT_WORKSHARE = 0,
+  ORT_TASK = 1,
+  ORT_PARALLEL = 2,
+  ORT_COMBINED_PARALLEL = 3
+};
+
 struct gimplify_omp_ctx
 {
   struct gimplify_omp_ctx *outer_context;
@@ -73,8 +81,7 @@ struct gimplify_omp_ctx
   struct pointer_set_t *privatized_types;
   location_t location;
   enum omp_clause_default_kind default_kind;
-  bool is_parallel;
-  bool is_combined_parallel;
+  enum omp_region_type region_type;
 };
 
 struct gimplify_ctx
@@ -269,7 +276,7 @@ splay_tree_compare_decl_uid (splay_tree_
 /* Create a new omp construct that deals with variable remapping.  */
 
 static struct gimplify_omp_ctx *
-new_omp_context (bool is_parallel, bool is_combined_parallel)
+new_omp_context (enum omp_region_type region_type)
 {
   struct gimplify_omp_ctx *c;
 
@@ -278,8 +285,7 @@ new_omp_context (bool is_parallel, bool 
   c->variables = splay_tree_new (splay_tree_compare_decl_uid, 0, 0);
   c->privatized_types = pointer_set_create ();
   c->location = input_location;
-  c->is_parallel = is_parallel;
-  c->is_combined_parallel = is_combined_parallel;
+  c->region_type = region_type;
   c->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
 
   return c;
@@ -746,7 +752,7 @@ gimple_add_tmp_var (tree tmp)
       if (gimplify_omp_ctxp)
 	{
 	  struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp;
-	  while (ctx && !ctx->is_parallel)
+	  while (ctx && ctx->region_type == ORT_WORKSHARE)
 	    ctx = ctx->outer_context;
 	  if (ctx)
 	    omp_add_variable (ctx, tmp, GOVD_LOCAL | GOVD_SEEN);
@@ -4532,7 +4538,7 @@ omp_firstprivatize_variable (struct gimp
 	  else
 	    return;
 	}
-      else if (ctx->is_parallel)
+      else if (ctx->region_type != ORT_WORKSHARE)
 	omp_add_variable (ctx, decl, GOVD_FIRSTPRIVATE);
 
       ctx = ctx->outer_context;
@@ -4726,7 +4732,7 @@ omp_notice_variable (struct gimplify_omp
     {
       enum omp_clause_default_kind default_kind, kind;
 
-      if (!ctx->is_parallel)
+      if (ctx->region_type == ORT_WORKSHARE)
 	goto do_outer;
 
       /* ??? Some compiler-generated variables (like SAVE_EXPRs) could be
@@ -4806,7 +4812,7 @@ omp_is_private (struct gimplify_omp_ctx 
 	}
       else if ((n->value & GOVD_EXPLICIT) != 0
 	       && (ctx == gimplify_omp_ctxp
-		   || (ctx->is_combined_parallel
+		   || (ctx->region_type == ORT_COMBINED_PARALLEL
 		       && gimplify_omp_ctxp->outer_context == ctx)))
 	{
 	  if ((n->value & GOVD_FIRSTPRIVATE) != 0)
@@ -4819,7 +4825,7 @@ omp_is_private (struct gimplify_omp_ctx 
       return true;
     }
 
-  if (ctx->is_parallel)
+  if (ctx->region_type != ORT_WORKSHARE)
     return false;
   else if (ctx->outer_context)
     return omp_is_private (ctx->outer_context, decl);
@@ -4848,7 +4854,7 @@ omp_check_private (struct gimplify_omp_c
       if (n != NULL)
 	return (n->value & GOVD_SHARED) == 0;
     }
-  while (!ctx->is_parallel);
+  while (ctx->region_type == ORT_WORKSHARE);
   return false;
 }
 
@@ -4856,13 +4862,13 @@ omp_check_private (struct gimplify_omp_c
    and previous omp contexts.  */
 
 static void
-gimplify_scan_omp_clauses (tree *list_p, tree *pre_p, bool in_parallel,
-			   bool in_combined_parallel)
+gimplify_scan_omp_clauses (tree *list_p, tree *pre_p,
+			   enum omp_region_type region_type)
 {
   struct gimplify_omp_ctx *ctx, *outer_ctx;
   tree c;
 
-  ctx = new_omp_context (in_parallel, in_combined_parallel);
+  ctx = new_omp_context (region_type);
   outer_ctx = ctx->outer_context;
 
   while ((c = *list_p) != NULL)
@@ -4934,7 +4940,7 @@ gimplify_scan_omp_clauses (tree *list_p,
 	  if (outer_ctx)
 	    omp_notice_variable (outer_ctx, decl, true);
 	  if (check_non_private
-	      && !in_parallel
+	      && region_type == ORT_WORKSHARE
 	      && omp_check_private (ctx, decl))
 	    {
 	      error ("%s variable %qs is private in outer context",
@@ -5126,8 +5132,10 @@ gimplify_omp_parallel (tree *expr_p, tre
 {
   tree expr = *expr_p;
 
-  gimplify_scan_omp_clauses (&OMP_PARALLEL_CLAUSES (expr), pre_p, true,
-			     OMP_PARALLEL_COMBINED (expr));
+  gimplify_scan_omp_clauses (&OMP_PARALLEL_CLAUSES (expr), pre_p,
+			     OMP_PARALLEL_COMBINED (expr)
+			     ? ORT_COMBINED_PARALLEL
+			     : ORT_PARALLEL);
 
   push_gimplify_context ();
 
@@ -5143,6 +5151,32 @@ gimplify_omp_parallel (tree *expr_p, tre
   return GS_ALL_DONE;
 }
 
+/* Gimplify the contents of an OMP_TASK statement.  This involves
+   gimplification of the body, as well as scanning the body for used
+   variables.  We need to do this scan now, because variable-sized
+   decls will be decomposed during gimplification.  */
+
+static enum gimplify_status
+gimplify_omp_task (tree *expr_p, tree *pre_p)
+{
+  tree expr = *expr_p;
+
+  gimplify_scan_omp_clauses (&OMP_TASK_CLAUSES (expr), pre_p, ORT_TASK);
+
+  push_gimplify_context ();
+
+  gimplify_stmt (&OMP_TASK_BODY (expr));
+
+  if (TREE_CODE (OMP_TASK_BODY (expr)) == BIND_EXPR)
+    pop_gimplify_context (OMP_TASK_BODY (expr));
+  else
+    pop_gimplify_context (NULL_TREE);
+
+  gimplify_adjust_omp_clauses (&OMP_TASK_CLAUSES (expr));
+
+  return GS_ALL_DONE;
+}
+
 /* Gimplify the gross structure of an OMP_FOR statement.  */
 
 static enum gimplify_status
@@ -5154,7 +5188,8 @@ gimplify_omp_for (tree *expr_p, tree *pr
 
   for_stmt = *expr_p;
 
-  gimplify_scan_omp_clauses (&OMP_FOR_CLAUSES (for_stmt), pre_p, false, false);
+  gimplify_scan_omp_clauses (&OMP_FOR_CLAUSES (for_stmt), pre_p,
+			     ORT_WORKSHARE);
 
   t = OMP_FOR_INIT (for_stmt);
   gcc_assert (TREE_CODE (t) == MODIFY_EXPR
@@ -5270,7 +5305,7 @@ gimplify_omp_workshare (tree *expr_p, tr
 {
   tree stmt = *expr_p;
 
-  gimplify_scan_omp_clauses (&OMP_CLAUSES (stmt), pre_p, false, false);
+  gimplify_scan_omp_clauses (&OMP_CLAUSES (stmt), pre_p, ORT_WORKSHARE);
   gimplify_to_stmt_list (&OMP_BODY (stmt));
   gimplify_adjust_omp_clauses (&OMP_CLAUSES (stmt));
 
@@ -5841,6 +5876,10 @@ gimplify_expr (tree *expr_p, tree *pre_p
 	  ret = gimplify_omp_parallel (expr_p, pre_p);
 	  break;
 
+	case OMP_TASK:
+	  ret = gimplify_omp_task (expr_p, pre_p);
+	  break;
+
 	case OMP_FOR:
 	  ret = gimplify_omp_for (expr_p, pre_p);
 	  break;
--- gcc/tree-inline.c.jj	2007-11-14 14:47:35.000000000 +0100
+++ gcc/tree-inline.c	2007-11-30 12:42:49.000000000 +0100
@@ -2395,6 +2395,7 @@ estimate_num_insns_1 (tree *tp, int *wal
       }
 
     case OMP_PARALLEL:
+    case OMP_TASK:
     case OMP_FOR:
     case OMP_SECTIONS:
     case OMP_SINGLE:
--- gcc/tree.h.jj	2007-11-14 14:30:29.000000000 +0100
+++ gcc/tree.h	2007-11-30 09:18:46.000000000 +0100
@@ -1747,6 +1747,12 @@ struct tree_constructor GTY(())
 #define OMP_TASK_FN(NODE)	   TREE_OPERAND (OMP_TASK_CHECK (NODE), 2)
 #define OMP_TASK_DATA_ARG(NODE)	   TREE_OPERAND (OMP_TASK_CHECK (NODE), 3)
 
+#define OMP_TASKREG_CHECK(NODE)	  TREE_RANGE_CHECK (NODE, OMP_PARALLEL, OMP_TASK)
+#define OMP_TASKREG_BODY(NODE)    TREE_OPERAND (OMP_TASKREG_CHECK (NODE), 0)
+#define OMP_TASKREG_CLAUSES(NODE) TREE_OPERAND (OMP_TASKREG_CHECK (NODE), 1)
+#define OMP_TASKREG_FN(NODE) TREE_OPERAND (OMP_TASKREG_CHECK (NODE), 2)
+#define OMP_TASKREG_DATA_ARG(NODE) TREE_OPERAND (OMP_TASKREG_CHECK (NODE), 3)
+
 #define OMP_FOR_BODY(NODE)	   TREE_OPERAND (OMP_FOR_CHECK (NODE), 0)
 #define OMP_FOR_CLAUSES(NODE)	   TREE_OPERAND (OMP_FOR_CHECK (NODE), 1)
 #define OMP_FOR_INIT(NODE)	   TREE_OPERAND (OMP_FOR_CHECK (NODE), 2)
--- gcc/omp-low.c.jj	2007-11-14 17:39:24.000000000 +0100
+++ gcc/omp-low.c	2007-11-30 12:48:35.000000000 +0100
@@ -108,7 +108,7 @@ struct omp_for_data
 
 
 static splay_tree all_contexts;
-static int parallel_nesting_level;
+static int taskreg_nesting_level;
 struct omp_region *root_omp_region;
 
 static void scan_omp (tree *, omp_context *);
@@ -137,6 +137,16 @@ is_parallel_ctx (omp_context *ctx)
 }
 
 
+/* Return true if CTX is for an omp parallel or omp task.  */
+
+static inline bool
+is_taskreg_ctx (omp_context *ctx)
+{
+  return TREE_CODE (ctx->stmt) == OMP_PARALLEL
+	 || TREE_CODE (ctx->stmt) == OMP_TASK;
+}
+
+
 /* Return true if REGION is a combined parallel+workshare region.  */
 
 static inline bool
@@ -593,7 +603,7 @@ build_outer_var_ref (tree var, omp_conte
       x = build_outer_var_ref (x, ctx);
       x = build_fold_indirect_ref (x);
     }
-  else if (is_parallel_ctx (ctx))
+  else if (is_taskreg_ctx (ctx))
     {
       bool by_ref = use_pointer_for_field (var, false);
       x = build_receiver_ref (var, by_ref, ctx);
@@ -711,7 +721,7 @@ omp_copy_decl (tree var, copy_body_data 
       return new_var;
     }
 
-  while (!is_parallel_ctx (ctx))
+  while (!is_taskreg_ctx (ctx))
     {
       ctx = ctx->outer;
       if (ctx == NULL)
@@ -962,7 +972,7 @@ scan_sharing_clauses (tree clauses, omp_
 	  break;
 
 	case OMP_CLAUSE_SHARED:
-	  gcc_assert (is_parallel_ctx (ctx));
+	  gcc_assert (is_taskreg_ctx (ctx));
 	  decl = OMP_CLAUSE_DECL (c);
 	  gcc_assert (!is_variable_sized (decl));
 	  by_ref = use_pointer_for_field (decl, true);
@@ -996,7 +1006,7 @@ scan_sharing_clauses (tree clauses, omp_
 	do_private:
 	  if (is_variable_sized (decl))
 	    break;
-	  else if (is_parallel_ctx (ctx)
+	  else if (is_taskreg_ctx (ctx)
 		   && ! is_global_var (maybe_lookup_decl_in_outer_ctx (decl,
 								       ctx)))
 	    {
@@ -1188,7 +1198,7 @@ scan_omp_parallel (tree *stmt_p, omp_con
     }
 
   ctx = new_omp_context (*stmt_p, outer_ctx);
-  if (parallel_nesting_level > 1)
+  if (taskreg_nesting_level > 1)
     ctx->is_nested = true;
   ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
   ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
@@ -1211,6 +1221,46 @@ scan_omp_parallel (tree *stmt_p, omp_con
     }
 }
 
+/* Scan an OpenMP task directive.  */
+
+static void
+scan_omp_task (tree *stmt_p, omp_context *outer_ctx)
+{
+  omp_context *ctx;
+  tree name;
+
+  /* Ignore task directives with empty bodies.  */
+  if (optimize > 0
+      && empty_body_p (OMP_TASK_BODY (*stmt_p)))
+    {
+      *stmt_p = build_empty_stmt ();
+      return;
+    }
+
+  ctx = new_omp_context (*stmt_p, outer_ctx);
+  if (taskreg_nesting_level > 1)
+    ctx->is_nested = true;
+  ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
+  ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
+  ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
+  name = create_tmp_var_name (".omp_data_s");
+  name = build_decl (TYPE_DECL, name, ctx->record_type);
+  TYPE_NAME (ctx->record_type) = name;
+  create_omp_child_function (ctx);
+  OMP_TASK_FN (*stmt_p) = ctx->cb.dst_fn;
+
+  scan_sharing_clauses (OMP_TASK_CLAUSES (*stmt_p), ctx);
+  scan_omp (&OMP_TASK_BODY (*stmt_p), ctx);
+
+  if (TYPE_FIELDS (ctx->record_type) == NULL)
+    ctx->record_type = ctx->receiver_decl = NULL;
+  else
+    {
+      layout_type (ctx->record_type);
+      fixup_child_record_type (ctx);
+    }
+}
+
 
 /* Scan an OpenMP loop directive.  */
 
@@ -1370,9 +1420,15 @@ scan_omp_1 (tree *tp, int *walk_subtrees
   switch (TREE_CODE (t))
     {
     case OMP_PARALLEL:
-      parallel_nesting_level++;
+      taskreg_nesting_level++;
       scan_omp_parallel (tp, ctx);
-      parallel_nesting_level--;
+      taskreg_nesting_level--;
+      break;
+
+    case OMP_TASK:
+      taskreg_nesting_level++;
+      scan_omp_task (tp, ctx);
+      taskreg_nesting_level--;
       break;
 
     case OMP_FOR:
@@ -2328,6 +2384,42 @@ expand_parallel_call (struct omp_region 
 }
 
 
+/* Build the function call to GOMP_task to actually
+   generate the task operation.  BB is the block where to insert the code.  */
+
+static void
+expand_task_call (basic_block bb, tree entry_stmt)
+{
+  tree t, t1, t2, untied, cond, c, clauses;
+  block_stmt_iterator si;
+
+  clauses = OMP_TASK_CLAUSES (entry_stmt);
+
+  c = find_omp_clause (clauses, OMP_CLAUSE_IF);
+  if (c)
+    cond = gimple_boolify (OMP_CLAUSE_IF_EXPR (c));
+  else
+    cond = boolean_true_node;
+
+  c = find_omp_clause (clauses, OMP_CLAUSE_UNTIED);
+  untied = c ? boolean_true_node : boolean_false_node;
+
+  si = bsi_last (bb);
+  t = OMP_TASK_DATA_ARG (entry_stmt);
+  if (t == NULL)
+    t1 = null_pointer_node;
+  else
+    t1 = build_fold_addr_expr (t);
+  t2 = build_fold_addr_expr (OMP_TASK_FN (entry_stmt));
+
+  t = build_call_expr (built_in_decls[BUILT_IN_GOMP_TASK], 4, t2, t1,
+		       cond, untied);
+
+  force_gimple_operand_bsi (&si, t, true, NULL_TREE,
+			    false, BSI_CONTINUE_LINKING);
+}
+
+
 /* If exceptions are enabled, wrap *STMT_P in a MUST_NOT_THROW catch
    handler.  This prevents programs from violating the structured
    block semantics with throws.  */
@@ -2437,10 +2529,10 @@ remove_exit_barriers (struct omp_region 
     }
 }
 
-/* Expand the OpenMP parallel directive starting at REGION.  */
+/* Expand the OpenMP parallel or task directive starting at REGION.  */
 
 static void
-expand_omp_parallel (struct omp_region *region)
+expand_omp_taskreg (struct omp_region *region)
 {
   basic_block entry_bb, exit_bb, new_bb;
   struct function *child_cfun;
@@ -2450,7 +2542,7 @@ expand_omp_parallel (struct omp_region *
   edge e;
 
   entry_stmt = last_stmt (region->entry);
-  child_fn = OMP_PARALLEL_FN (entry_stmt);
+  child_fn = OMP_TASKREG_FN (entry_stmt);
   child_cfun = DECL_STRUCT_FUNCTION (child_fn);
 
   entry_bb = region->entry;
@@ -2472,7 +2564,8 @@ expand_omp_parallel (struct omp_region *
       entry_succ_e = single_succ_edge (entry_bb);
 
       si = bsi_last (entry_bb);
-      gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_PARALLEL);
+      gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_PARALLEL
+		  || TREE_CODE (bsi_stmt (si)) == OMP_TASK);
       bsi_remove (&si, true);
 
       new_bb = entry_bb;
@@ -2498,7 +2591,7 @@ expand_omp_parallel (struct omp_region *
 	 a function call that has been inlined, the original PARM_DECL
 	 .OMP_DATA_I may have been converted into a different local
 	 variable.  In which case, we need to keep the assignment.  */
-      if (OMP_PARALLEL_DATA_ARG (entry_stmt))
+      if (OMP_TASKREG_DATA_ARG (entry_stmt))
 	{
 	  basic_block entry_succ_bb = single_succ (entry_bb);
 	  block_stmt_iterator si;
@@ -2517,7 +2610,7 @@ expand_omp_parallel (struct omp_region *
 	      STRIP_NOPS (arg);
 	      if (TREE_CODE (arg) == ADDR_EXPR
 		  && TREE_OPERAND (arg, 0)
-		     == OMP_PARALLEL_DATA_ARG (entry_stmt))
+		     == OMP_TASKREG_DATA_ARG (entry_stmt))
 		{
 		  parcopy_stmt = stmt;
 		  break;
@@ -2556,11 +2649,12 @@ expand_omp_parallel (struct omp_region *
       for (t = DECL_ARGUMENTS (child_fn); t; t = TREE_CHAIN (t))
 	DECL_CONTEXT (t) = child_fn;
 
-      /* Split ENTRY_BB at OMP_PARALLEL so that it can be moved to the
-	 child function.  */
+      /* Split ENTRY_BB at OMP_PARALLEL or OMP_TASK, so that it can be
+	 moved to the child function.  */
       si = bsi_last (entry_bb);
       t = bsi_stmt (si);
-      gcc_assert (t && TREE_CODE (t) == OMP_PARALLEL);
+      gcc_assert (t && (TREE_CODE (t) == OMP_PARALLEL
+			|| TREE_CODE (t) == OMP_TASK));
       bsi_remove (&si, true);
       e = split_block (entry_bb, t);
       entry_bb = e->dest;
@@ -2604,7 +2698,10 @@ expand_omp_parallel (struct omp_region *
     }
   
   /* Emit a library call to launch the children threads.  */
-  expand_parallel_call (region, new_bb, entry_stmt, ws_args);
+  if (TREE_CODE (entry_stmt) == OMP_PARALLEL)
+    expand_parallel_call (region, new_bb, entry_stmt, ws_args);
+  else
+    expand_task_call (new_bb, entry_stmt);
   update_ssa (TODO_update_ssa_only_virtuals);
 }
 
@@ -3912,7 +4009,11 @@ expand_omp (struct omp_region *region)
       switch (region->type)
 	{
 	case OMP_PARALLEL:
-	  expand_omp_parallel (region);
+	  expand_omp_taskreg (region);
+	  break;
+
+	case OMP_TASK:
+	  expand_omp_taskreg (region);
 	  break;
 
 	case OMP_FOR:
@@ -4704,11 +4805,11 @@ check_combined_parallel (tree *tp, int *
   return NULL;
 }
 
-/* Lower the OpenMP parallel directive in *STMT_P.  CTX holds context
+/* Lower the OpenMP parallel or task directive in *STMT_P.  CTX holds context
    information for the directive.  */
 
 static void
-lower_omp_parallel (tree *stmt_p, omp_context *ctx)
+lower_omp_taskreg (tree *stmt_p, omp_context *ctx)
 {
   tree clauses, par_bind, par_body, new_body, bind;
   tree olist, ilist, par_olist, par_ilist;
@@ -4716,11 +4817,11 @@ lower_omp_parallel (tree *stmt_p, omp_co
 
   stmt = *stmt_p;
 
-  clauses = OMP_PARALLEL_CLAUSES (stmt);
-  par_bind = OMP_PARALLEL_BODY (stmt);
+  clauses = OMP_TASKREG_CLAUSES (stmt);
+  par_bind = OMP_TASKREG_BODY (stmt);
   par_body = BIND_EXPR_BODY (par_bind);
   child_fn = ctx->cb.dst_fn;
-  if (!OMP_PARALLEL_COMBINED (stmt))
+  if (TREE_CODE (stmt) == OMP_PARALLEL && !OMP_PARALLEL_COMBINED (stmt))
     {
       struct walk_stmt_info wi;
       int ws_num = 0;
@@ -4740,7 +4841,8 @@ lower_omp_parallel (tree *stmt_p, omp_co
   par_ilist = NULL_TREE;
   lower_rec_input_clauses (clauses, &par_ilist, &par_olist, ctx);
   lower_omp (&par_body, ctx);
-  lower_reduction_clauses (clauses, &par_olist, ctx);
+  if (TREE_CODE (stmt) == OMP_PARALLEL)
+    lower_reduction_clauses (clauses, &par_olist, ctx);
 
   /* Declare all the variables created by mapping and the variables
      declared in the scope of the parallel body.  */
@@ -4750,7 +4852,7 @@ lower_omp_parallel (tree *stmt_p, omp_co
   if (ctx->record_type)
     {
       ctx->sender_decl = create_tmp_var (ctx->record_type, ".omp_data_o");
-      OMP_PARALLEL_DATA_ARG (stmt) = ctx->sender_decl;
+      OMP_TASKREG_DATA_ARG (stmt) = ctx->sender_decl;
     }
 
   olist = NULL_TREE;
@@ -4759,7 +4861,7 @@ lower_omp_parallel (tree *stmt_p, omp_co
   lower_send_shared_vars (&ilist, &olist, ctx);
 
   /* Once all the expansions are done, sequence all the different
-     fragments inside OMP_PARALLEL_BODY.  */
+     fragments inside OMP_TASKREG_BODY.  */
   bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
   append_to_statement_list (ilist, &BIND_EXPR_BODY (bind));
 
@@ -4780,7 +4882,7 @@ lower_omp_parallel (tree *stmt_p, omp_co
   maybe_catch_exception (&new_body);
   t = make_node (OMP_RETURN);
   append_to_statement_list (t, &new_body);
-  OMP_PARALLEL_BODY (stmt) = new_body;
+  OMP_TASKREG_BODY (stmt) = new_body;
 
   append_to_statement_list (stmt, &BIND_EXPR_BODY (bind));
   append_to_statement_list (olist, &BIND_EXPR_BODY (bind));
@@ -4868,8 +4970,9 @@ lower_omp_1 (tree *tp, int *walk_subtree
   switch (TREE_CODE (*tp))
     {
     case OMP_PARALLEL:
+    case OMP_TASK:
       ctx = maybe_lookup_ctx (t);
-      lower_omp_parallel (tp, ctx);
+      lower_omp_taskreg (tp, ctx);
       break;
 
     case OMP_FOR:
@@ -4979,7 +5082,7 @@ execute_lower_omp (void)
 				 delete_omp_context);
 
   scan_omp (&DECL_SAVED_TREE (current_function_decl), NULL);
-  gcc_assert (parallel_nesting_level == 0);
+  gcc_assert (taskreg_nesting_level == 0);
 
   if (all_contexts->root)
     lower_omp (&DECL_SAVED_TREE (current_function_decl), NULL);
@@ -5074,6 +5177,7 @@ diagnose_sb_1 (tree *tp, int *walk_subtr
   switch (TREE_CODE (t))
     {
     case OMP_PARALLEL:
+    case OMP_TASK:
     case OMP_SECTIONS:
     case OMP_SINGLE:
       walk_tree (&OMP_CLAUSES (t), diagnose_sb_1, wi, NULL);
@@ -5128,6 +5232,7 @@ diagnose_sb_2 (tree *tp, int *walk_subtr
   switch (TREE_CODE (t))
     {
     case OMP_PARALLEL:
+    case OMP_TASK:
     case OMP_SECTIONS:
     case OMP_SINGLE:
       walk_tree (&OMP_CLAUSES (t), diagnose_sb_2, wi, NULL);
--- gcc/tree-cfg.c.jj	2007-11-14 14:48:33.000000000 +0100
+++ gcc/tree-cfg.c	2007-11-30 12:42:18.000000000 +0100
@@ -505,6 +505,7 @@ make_edges (void)
 	      break;
 
 	    case OMP_PARALLEL:
+	    case OMP_TASK:
 	    case OMP_FOR:
 	    case OMP_SINGLE:
 	    case OMP_MASTER:
--- libgomp/testsuite/libgomp.c/icv-1.c.jj	2007-11-30 13:29:56.000000000 +0100
+++ libgomp/testsuite/libgomp.c/icv-1.c	2007-11-30 13:45:57.000000000 +0100
@@ -0,0 +1,34 @@
+#include <omp.h>
+#include <stdlib.h>
+
+int
+main (void)
+{
+  int err = 0;
+
+  omp_set_num_threads (4);
+  if (omp_get_max_threads () != 4)
+    abort ();
+  #pragma omp parallel reduction(|: err) num_threads(1)
+  {
+    if (omp_get_max_threads () != 4)
+      err |= 1;
+    omp_set_num_threads (6);
+    #pragma omp task if(0) shared(err)
+    {
+      if (omp_get_max_threads () != 6)
+	err |= 2;
+      omp_set_num_threads (5);
+      if (omp_get_max_threads () != 5)
+	err |= 4;
+    }
+    if (omp_get_max_threads () != 6)
+      err |= 8;
+  }
+  if (err)
+    abort ();
+/* FIXME XXX
+  if (omp_get_max_threads () != 4)
+    abort (); */
+  return 0;
+}

	Jakub


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