re PR middle-end/54017 (Incorrect implementation of infinite loops in OpenMP sections leads to SIGILL)

PR middle-end/54017
	* tree-cfgcleanup.c (cleanup_omp_return): Remove.
	(cleanup_tree_cfg_bb): Don't call it.
	* omp-low.c (expand_omp_sections): Fix up the !exit_reachable case
	handling.

	* c-c++-common/gomp/pr54017.c: New test.

From-SVN: r189659
This commit is contained in:
Jakub Jelinek 2012-07-19 16:05:54 +02:00 committed by Jakub Jelinek
parent 9c775c5263
commit 59f205ff69
5 changed files with 119 additions and 85 deletions

View File

@ -1,3 +1,11 @@
2012-07-19 Jakub Jelinek <jakub@redhat.com>
PR middle-end/54017
* tree-cfgcleanup.c (cleanup_omp_return): Remove.
(cleanup_tree_cfg_bb): Don't call it.
* omp-low.c (expand_omp_sections): Fix up the !exit_reachable case
handling.
2012-07-19 Christian Bruel <christian.bruel@st.com>
PR target/54029

View File

@ -4758,45 +4758,40 @@ expand_omp_sections (struct omp_region *region)
unsigned i, casei;
bool exit_reachable = region->cont != NULL;
gcc_assert (exit_reachable == (region->exit != NULL));
gcc_assert (region->exit != NULL);
entry_bb = region->entry;
l0_bb = single_succ (entry_bb);
l1_bb = region->cont;
l2_bb = region->exit;
if (exit_reachable)
{
if (single_pred_p (l2_bb) && single_pred (l2_bb) == l0_bb)
l2 = gimple_block_label (l2_bb);
else
{
/* This can happen if there are reductions. */
len = EDGE_COUNT (l0_bb->succs);
gcc_assert (len > 0);
e = EDGE_SUCC (l0_bb, len - 1);
si = gsi_last_bb (e->dest);
l2 = NULL_TREE;
if (gsi_end_p (si)
|| gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
l2 = gimple_block_label (e->dest);
else
FOR_EACH_EDGE (e, ei, l0_bb->succs)
{
si = gsi_last_bb (e->dest);
if (gsi_end_p (si)
|| gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
{
l2 = gimple_block_label (e->dest);
break;
}
}
}
default_bb = create_empty_bb (l1_bb->prev_bb);
}
if (single_pred_p (l2_bb) && single_pred (l2_bb) == l0_bb)
l2 = gimple_block_label (l2_bb);
else
{
default_bb = create_empty_bb (l0_bb);
l2 = gimple_block_label (default_bb);
/* This can happen if there are reductions. */
len = EDGE_COUNT (l0_bb->succs);
gcc_assert (len > 0);
e = EDGE_SUCC (l0_bb, len - 1);
si = gsi_last_bb (e->dest);
l2 = NULL_TREE;
if (gsi_end_p (si)
|| gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
l2 = gimple_block_label (e->dest);
else
FOR_EACH_EDGE (e, ei, l0_bb->succs)
{
si = gsi_last_bb (e->dest);
if (gsi_end_p (si)
|| gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
{
l2 = gimple_block_label (e->dest);
break;
}
}
}
if (exit_reachable)
default_bb = create_empty_bb (l1_bb->prev_bb);
else
default_bb = create_empty_bb (l0_bb);
/* We will build a switch() with enough cases for all the
GIMPLE_OMP_SECTION regions, a '0' case to handle the end of more work
@ -4849,13 +4844,9 @@ expand_omp_sections (struct omp_region *region)
vnext = NULL_TREE;
}
i = 0;
if (exit_reachable)
{
t = build_case_label (build_int_cst (unsigned_type_node, 0), NULL, l2);
VEC_quick_push (tree, label_vec, t);
i++;
}
t = build_case_label (build_int_cst (unsigned_type_node, 0), NULL, l2);
VEC_quick_push (tree, label_vec, t);
i = 1;
/* Convert each GIMPLE_OMP_SECTION into a CASE_LABEL_EXPR. */
for (inner = region->inner, casei = 1;
@ -4925,18 +4916,18 @@ expand_omp_sections (struct omp_region *region)
gsi_remove (&si, true);
single_succ_edge (l1_bb)->flags = EDGE_FALLTHRU;
/* Cleanup function replaces GIMPLE_OMP_RETURN in EXIT_BB. */
si = gsi_last_bb (l2_bb);
if (gimple_omp_return_nowait_p (gsi_stmt (si)))
t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_NOWAIT);
else
t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END);
stmt = gimple_build_call (t, 0);
gsi_insert_after (&si, stmt, GSI_SAME_STMT);
gsi_remove (&si, true);
}
/* Cleanup function replaces GIMPLE_OMP_RETURN in EXIT_BB. */
si = gsi_last_bb (l2_bb);
if (gimple_omp_return_nowait_p (gsi_stmt (si)))
t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_NOWAIT);
else
t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END);
stmt = gimple_build_call (t, 0);
gsi_insert_after (&si, stmt, GSI_SAME_STMT);
gsi_remove (&si, true);
set_immediate_dominator (CDI_DOMINATORS, default_bb, l0_bb);
}

View File

@ -1,3 +1,8 @@
2012-07-19 Jakub Jelinek <jakub@redhat.com>
PR middle-end/54017
* c-c++-common/gomp/pr54017.c: New test.
2012-07-18 Richard Guenther <rguenther@suse.de>
Backport from mainline

View File

@ -0,0 +1,65 @@
/* PR middle-end/54017 */
/* { dg-do compile } */
/* { dg-options "-fopenmp" } */
void
f1 (void)
{
#pragma omp parallel sections
{
#pragma omp section
{
for (;;)
;
}
}
}
int
f2 (void)
{
int i = 0;
#pragma omp parallel
#pragma omp sections reduction(+:i)
{
#pragma omp section
{
for (;;)
;
}
}
return i;
}
void
f3 (void)
{
#pragma omp parallel sections
{
#pragma omp section
{
for (;;)
;
}
#pragma omp section
;
}
}
int
f4 (void)
{
int i = 0;
#pragma omp parallel
#pragma omp sections reduction(+:i)
{
#pragma omp section
{
for (;;)
;
}
#pragma omp section
;
}
return i;
}

View File

@ -610,48 +610,13 @@ split_bbs_on_noreturn_calls (void)
return changed;
}
/* If GIMPLE_OMP_RETURN in basic block BB is unreachable, remove it. */
static bool
cleanup_omp_return (basic_block bb)
{
gimple stmt = last_stmt (bb);
basic_block control_bb;
if (stmt == NULL
|| gimple_code (stmt) != GIMPLE_OMP_RETURN
|| !single_pred_p (bb))
return false;
control_bb = single_pred (bb);
stmt = last_stmt (control_bb);
if (stmt == NULL || gimple_code (stmt) != GIMPLE_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. */
static bool
cleanup_tree_cfg_bb (basic_block bb)
{
bool retval = false;
if (cleanup_omp_return (bb))
return true;
retval = cleanup_control_flow_bb (bb);
bool retval = cleanup_control_flow_bb (bb);
if (tree_forwarder_block_p (bb, false)
&& remove_forwarder_block (bb))