]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
backport: re PR middle-end/66133 (Wrong-code with noreturn #pragma omp task body)
authorJakub Jelinek <jakub@redhat.com>
Wed, 3 Jun 2015 21:36:26 +0000 (23:36 +0200)
committerJakub Jelinek <jakub@gcc.gnu.org>
Wed, 3 Jun 2015 21:36:26 +0000 (23:36 +0200)
Backported from mainline
2015-05-13  Jakub Jelinek  <jakub@redhat.com>

PR middle-end/66133
* omp-low.c (expand_omp_taskreg): For GIMPLE_OMP_TASK expansion,
make sure it is never noreturn, even when the task body does not
return.
(lower_omp_taskreg): For GIMPLE_OMP_TASK, emit GIMPLE_OMP_CONTINUE
right before GIMPLE_OMP_RETURN.
* tree-cfg.c (make_edges): Accept GIMPLE_OMP_CONTINUE as ->cont
for GIMPLE_OMP_TASK.  For GIMPLE_OMP_RETURN corresponding to
GIMPLE_OMP_TASK add an EDGE_ABNORMAL edge from entry to exit.

* testsuite/libgomp.c/pr66133.c: New test.

From-SVN: r224105

gcc/ChangeLog
gcc/omp-low.c
gcc/tree-cfg.c
libgomp/ChangeLog
libgomp/testsuite/libgomp.c/pr66133.c [new file with mode: 0644]

index be581f6a5d29022eda2011658a38e5e729bf3243..10676df506ce659ddaa150a7cfcb5671b7001a19 100644 (file)
@@ -1,6 +1,18 @@
 2015-06-03  Jakub Jelinek  <jakub@redhat.com>
 
        Backported from mainline
+       2015-05-13  Jakub Jelinek  <jakub@redhat.com>
+
+       PR middle-end/66133
+       * omp-low.c (expand_omp_taskreg): For GIMPLE_OMP_TASK expansion,
+       make sure it is never noreturn, even when the task body does not
+       return.
+       (lower_omp_taskreg): For GIMPLE_OMP_TASK, emit GIMPLE_OMP_CONTINUE
+       right before GIMPLE_OMP_RETURN.
+       * tree-cfg.c (make_edges): Accept GIMPLE_OMP_CONTINUE as ->cont
+       for GIMPLE_OMP_TASK.  For GIMPLE_OMP_RETURN corresponding to
+       GIMPLE_OMP_TASK add an EDGE_ABNORMAL edge from entry to exit.
+
        2015-04-07  Jakub Jelinek  <jakub@redhat.com>
 
        PR middle-end/65680
index 694d24f11ae1b80dccca83ae88fbca8801c72f62..6a3969bd7b3a1106c981d78d0e33d05c1a489551 100644 (file)
@@ -3487,7 +3487,10 @@ expand_omp_taskreg (struct omp_region *region)
   child_cfun = DECL_STRUCT_FUNCTION (child_fn);
 
   entry_bb = region->entry;
-  exit_bb = region->exit;
+  if (gimple_code (entry_stmt) == GIMPLE_OMP_TASK)
+    exit_bb = region->cont;
+  else
+    exit_bb = region->exit;
 
   if (is_combined_parallel (region))
     ws_args = region->ws_args;
@@ -3536,7 +3539,9 @@ expand_omp_taskreg (struct omp_region *region)
         variable.  In which case, we need to keep the assignment.  */
       if (gimple_omp_taskreg_data_arg (entry_stmt))
        {
-         basic_block entry_succ_bb = single_succ (entry_bb);
+         basic_block entry_succ_bb
+           = single_succ_p (entry_bb) ? single_succ (entry_bb)
+                                      : FALLTHRU_EDGE (entry_bb)->dest;
          gimple_stmt_iterator gsi;
          tree arg, narg;
          gimple parcopy_stmt = NULL;
@@ -3625,14 +3630,28 @@ expand_omp_taskreg (struct omp_region *region)
       gsi_remove (&gsi, true);
       e = split_block (entry_bb, stmt);
       entry_bb = e->dest;
-      single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
+      edge e2 = NULL;
+      if (gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL)
+       single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
+      else
+       {
+         e2 = make_edge (e->src, BRANCH_EDGE (entry_bb)->dest, EDGE_ABNORMAL);
+         gcc_assert (e2->dest == region->exit);
+         remove_edge (BRANCH_EDGE (entry_bb));
+         set_immediate_dominator (CDI_DOMINATORS, e2->dest, e->src);
+         gsi = gsi_last_bb (region->exit);
+         gcc_assert (!gsi_end_p (gsi)
+                     && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
+         gsi_remove (&gsi, true);
+       }
 
-      /* Convert GIMPLE_OMP_RETURN into a RETURN_EXPR.  */
+      /* Convert GIMPLE_OMP_{RETURN,CONTINUE} into a RETURN_EXPR.  */
       if (exit_bb)
        {
          gsi = gsi_last_bb (exit_bb);
          gcc_assert (!gsi_end_p (gsi)
-                     && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
+                     && (gimple_code (gsi_stmt (gsi))
+                         == (e2 ? GIMPLE_OMP_CONTINUE : GIMPLE_OMP_RETURN)));
          stmt = gimple_build_return (NULL);
          gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
          gsi_remove (&gsi, true);
@@ -3653,6 +3672,14 @@ expand_omp_taskreg (struct omp_region *region)
       new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
       if (exit_bb)
        single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
+      if (e2)
+       {
+         basic_block dest_bb = e2->dest;
+         if (!exit_bb)
+           make_edge (new_bb, dest_bb, EDGE_FALLTHRU);
+         remove_edge (e2);
+         set_immediate_dominator (CDI_DOMINATORS, dest_bb, new_bb);
+       }
 
       /* Remove non-local VAR_DECLs from child_cfun->local_decls list.  */
       num = vec_safe_length (child_cfun->local_decls);
@@ -7020,6 +7047,10 @@ lower_omp_taskreg (gimple_stmt_iterator *gsi_p, omp_context *ctx)
   gimple_seq_add_seq (&new_body, par_body);
   gimple_seq_add_seq (&new_body, par_olist);
   new_body = maybe_catch_exception (new_body);
+  if (gimple_code (stmt) == GIMPLE_OMP_TASK)
+    gimple_seq_add_stmt (&new_body,
+                        gimple_build_omp_continue (integer_zero_node,
+                                                   integer_zero_node));
   gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
   gimple_omp_set_body (stmt, new_body);
 
index b32da2ef6fefb2a8c2ff6b111656afe8b33207f1..71642093e107f396f45563fca415a8474f1875c9 100644 (file)
@@ -589,6 +589,10 @@ make_edges (void)
                 somewhere other than the next block.  This will be
                 created later.  */
              cur_region->exit = bb;
+             if (cur_region->type == GIMPLE_OMP_TASK)
+               /* Add an edge corresponding to not scheduling the task
+                  immediately.  */
+               make_edge (cur_region->entry, bb, EDGE_ABNORMAL);
              fallthru = cur_region->type != GIMPLE_OMP_SECTION;
              cur_region = cur_region->outer;
              break;
@@ -637,6 +641,10 @@ make_edges (void)
                  }
                  break;
 
+               case GIMPLE_OMP_TASK:
+                 fallthru = true;
+                 break;
+
                default:
                  gcc_unreachable ();
                }
index 4da1ff2439913ef917f4789f71f193d81a97d8da..1128d5f2f9d77ec6c7c4735597314daa24269366 100644 (file)
@@ -1,3 +1,11 @@
+2015-06-03  Jakub Jelinek  <jakub@redhat.com>
+
+       Backported from mainline
+       2015-05-13  Jakub Jelinek  <jakub@redhat.com>
+
+       PR middle-end/66133
+       * testsuite/libgomp.c/pr66133.c: New test.
+
 2014-12-19  Release Manager
 
        * GCC 4.8.4 released.
diff --git a/libgomp/testsuite/libgomp.c/pr66133.c b/libgomp/testsuite/libgomp.c/pr66133.c
new file mode 100644 (file)
index 0000000..e98e5aa
--- /dev/null
@@ -0,0 +1,35 @@
+/* PR middle-end/66133 */
+/* { dg-do run } */
+/* { dg-options "-O2 -fopenmp" } */
+
+#include <stdlib.h>
+#include <unistd.h>
+
+volatile int x;
+
+__attribute__((noinline)) void
+foo (void)
+{
+  if (x == 0)
+    {
+      #pragma omp task
+       {
+         usleep (2000);
+         exit (0);
+       }
+    }
+  else
+    abort ();
+}
+
+int
+main ()
+{
+  #pragma omp parallel num_threads (2)
+    {
+      #pragma omp barrier
+      #pragma omp single
+       foo ();
+    }
+  exit (0);
+}