[gomp] Fix ICE on noreturn OpenMP structured blocks (PR middle-end/27328)

Jakub Jelinek jakub@redhat.com
Fri Apr 28 09:21:00 GMT 2006


Hi!

As shown by the testcase below, if the structured block is proven to
never return (because of a call to noreturn function, endless
loop etc.), region->exit bb is NULL (unreachable, at ompexp time
optimized out).  While some code took that into account (e.g. omp region
dumping code), some other functions did not.

Ok for trunk?

2006-04-28  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.

	* gcc.dg/gomp/pr27328.c: New test.

--- gcc/omp-low.c.jj	2006-04-27 18:25:51.000000000 +0200
+++ gcc/omp-low.c	2006-04-28 11:09:53.000000000 +0200
@@ -2235,6 +2235,11 @@ remove_exit_barrier (struct omp_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
@@ -2380,15 +2385,20 @@ expand_omp_parallel (struct omp_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.  */
--- gcc/tree-cfg.c.jj	2006-04-18 15:33:42.000000000 +0200
+++ gcc/tree-cfg.c	2006-04-28 11:01:43.000000000 +0200
@@ -4823,7 +4823,8 @@ move_sese_region_to_fn (struct function 
   /* 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);
@@ -4844,15 +4845,25 @@ move_sese_region_to_fn (struct function 
       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.  */
@@ -4932,7 +4943,8 @@ move_sese_region_to_fn (struct function 
      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,
@@ -4944,10 +4956,13 @@ move_sese_region_to_fn (struct function 
   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);
--- gcc/testsuite/gcc.dg/gomp/pr27328.c.jj	2006-04-28 11:15:25.000000000 +0200
+++ gcc/testsuite/gcc.dg/gomp/pr27328.c	2006-04-28 11:15:46.000000000 +0200
@@ -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 ();
+}

	Jakub



More information about the Gcc-patches mailing list