This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[gomp] Some more progress on OMP_TASK support
- From: Jakub Jelinek <jakub at redhat dot com>
- To: Richard Henderson <rth at redhat dot com>
- Cc: gcc-patches at gcc dot gnu dot org
- Date: Fri, 30 Nov 2007 08:16:39 -0500
- Subject: [gomp] Some more progress on OMP_TASK support
- Reply-to: Jakub Jelinek <jakub at redhat dot com>
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