Hi!

In certain cases like the testcases below there are multiple return stmts
in the function for which we create simd clones and the simd clone adjusting
code wasn't handling that case properly, some bbs could end up with
non-fallthru edges to the increment bb even without a gimple_goto at the
end, others could be missed from redirection to incr_bb.

Fixed thusly, bootstrapped/regtested on x86_64-linux and i686-linux,
committed to trunk.

2018-11-20  Jakub Jelinek  <ja...@redhat.com>

        PR tree-optimization/87895
        * omp-simd-clone.c (ipa_simd_modify_function_body): When removing
        or replacing GIMPLE_RETURN, set EDGE_FALLTHRU on the edge to EXIT.
        (simd_clone_adjust): Don't set EDGE_FALLTHRU here. In a loop that
        redirects edges to EXIT to edges to incr_bb, iterate while EXIT
        has any preds and always use EDGE_PRED (, 0).

        * gcc.dg/gomp/pr87895-1.c: New test.
        * gcc.dg/gomp/pr87895-2.c: New test.
        * gcc.dg/gomp/pr87895-3.c: New test.

--- gcc/omp-simd-clone.c.jj     2018-11-14 01:01:56.758459348 +0100
+++ gcc/omp-simd-clone.c        2018-11-20 13:57:53.902488981 +0100
@@ -994,6 +994,8 @@ ipa_simd_modify_function_body (struct cg
          if (greturn *return_stmt = dyn_cast <greturn *> (stmt))
            {
              tree retval = gimple_return_retval (return_stmt);
+             edge e = find_edge (bb, EXIT_BLOCK_PTR_FOR_FN (cfun));
+             e->flags |= EDGE_FALLTHRU;
              if (!retval)
                {
                  gsi_remove (&gsi, true);
@@ -1150,14 +1152,9 @@ simd_clone_adjust (struct cgraph_node *n
       incr_bb = create_empty_bb (orig_exit);
       incr_bb->count = profile_count::zero ();
       add_bb_to_loop (incr_bb, body_bb->loop_father);
-      /* The succ of orig_exit was EXIT_BLOCK_PTR_FOR_FN (cfun), with an empty
-        flag.  Set it now to be a FALLTHRU_EDGE.  */
-      gcc_assert (EDGE_COUNT (orig_exit->succs) == 1);
-      EDGE_SUCC (orig_exit, 0)->flags |= EDGE_FALLTHRU;
-      for (unsigned i = 0;
-          i < EDGE_COUNT (EXIT_BLOCK_PTR_FOR_FN (cfun)->preds); ++i)
+      while (EDGE_COUNT (EXIT_BLOCK_PTR_FOR_FN (cfun)->preds))
        {
-         edge e = EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun), i);
+         edge e = EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun), 0);
          redirect_edge_succ (e, incr_bb);
          incr_bb->count += e->count ();
        }
--- gcc/testsuite/gcc.dg/gomp/pr87895-1.c.jj    2018-11-20 13:18:00.483355400 
+0100
+++ gcc/testsuite/gcc.dg/gomp/pr87895-1.c       2018-11-20 13:18:28.792884133 
+0100
@@ -0,0 +1,19 @@
+/* PR tree-optimization/87895 */
+/* { dg-do compile } */
+/* { dg-additional-options "-O0" } */
+
+#pragma omp declare simd
+int
+foo (int x)
+{
+  if (x == 0)
+    return 0;
+}
+
+#pragma omp declare simd
+int
+bar (int *x, int y)
+{
+  if ((y == 0) ? (*x = 0) : *x)
+    return 0;
+}
--- gcc/testsuite/gcc.dg/gomp/pr87895-2.c.jj    2018-11-20 13:18:07.780233931 
+0100
+++ gcc/testsuite/gcc.dg/gomp/pr87895-2.c       2018-11-20 13:18:57.265410143 
+0100
@@ -0,0 +1,5 @@
+/* PR tree-optimization/87895 */
+/* { dg-do compile } */
+/* { dg-additional-options "-O1" } */
+
+#include "pr87895-1.c"
--- gcc/testsuite/gcc.dg/gomp/pr87895-3.c.jj    2018-11-20 14:06:23.131004074 
+0100
+++ gcc/testsuite/gcc.dg/gomp/pr87895-3.c       2018-11-20 14:06:03.697327933 
+0100
@@ -0,0 +1,18 @@
+/* PR tree-optimization/87895 */
+/* { dg-do compile } */
+/* { dg-additional-options "-O2" } */
+
+#pragma omp declare simd
+int foo (int x) __attribute__((noreturn));
+
+#pragma omp declare simd
+int
+bar (int x, int y)
+{
+  if (y == 1)
+    foo (x + 2);
+  if (y == 10)
+    foo (x + 6);
+  if (y != 25)
+    return 4;
+}

        Jakub

Reply via email to