summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog5
-rw-r--r--gcc/omp-low.c22
-rw-r--r--gcc/testsuite/ChangeLog3
-rw-r--r--gcc/testsuite/gcc.dg/gomp/pr27328.c19
-rw-r--r--gcc/tree-cfg.c39
5 files changed, 70 insertions, 18 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 984916d5a0c..9a0849a8794 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,10 @@
2006-05-02 Jakub Jelinek <jakub@redhat.com>
+ PR middle-end/27328
+ * omp-low.c (remove_exit_barrier): Handle NULL exit_bb.
+ (expand_omp_parallel): Likewise.
+ * tree-cfg.c (move_sese_region_to_fn): Likewise.
+
PR middle-end/27325
* omp-low.c (lower_omp_sections): Call maybe_catch_exception
on statement list containing also constructors and destructors.
diff --git a/gcc/omp-low.c b/gcc/omp-low.c
index 92d71ae025c..62b715e37ad 100644
--- a/gcc/omp-low.c
+++ b/gcc/omp-low.c
@@ -2227,6 +2227,11 @@ remove_exit_barrier (struct omp_region *region)
exit_bb = region->exit;
+ /* If the parallel region doesn't return, we don't have REGION->EXIT
+ block at all. */
+ if (! exit_bb)
+ return;
+
/* The last insn in the block will be the parallel's OMP_RETURN. The
workshare's OMP_RETURN will be in a preceding block. The kinds of
statements that can appear in between are extremely limited -- no
@@ -2372,15 +2377,20 @@ expand_omp_parallel (struct omp_region *region)
regions has invalidated it. */
free_dominance_info (CDI_DOMINATORS);
new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb);
- single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
+ if (exit_bb)
+ single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
cgraph_add_new_function (child_fn);
/* Convert OMP_RETURN into a RETURN_EXPR. */
- si = bsi_last (exit_bb);
- gcc_assert (!bsi_end_p (si) && TREE_CODE (bsi_stmt (si)) == OMP_RETURN);
- t = build1 (RETURN_EXPR, void_type_node, NULL);
- bsi_insert_after (&si, t, TSI_SAME_STMT);
- bsi_remove (&si, true);
+ if (exit_bb)
+ {
+ si = bsi_last (exit_bb);
+ gcc_assert (!bsi_end_p (si)
+ && TREE_CODE (bsi_stmt (si)) == OMP_RETURN);
+ t = build1 (RETURN_EXPR, void_type_node, NULL);
+ bsi_insert_after (&si, t, TSI_SAME_STMT);
+ bsi_remove (&si, true);
+ }
}
/* Emit a library call to launch the children threads. */
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index b0fda63339d..b890b64302b 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,5 +1,8 @@
2006-05-02 Jakub Jelinek <jakub@redhat.com>
+ PR middle-end/27328
+ * gcc.dg/gomp/pr27328.c: New test.
+
PR middle-end/27325
* g++.dg/gomp/pr27325.C: New test.
diff --git a/gcc/testsuite/gcc.dg/gomp/pr27328.c b/gcc/testsuite/gcc.dg/gomp/pr27328.c
new file mode 100644
index 00000000000..afde738a725
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/gomp/pr27328.c
@@ -0,0 +1,19 @@
+/* PR middle-end/27328 */
+/* { dg-do compile } */
+
+extern void baz (void) __attribute__((noreturn));
+
+void
+foo (void)
+{
+#pragma omp parallel
+ for (;;)
+ ;
+}
+
+void
+bar (void)
+{
+#pragma omp parallel
+ baz ();
+}
diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c
index 744a9032b5f..4c5aa4bd4e7 100644
--- a/gcc/tree-cfg.c
+++ b/gcc/tree-cfg.c
@@ -4814,7 +4814,8 @@ move_sese_region_to_fn (struct function *dest_cfun, basic_block entry_bb,
/* If ENTRY does not strictly dominate EXIT, this cannot be an SESE
region. */
gcc_assert (entry_bb != exit_bb
- && dominated_by_p (CDI_DOMINATORS, exit_bb, entry_bb));
+ && (!exit_bb
+ || dominated_by_p (CDI_DOMINATORS, exit_bb, entry_bb)));
bbs = NULL;
VEC_safe_push (basic_block, heap, bbs, entry_bb);
@@ -4835,15 +4836,25 @@ move_sese_region_to_fn (struct function *dest_cfun, basic_block entry_bb,
remove_edge (e);
}
- num_exit_edges = EDGE_COUNT (exit_bb->succs);
- exit_succ = (basic_block *) xcalloc (num_exit_edges, sizeof (basic_block));
- exit_flag = (int *) xcalloc (num_exit_edges, sizeof (int));
- i = 0;
- for (ei = ei_start (exit_bb->succs); (e = ei_safe_edge (ei)) != NULL;)
+ if (exit_bb)
{
- exit_flag[i] = e->flags;
- exit_succ[i++] = e->dest;
- remove_edge (e);
+ num_exit_edges = EDGE_COUNT (exit_bb->succs);
+ exit_succ = (basic_block *) xcalloc (num_exit_edges,
+ sizeof (basic_block));
+ exit_flag = (int *) xcalloc (num_exit_edges, sizeof (int));
+ i = 0;
+ for (ei = ei_start (exit_bb->succs); (e = ei_safe_edge (ei)) != NULL;)
+ {
+ exit_flag[i] = e->flags;
+ exit_succ[i++] = e->dest;
+ remove_edge (e);
+ }
+ }
+ else
+ {
+ num_exit_edges = 0;
+ exit_succ = NULL;
+ exit_flag = NULL;
}
/* Switch context to the child function to initialize DEST_FN's CFG. */
@@ -4923,7 +4934,8 @@ move_sese_region_to_fn (struct function *dest_cfun, basic_block entry_bb,
these helpers. */
cfun = dest_cfun;
make_edge (ENTRY_BLOCK_PTR, entry_bb, EDGE_FALLTHRU);
- make_edge (exit_bb, EXIT_BLOCK_PTR, 0);
+ if (exit_bb)
+ make_edge (exit_bb, EXIT_BLOCK_PTR, 0);
cfun = saved_cfun;
/* Back in the original function, the SESE region has disappeared,
@@ -4935,10 +4947,13 @@ move_sese_region_to_fn (struct function *dest_cfun, basic_block entry_bb,
for (i = 0; i < num_exit_edges; i++)
make_edge (bb, exit_succ[i], exit_flag[i]);
- free (exit_flag);
+ if (exit_bb)
+ {
+ free (exit_flag);
+ free (exit_succ);
+ }
free (entry_flag);
free (entry_pred);
- free (exit_succ);
free_dominance_info (CDI_DOMINATORS);
free_dominance_info (CDI_POST_DOMINATORS);
VEC_free (basic_block, heap, bbs);