Commit e5c95afe by Zdenek Dvorak Committed by Zdenek Dvorak

tree-pretty-print.c (dump_generic_node): Dump OMP_SECTIONS_SWITCH.

	* tree-pretty-print.c (dump_generic_node): Dump OMP_SECTIONS_SWITCH.
	Display new operands of OMP_SECTIONS and OMP_CONTINUE.
	* tree.h (OMP_SECTIONS_CONTROL): New macro.
	(OMP_DIRECTIVE_P): Add OMP_SECTIONS_SWITCH.
	* omp-low.c (get_ws_args_for, determine_parallel_type,
	expand_omp_for_generic, expand_omp_for_static_nochunk,
	expand_omp_for_static_chunk, expand_omp_for, expand_omp_sections):
	Work with more precise CFG.
	(build_omp_regions_1): Handle OMP_SECTIONS_SWITCH.
	(lower_omp_sections): Emit OMP_SECTIONS_SWITCH.  Add arguments to
	OMP_CONTINUE.
	* tree-gimple.c (is_gimple_stmt): Handle OMP_SECTIONS_SWITCH.
	* gimple-low.c (lower_stmt): Ditto.
	* tree-inline.c (estimate_num_insns_1): Ditto.
	* tree.def (OMP_SECTIONS, OMP_CONTINUE): Added new operands.
	(OMP_SECTIONS_SWITCH): New.
	* tree-cfgcleanup.c (cleanup_omp_return): New.
	(cleanup_tree_cfg_bb): Call cleanup_omp_return.
	* tree-cfg.c (make_edges): Create back edges for OMP_CONTINUE
	and exit edge for OMP_FOR.  Handle OMP_SECTIONS_SWITCH.
	(tree_redirect_edge_and_branch): Handle omp constructs.

	* fortran/trans-openmp.c (gfc_trans_omp_sections): Build OMP_SECTIONS
	with three arguments.

From-SVN: r127121
parent 203bb67e
2007-08-01 Zdenek Dvorak <ook@ucw.cz>
* tree-pretty-print.c (dump_generic_node): Dump OMP_SECTIONS_SWITCH.
Display new operands of OMP_SECTIONS and OMP_CONTINUE.
* tree.h (OMP_SECTIONS_CONTROL): New macro.
(OMP_DIRECTIVE_P): Add OMP_SECTIONS_SWITCH.
* omp-low.c (get_ws_args_for, determine_parallel_type,
expand_omp_for_generic, expand_omp_for_static_nochunk,
expand_omp_for_static_chunk, expand_omp_for, expand_omp_sections):
Work with more precise CFG.
(build_omp_regions_1): Handle OMP_SECTIONS_SWITCH.
(lower_omp_sections): Emit OMP_SECTIONS_SWITCH. Add arguments to
OMP_CONTINUE.
* tree-gimple.c (is_gimple_stmt): Handle OMP_SECTIONS_SWITCH.
* gimple-low.c (lower_stmt): Ditto.
* tree-inline.c (estimate_num_insns_1): Ditto.
* tree.def (OMP_SECTIONS, OMP_CONTINUE): Added new operands.
(OMP_SECTIONS_SWITCH): New.
* tree-cfgcleanup.c (cleanup_omp_return): New.
(cleanup_tree_cfg_bb): Call cleanup_omp_return.
* tree-cfg.c (make_edges): Create back edges for OMP_CONTINUE
and exit edge for OMP_FOR. Handle OMP_SECTIONS_SWITCH.
(tree_redirect_edge_and_branch): Handle omp constructs.
* fortran/trans-openmp.c (gfc_trans_omp_sections): Build OMP_SECTIONS
with three arguments.
2007-08-01 Zdenek Dvorak <ook@ucw.cz>
* tree-cfg.c (tree_merge_blocks): Preserve loop exit phi nodes only
in loop closed ssa.
......
......@@ -1205,7 +1205,7 @@ gfc_trans_omp_sections (gfc_code *code, gfc_omp_clauses *clauses)
}
stmt = gfc_finish_block (&body);
stmt = build2_v (OMP_SECTIONS, stmt, omp_clauses);
stmt = build3_v (OMP_SECTIONS, stmt, omp_clauses, NULL_TREE);
gfc_add_expr_to_block (&block, stmt);
return gfc_finish_block (&block);
......
......@@ -244,6 +244,7 @@ lower_stmt (tree_stmt_iterator *tsi, struct lower_data *data)
case CHANGE_DYNAMIC_TYPE_EXPR:
case OMP_FOR:
case OMP_SECTIONS:
case OMP_SECTIONS_SWITCH:
case OMP_SECTION:
case OMP_SINGLE:
case OMP_MASTER:
......
......@@ -517,6 +517,10 @@ make_edges (void)
case OMP_SECTIONS:
cur_region = new_omp_region (bb, code, cur_region);
fallthru = true;
break;
case OMP_SECTIONS_SWITCH:
fallthru = false;
break;
......@@ -533,31 +537,42 @@ make_edges (void)
switch (cur_region->type)
{
case OMP_FOR:
/* ??? Technically there should be a some sort of loopback
edge here, but it goes to a block that doesn't exist yet,
and without it, updating the ssa form would be a real
bear. Fortunately, we don't yet do ssa before expanding
these nodes. */
/* Make the loopback edge. */
make_edge (bb, single_succ (cur_region->entry), 0);
/* Create an edge from OMP_FOR to exit, which corresponds to
the case that the body of the loop is not executed at
all. */
make_edge (cur_region->entry, bb->next_bb, 0);
fallthru = true;
break;
case OMP_SECTIONS:
/* Wire up the edges into and out of the nested sections. */
/* ??? Similarly wrt loopback. */
{
basic_block switch_bb = single_succ (cur_region->entry);
struct omp_region *i;
for (i = cur_region->inner; i ; i = i->next)
{
gcc_assert (i->type == OMP_SECTION);
make_edge (cur_region->entry, i->entry, 0);
make_edge (switch_bb, i->entry, 0);
make_edge (i->exit, bb, EDGE_FALLTHRU);
}
/* Make the loopback edge to the block with
OMP_SECTIONS_SWITCH. */
make_edge (bb, switch_bb, 0);
/* Make the edge from the switch to exit. */
make_edge (switch_bb, bb->next_bb, 0);
fallthru = false;
}
break;
default:
gcc_unreachable ();
}
fallthru = true;
break;
default:
......@@ -4807,6 +4822,13 @@ tree_redirect_edge_and_branch (edge e, basic_block dest)
e->flags |= EDGE_FALLTHRU;
break;
case OMP_RETURN:
case OMP_CONTINUE:
case OMP_SECTIONS_SWITCH:
case OMP_FOR:
/* The edges from OMP constructs can be simply redirected. */
break;
default:
/* Otherwise it must be a fallthru edge, and we don't need to
do anything besides redirecting it. */
......
......@@ -507,6 +507,36 @@ split_bbs_on_noreturn_calls (void)
return changed;
}
/* If OMP_RETURN in basic block BB is unreachable, remove it. */
static bool
cleanup_omp_return (basic_block bb)
{
tree stmt = last_stmt (bb);
basic_block control_bb;
if (stmt == NULL_TREE
|| TREE_CODE (stmt) != OMP_RETURN
|| !single_pred_p (bb))
return false;
control_bb = single_pred (bb);
stmt = last_stmt (control_bb);
if (TREE_CODE (stmt) != OMP_SECTIONS_SWITCH)
return false;
/* The block with the control statement normally has two entry edges -- one
from entry, one from continue. If continue is removed, return is
unreachable, so we remove it here as well. */
if (EDGE_COUNT (control_bb->preds) == 2)
return false;
gcc_assert (EDGE_COUNT (control_bb->preds) == 1);
remove_edge_and_dominated_blocks (single_pred_edge (bb));
return true;
}
/* Tries to cleanup cfg in basic block BB. Returns true if anything
changes. */
......@@ -515,8 +545,11 @@ cleanup_tree_cfg_bb (basic_block bb)
{
bool retval = false;
retval = cleanup_control_flow_bb (bb);
if (cleanup_omp_return (bb))
return true;
retval = cleanup_control_flow_bb (bb);
/* Forwarder blocks can carry line number information which is
useful when debugging, so we only clean them up when
optimizing. */
......
......@@ -230,6 +230,7 @@ is_gimple_stmt (tree t)
case OMP_PARALLEL:
case OMP_FOR:
case OMP_SECTIONS:
case OMP_SECTIONS_SWITCH:
case OMP_SECTION:
case OMP_SINGLE:
case OMP_MASTER:
......
......@@ -2010,6 +2010,7 @@ estimate_num_insns_1 (tree *tp, int *walk_subtrees, void *data)
case OMP_CLAUSE:
case OMP_RETURN:
case OMP_CONTINUE:
case OMP_SECTIONS_SWITCH:
break;
/* We don't account constants for now. Assume that the cost is amortized
......
......@@ -1851,9 +1851,21 @@ dump_generic_node (pretty_printer *buffer, tree node, int spc, int flags,
case OMP_SECTIONS:
pp_string (buffer, "#pragma omp sections");
if (OMP_SECTIONS_CONTROL (node))
{
pp_string (buffer, " <");
dump_generic_node (buffer, OMP_SECTIONS_CONTROL (node), spc,
flags, false);
pp_string (buffer, ">");
}
dump_omp_clauses (buffer, OMP_SECTIONS_CLAUSES (node), spc, flags);
goto dump_omp_body;
case OMP_SECTIONS_SWITCH:
pp_string (buffer, "OMP_SECTIONS_SWITCH");
is_expr = false;
break;
case OMP_SECTION:
pp_string (buffer, "#pragma omp section");
goto dump_omp_body;
......@@ -1901,7 +1913,11 @@ dump_generic_node (pretty_printer *buffer, tree node, int spc, int flags,
break;
case OMP_CONTINUE:
pp_string (buffer, "OMP_CONTINUE");
pp_string (buffer, "OMP_CONTINUE <");
dump_generic_node (buffer, TREE_OPERAND (node, 0), spc, flags, false);
pp_string (buffer, " <- ");
dump_generic_node (buffer, TREE_OPERAND (node, 1), spc, flags, false);
pp_string (buffer, ">");
is_expr = false;
break;
......
......@@ -999,8 +999,14 @@ DEFTREECODE (OMP_FOR, "omp_for", tcc_statement, 6)
/* OpenMP - #pragma omp sections [clause1 ... clauseN]
Operand 0: OMP_SECTIONS_BODY: Sections body.
Operand 1: OMP_SECTIONS_CLAUSES: List of clauses. */
DEFTREECODE (OMP_SECTIONS, "omp_sections", tcc_statement, 2)
Operand 1: OMP_SECTIONS_CLAUSES: List of clauses.
Operand 2: OMP_SECTIONS_CONTROL: The control variable used for deciding
which of the sections to execute. */
DEFTREECODE (OMP_SECTIONS, "omp_sections", tcc_statement, 3)
/* This tree immediatelly follows OMP_SECTIONS, and represents the switch
used to decide which branch is taken. */
DEFTREECODE (OMP_SECTIONS_SWITCH, "omp_sections_switch", tcc_statement, 0)
/* OpenMP - #pragma omp single
Operand 0: OMP_SINGLE_BODY: Single section body.
......@@ -1028,8 +1034,9 @@ DEFTREECODE (OMP_CRITICAL, "omp_critical", tcc_statement, 2)
DEFTREECODE (OMP_RETURN, "omp_return", tcc_statement, 0)
/* OpenMP - An intermediate tree code to mark the location of the
loop or sections iteration in the partially lowered code. */
DEFTREECODE (OMP_CONTINUE, "omp_continue", tcc_statement, 0)
loop or sections iteration in the partially lowered code.
The arguments are definition and use of the control variable. */
DEFTREECODE (OMP_CONTINUE, "omp_continue", tcc_statement, 2)
/* OpenMP - #pragma omp atomic
Operand 0: The address at which the atomic operation is to be performed.
......
......@@ -187,6 +187,7 @@ extern const enum tree_code_class tree_code_type[];
(TREE_CODE (NODE) == OMP_PARALLEL \
|| TREE_CODE (NODE) == OMP_FOR \
|| TREE_CODE (NODE) == OMP_SECTIONS \
|| TREE_CODE (NODE) == OMP_SECTIONS_SWITCH \
|| TREE_CODE (NODE) == OMP_SINGLE \
|| TREE_CODE (NODE) == OMP_SECTION \
|| TREE_CODE (NODE) == OMP_MASTER \
......@@ -1695,6 +1696,7 @@ struct tree_constructor GTY(())
#define OMP_SECTIONS_BODY(NODE) TREE_OPERAND (OMP_SECTIONS_CHECK (NODE), 0)
#define OMP_SECTIONS_CLAUSES(NODE) TREE_OPERAND (OMP_SECTIONS_CHECK (NODE), 1)
#define OMP_SECTIONS_CONTROL(NODE) TREE_OPERAND (OMP_SECTIONS_CHECK (NODE), 2)
#define OMP_SECTION_BODY(NODE) TREE_OPERAND (OMP_SECTION_CHECK (NODE), 0)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment