aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@gcc.gnu.org>2012-07-19 16:02:32 +0200
committerJakub Jelinek <jakub@gcc.gnu.org>2012-07-19 16:02:32 +0200
commit65e7bfe359febac74ebd3de0c36e735166205950 (patch)
treeb2ceb968dce32746620d8c2755e65d81bba8a568
parent867ff7ed192fe7f614ad5c5429519f7e865e20f0 (diff)
downloadgcc-65e7bfe359febac74ebd3de0c36e735166205950.zip
gcc-65e7bfe359febac74ebd3de0c36e735166205950.tar.gz
gcc-65e7bfe359febac74ebd3de0c36e735166205950.tar.bz2
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: r189658
-rw-r--r--gcc/ChangeLog8
-rw-r--r--gcc/omp-low.c83
-rw-r--r--gcc/testsuite/ChangeLog7
-rw-r--r--gcc/testsuite/c-c++-common/gomp/pr54017.c65
-rw-r--r--gcc/tree-cfgcleanup.c37
5 files changed, 117 insertions, 83 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 1ad278a..dc5187f 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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
diff --git a/gcc/omp-low.c b/gcc/omp-low.c
index 8f0932b..03eb399 100644
--- a/gcc/omp-low.c
+++ b/gcc/omp-low.c
@@ -4751,45 +4751,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
{
- if (single_pred_p (l2_bb) && single_pred (l2_bb) == l0_bb)
- l2 = gimple_block_label (l2_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
- {
- /* 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)
+ 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)
{
- 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;
- }
+ l2 = gimple_block_label (e->dest);
+ break;
}
- }
- default_bb = create_empty_bb (l1_bb->prev_bb);
+ }
}
+ if (exit_reachable)
+ default_bb = create_empty_bb (l1_bb->prev_bb);
else
- {
- default_bb = create_empty_bb (l0_bb);
- l2 = gimple_block_label (default_bb);
- }
+ 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
@@ -4842,13 +4837,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;
@@ -4918,18 +4909,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);
}
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index dee868f..3283840 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,5 +1,10 @@
+2012-07-19 Jakub Jelinek <jakub@redhat.com>
+
+ PR middle-end/54017
+ * c-c++-common/gomp/pr54017.c: New test.
+
2012-07-19 Richard Guenther <rguenther@suse.de>
- Eric Botcazou <ebotcazou@adacore.com>
+ Eric Botcazou <ebotcazou@adacore.com>
* gnat.dg/loop_optimization11.adb: New testcase.
* gnat.dg/loop_optimization11_pkg.ads: Likewise.
diff --git a/gcc/testsuite/c-c++-common/gomp/pr54017.c b/gcc/testsuite/c-c++-common/gomp/pr54017.c
new file mode 100644
index 0000000..724efe1
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/pr54017.c
@@ -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;
+}
diff --git a/gcc/tree-cfgcleanup.c b/gcc/tree-cfgcleanup.c
index ca79e79..b665c58 100644
--- a/gcc/tree-cfgcleanup.c
+++ b/gcc/tree-cfgcleanup.c
@@ -606,48 +606,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))