Add empty loop exit block in transform_to_exit_first_loop_alt
authorTom de Vries <tom@codesourcery.com>
Tue, 7 Jul 2015 16:25:22 +0000 (16:25 +0000)
committerTom de Vries <vries@gcc.gnu.org>
Tue, 7 Jul 2015 16:25:22 +0000 (16:25 +0000)
2015-07-07  Tom de Vries  <tom@codesourcery.com>

PR tree-optimization/66642
* tree-parloops.c (transform_to_exit_first_loop_alt): Update function
header comment.  Rename split_edge variable to edge_at_split.  Split
exit edge to create new loop exit bb.  Insert loop exit phis in new loop
exit bb.

* testsuite/libgomp.c/parloops-exit-first-loop-alt-3.c (main): Test low
iteration count case.
* testsuite/libgomp.c/parloops-exit-first-loop-alt.c (init): New
function, factor out of ...
(main): ... here.  Test low iteration count case.

From-SVN: r225521

gcc/ChangeLog
gcc/tree-parloops.c
libgomp/ChangeLog
libgomp/testsuite/libgomp.c/parloops-exit-first-loop-alt-3.c
libgomp/testsuite/libgomp.c/parloops-exit-first-loop-alt.c

index 7dee74d5d3b91b59c6067079565e2c6bc653b2e1..28022d7f54d56987098dc9d90dce894baa153c55 100644 (file)
@@ -1,3 +1,11 @@
+2015-07-07  Tom de Vries  <tom@codesourcery.com>
+
+       PR tree-optimization/66642
+       * tree-parloops.c (transform_to_exit_first_loop_alt): Update function
+       header comment.  Rename split_edge variable to edge_at_split.  Split
+       exit edge to create new loop exit bb.  Insert loop exit phis in new loop
+       exit bb.
+
 2015-07-07  Tom de Vries  <tom@codesourcery.com>
 
        * tree-cfg.c (get_virtual_phi): New function.
index 4a2757dc71bf89d385f61a211ea210a7fcb8c705..aecee69c4739aff299de672737b2235efda16f47 100644 (file)
@@ -1516,7 +1516,7 @@ replace_uses_in_bb_by (tree name, tree val, basic_block bb)
      goto <bb header>
 
      <bb exit>:
-     sum_z = PHI <sum_b (cond[1])>
+     sum_z = PHI <sum_b (cond[1]), ...>
 
      [1] Where <bb cond> is single_pred (bb latch); In the simplest case,
         that's <bb header>.
@@ -1543,14 +1543,17 @@ replace_uses_in_bb_by (tree name, tree val, basic_block bb)
      if (ivtmp_c < n + 1)
        goto <bb header>;
      else
-       goto <bb exit>;
+       goto <bb newexit>;
 
      <bb latch>:
      ivtmp_b = ivtmp_a + 1;
      goto <bb newheader>
 
+     <bb newexit>:
+     sum_y = PHI <sum_c (newheader)>
+
      <bb exit>:
-     sum_z = PHI <sum_c (newheader)>
+     sum_z = PHI <sum_y (newexit), ...>
 
 
    In unified diff format:
@@ -1587,9 +1590,12 @@ replace_uses_in_bb_by (tree name, tree val, basic_block bb)
 -     goto <bb header>
 +     goto <bb newheader>
 
++    <bb newexit>:
++    sum_y = PHI <sum_c (newheader)>
+
       <bb exit>:
--     sum_z = PHI <sum_b (cond[1])>
-+     sum_z = PHI <sum_c (newheader)>
+-     sum_z = PHI <sum_b (cond[1]), ...>
++     sum_z = PHI <sum_y (newexit), ...>
 
    Note: the example does not show any virtual phis, but these are handled more
    or less as reductions.
@@ -1620,7 +1626,7 @@ transform_to_exit_first_loop_alt (struct loop *loop,
 
   /* Create the new_header block.  */
   basic_block new_header = split_block_before_cond_jump (exit->src);
-  edge split_edge = single_pred_edge (new_header);
+  edge edge_at_split = single_pred_edge (new_header);
 
   /* Redirect entry edge to new_header.  */
   edge entry = loop_preheader_edge (loop);
@@ -1637,9 +1643,9 @@ transform_to_exit_first_loop_alt (struct loop *loop,
   e = redirect_edge_and_branch (post_cond_edge, header);
   gcc_assert (e == post_cond_edge);
 
-  /* Redirect split_edge to latch.  */
-  e = redirect_edge_and_branch (split_edge, latch);
-  gcc_assert (e == split_edge);
+  /* Redirect edge_at_split to latch.  */
+  e = redirect_edge_and_branch (edge_at_split, latch);
+  gcc_assert (e == edge_at_split);
 
   /* Set the new loop bound.  */
   gimple_cond_set_rhs (cond_stmt, bound);
@@ -1691,21 +1697,36 @@ transform_to_exit_first_loop_alt (struct loop *loop,
   /* Set the latch arguments of the new phis to ivtmp/sum_b.  */
   flush_pending_stmts (post_inc_edge);
 
-  /* Register the reduction exit phis.  */
+  /* Create a new empty exit block, inbetween the new loop header and the old
+     exit block.  The function separate_decls_in_region needs this block to
+     insert code that is active on loop exit, but not any other path.  */
+  basic_block new_exit_block = split_edge (exit);
+
+  /* Insert and register the reduction exit phis.  */
   for (gphi_iterator gsi = gsi_start_phis (exit_block);
        !gsi_end_p (gsi);
        gsi_next (&gsi))
     {
       gphi *phi = gsi.phi ();
       tree res_z = PHI_RESULT (phi);
+
+      /* Now that we have a new exit block, duplicate the phi of the old exit
+        block in the new exit block to preserve loop-closed ssa.  */
+      edge succ_new_exit_block = single_succ_edge (new_exit_block);
+      edge pred_new_exit_block = single_pred_edge (new_exit_block);
+      tree res_y = copy_ssa_name (res_z, phi);
+      gphi *nphi = create_phi_node (res_y, new_exit_block);
+      tree res_c = PHI_ARG_DEF_FROM_EDGE (phi, succ_new_exit_block);
+      add_phi_arg (nphi, res_c, pred_new_exit_block, UNKNOWN_LOCATION);
+      add_phi_arg (phi, res_y, succ_new_exit_block, UNKNOWN_LOCATION);
+
       if (virtual_operand_p (res_z))
        continue;
 
-      tree res_c = PHI_ARG_DEF_FROM_EDGE (phi, exit);
       gimple reduc_phi = SSA_NAME_DEF_STMT (res_c);
       struct reduction_info *red = reduction_phi (reduction_list, reduc_phi);
       if (red != NULL)
-       red->keep_res = phi;
+       red->keep_res = nphi;
     }
 
   /* We're going to cancel the loop at the end of gen_parallel_loop, but until
index b52a29bc2ffb8374c14ff4bf166da99f7138db65..cac45ab3e003539665896db42c453386f2aee903 100644 (file)
@@ -1,3 +1,12 @@
+2015-07-07  Tom de Vries  <tom@codesourcery.com>
+
+       PR tree-optimization/66642
+       * testsuite/libgomp.c/parloops-exit-first-loop-alt-3.c (main): Test low
+       iteration count case.
+       * testsuite/libgomp.c/parloops-exit-first-loop-alt.c (init): New
+       function, factor out of ...
+       (main): ... here.  Test low iteration count case.
+
 2015-07-06  Sebastian Huber  <sebastian.huber@embedded-brains.de>
 
        * libgomp.h (gomp_thread_pool): Comment last_team field.
index 7de1377cd56956f8552fa29be0571d5f5d366f88..958e554649c1e133635c64a4c669a279a517b3da 100644 (file)
@@ -36,5 +36,10 @@ main (void)
   if (res != 11995)
     abort ();
 
+  /* Test low iteration count case.  */
+  res = f (10);
+  if (res != 25)
+    abort ();
+
   return 0;
 }
index d67a4f67ece531177c9e6056fa6a04a47fe6ad7b..557764d329370e07e587e41e1981a21d3b65fefd 100644 (file)
@@ -22,8 +22,8 @@ f (unsigned int n, unsigned int *__restrict__ a, unsigned int *__restrict__ b,
     c[i] = a[i] + b[i];
 }
 
-int
-main (void)
+static void __attribute__((noclone,noinline))
+init (void)
 {
   int i, j;
 
@@ -36,6 +36,14 @@ main (void)
        b[k] = (k * 3) % 7;
        c[k] = k * 2;
       }
+}
+
+int
+main (void)
+{
+  int i;
+
+  init ();
 
   f (N, a, b, c);
 
@@ -47,5 +55,21 @@ main (void)
        abort ();
     }
 
+  /* Test low iteration count case.  */
+
+  init ();
+
+  f (10);
+
+  for (i = 0; i < N; i++)
+    {
+      unsigned int actual = c[i];
+      unsigned int expected = (i < 10
+                              ? i + ((i * 3) % 7)
+                              : i * 2);
+      if (actual != expected)
+       abort ();
+    }
+
   return 0;
 }