From b37dddbc771d55d42c25edb0ef4dad663dff21e8 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Wed, 13 May 2015 18:59:20 +0200 Subject: [PATCH] re PR middle-end/66133 (Wrong-code with noreturn #pragma omp task body) 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. (make_gimple_omp_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: r223171 --- gcc/ChangeLog | 12 +++++++ gcc/omp-low.c | 49 ++++++++++++++++++++++++--- libgomp/ChangeLog | 5 +++ libgomp/testsuite/libgomp.c/pr66133.c | 35 +++++++++++++++++++ 4 files changed, 96 insertions(+), 5 deletions(-) create mode 100644 libgomp/testsuite/libgomp.c/pr66133.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index ce50a3625e9..dc25116f57e 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,15 @@ +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. + (make_gimple_omp_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-05-13 Kyrylo Tkachov * params.def (PARAM_MAX_POW_SQRT_DEPTH): New param. diff --git a/gcc/omp-low.c b/gcc/omp-low.c index 34e2e5c9ef1..d352801c0ce 100644 --- a/gcc/omp-low.c +++ b/gcc/omp-low.c @@ -5377,7 +5377,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; bool is_cilk_for = (flag_cilkplus @@ -5436,7 +5439,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; tree arg, narg; gimple parcopy_stmt = NULL; @@ -5524,14 +5529,28 @@ expand_omp_taskreg (struct omp_region *region) e = split_block (entry_bb, stmt); gsi_remove (&gsi, true); 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); @@ -5552,6 +5571,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); + } /* When the OMP expansion process cannot guarantee an up-to-date loop tree arrange for the child function to fixup loops. */ if (loops_state_satisfies_p (LOOPS_NEED_FIXUP)) @@ -11158,6 +11185,10 @@ lower_omp_taskreg (gimple_stmt_iterator *gsi_p, omp_context *ctx) gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label)); 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); @@ -12272,6 +12303,10 @@ make_gimple_omp_edges (basic_block bb, struct omp_region **region, 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; @@ -12320,6 +12355,10 @@ make_gimple_omp_edges (basic_block bb, struct omp_region **region, } break; + case GIMPLE_OMP_TASK: + fallthru = true; + break; + default: gcc_unreachable (); } diff --git a/libgomp/ChangeLog b/libgomp/ChangeLog index 674c7c7cb59..33ea5fbf2a2 100644 --- a/libgomp/ChangeLog +++ b/libgomp/ChangeLog @@ -1,3 +1,8 @@ +2015-05-13 Jakub Jelinek + + PR middle-end/66133 + * testsuite/libgomp.c/pr66133.c: New test. + 2015-05-13 Michael Haubenwallner * Makefile.in: Regenerated with automake-1.11.6. diff --git a/libgomp/testsuite/libgomp.c/pr66133.c b/libgomp/testsuite/libgomp.c/pr66133.c new file mode 100644 index 00000000000..e98e5aac412 --- /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); +}