From: Jakub Jelinek Date: Wed, 3 Jun 2015 21:36:26 +0000 (+0200) Subject: backport: re PR middle-end/66133 (Wrong-code with noreturn #pragma omp task body) X-Git-Tag: releases/gcc-4.8.5~90 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=30af273b80f88165cfacde7f6547561301c4c0fb;p=thirdparty%2Fgcc.git backport: re PR middle-end/66133 (Wrong-code with noreturn #pragma omp task body) Backported from mainline 2015-05-13 Jakub Jelinek 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 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index be581f6a5d29..10676df506ce 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,6 +1,18 @@ 2015-06-03 Jakub Jelinek Backported from mainline + 2015-05-13 Jakub Jelinek + + 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 PR middle-end/65680 diff --git a/gcc/omp-low.c b/gcc/omp-low.c index 694d24f11ae1..6a3969bd7b3a 100644 --- a/gcc/omp-low.c +++ b/gcc/omp-low.c @@ -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); diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c index b32da2ef6fef..71642093e107 100644 --- a/gcc/tree-cfg.c +++ b/gcc/tree-cfg.c @@ -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 (); } diff --git a/libgomp/ChangeLog b/libgomp/ChangeLog index 4da1ff243991..1128d5f2f9d7 100644 --- a/libgomp/ChangeLog +++ b/libgomp/ChangeLog @@ -1,3 +1,11 @@ +2015-06-03 Jakub Jelinek + + Backported from mainline + 2015-05-13 Jakub Jelinek + + 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 index 000000000000..e98e5aac4129 --- /dev/null +++ b/libgomp/testsuite/libgomp.c/pr66133.c @@ -0,0 +1,35 @@ +/* PR middle-end/66133 */ +/* { dg-do run } */ +/* { dg-options "-O2 -fopenmp" } */ + +#include +#include + +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); +}