From 815d9cc6641a3eeb6734a98f64ea8b183a495ee5 Mon Sep 17 00:00:00 2001 From: Xi Ruoyao Date: Mon, 1 May 2017 22:26:02 +0000 Subject: [PATCH] re PR c++/80038 (Random segfault using local vectors in Cilk function) 2017-05-01 Xi Ruoyao PR c++/80038 * cilk_common.c (expand_builtin_cilk_detach): Move pedigree operations here. * gimplify.c (gimplify_cilk_detach): New function. (gimplify_call_expr, gimplify_modify_expr): Call it as needed. * tree-core.h: Document EXPR_CILK_SPAWN. * tree.h (EXPR_CILK_SPAWN): Define. PR c++/80038 * c-common.h (cilk_gimplify_call_params_in_spawned_fn): Remove prototype. (cilk_install_body_pedigree_operations): Likewise. * cilk.c (cilk_set_spawn_marker): Mark functions that should be detatched. (cilk_gimplify_call_params_in_spawned_fn): Remove. (cilk_install_body_pedigree_operations): Likewise. (gimplify_cilk_spawn): Add EXPR_STMT and CLEANUP_POINT_EXPR unwrapping. PR c++/80038 * c-gimplify.c (c_gimplify_expr): Remove calls to cilk_gimplifY_call_params_in_spawned_fn. PR c++/80038 * cp-cilkplus.c (cilk_install_body_with_frame_cleanup): Don't add pedigree operation and detach call here. * cp-gimplify.c (cp_gimplify_expr): Remove the calls to cilk_cp_gimplify_call_params_in_spawned_fn. (cilk_cp_gimplify_call_params_in_spawned_fn): Remove function. * semantics.c (simplify_aggr_init_expr): Copy EXPR_CILK_SPAWN. PR c++/80038 * lto-lang.c (lto_init): Set in_lto_p earlier. PR c++/80038 * g++.dg/cilk-plus/CK/pr80038.cc: New test. From-SVN: r247446 --- gcc/ChangeLog | 10 ++ gcc/c-family/ChangeLog | 13 +++ gcc/c-family/c-common.h | 2 - gcc/c-family/c-gimplify.c | 10 +- gcc/c-family/cilk.c | 102 ++----------------- gcc/c/ChangeLog | 6 ++ gcc/c/c-typeck.c | 8 +- gcc/cilk-common.c | 49 +++++++++ gcc/cp/ChangeLog | 10 ++ gcc/cp/cp-cilkplus.c | 6 +- gcc/cp/cp-gimplify.c | 40 +------- gcc/cp/semantics.c | 2 + gcc/gimplify.c | 21 ++++ gcc/lto/ChangeLog | 5 + gcc/lto/lto-lang.c | 6 +- gcc/testsuite/ChangeLog | 5 + gcc/testsuite/g++.dg/cilk-plus/CK/pr80038.cc | 47 +++++++++ gcc/tree-core.h | 4 + gcc/tree.h | 6 ++ 19 files changed, 199 insertions(+), 153 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cilk-plus/CK/pr80038.cc diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 6441ac1e688..4b01ed82fb8 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,13 @@ +2017-05-01 Xi Ruoyao + + PR c++/80038 + * cilk_common.c (expand_builtin_cilk_detach): Move pedigree + operations here. + * gimplify.c (gimplify_cilk_detach): New function. + (gimplify_call_expr, gimplify_modify_expr): Call it as needed. + * tree-core.h: Document EXPR_CILK_SPAWN. + * tree.h (EXPR_CILK_SPAWN): Define. + 2017-05-01 David Malcolm * diagnostic-show-locus.c (layout::get_expanded_location): Rewrite diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog index 8f6f55b73bf..23f52389ee0 100644 --- a/gcc/c-family/ChangeLog +++ b/gcc/c-family/ChangeLog @@ -1,3 +1,16 @@ +2017-05-01 Xi Ruoyao + + PR c++/80038 + * c-common.h (cilk_gimplify_call_params_in_spawned_fn): Remove + prototype. + (cilk_install_body_pedigree_operations): Likewise. + * cilk.c (cilk_set_spawn_marker): Mark functions that should be + detatched. + (cilk_gimplify_call_params_in_spawned_fn): Remove. + (cilk_install_body_pedigree_operations): Likewise. + (gimplify_cilk_spawn): Add EXPR_STMT and CLEANUP_POINT_EXPR + unwrapping. + 2017-04-27 Jakub Jelinek PR c++/80534 diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h index b9333420434..138a0a675ac 100644 --- a/gcc/c-family/c-common.h +++ b/gcc/c-family/c-common.h @@ -1463,7 +1463,6 @@ extern bool is_cilkplus_vector_p (tree); extern tree insert_cilk_frame (tree); extern void cilk_init_builtins (void); extern int gimplify_cilk_spawn (tree *); -extern void cilk_gimplify_call_params_in_spawned_fn (tree *, gimple_seq *); extern void cilk_install_body_with_frame_cleanup (tree, tree, void *); extern bool cilk_detect_spawn_and_unwrap (tree *); extern bool cilk_set_spawn_marker (location_t, tree); @@ -1471,7 +1470,6 @@ extern tree build_cilk_sync (void); extern tree build_cilk_spawn (location_t, tree); extern tree make_cilk_frame (tree); extern tree create_cilk_function_exit (tree, bool, bool); -extern tree cilk_install_body_pedigree_operations (tree); extern void cilk_outline (tree, tree *, void *); extern bool contains_cilk_spawn_stmt (tree); extern tree cilk_for_number_of_iterations (tree); diff --git a/gcc/c-family/c-gimplify.c b/gcc/c-family/c-gimplify.c index 57edb41af0f..1ae75d294ff 100644 --- a/gcc/c-family/c-gimplify.c +++ b/gcc/c-family/c-gimplify.c @@ -280,10 +280,7 @@ c_gimplify_expr (tree *expr_p, gimple_seq *pre_p ATTRIBUTE_UNUSED, && cilk_detect_spawn_and_unwrap (expr_p)); if (!seen_error ()) - { - cilk_gimplify_call_params_in_spawned_fn (expr_p, pre_p); - return (enum gimplify_status) gimplify_cilk_spawn (expr_p); - } + return (enum gimplify_status) gimplify_cilk_spawn (expr_p); return GS_ERROR; case MODIFY_EXPR: @@ -295,10 +292,7 @@ c_gimplify_expr (tree *expr_p, gimple_seq *pre_p ATTRIBUTE_UNUSED, original expression (MODIFY/INIT/CALL_EXPR) is processes as it is supposed to be. */ && !seen_error ()) - { - cilk_gimplify_call_params_in_spawned_fn (expr_p, pre_p); - return (enum gimplify_status) gimplify_cilk_spawn (expr_p); - } + return (enum gimplify_status) gimplify_cilk_spawn (expr_p); default:; } diff --git a/gcc/c-family/cilk.c b/gcc/c-family/cilk.c index 43478fff914..e6df498e471 100644 --- a/gcc/c-family/cilk.c +++ b/gcc/c-family/cilk.c @@ -109,6 +109,10 @@ cilk_set_spawn_marker (location_t loc, tree fcall) else { cfun->calls_cilk_spawn = true; + if (TREE_CODE (fcall) == CALL_EXPR) + EXPR_CILK_SPAWN (fcall) = 1; + else /* TREE_CODE (fcall) == TARGET_EXPR */ + EXPR_CILK_SPAWN (TREE_OPERAND (fcall, 1)) = 1; return true; } } @@ -775,37 +779,6 @@ create_cilk_wrapper (tree exp, tree *args_out) return fndecl; } -/* Gimplify all the parameters for the Spawned function. *EXPR_P can be a - CALL_EXPR, INIT_EXPR, MODIFY_EXPR or TARGET_EXPR. *PRE_P and *POST_P are - gimple sequences from the caller of gimplify_cilk_spawn. */ - -void -cilk_gimplify_call_params_in_spawned_fn (tree *expr_p, gimple_seq *pre_p) -{ - int ii = 0; - tree *fix_parm_expr = expr_p; - - /* Remove CLEANUP_POINT_EXPR and EXPR_STMT from *spawn_p. */ - while (TREE_CODE (*fix_parm_expr) == CLEANUP_POINT_EXPR - || TREE_CODE (*fix_parm_expr) == EXPR_STMT) - *fix_parm_expr = TREE_OPERAND (*fix_parm_expr, 0); - - if ((TREE_CODE (*expr_p) == INIT_EXPR) - || (TREE_CODE (*expr_p) == TARGET_EXPR) - || (TREE_CODE (*expr_p) == MODIFY_EXPR)) - fix_parm_expr = &TREE_OPERAND (*expr_p, 1); - - if (TREE_CODE (*fix_parm_expr) == CALL_EXPR) - { - /* Cilk outlining assumes GENERIC bodies, avoid leaking SSA names - via parameters. */ - for (ii = 0; ii < call_expr_nargs (*fix_parm_expr); ii++) - gimplify_arg (&CALL_EXPR_ARG (*fix_parm_expr, ii), pre_p, - EXPR_LOCATION (*fix_parm_expr), false); - } -} - - /* Transform *SPAWN_P, a spawned CALL_EXPR, to gimple. *SPAWN_P can be a CALL_EXPR, INIT_EXPR or MODIFY_EXPR. Returns GS_OK if everything is fine, and GS_UNHANDLED, otherwise. */ @@ -823,6 +796,12 @@ gimplify_cilk_spawn (tree *spawn_p) cfun->calls_cilk_spawn = 1; cfun->is_cilk_function = 1; + + /* Remove CLEANUP_POINT_EXPR and EXPR_STMT from *spawn_p. */ + while (TREE_CODE (expr) == CLEANUP_POINT_EXPR + || TREE_CODE (expr) == EXPR_STMT) + expr = TREE_OPERAND (expr, 0); + new_args = NULL; function = create_cilk_wrapper (expr, &new_args); @@ -889,67 +868,6 @@ make_cilk_frame (tree fn) return decl; } -/* Returns a STATEMENT_LIST with all the pedigree operations required for - install body with frame cleanup functions. FRAME_PTR is the pointer to - __cilkrts_stack_frame created by make_cilk_frame. */ - -tree -cilk_install_body_pedigree_operations (tree frame_ptr) -{ - tree body_list = alloc_stmt_list (); - tree enter_frame = build_call_expr (cilk_enter_fast_fndecl, 1, frame_ptr); - append_to_statement_list (enter_frame, &body_list); - - tree parent = cilk_arrow (frame_ptr, CILK_TI_FRAME_PARENT, 0); - tree worker = cilk_arrow (frame_ptr, CILK_TI_FRAME_WORKER, 0); - - tree pedigree = cilk_arrow (frame_ptr, CILK_TI_FRAME_PEDIGREE, 0); - tree pedigree_rank = cilk_dot (pedigree, CILK_TI_PEDIGREE_RANK, 0); - tree parent_pedigree = cilk_dot (pedigree, CILK_TI_PEDIGREE_PARENT, 0); - tree pedigree_parent = cilk_arrow (parent, CILK_TI_FRAME_PEDIGREE, 0); - tree pedigree_parent_rank = cilk_dot (pedigree_parent, - CILK_TI_PEDIGREE_RANK, 0); - tree pedigree_parent_parent = cilk_dot (pedigree_parent, - CILK_TI_PEDIGREE_PARENT, 0); - tree worker_pedigree = cilk_arrow (worker, CILK_TI_WORKER_PEDIGREE, 1); - tree w_pedigree_rank = cilk_dot (worker_pedigree, CILK_TI_PEDIGREE_RANK, 0); - tree w_pedigree_parent = cilk_dot (worker_pedigree, - CILK_TI_PEDIGREE_PARENT, 0); - - /* sf.pedigree.rank = worker->pedigree.rank. */ - tree exp1 = build2 (MODIFY_EXPR, void_type_node, pedigree_rank, - w_pedigree_rank); - append_to_statement_list (exp1, &body_list); - - /* sf.pedigree.parent = worker->pedigree.parent. */ - exp1 = build2 (MODIFY_EXPR, void_type_node, parent_pedigree, - w_pedigree_parent); - append_to_statement_list (exp1, &body_list); - - /* sf.call_parent->pedigree.rank = worker->pedigree.rank. */ - exp1 = build2 (MODIFY_EXPR, void_type_node, pedigree_parent_rank, - w_pedigree_rank); - append_to_statement_list (exp1, &body_list); - - /* sf.call_parent->pedigree.parent = worker->pedigree.parent. */ - exp1 = build2 (MODIFY_EXPR, void_type_node, pedigree_parent_parent, - w_pedigree_parent); - append_to_statement_list (exp1, &body_list); - - /* sf->worker.pedigree.rank = 0. */ - exp1 = build2 (MODIFY_EXPR, void_type_node, w_pedigree_rank, - build_zero_cst (uint64_type_node)); - append_to_statement_list (exp1, &body_list); - - /* sf->pedigree.parent = &sf->pedigree. */ - exp1 = build2 (MODIFY_EXPR, void_type_node, w_pedigree_parent, - build1 (ADDR_EXPR, - build_pointer_type (cilk_pedigree_type_decl), - pedigree)); - append_to_statement_list (exp1, &body_list); - return body_list; -} - /* Add a new variable, VAR to a variable list in WD->DECL_MAP. HOW indicates whether the variable is previously defined, currently defined, or a variable that is being written to. */ diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog index 5587e2f8b84..3c26eac9050 100644 --- a/gcc/c/ChangeLog +++ b/gcc/c/ChangeLog @@ -1,3 +1,9 @@ +2017-05-01 Xi Ruoyao + + PR c++/80038 + * c-gimplify.c (c_gimplify_expr): Remove calls to + cilk_gimplifY_call_params_in_spawned_fn. + 2017-04-25 David Malcolm * c-parser.c (c_parser_struct_or_union_specifier): Add fix-it diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c index ff239e2d628..6f9909c6396 100644 --- a/gcc/c/c-typeck.c +++ b/gcc/c/c-typeck.c @@ -14215,14 +14215,8 @@ cilk_install_body_with_frame_cleanup (tree fndecl, tree body, void *w) add_local_decl (cfun, frame); DECL_SAVED_TREE (fndecl) = list; - tree frame_ptr = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (frame)), - frame); - tree body_list = cilk_install_body_pedigree_operations (frame_ptr); - gcc_assert (TREE_CODE (body_list) == STATEMENT_LIST); - - tree detach_expr = build_call_expr (cilk_detach_fndecl, 1, frame_ptr); - append_to_statement_list (detach_expr, &body_list); + tree body_list = alloc_stmt_list (); cilk_outline (fndecl, &body, (struct wrapper_data *) w); body = fold_build_cleanup_point_expr (void_type_node, body); diff --git a/gcc/cilk-common.c b/gcc/cilk-common.c index 46626b75b23..9cbe03f8e02 100644 --- a/gcc/cilk-common.c +++ b/gcc/cilk-common.c @@ -365,11 +365,60 @@ expand_builtin_cilk_detach (tree exp) tree worker = cilk_dot (fptr, CILK_TI_FRAME_WORKER, 0); tree tail = cilk_arrow (worker, CILK_TI_WORKER_TAIL, 1); + tree faddr = build1 (ADDR_EXPR, cilk_frame_ptr_type_decl, fptr); + tree enter_frame = build_call_expr (cilk_enter_fast_fndecl, 1, faddr); + expand_expr (enter_frame, const0_rtx, VOIDmode, EXPAND_NORMAL); + + tree pedigree = cilk_dot (fptr, CILK_TI_FRAME_PEDIGREE, 0); + tree pedigree_rank = cilk_dot (pedigree, CILK_TI_PEDIGREE_RANK, 0); + tree parent_pedigree = cilk_dot (pedigree, CILK_TI_PEDIGREE_PARENT, 0); + tree pedigree_parent = cilk_arrow (parent, CILK_TI_FRAME_PEDIGREE, 0); + tree pedigree_parent_rank = cilk_dot (pedigree_parent, + CILK_TI_PEDIGREE_RANK, 0); + tree pedigree_parent_parent = cilk_dot (pedigree_parent, + CILK_TI_PEDIGREE_PARENT, 0); + tree worker_pedigree = cilk_arrow (worker, CILK_TI_WORKER_PEDIGREE, 1); + tree w_pedigree_rank = cilk_dot (worker_pedigree, CILK_TI_PEDIGREE_RANK, 0); + tree w_pedigree_parent = cilk_dot (worker_pedigree, + CILK_TI_PEDIGREE_PARENT, 0); + rtx wreg = expand_expr (worker, NULL_RTX, Pmode, EXPAND_NORMAL); if (GET_CODE (wreg) != REG) wreg = copy_to_reg (wreg); rtx preg = expand_expr (parent, NULL_RTX, Pmode, EXPAND_NORMAL); + /* sf.pedigree.rank = worker->pedigree.rank. */ + tree exp1 = build2 (MODIFY_EXPR, void_type_node, pedigree_rank, + w_pedigree_rank); + expand_expr (exp1, const0_rtx, VOIDmode, EXPAND_NORMAL); + + /* sf.pedigree.parent = worker->pedigree.parent. */ + exp1 = build2 (MODIFY_EXPR, void_type_node, parent_pedigree, + w_pedigree_parent); + expand_expr (exp1, const0_rtx, VOIDmode, EXPAND_NORMAL); + + /* sf.call_parent->pedigree.rank = worker->pedigree.rank. */ + exp1 = build2 (MODIFY_EXPR, void_type_node, pedigree_parent_rank, + w_pedigree_rank); + expand_expr (exp1, const0_rtx, VOIDmode, EXPAND_NORMAL); + + /* sf.call_parent->pedigree.parent = worker->pedigree.parent. */ + exp1 = build2 (MODIFY_EXPR, void_type_node, pedigree_parent_parent, + w_pedigree_parent); + expand_expr (exp1, const0_rtx, VOIDmode, EXPAND_NORMAL); + + /* sf->worker.pedigree.rank = 0. */ + exp1 = build2 (MODIFY_EXPR, void_type_node, w_pedigree_rank, + build_zero_cst (uint64_type_node)); + expand_expr (exp1, const0_rtx, VOIDmode, EXPAND_NORMAL); + + /* sf->pedigree.parent = &sf->pedigree. */ + exp1 = build2 (MODIFY_EXPR, void_type_node, w_pedigree_parent, + build1 (ADDR_EXPR, + build_pointer_type (cilk_pedigree_type_decl), + pedigree)); + expand_expr (exp1, const0_rtx, VOIDmode, EXPAND_NORMAL); + /* TMP <- WORKER.TAIL *TMP <- PARENT TMP <- TMP + 1 diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 9c9818fa9ab..183f7365a59 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,13 @@ +2017-05-01 Xi Ruoyao + + PR c++/80038 + * cp-cilkplus.c (cilk_install_body_with_frame_cleanup): Don't + add pedigree operation and detach call here. + * cp-gimplify.c (cp_gimplify_expr): Remove the calls to + cilk_cp_gimplify_call_params_in_spawned_fn. + (cilk_cp_gimplify_call_params_in_spawned_fn): Remove function. + * semantics.c (simplify_aggr_init_expr): Copy EXPR_CILK_SPAWN. + 2017-04-29 Volker Reichelt * parser.c (cp_parser_member_declaration): Add fix-it hints for diff --git a/gcc/cp/cp-cilkplus.c b/gcc/cp/cp-cilkplus.c index d147e7eac13..7c664482371 100644 --- a/gcc/cp/cp-cilkplus.c +++ b/gcc/cp/cp-cilkplus.c @@ -223,11 +223,7 @@ cilk_install_body_with_frame_cleanup (tree fndecl, tree orig_body, void *wd) location_t loc = EXPR_LOCATION (orig_body); tree list = alloc_stmt_list (); DECL_SAVED_TREE (fndecl) = list; - tree fptr = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (frame)), frame); - tree body = cilk_install_body_pedigree_operations (fptr); - gcc_assert (TREE_CODE (body) == STATEMENT_LIST); - tree detach_expr = build_call_expr (cilk_detach_fndecl, 1, fptr); - append_to_statement_list (detach_expr, &body); + tree body = alloc_stmt_list (); cilk_outline (fndecl, &orig_body, (struct wrapper_data *) wd); append_to_statement_list (orig_body, &body); if (flag_exceptions) diff --git a/gcc/cp/cp-gimplify.c b/gcc/cp/cp-gimplify.c index f2c52963a9f..de62414ec3c 100644 --- a/gcc/cp/cp-gimplify.c +++ b/gcc/cp/cp-gimplify.c @@ -88,25 +88,6 @@ finish_bc_block (tree *block, enum bc_t bc, tree label) DECL_CHAIN (label) = NULL_TREE; } -/* This function is a wrapper for cilk_gimplify_call_params_in_spawned_fn. - *EXPR_P can be a CALL_EXPR, INIT_EXPR, MODIFY_EXPR, AGGR_INIT_EXPR or - TARGET_EXPR. *PRE_P and *POST_P are gimple sequences from the caller - of gimplify_cilk_spawn. */ - -static void -cilk_cp_gimplify_call_params_in_spawned_fn (tree *expr_p, gimple_seq *pre_p, - gimple_seq *post_p) -{ - int ii = 0; - - cilk_gimplify_call_params_in_spawned_fn (expr_p, pre_p); - if (TREE_CODE (*expr_p) == AGGR_INIT_EXPR) - for (ii = 0; ii < aggr_init_expr_nargs (*expr_p); ii++) - gimplify_expr (&AGGR_INIT_EXPR_ARG (*expr_p, ii), pre_p, post_p, - is_gimple_reg, fb_rvalue); -} - - /* Get the LABEL_EXPR to represent a break or continue statement in the current block scope. BC indicates which. */ @@ -647,11 +628,7 @@ cp_gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p) if (fn_contains_cilk_spawn_p (cfun)) { if (cilk_cp_detect_spawn_and_unwrap (expr_p)) - { - cilk_cp_gimplify_call_params_in_spawned_fn (expr_p, - pre_p, post_p); - return (enum gimplify_status) gimplify_cilk_spawn (expr_p); - } + return (enum gimplify_status) gimplify_cilk_spawn (expr_p); if (seen_error () && contains_cilk_spawn_stmt (*expr_p)) return GS_ERROR; } @@ -666,10 +643,7 @@ cp_gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p) if (fn_contains_cilk_spawn_p (cfun) && cilk_cp_detect_spawn_and_unwrap (expr_p) && !seen_error ()) - { - cilk_cp_gimplify_call_params_in_spawned_fn (expr_p, pre_p, post_p); - return (enum gimplify_status) gimplify_cilk_spawn (expr_p); - } + return (enum gimplify_status) gimplify_cilk_spawn (expr_p); /* If the back end isn't clever enough to know that the lhs and rhs types are the same, add an explicit conversion. */ tree op0 = TREE_OPERAND (*expr_p, 0); @@ -787,20 +761,14 @@ cp_gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p) && cilk_cp_detect_spawn_and_unwrap (expr_p)); if (!seen_error ()) - { - cilk_cp_gimplify_call_params_in_spawned_fn (expr_p, pre_p, post_p); - return (enum gimplify_status) gimplify_cilk_spawn (expr_p); - } + return (enum gimplify_status) gimplify_cilk_spawn (expr_p); return GS_ERROR; case CALL_EXPR: if (fn_contains_cilk_spawn_p (cfun) && cilk_cp_detect_spawn_and_unwrap (expr_p) && !seen_error ()) - { - cilk_cp_gimplify_call_params_in_spawned_fn (expr_p, pre_p, post_p); - return (enum gimplify_status) gimplify_cilk_spawn (expr_p); - } + return (enum gimplify_status) gimplify_cilk_spawn (expr_p); ret = GS_OK; if (!CALL_EXPR_FN (*expr_p)) /* Internal function call. */; diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 0a695008ada..4db2462734d 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -4103,6 +4103,8 @@ simplify_aggr_init_expr (tree *tp) = CALL_EXPR_OPERATOR_SYNTAX (aggr_init_expr); CALL_EXPR_ORDERED_ARGS (call_expr) = CALL_EXPR_ORDERED_ARGS (aggr_init_expr); CALL_EXPR_REVERSE_ARGS (call_expr) = CALL_EXPR_REVERSE_ARGS (aggr_init_expr); + /* Preserve CILK_SPAWN flag. */ + EXPR_CILK_SPAWN (call_expr) = EXPR_CILK_SPAWN (aggr_init_expr); if (style == ctor) { diff --git a/gcc/gimplify.c b/gcc/gimplify.c index c69d5b93534..fd27eb1523f 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -3071,6 +3071,19 @@ maybe_fold_stmt (gimple_stmt_iterator *gsi) return fold_stmt (gsi); } +/* Add a gimple call to __builtin_cilk_detach to GIMPLE sequence PRE_P, + with the pointer to the proper cilk frame. */ +static void +gimplify_cilk_detach (gimple_seq *pre_p) +{ + tree frame = cfun->cilk_frame_decl; + tree ptrf = build1 (ADDR_EXPR, cilk_frame_ptr_type_decl, + frame); + gcall *detach = gimple_build_call (cilk_detach_fndecl, 1, + ptrf); + gimplify_seq_add_stmt(pre_p, detach); +} + /* Gimplify the CALL_EXPR node *EXPR_P into the GIMPLE sequence PRE_P. WANT_VALUE is true if the result of the call is desired. */ @@ -3107,6 +3120,9 @@ gimplify_call_expr (tree *expr_p, gimple_seq *pre_p, bool want_value) EXPR_LOCATION (*expr_p)); vargs.quick_push (CALL_EXPR_ARG (*expr_p, i)); } + + if (EXPR_CILK_SPAWN (*expr_p)) + gimplify_cilk_detach (pre_p); gimple *call = gimple_build_call_internal_vec (ifn, vargs); gimplify_seq_add_stmt (pre_p, call); return GS_ALL_DONE; @@ -3338,6 +3354,8 @@ gimplify_call_expr (tree *expr_p, gimple_seq *pre_p, bool want_value) call = gimple_build_call_from_tree (*expr_p); gimple_call_set_fntype (call, TREE_TYPE (fnptrtype)); notice_special_calls (call); + if (EXPR_CILK_SPAWN (*expr_p)) + gimplify_cilk_detach (pre_p); gimplify_seq_add_stmt (pre_p, call); gsi = gsi_last (*pre_p); maybe_fold_stmt (&gsi); @@ -5620,6 +5638,9 @@ gimplify_modify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, SSA name w/o a definition. We may have uses in the GIMPLE IL. ??? This doesn't make it a default-def. */ SSA_NAME_DEF_STMT (*to_p) = gimple_build_nop (); + + if (EXPR_CILK_SPAWN (*from_p)) + gimplify_cilk_detach (pre_p); assign = call_stmt; } else diff --git a/gcc/lto/ChangeLog b/gcc/lto/ChangeLog index d24dd0cfa0f..62304fcc3a1 100644 --- a/gcc/lto/ChangeLog +++ b/gcc/lto/ChangeLog @@ -1,3 +1,8 @@ +2017-05-01 Xi Ruoyao + + PR c++/80038 + * lto-lang.c (lto_init): Set in_lto_p earlier. + 2017-04-12 Richard Biener Bernd Edlinger diff --git a/gcc/lto/lto-lang.c b/gcc/lto/lto-lang.c index ca8945e53bb..52ab2a8cb81 100644 --- a/gcc/lto/lto-lang.c +++ b/gcc/lto/lto-lang.c @@ -1201,6 +1201,9 @@ lto_init (void) { int i; + /* Initialize LTO-specific data structures. */ + in_lto_p = true; + /* We need to generate LTO if running in WPA mode. */ flag_generate_lto = (flag_wpa != NULL); @@ -1283,9 +1286,6 @@ lto_init (void) } #undef NAME_TYPE - /* Initialize LTO-specific data structures. */ - in_lto_p = true; - return true; } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index dc80b563f5f..205c083e3be 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2017-05-01 Xi Ruoyao + + PR c++/80038 + * g++.dg/cilk-plus/CK/pr80038.cc: New test. + 2017-05-01 David Malcolm * gcc.dg/Wmissing-braces-fixits.c: Update expected output to diff --git a/gcc/testsuite/g++.dg/cilk-plus/CK/pr80038.cc b/gcc/testsuite/g++.dg/cilk-plus/CK/pr80038.cc new file mode 100644 index 00000000000..85990e5a007 --- /dev/null +++ b/gcc/testsuite/g++.dg/cilk-plus/CK/pr80038.cc @@ -0,0 +1,47 @@ +/* { dg-options "-fcilkplus" } */ +/* { dg-do run } */ +/* { dg-require-effective-target cilkplus_runtime } */ + +#include +extern "C" { + extern int __cilkrts_set_param (const char *, const char *); +} + +int objcnt = 0; + +struct foo +{ + int live; + foo () + { objcnt++; } + foo (const foo &) + { objcnt++; } + ~foo () + { objcnt--; } +}; + +void +spawnee (foo f) +{ + usleep(2000); + /* Now both my_test::f and spawnee::f should be alive. */ + if (objcnt != 2) + __builtin_abort (); +} + +void +my_test () +{ + foo f; + _Cilk_spawn spawnee (f); + _Cilk_sync ; +} + +int +main () +{ + if (__cilkrts_set_param ("nworkers", "2") != 0) + __builtin_abort (); + + my_test (); +} diff --git a/gcc/tree-core.h b/gcc/tree-core.h index a646ecb5c95..c76fc7bc8ef 100644 --- a/gcc/tree-core.h +++ b/gcc/tree-core.h @@ -1194,6 +1194,10 @@ struct GTY(()) tree_base { SSA_NAME_OCCURS_IN_ABNORMAL_PHI in SSA_NAME + EXPR_CILK_SPAWN in + CALL_EXPR + AGGR_INIT_EXPR + used_flag: TREE_USED in diff --git a/gcc/tree.h b/gcc/tree.h index 6851cd7e0fc..3bca90a38a5 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -894,6 +894,12 @@ extern void omp_clause_range_check_failed (const_tree, const char *, int, /* Cilk keywords accessors. */ #define CILK_SPAWN_FN(NODE) TREE_OPERAND (CILK_SPAWN_STMT_CHECK (NODE), 0) +/* If this is true, we should insert a __cilk_detach call just before + this function call. */ +#define EXPR_CILK_SPAWN(NODE) \ + (tree_check2 (NODE, __FILE__, __LINE__, __FUNCTION__, \ + CALL_EXPR, AGGR_INIT_EXPR)->base.u.bits.unsigned_flag) + /* In a RESULT_DECL, PARM_DECL and VAR_DECL, means that it is passed by invisible reference (and the TREE_TYPE is a pointer to the true type). */ -- 2.30.2