Patchwork [committed] Fix move_sese_region_to_fn (PR middle-end/58551)

login
register
mail settings
Submitter Jakub Jelinek
Date Sept. 27, 2013, 1:54 p.m.
Message ID <20130927135420.GL30970@tucnak.zalov.cz>
Download mbox | patch
Permalink /patch/278589/
State New
Headers show

Comments

Jakub Jelinek - Sept. 27, 2013, 1:54 p.m.
Hi!

I've committed the following fix to a regression introduced in 4.9
early loop construction.  SESE regions, as documented above
move_sese_region_to_fn, are allowed to contain calls to noreturn functions
like abort/exit.  But, basic blocks leading to noreturn functions aren't
actually placed in the loop inside of which the SESE region is present,
but directly inside of the outermost loop of the function.

So, we can't just move change loop_father of bb's belonging to
entry_bb's loop_father to new function's outermost loop and move
loops which have their outer loop equal to entry_bb's loop_father
and have their header in the SESE region into the new function,
but we also have to handle the same way the outermost loop of the
original function.

Bootstrapped/regtested on x86_64-linux and i686-linux, preapproved by richi
on IRC, committed to trunk.

2013-09-27  Jakub Jelinek  <jakub@redhat.com>

	PR middle-end/58551
	* tree-cfg.c (move_sese_region_to_fn): Also move loops that
	are children of outermost saved_cfun's loop, and set it up to
	be moved to dest_cfun's outermost loop.  Fix up num_nodes adjustments
	if loop != loop0 and SESE region contains bbs that belong to loop0.

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



	Jakub

Patch

--- gcc/tree-cfg.c.jj	2013-09-13 14:41:28.000000000 +0200
+++ gcc/tree-cfg.c	2013-09-27 12:23:48.582217401 +0200
@@ -6662,12 +6662,13 @@  move_sese_region_to_fn (struct function
   struct function *saved_cfun = cfun;
   int *entry_flag, *exit_flag;
   unsigned *entry_prob, *exit_prob;
-  unsigned i, num_entry_edges, num_exit_edges;
+  unsigned i, num_entry_edges, num_exit_edges, num_nodes;
   edge e;
   edge_iterator ei;
   htab_t new_label_map;
   struct pointer_map_t *vars_map, *eh_map;
   struct loop *loop = entry_bb->loop_father;
+  struct loop *loop0 = get_loop (saved_cfun, 0);
   struct move_stmt_d d;
 
   /* If ENTRY does not strictly dominate EXIT, this cannot be an SESE
@@ -6760,16 +6761,29 @@  move_sese_region_to_fn (struct function
   set_loops_for_fn (dest_cfun, loops);
 
   /* Move the outlined loop tree part.  */
+  num_nodes = bbs.length ();
   FOR_EACH_VEC_ELT (bbs, i, bb)
     {
-      if (bb->loop_father->header == bb
-	  && loop_outer (bb->loop_father) == loop)
+      if (bb->loop_father->header == bb)
 	{
 	  struct loop *this_loop = bb->loop_father;
-	  flow_loop_tree_node_remove (bb->loop_father);
-	  flow_loop_tree_node_add (get_loop (dest_cfun, 0), this_loop);
-	  fixup_loop_arrays_after_move (saved_cfun, cfun, this_loop);
+	  struct loop *outer = loop_outer (this_loop);
+	  if (outer == loop
+	      /* If the SESE region contains some bbs ending with
+		 a noreturn call, those are considered to belong
+		 to the outermost loop in saved_cfun, rather than
+		 the entry_bb's loop_father.  */
+	      || outer == loop0)
+	    {
+	      if (outer != loop)
+		num_nodes -= this_loop->num_nodes;
+	      flow_loop_tree_node_remove (bb->loop_father);
+	      flow_loop_tree_node_add (get_loop (dest_cfun, 0), this_loop);
+	      fixup_loop_arrays_after_move (saved_cfun, cfun, this_loop);
+	    }
 	}
+      else if (bb->loop_father == loop0 && loop0 != loop)
+	num_nodes--;
 
       /* Remove loop exits from the outlined region.  */
       if (loops_for_fn (saved_cfun)->exits)
@@ -6789,6 +6803,7 @@  move_sese_region_to_fn (struct function
 
   /* Setup a mapping to be used by move_block_to_fn.  */
   loop->aux = current_loops->tree_root;
+  loop0->aux = current_loops->tree_root;
 
   pop_cfun ();
 
@@ -6817,11 +6832,13 @@  move_sese_region_to_fn (struct function
     }
 
   loop->aux = NULL;
+  loop0->aux = NULL;
   /* Loop sizes are no longer correct, fix them up.  */
-  loop->num_nodes -= bbs.length ();
+  loop->num_nodes -= num_nodes;
   for (struct loop *outer = loop_outer (loop);
        outer; outer = loop_outer (outer))
-    outer->num_nodes -= bbs.length ();
+    outer->num_nodes -= num_nodes;
+  loop0->num_nodes -= bbs.length () - num_nodes;
 
   if (saved_cfun->has_simduid_loops || saved_cfun->has_force_vect_loops)
     {
--- gcc/testsuite/c-c++-common/gomp/pr58551.c.jj	2013-09-27 11:18:20.825251967 +0200
+++ gcc/testsuite/c-c++-common/gomp/pr58551.c	2013-09-27 11:17:56.000000000 +0200
@@ -0,0 +1,33 @@ 
+/* PR middle-end/58551 */
+/* { dg-do compile } */
+/* { dg-options "-O0 -fopenmp" } */
+
+void
+foo (int *a)
+{
+  int i;
+  for (i = 0; i < 8; i++)
+    #pragma omp task
+    if (a[i])
+      __builtin_abort ();
+}
+
+void bar (int, int);
+
+void
+baz (int *a)
+{
+  int i;
+  for (i = 0; i < 8; i++)
+    #pragma omp task
+    if (a[i])
+      {
+	int j, k;
+	for (j = 0; j < 10; j++)
+	  for (k = 0; k < 8; k++)
+	    bar (j, k);
+	for (k = 0; k < 12; k++)
+	  bar (-1, k);
+	__builtin_abort ();
+      }
+}