GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
-Software Foundation; either version 2, or (at your option) any later
+Software Foundation; either version 3, or (at your option) any later
version.
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
for more details.
You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING. If not, write to the Free
-Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
-02110-1301, USA. */
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
#include "config.h"
#include "system.h"
if (single_succ (par_entry_bb) == ws_entry_bb
&& single_succ (ws_exit_bb) == par_exit_bb
- && workshare_safe_to_combine_p (par_entry_bb, ws_entry_bb))
+ && workshare_safe_to_combine_p (par_entry_bb, ws_entry_bb)
+ && (OMP_PARALLEL_COMBINED (last_stmt (par_entry_bb))
+ || (last_and_only_stmt (ws_entry_bb)
+ && last_and_only_stmt (par_exit_bb))))
{
- tree ws_stmt = last_stmt (region->inner->entry);
+ tree ws_stmt = last_stmt (ws_entry_bb);
if (region->inner->type == OMP_FOR)
{
TREE_ADDRESSABLE (copy) = TREE_ADDRESSABLE (var);
DECL_GIMPLE_REG_P (copy) = DECL_GIMPLE_REG_P (var);
+ DECL_NO_TBAA_P (copy) = DECL_NO_TBAA_P (var);
DECL_ARTIFICIAL (copy) = DECL_ARTIFICIAL (var);
DECL_IGNORED_P (copy) = DECL_IGNORED_P (var);
TREE_USED (copy) = 1;
for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
t = maybe_lookup_decl (decl, up);
- gcc_assert (t);
+ gcc_assert (t || is_global_var (decl));
- return t;
+ return t ? t : decl;
}
{
basic_block cond_bb, then_bb, else_bb;
edge e;
- tree t, then_lab, else_lab, tmp;
+ tree t, tmp;
tmp = create_tmp_var (TREE_TYPE (val), NULL);
e = split_block (bb, NULL);
then_bb = create_empty_bb (cond_bb);
else_bb = create_empty_bb (then_bb);
- then_lab = create_artificial_label ();
- else_lab = create_artificial_label ();
t = build3 (COND_EXPR, void_type_node,
- cond,
- build_and_jump (&then_lab),
- build_and_jump (&else_lab));
+ cond, NULL_TREE, NULL_TREE);
si = bsi_start (cond_bb);
bsi_insert_after (&si, t, BSI_CONTINUE_LINKING);
si = bsi_start (then_bb);
- t = build1 (LABEL_EXPR, void_type_node, then_lab);
- bsi_insert_after (&si, t, BSI_CONTINUE_LINKING);
t = build_gimple_modify_stmt (tmp, val);
bsi_insert_after (&si, t, BSI_CONTINUE_LINKING);
si = bsi_start (else_bb);
- t = build1 (LABEL_EXPR, void_type_node, else_lab);
- bsi_insert_after (&si, t, BSI_CONTINUE_LINKING);
t = build_gimple_modify_stmt (tmp,
build_int_cst (unsigned_type_node, 1));
bsi_insert_after (&si, t, BSI_CONTINUE_LINKING);
block_stmt_iterator si;
tree entry_stmt;
edge e;
+ bool do_cleanup_cfg = false;
entry_stmt = last_stmt (region->entry);
child_fn = OMP_PARALLEL_FN (entry_stmt);
exit_succ_e = single_succ_edge (exit_bb);
make_edge (new_bb, exit_succ_e->dest, EDGE_FALLTHRU);
}
+ do_cleanup_cfg = true;
}
else
{
/* Declare local variables needed in CHILD_CFUN. */
block = DECL_INITIAL (child_fn);
BLOCK_VARS (block) = list2chain (child_cfun->unexpanded_var_list);
- DECL_SAVED_TREE (child_fn) = single_succ (entry_bb)->stmt_list;
+ DECL_SAVED_TREE (child_fn) = bb_stmt_list (single_succ (entry_bb));
/* Reset DECL_CONTEXT on locals and function arguments. */
for (t = BLOCK_VARS (block); t; t = TREE_CHAIN (t))
/* Emit a library call to launch the children threads. */
expand_parallel_call (region, new_bb, entry_stmt, ws_args);
+
+ if (do_cleanup_cfg)
+ {
+ /* Clean up the unreachable sub-graph we created above. */
+ free_dominance_info (CDI_DOMINATORS);
+ free_dominance_info (CDI_POST_DOMINATORS);
+ cleanup_tree_cfg ();
+ }
}
enum built_in_function start_fn,
enum built_in_function next_fn)
{
- tree l0, l1, l2 = NULL, l3 = NULL;
tree type, istart0, iend0, iend;
tree t, list;
basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb;
l0_bb = create_empty_bb (entry_bb);
l1_bb = single_succ (entry_bb);
- l0 = tree_block_label (l0_bb);
- l1 = tree_block_label (l1_bb);
-
cont_bb = region->cont;
exit_bb = region->exit;
if (cont_bb)
{
l2_bb = create_empty_bb (cont_bb);
l3_bb = single_succ (cont_bb);
-
- l2 = tree_block_label (l2_bb);
- l3 = tree_block_label (l3_bb);
}
si = bsi_last (entry_bb);
t = get_formal_tmp_var (t, &list);
if (cont_bb)
{
- t = build3 (COND_EXPR, void_type_node, t, build_and_jump (&l0),
- build_and_jump (&l3));
+ t = build3 (COND_EXPR, void_type_node, t, NULL_TREE, NULL_TREE);
append_to_statement_list (t, &list);
}
bsi_insert_after (&si, list, BSI_SAME_STMT);
t = build2 (fd->cond_code, boolean_type_node, fd->v, iend);
t = get_formal_tmp_var (t, &list);
- t = build3 (COND_EXPR, void_type_node, t, build_and_jump (&l1),
- build_and_jump (&l2));
+ t = build3 (COND_EXPR, void_type_node, t, NULL_TREE, NULL_TREE);
append_to_statement_list (t, &list);
si = bsi_last (cont_bb);
build_fold_addr_expr (istart0),
build_fold_addr_expr (iend0));
t = get_formal_tmp_var (t, &list);
- t = build3 (COND_EXPR, void_type_node, t, build_and_jump (&l0),
- build_and_jump (&l3));
+ t = build3 (COND_EXPR, void_type_node, t, NULL_TREE, NULL_TREE);
append_to_statement_list (t, &list);
si = bsi_start (l2_bb);
expand_omp_for_static_nochunk (struct omp_region *region,
struct omp_for_data *fd)
{
- tree l0, l1, l2, n, q, s0, e0, e, t, nthreads, threadid;
+ tree n, q, s0, e0, e, t, nthreads, threadid;
tree type, list;
basic_block entry_bb, exit_bb, seq_start_bb, body_bb, cont_bb;
basic_block fin_bb;
fin_bb = single_succ (cont_bb);
exit_bb = region->exit;
- l0 = tree_block_label (seq_start_bb);
- l1 = tree_block_label (body_bb);
- l2 = tree_block_label (fin_bb);
-
/* Iteration space partitioning goes in ENTRY_BB. */
list = alloc_stmt_list ();
e0 = get_formal_tmp_var (t, &list);
t = build2 (GE_EXPR, boolean_type_node, s0, e0);
- t = build3 (COND_EXPR, void_type_node, t, build_and_jump (&l2),
- build_and_jump (&l0));
+ t = build3 (COND_EXPR, void_type_node, t, NULL_TREE, NULL_TREE);
append_to_statement_list (t, &list);
si = bsi_last (entry_bb);
t = build2 (fd->cond_code, boolean_type_node, fd->v, e);
t = get_formal_tmp_var (t, &list);
- t = build3 (COND_EXPR, void_type_node, t, build_and_jump (&l1),
- build_and_jump (&l2));
+ t = build3 (COND_EXPR, void_type_node, t, NULL_TREE, NULL_TREE);
append_to_statement_list (t, &list);
si = bsi_last (cont_bb);
static void
expand_omp_for_static_chunk (struct omp_region *region, struct omp_for_data *fd)
{
- tree l0, l1, l2, l3, l4, n, s0, e0, e, t;
+ tree n, s0, e0, e, t;
tree trip, nthreads, threadid;
tree type;
basic_block entry_bb, exit_bb, body_bb, seq_start_bb, iter_part_bb;
fin_bb = single_succ (cont_bb);
exit_bb = region->exit;
- l0 = tree_block_label (iter_part_bb);
- l1 = tree_block_label (seq_start_bb);
- l2 = tree_block_label (body_bb);
- l3 = tree_block_label (trip_update_bb);
- l4 = tree_block_label (fin_bb);
-
/* Trip and adjustment setup goes in ENTRY_BB. */
list = alloc_stmt_list ();
e0 = get_formal_tmp_var (t, &list);
t = build2 (LT_EXPR, boolean_type_node, s0, n);
- t = build3 (COND_EXPR, void_type_node, t,
- build_and_jump (&l1), build_and_jump (&l4));
+ t = build3 (COND_EXPR, void_type_node, t, NULL_TREE, NULL_TREE);
append_to_statement_list (t, &list);
si = bsi_start (iter_part_bb);
t = build2 (fd->cond_code, boolean_type_node, fd->v, e);
t = get_formal_tmp_var (t, &list);
- t = build3 (COND_EXPR, void_type_node, t,
- build_and_jump (&l2), build_and_jump (&l3));
+ t = build3 (COND_EXPR, void_type_node, t, NULL_TREE, NULL_TREE);
append_to_statement_list (t, &list);
si = bsi_last (cont_bb);
*stmt_p = new_stmt;
}
+/* Callback for walk_stmts. Check if *TP only contains OMP_FOR
+ or OMP_PARALLEL. */
+
+static tree
+check_combined_parallel (tree *tp, int *walk_subtrees, void *data)
+{
+ struct walk_stmt_info *wi = data;
+ int *info = wi->info;
+
+ *walk_subtrees = 0;
+ switch (TREE_CODE (*tp))
+ {
+ case OMP_FOR:
+ case OMP_SECTIONS:
+ *info = *info == 0 ? 1 : -1;
+ break;
+ default:
+ *info = -1;
+ break;
+ }
+ return NULL;
+}
/* Lower the OpenMP parallel directive in *STMT_P. CTX holds context
information for the directive. */
par_bind = OMP_PARALLEL_BODY (stmt);
par_body = BIND_EXPR_BODY (par_bind);
child_fn = ctx->cb.dst_fn;
+ if (!OMP_PARALLEL_COMBINED (stmt))
+ {
+ struct walk_stmt_info wi;
+ int ws_num = 0;
+
+ memset (&wi, 0, sizeof (wi));
+ wi.callback = check_combined_parallel;
+ wi.info = &ws_num;
+ wi.val_only = true;
+ walk_stmts (&wi, &par_bind);
+ if (ws_num == 1)
+ OMP_PARALLEL_COMBINED (stmt) = 1;
+ }
push_gimplify_context ();