marshalling to implement data sharing and copying clauses.
Contributed by Diego Novillo <dnovillo@redhat.com>
- Copyright (C) 2005 Free Software Foundation, Inc.
+ Copyright (C) 2005, 2006 Free Software Foundation, Inc.
This file is part of GCC.
phases. The first phase scans the function looking for OMP statements
and then for variables that must be replaced to satisfy data sharing
clauses. The second phase expands code for the constructs, as well as
- re-gimplifing things when variables have been replaced with complex
+ re-gimplifying things when variables have been replaced with complex
expressions.
- Lowering of a parallel statement results in the contents of the
- parallel being moved to a new function, to be invoked by the thread
- library. The variable remapping process is complex enough that only
- one level of parallel statement is handled at one time. If there are
- nested parallel statements, those nested statements are handled when
- the new function is lowered and optimized. The result is not 100%
- optimal, but lexically nested parallels effectively only happens in
- test suites. */
+ Final code generation is done by pass_expand_omp. The flowgraph is
+ scanned for parallel regions which are then moved to a new
+ function, to be invoked by the thread library. */
/* Parallel region information. Every parallel and workshare
directive is enclosed between two markers, the OMP_* directive
find_omp_clause (tree clauses, enum tree_code kind)
{
for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
- if (TREE_CODE (clauses) == kind)
+ if (OMP_CLAUSE_CODE (clauses) == kind)
return clauses;
return NULL_TREE;
fd->chunk_size = NULL_TREE;
for (t = OMP_FOR_CLAUSES (for_stmt); t ; t = OMP_CLAUSE_CHAIN (t))
- switch (TREE_CODE (t))
+ switch (OMP_CLAUSE_CODE (t))
{
case OMP_CLAUSE_NOWAIT:
fd->have_nowait = true;
{
bool by_ref;
- switch (TREE_CODE (c))
+ switch (OMP_CLAUSE_CODE (c))
{
case OMP_CLAUSE_PRIVATE:
decl = OMP_CLAUSE_DECL (c);
break;
}
/* We don't need to copy const scalar vars back. */
- TREE_SET_CODE (c, OMP_CLAUSE_FIRSTPRIVATE);
+ OMP_CLAUSE_SET_CODE (c, OMP_CLAUSE_FIRSTPRIVATE);
goto do_private;
case OMP_CLAUSE_LASTPRIVATE:
case OMP_CLAUSE_NUM_THREADS:
case OMP_CLAUSE_SCHEDULE:
if (ctx->outer)
- scan_omp (&TREE_OPERAND (c, 0), ctx->outer);
+ scan_omp (&OMP_CLAUSE_OPERAND (c, 0), ctx->outer);
break;
case OMP_CLAUSE_NOWAIT:
for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
{
- switch (TREE_CODE (c))
+ switch (OMP_CLAUSE_CODE (c))
{
case OMP_CLAUSE_LASTPRIVATE:
/* Let the corresponding firstprivate clause create
if (is_variable_sized (decl))
install_var_local (decl, ctx);
fixup_remapped_decl (decl, ctx,
- TREE_CODE (c) == OMP_CLAUSE_PRIVATE
+ OMP_CLAUSE_CODE (c) == OMP_CLAUSE_PRIVATE
&& OMP_CLAUSE_PRIVATE_DEBUG (c));
- if (TREE_CODE (c) == OMP_CLAUSE_REDUCTION
+ if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
&& OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
scan_array_reductions = true;
break;
if (scan_array_reductions)
for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
- if (TREE_CODE (c) == OMP_CLAUSE_REDUCTION
+ if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
&& OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
{
scan_omp (&OMP_CLAUSE_REDUCTION_INIT (c), ctx);
{
for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
{
- enum tree_code c_kind = TREE_CODE (c);
+ enum omp_clause_code c_kind = OMP_CLAUSE_CODE (c);
tree var, new_var;
bool by_ref;
else if (pass != 0)
continue;
- switch (TREE_CODE (c))
+ switch (OMP_CLAUSE_CODE (c))
{
case OMP_CLAUSE_SHARED:
/* Set up the DECL_VALUE_EXPR for shared variables now. This
{
tree var, new_var;
- if (TREE_CODE (c) != OMP_CLAUSE_LASTPRIVATE)
+ if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_LASTPRIVATE)
continue;
var = OMP_CLAUSE_DECL (c);
/* First see if there is exactly one reduction clause. Use OMP_ATOMIC
update in that case, otherwise use a lock. */
for (c = clauses; c && count < 2; c = OMP_CLAUSE_CHAIN (c))
- if (TREE_CODE (c) == OMP_CLAUSE_REDUCTION)
+ if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
{
if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
{
tree var, ref, new_var;
enum tree_code code;
- if (TREE_CODE (c) != OMP_CLAUSE_REDUCTION)
+ if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
continue;
var = OMP_CLAUSE_DECL (c);
tree var, ref, x;
bool by_ref;
- if (TREE_CODE (c) != OMP_CLAUSE_COPYPRIVATE)
+ if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYPRIVATE)
continue;
var = OMP_CLAUSE_DECL (c);
tree val, ref, x, var;
bool by_ref, do_in = false, do_out = false;
- switch (TREE_CODE (c))
+ switch (OMP_CLAUSE_CODE (c))
{
case OMP_CLAUSE_FIRSTPRIVATE:
case OMP_CLAUSE_COPYIN:
continue;
by_ref = use_pointer_for_field (val, false);
- switch (TREE_CODE (c))
+ switch (OMP_CLAUSE_CODE (c))
{
case OMP_CLAUSE_FIRSTPRIVATE:
case OMP_CLAUSE_COPYIN:
clauses = OMP_PARALLEL_CLAUSES (region->entry);
push_gimplify_context ();
- /* Determine what flavour of GOMP_parallel_start we will be
+ /* Determine what flavor of GOMP_parallel_start we will be
emitting. */
start_ix = BUILT_IN_GOMP_PARALLEL_START;
if (is_combined_parallel (region))
entry_bb = bb_for_stmt (region->entry);
exit_bb = bb_for_stmt (region->exit);
- /* Barriers at the end of the function are not necessary and can be
- removed. Since the caller will have a barrier of its own, this
- one is superfluous. */
- remove_exit_barrier (region);
-
if (is_combined_parallel (region))
- ws_args = region->ws_args;
+ {
+ ws_args = region->ws_args;
+
+ /* For combined parallel+workshare calls, barriers at the end of
+ the function are not necessary and can be removed. Since the
+ caller will have a barrier of its own, the workshare barrier is
+ superfluous. */
+ remove_exit_barrier (region);
+ }
else
ws_args = NULL_TREE;
istart0 = create_tmp_var (long_integer_type_node, ".istart0");
iend0 = create_tmp_var (long_integer_type_node, ".iend0");
+ TREE_ADDRESSABLE (istart0) = 1;
+ TREE_ADDRESSABLE (iend0) = 1;
l0 = create_artificial_label ();
l1 = create_artificial_label ();
gcc_unreachable ();
}
+ /* Expansion adds and removes basic block, edges, creates
+ and exposes unreachable regions that need to be cleaned up
+ before proceeding. */
+ free_dominance_info (CDI_DOMINATORS);
+ free_dominance_info (CDI_POST_DOMINATORS);
+ cleanup_tree_cfg ();
+
region = region->next;
}
}
/* Main entry point for expanding OMP-GIMPLE into runtime calls. */
-static void
+static unsigned int
execute_expand_omp (void)
{
build_omp_regions ();
splay_tree_delete (omp_regions);
root_omp_region = NULL;
omp_regions = NULL;
- free_dominance_info (CDI_DOMINATORS);
- free_dominance_info (CDI_POST_DOMINATORS);
}
-
- /* Expansion adds basic blocks that may be merged. */
- cleanup_tree_cfg ();
+ return 0;
}
static bool
new_body = alloc_stmt_list ();
append_to_statement_list (ilist, &new_body);
append_to_statement_list (stmt, &new_body);
+ /* ??? The OMP_RETURN doesn't logically belong here, but in
+ expand_omp_sections we expect this marker to be where the
+ individual sections join after completing the loop. */
append_to_statement_list (region_exit, &new_body);
append_to_statement_list (olist, &new_body);
append_to_statement_list (dlist, &new_body);
lower_omp_single_simple (single_stmt, &BIND_EXPR_BODY (bind));
append_to_statement_list (dlist, &BIND_EXPR_BODY (bind));
+ maybe_catch_exception (&BIND_EXPR_BODY (bind));
t = make_node (OMP_RETURN_EXPR);
append_to_statement_list (t, &BIND_EXPR_BODY (bind));
- maybe_catch_exception (&BIND_EXPR_BODY (bind));
pop_gimplify_context (bind);
BIND_EXPR_VARS (bind) = chainon (BIND_EXPR_VARS (bind), ctx->block_vars);
x = build1 (LABEL_EXPR, void_type_node, lab);
gimplify_and_add (x, &BIND_EXPR_BODY (bind));
+ maybe_catch_exception (&BIND_EXPR_BODY (bind));
x = make_node (OMP_RETURN_EXPR);
append_to_statement_list (x, &BIND_EXPR_BODY (bind));
- maybe_catch_exception (&BIND_EXPR_BODY (bind));
pop_gimplify_context (bind);
BIND_EXPR_VARS (bind) = chainon (BIND_EXPR_VARS (bind), ctx->block_vars);
x = built_in_decls[BUILT_IN_GOMP_ORDERED_END];
x = build_function_call_expr (x, NULL);
gimplify_and_add (x, &BIND_EXPR_BODY (bind));
+ maybe_catch_exception (&BIND_EXPR_BODY (bind));
x = make_node (OMP_RETURN_EXPR);
append_to_statement_list (x, &BIND_EXPR_BODY (bind));
- maybe_catch_exception (&BIND_EXPR_BODY (bind));
pop_gimplify_context (bind);
BIND_EXPR_VARS (bind) = chainon (BIND_EXPR_VARS (bind), ctx->block_vars);
\f
/* Main entry point. */
-static void
+static unsigned int
execute_lower_omp (void)
{
all_contexts = splay_tree_new (splay_tree_compare_pointers, 0,
splay_tree_delete (all_contexts);
all_contexts = NULL;
}
+ return 0;
}
static bool