diff options
author | Balaji V. Iyer <balaji.v.iyer@intel.com> | 2013-12-11 18:23:27 +0000 |
---|---|---|
committer | Balaji V. Iyer <bviyer@gcc.gnu.org> | 2013-12-11 10:23:27 -0800 |
commit | 12893402ec1718a978e540eb1f6bd9c32a4555ab (patch) | |
tree | 9072ab2966c9b71528a27a7a515b6a3bd19545b2 /gcc | |
parent | 996947e67d449d87376e12b389485c5f1cc76f48 (diff) | |
download | gcc-12893402ec1718a978e540eb1f6bd9c32a4555ab.zip gcc-12893402ec1718a978e540eb1f6bd9c32a4555ab.tar.gz gcc-12893402ec1718a978e540eb1f6bd9c32a4555ab.tar.bz2 |
Added Compiler Support for _Cilk_spawn and _Cilk_sync for C++.
gcc/c-family/ChangeLog
2013-12-11 Balaji V. Iyer <balaji.v.iyer@intel.com>
* cilk.c (cilk_outline): Made this function non-static.
(gimplify_cilk_spawn): Removed pre_p and post_p arguments.
(create_cilk_wrapper): Added a new parameter: a function pointer.
(c_install_body_w_frame_cleanup): Remove
(extract_free_variables): Added VEC_INIT_EXPR and CONSTRUCTOR case.
* c-common.h (cilk_outline): New prototype.
(gimplify_cilk_spawn): Removed two parameters.
(cilk_install_body_with_frame_cleanup): New prototype.
* c-gimplify.c (c_gimplify_expr): Added MODIFY_EXPR, CALL_EXPR and
CILK_SPAWN_STMT case.
gcc/c/ChangeLog
2013-12-11 Balaji V. Iyer <balaji.v.iyer@intel.com>
* c-objc-common.h (LANG_HOOKS_CILKPLUS_FRAME_CLEANUP): Remove.
(LANG_HOOKS_CILKPLUS_DETECT_SPAWN_AND_UNWRAP): Likewise.
(LANG_HOOKS_CILKPLUS_CILKPLUS_GIMPLIFY_SPAWN): Likewise.
* c-typeck.c (cilk_install_body_with_frame_cleanup): New function.
gcc/ChangeLog
2013-12-11 Balaji V. Iyer <balaji.v.iyer@intel.com>
* langhooks.h (lang_hooks_for_decls): Remove lang_hooks_for_cilkplus.
(lang_hooks_for_cilkplus): Remove.
* langhooks.c (lhd_cilk_detect_spawn): Likewise.
(lhd_install_body_with_frame_cleanup): Likewise.
* langhooks-def.h (LANG_HOOKS_CILKPLUS_FRAME_CLEANUP): Likewise.
(LANG_HOOKS_CILKPLUS_DETECT_SPAWN_AND_UNWRAP): Likewise.
(LANG_HOOKS_CILKPLUS_CILKPLUS_GIMPLIFY_SPAWN): Likewise.
(LANG_HOOKS_CILKPLUS): Likewise.
(LANG_HOOKS_DECLS): Remove LANG_HOOKS_CILKPLUS.
* gimplify.c (gimplify_expr): Removed CILK_SPAWN_STMT case.
(gimplify_modify_expr): Removed handling of _Cilk_spawn in expr.
(gimplify_call_expr): Likewise.
gcc/cp/ChangeLog
2013-12-11 Balaji V. Iyer <balaji.v.iyer@intel.com>
* cp-tree.h (cilk_valid_spawn): New prototype.
(gimplify_cilk_spawn): Likewise.
(create_try_catch_expr): Likewise.
* decl.c (finish_function): Insert Cilk function-calls when a
_Cilk_spawn is used in a function.
* parser.c (cp_parser_postfix_expression): Added RID_CILK_SPAWN and
RID_CILK_SYNC cases.
* cp-cilkplus.c (set_cilk_except_flag): New function.
(set_cilk_except_data): Likewise.
(cilk_install_body_with_frame_cleanup): Likewise.
* except.c (create_try_catch_expr): Likewise.
* parser.h (IN_CILK_SPAWN): New #define.
* pt.c (tsubst_expr): Added CILK_SPAWN_STMT and CILK_SYNC_STMT cases.
* semantics.c (potential_constant_expression_1): Likewise.
* typeck.c (cp_build_compound_expr): Reject a spawned function in a
compound expression.
(check_return_expr): Reject a spawned function in a return expression.
* cp-gimplify.c (cp_gimplify_expr): Added a CILK_SPAWN_STMT and
CALL_EXPR case. Added handling of spawned function in MODIFY_EXPR
and INIT_EXPR.
gcc/testsuite/ChangeLog
2013-12-11 Balaji V. Iyer <balaji.v.iyer@intel.com>
* g++.dg/cilk-plus/CK/catch_exc.cc: New test case.
* g++.dg/cilk-plus/CK/const_spawn.cc: Likewise.
* g++.dg/cilk-plus/CK/fib-opr-overload.cc: Likewise.
* g++.dg/cilk-plus/CK/fib-tplt.cc: Likewise.
* g++.dg/cilk-plus/CK/lambda_spawns.cc: Likewise.
* g++.dg/cilk-plus/CK/lambda_spawns_tplt.cc: Likewise.
* g++.dg/cilk-plus/cilk-plus.exp: Added support to run Cilk Keywords
test stored in c-c++-common. Also, added the Cilk runtime's library
to the ld_library_path.
From-SVN: r205902
Diffstat (limited to 'gcc')
33 files changed, 1078 insertions, 122 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 13702fe..3e41401 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,18 @@ +2013-12-11 Balaji V. Iyer <balaji.v.iyer@intel.com> + + * langhooks.h (lang_hooks_for_decls): Remove lang_hooks_for_cilkplus. + (lang_hooks_for_cilkplus): Remove. + * langhooks.c (lhd_cilk_detect_spawn): Likewise. + (lhd_install_body_with_frame_cleanup): Likewise. + * langhooks-def.h (LANG_HOOKS_CILKPLUS_FRAME_CLEANUP): Likewise. + (LANG_HOOKS_CILKPLUS_DETECT_SPAWN_AND_UNWRAP): Likewise. + (LANG_HOOKS_CILKPLUS_CILKPLUS_GIMPLIFY_SPAWN): Likewise. + (LANG_HOOKS_CILKPLUS): Likewise. + (LANG_HOOKS_DECLS): Remove LANG_HOOKS_CILKPLUS. + * gimplify.c (gimplify_expr): Removed CILK_SPAWN_STMT case. + (gimplify_modify_expr): Removed handling of _Cilk_spawn in expr. + (gimplify_call_expr): Likewise. + 2013-12-11 Bernd Edlinger <bernd.edlinger@hotmail.de> * expr.c (expand_assignment): Remove dependency on diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog index 1cdd108..462b4b1 100644 --- a/gcc/c-family/ChangeLog +++ b/gcc/c-family/ChangeLog @@ -1,3 +1,16 @@ +2013-12-11 Balaji V. Iyer <balaji.v.iyer@intel.com> + + * cilk.c (cilk_outline): Made this function non-static. + (gimplify_cilk_spawn): Removed pre_p and post_p arguments. + (create_cilk_wrapper): Added a new parameter: a function pointer. + (c_install_body_w_frame_cleanup): Remove + (extract_free_variables): Added VEC_INIT_EXPR and CONSTRUCTOR case. + * c-common.h (cilk_outline): New prototype. + (gimplify_cilk_spawn): Removed two parameters. + (cilk_install_body_with_frame_cleanup): New prototype. + * c-gimplify.c (c_gimplify_expr): Added MODIFY_EXPR, CALL_EXPR and + CILK_SPAWN_STMT case. + 2013-12-11 Bernd Schmidt <bernds@codesourcery.com> * c-common.c (c_fully_fold_internal): Handle ADDR_SPACE_CONVERT_EXPR. diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h index 7e7a4f7..4357d1f 100644 --- a/gcc/c-family/c-common.h +++ b/gcc/c-family/c-common.h @@ -1376,8 +1376,8 @@ extern vec <tree, va_gc> *fix_sec_implicit_args /* In cilk.c. */ extern tree insert_cilk_frame (tree); extern void cilk_init_builtins (void); -extern int gimplify_cilk_spawn (tree *, gimple_seq *, gimple_seq *); -extern void c_cilk_install_body_w_frame_cleanup (tree, tree); +extern int gimplify_cilk_spawn (tree *); +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); extern tree build_cilk_sync (void); @@ -1385,5 +1385,5 @@ 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 *); #endif /* ! GCC_C_COMMON_H */ diff --git a/gcc/c-family/c-gimplify.c b/gcc/c-family/c-gimplify.c index 9f79ccb..b919737 100644 --- a/gcc/c-family/c-gimplify.c +++ b/gcc/c-family/c-gimplify.c @@ -44,7 +44,7 @@ along with GCC; see the file COPYING3. If not see #include "dumpfile.h" #include "c-pretty-print.h" #include "cgraph.h" - +#include "cilk.h" /* The gimplification pass converts the language-dependent trees (ld-trees) emitted by the parser into language-independent trees @@ -207,6 +207,26 @@ c_gimplify_expr (tree *expr_p, gimple_seq *pre_p ATTRIBUTE_UNUSED, } break; } + + case CILK_SPAWN_STMT: + gcc_assert + (fn_contains_cilk_spawn_p (cfun) + && cilk_detect_spawn_and_unwrap (expr_p)); + + /* If errors are seen, then just process it as a CALL_EXPR. */ + if (!seen_error ()) + return (enum gimplify_status) gimplify_cilk_spawn (expr_p); + + case MODIFY_EXPR: + case INIT_EXPR: + case CALL_EXPR: + if (fn_contains_cilk_spawn_p (cfun) + && cilk_detect_spawn_and_unwrap (expr_p) + /* If an error is found, the spawn wrapper is removed and the + original expression (MODIFY/INIT/CALL_EXPR) is processes as + it is supposed to be. */ + && !seen_error ()) + 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 99d9c7e..1b45172 100644 --- a/gcc/c-family/cilk.c +++ b/gcc/c-family/cilk.c @@ -477,9 +477,10 @@ wrapper_local_cb (const void *k_v, void **vp, void *data) /* Alter a tree STMT from OUTER_FN to form the body of INNER_FN. */ -static void -cilk_outline (tree inner_fn, tree *stmt_p, struct wrapper_data *wd) +void +cilk_outline (tree inner_fn, tree *stmt_p, void *w) { + struct wrapper_data *wd = (struct wrapper_data *) w; const tree outer_fn = wd->context; const bool nested = (wd->type == CILK_BLOCK_FOR); copy_body_data id; @@ -512,8 +513,7 @@ cilk_outline (tree inner_fn, tree *stmt_p, struct wrapper_data *wd) /* We don't want the private variables any more. */ pointer_map_traverse (wd->decl_map, nested ? for_local_cb : wrapper_local_cb, &id); - - walk_tree (stmt_p, copy_tree_body_r, &id, NULL); + walk_tree (stmt_p, copy_tree_body_r, (void *) &id, NULL); /* See if this function can throw or calls something that should not be spawned. The exception part is only necessary if @@ -554,10 +554,8 @@ create_cilk_wrapper_body (tree stmt, struct wrapper_data *wd) for (p = wd->parms; p; p = TREE_CHAIN (p)) DECL_CONTEXT (p) = fndecl; - cilk_outline (fndecl, &stmt, wd); - stmt = fold_build_cleanup_point_expr (void_type_node, stmt); gcc_assert (!DECL_SAVED_TREE (fndecl)); - lang_hooks.cilkplus.install_body_with_frame_cleanup (fndecl, stmt); + cilk_install_body_with_frame_cleanup (fndecl, stmt, (void *) wd); gcc_assert (DECL_SAVED_TREE (fndecl)); pop_cfun_to (outer); @@ -733,8 +731,7 @@ create_cilk_wrapper (tree exp, tree *args_out) and GS_UNHANDLED, otherwise. */ int -gimplify_cilk_spawn (tree *spawn_p, gimple_seq *before ATTRIBUTE_UNUSED, - gimple_seq *after ATTRIBUTE_UNUSED) +gimplify_cilk_spawn (tree *spawn_p) { tree expr = *spawn_p; tree function, call1, call2, new_args; @@ -878,30 +875,6 @@ cilk_install_body_pedigree_operations (tree frame_ptr) return body_list; } -/* Inserts "cleanup" functions after the function-body of FNDECL. FNDECL is a - spawn-helper and BODY is the newly created body for FNDECL. */ - -void -c_cilk_install_body_w_frame_cleanup (tree fndecl, tree body) -{ - tree list = alloc_stmt_list (); - tree frame = make_cilk_frame (fndecl); - tree dtor = create_cilk_function_exit (frame, false, true); - 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); - append_to_statement_list (body, &body_list); - append_to_statement_list (build_stmt (EXPR_LOCATION (body), TRY_FINALLY_EXPR, - body_list, dtor), &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. */ @@ -1062,6 +1035,7 @@ extract_free_variables (tree t, struct wrapper_data *wd, extract_free_variables (TREE_OPERAND (t, 0), wd, ADD_READ); return; + case VEC_INIT_EXPR: case INIT_EXPR: extract_free_variables (TREE_OPERAND (t, 0), wd, ADD_BIND); extract_free_variables (TREE_OPERAND (t, 1), wd, ADD_READ); @@ -1222,6 +1196,15 @@ extract_free_variables (tree t, struct wrapper_data *wd, break; } + case CONSTRUCTOR: + { + unsigned HOST_WIDE_INT idx = 0; + constructor_elt *ce; + for (idx = 0; vec_safe_iterate (CONSTRUCTOR_ELTS (t), idx, &ce); idx++) + extract_free_variables (ce->value, wd, ADD_READ); + break; + } + default: if (is_expr) { @@ -1238,7 +1221,6 @@ extract_free_variables (tree t, struct wrapper_data *wd, } } - /* Add appropriate frames needed for a Cilk spawned function call, FNDECL. Returns the __cilkrts_stack_frame * variable. */ diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog index 4f353e8..17ca2c5 100644 --- a/gcc/c/ChangeLog +++ b/gcc/c/ChangeLog @@ -1,3 +1,10 @@ +2013-12-11 Balaji V. Iyer <balaji.v.iyer@intel.com> + + * c-objc-common.h (LANG_HOOKS_CILKPLUS_FRAME_CLEANUP): Remove. + (LANG_HOOKS_CILKPLUS_DETECT_SPAWN_AND_UNWRAP): Likewise. + (LANG_HOOKS_CILKPLUS_CILKPLUS_GIMPLIFY_SPAWN): Likewise. + * c-typeck.c (cilk_install_body_with_frame_cleanup): New function. + 2013-12-04 Joseph Myers <joseph@codesourcery.com> PR c/52023 diff --git a/gcc/c/c-objc-common.h b/gcc/c/c-objc-common.h index 6ae7b3e..4b7987d 100644 --- a/gcc/c/c-objc-common.h +++ b/gcc/c/c-objc-common.h @@ -104,14 +104,4 @@ along with GCC; see the file COPYING3. If not see #undef LANG_HOOKS_TREE_INLINING_VAR_MOD_TYPE_P #define LANG_HOOKS_TREE_INLINING_VAR_MOD_TYPE_P c_vla_unspec_p - -#undef LANG_HOOKS_CILKPLUS_GIMPLIFY_SPAWN -#define LANG_HOOKS_CILKPLUS_GIMPLIFY_SPAWN gimplify_cilk_spawn - -#undef LANG_HOOKS_CILKPLUS_FRAME_CLEANUP -#define LANG_HOOKS_CILKPLUS_FRAME_CLEANUP c_cilk_install_body_w_frame_cleanup - -#undef LANG_HOOKS_CILKPLUS_DETECT_SPAWN_AND_UNWRAP -#define LANG_HOOKS_CILKPLUS_DETECT_SPAWN_AND_UNWRAP \ - cilk_detect_spawn_and_unwrap #endif /* GCC_C_OBJC_COMMON */ diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c index 672a564..5674ac3 100644 --- a/gcc/c/c-typeck.c +++ b/gcc/c/c-typeck.c @@ -49,6 +49,7 @@ along with GCC; see the file COPYING3. If not see #include "c-family/c-objc.h" #include "c-family/c-common.h" #include "c-family/c-ubsan.h" +#include "cilk.h" /* Possible cases of implicit bad conversions. Used to select diagnostic messages in convert_for_assignment. */ @@ -12438,3 +12439,31 @@ c_tree_equal (tree t1, tree t2) /* We can get here with --disable-checking. */ return false; } + +/* Inserts "cleanup" functions after the function-body of FNDECL. FNDECL is a + spawn-helper and BODY is the newly created body for FNDECL. */ + +void +cilk_install_body_with_frame_cleanup (tree fndecl, tree body, void *w) +{ + tree list = alloc_stmt_list (); + tree frame = make_cilk_frame (fndecl); + tree dtor = create_cilk_function_exit (frame, false, true); + 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); + + cilk_outline (fndecl, &body, (struct wrapper_data *) w); + body = fold_build_cleanup_point_expr (void_type_node, body); + + append_to_statement_list (body, &body_list); + append_to_statement_list (build_stmt (EXPR_LOCATION (body), TRY_FINALLY_EXPR, + body_list, dtor), &list); +} @@ -90,6 +90,7 @@ extern tree cilk_dot (tree, int, bool); extern void cilk_init_builtins (void); extern void gimplify_cilk_sync (tree *, gimple_seq *); extern tree cilk_call_setjmp (tree); + /* Returns true if Cilk Plus is enabled and if F->cilk_frame_decl is not NULL_TREE. */ @@ -99,4 +100,5 @@ fn_contains_cilk_spawn_p (function *f) return (flag_enable_cilkplus && (f->calls_cilk_spawn || f->cilk_frame_decl != NULL_TREE)); } + #endif diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 2acc8c7..fd5d4b7 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,26 @@ +2013-12-11 Balaji V. Iyer <balaji.v.iyer@intel.com> + + * cp-tree.h (cilk_valid_spawn): New prototype. + (gimplify_cilk_spawn): Likewise. + (create_try_catch_expr): Likewise. + * decl.c (finish_function): Insert Cilk function-calls when a + _Cilk_spawn is used in a function. + * parser.c (cp_parser_postfix_expression): Added RID_CILK_SPAWN and + RID_CILK_SYNC cases. + * cp-cilkplus.c (set_cilk_except_flag): New function. + (set_cilk_except_data): Likewise. + (cilk_install_body_with_frame_cleanup): Likewise. + * except.c (create_try_catch_expr): Likewise. + * parser.h (IN_CILK_SPAWN): New #define. + * pt.c (tsubst_expr): Added CILK_SPAWN_STMT and CILK_SYNC_STMT cases. + * semantics.c (potential_constant_expression_1): Likewise. + * typeck.c (cp_build_compound_expr): Reject a spawned function in a + compound expression. + (check_return_expr): Reject a spawned function in a return expression. + * cp-gimplify.c (cp_gimplify_expr): Added a CILK_SPAWN_STMT and + CALL_EXPR case. Added handling of spawned function in MODIFY_EXPR + and INIT_EXPR. + 2013-12-09 Paolo Carlini <paolo.carlini@oracle.com> PR c++/59435 diff --git a/gcc/cp/cp-cilkplus.c b/gcc/cp/cp-cilkplus.c index 5c1090a..d3f3323 100644 --- a/gcc/cp/cp-cilkplus.c +++ b/gcc/cp/cp-cilkplus.c @@ -25,7 +25,10 @@ #include "coretypes.h" #include "cp-tree.h" #include "diagnostic-core.h" - +#include "tree-iterator.h" +#include "tree-inline.h" /* for copy_tree_body_r. */ +#include "ggc.h" +#include "cilk.h" /* Callback for cp_walk_tree to validate the body of a pragma simd loop or _cilk_for loop. @@ -75,3 +78,68 @@ cpp_validate_cilk_plus_loop (tree body) (void *) &valid, NULL); return valid; } + +/* Sets the EXCEPTION bit (0x10) in the FRAME.flags field. */ + +static tree +set_cilk_except_flag (tree frame) +{ + tree flags = cilk_dot (frame, CILK_TI_FRAME_FLAGS, 0); + + flags = build2 (MODIFY_EXPR, void_type_node, flags, + build2 (BIT_IOR_EXPR, TREE_TYPE (flags), flags, + build_int_cst (TREE_TYPE (flags), + CILK_FRAME_EXCEPTING))); + return flags; +} + +/* Sets the frame.EXCEPT_DATA field to the head of the exception pointer. */ + +static tree +set_cilk_except_data (tree frame) +{ + tree except_data = cilk_dot (frame, CILK_TI_FRAME_EXCEPTION, 0); + tree uresume_fn = builtin_decl_implicit (BUILT_IN_EH_POINTER); + tree ret_expr; + uresume_fn = build_call_expr (uresume_fn, 1, + build_int_cst (integer_type_node, 0)); + ret_expr = build2 (MODIFY_EXPR, void_type_node, except_data, uresume_fn); + return ret_expr; +} + +/* Installs BODY into function FNDECL with appropriate exception handling + code. WD holds information of wrapper function used to pass into the + outlining function, cilk_outline. */ + +void +cilk_install_body_with_frame_cleanup (tree fndecl, tree orig_body, void *wd) +{ + tree frame = make_cilk_frame (fndecl); + tree dtor = create_cilk_function_exit (frame, false, false); + add_local_decl (cfun, frame); + + cfun->language = ggc_alloc_cleared_language_function (); + + 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); + cilk_outline (fndecl, &orig_body, (struct wrapper_data *) wd); + append_to_statement_list (orig_body, &body); + if (flag_exceptions) + { + tree except_flag = set_cilk_except_flag (frame); + tree except_data = set_cilk_except_data (frame); + tree catch_list = alloc_stmt_list (); + append_to_statement_list (except_flag, &catch_list); + append_to_statement_list (except_data, &catch_list); + body = create_try_catch_expr (body, catch_list); + } + append_to_statement_list (build_stmt (loc, TRY_FINALLY_EXPR, body, dtor), + &list); +} + diff --git a/gcc/cp/cp-gimplify.c b/gcc/cp/cp-gimplify.c index b1270a1..5fa564c 100644 --- a/gcc/cp/cp-gimplify.c +++ b/gcc/cp/cp-gimplify.c @@ -41,6 +41,7 @@ along with GCC; see the file COPYING3. If not see #include "splay-tree.h" #include "target.h" #include "c-family/c-ubsan.h" +#include "cilk.h" /* Forward declarations. */ @@ -584,12 +585,21 @@ cp_gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p) LHS of an assignment might also be involved in the RHS, as in bug 25979. */ case INIT_EXPR: + if (fn_contains_cilk_spawn_p (cfun) + && cilk_detect_spawn_and_unwrap (expr_p) + && !seen_error ()) + return (enum gimplify_status) gimplify_cilk_spawn (expr_p); cp_gimplify_init_expr (expr_p); if (TREE_CODE (*expr_p) != INIT_EXPR) return GS_OK; /* Otherwise fall through. */ case MODIFY_EXPR: { + if (fn_contains_cilk_spawn_p (cfun) + && cilk_detect_spawn_and_unwrap (expr_p) + && !seen_error ()) + 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); @@ -698,6 +708,21 @@ cp_gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p) } break; + case CILK_SPAWN_STMT: + gcc_assert + (fn_contains_cilk_spawn_p (cfun) + && cilk_detect_spawn_and_unwrap (expr_p)); + + /* If errors are seen, then just process it as a CALL_EXPR. */ + if (!seen_error ()) + return (enum gimplify_status) gimplify_cilk_spawn (expr_p); + + case CALL_EXPR: + if (fn_contains_cilk_spawn_p (cfun) + && cilk_detect_spawn_and_unwrap (expr_p) + && !seen_error ()) + return (enum gimplify_status) gimplify_cilk_spawn (expr_p); + default: ret = (enum gimplify_status) c_gimplify_expr (expr_p, pre_p, post_p); break; diff --git a/gcc/cp/cp-objcp-common.h b/gcc/cp/cp-objcp-common.h index ee22423..0a8fdee 100644 --- a/gcc/cp/cp-objcp-common.h +++ b/gcc/cp/cp-objcp-common.h @@ -153,5 +153,4 @@ extern void cp_common_init_ts (void); #undef LANG_HOOKS_EH_PROTECT_CLEANUP_ACTIONS #define LANG_HOOKS_EH_PROTECT_CLEANUP_ACTIONS cp_protect_cleanup_actions - #endif /* GCC_CP_OBJCP_COMMON */ diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 1fc4b59..0686825 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -5356,6 +5356,7 @@ extern tree begin_eh_spec_block (void); extern void finish_eh_spec_block (tree, tree); extern tree build_eh_type_type (tree); extern tree cp_protect_cleanup_actions (void); +extern tree create_try_catch_expr (tree, tree); /* in expr.c */ extern tree cplus_expand_constant (tree); @@ -6185,6 +6186,9 @@ extern bool cpp_validate_cilk_plus_loop (tree); extern tree expand_array_notation_exprs (tree); bool cilkplus_an_triplet_types_ok_p (location_t, tree, tree, tree, tree); +/* In c-family/cilk.c */ +extern bool cilk_valid_spawn (tree); + /* -- end of C++ */ #endif /* ! GCC_CP_TREE_H */ diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index a6744c7..5d06b37 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -59,6 +59,7 @@ along with GCC; see the file COPYING3. If not see #include "splay-tree.h" #include "plugin.h" #include "cgraph.h" +#include "cilk.h" /* Possible cases of bad specifiers type used by bad_specifiers. */ enum bad_spec_place { @@ -13889,6 +13890,9 @@ finish_function (int flags) /* If we're saving up tree structure, tie off the function now. */ DECL_SAVED_TREE (fndecl) = pop_stmt_list (DECL_SAVED_TREE (fndecl)); + if (fn_contains_cilk_spawn_p (cfun) && !processing_template_decl) + cfun->cilk_frame_decl = insert_cilk_frame (fndecl); + finish_fname_decls (); /* If this function can't throw any exceptions, remember that. */ diff --git a/gcc/cp/except.c b/gcc/cp/except.c index d7d009b..be487cd 100644 --- a/gcc/cp/except.c +++ b/gcc/cp/except.c @@ -1342,4 +1342,22 @@ build_noexcept_spec (tree expr, int complain) } } +/* Returns a TRY_CATCH_EXPR that will put TRY_LIST and CATCH_LIST in the + TRY and CATCH locations. CATCH_LIST must be a STATEMENT_LIST */ + +tree +create_try_catch_expr (tree try_expr, tree catch_list) +{ + location_t loc = EXPR_LOCATION (try_expr); + + append_to_statement_list (do_begin_catch (), &catch_list); + append_to_statement_list (build_throw (NULL_TREE), &catch_list); + tree catch_tf_expr = build_stmt (loc, TRY_FINALLY_EXPR, catch_list, + do_end_catch (NULL_TREE)); + catch_list = build2 (CATCH_EXPR, void_type_node, NULL_TREE, + catch_tf_expr); + tree try_catch_expr = build_stmt (loc, TRY_CATCH_EXPR, try_expr, catch_list); + return try_catch_expr; +} + #include "gt-cp-except.h" diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 063d2ac..dd02734 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -5627,6 +5627,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p, cp_id_kind idk = CP_ID_KIND_NONE; tree postfix_expression = NULL_TREE; bool is_member_access = false; + int saved_in_statement = -1; /* Peek at the next token. */ token = cp_lexer_peek_token (parser->lexer); @@ -5771,6 +5772,66 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p, } break; + case RID_CILK_SPAWN: + { + cp_lexer_consume_token (parser->lexer); + token = cp_lexer_peek_token (parser->lexer); + if (token->type == CPP_SEMICOLON) + { + error_at (token->location, "%<_Cilk_spawn%> must be followed by " + "an expression"); + postfix_expression = error_mark_node; + break; + } + else if (!current_function_decl) + { + error_at (token->location, "%<_Cilk_spawn%> may only be used " + "inside a function"); + postfix_expression = error_mark_node; + break; + } + else + { + /* Consecutive _Cilk_spawns are not allowed in a statement. */ + saved_in_statement = parser->in_statement; + parser->in_statement |= IN_CILK_SPAWN; + } + cfun->calls_cilk_spawn = 1; + postfix_expression = + cp_parser_postfix_expression (parser, false, false, + false, false, &idk); + if (saved_in_statement & IN_CILK_SPAWN) + { + error_at (token->location, "consecutive %<_Cilk_spawn%> keywords " + "are not permitted"); + postfix_expression = error_mark_node; + cfun->calls_cilk_spawn = 0; + } + else + { + postfix_expression = build_cilk_spawn (token->location, + postfix_expression); + if (postfix_expression != error_mark_node) + SET_EXPR_LOCATION (postfix_expression, input_location); + parser->in_statement = parser->in_statement & ~IN_CILK_SPAWN; + } + break; + } + + case RID_CILK_SYNC: + if (flag_enable_cilkplus) + { + tree sync_expr = build_cilk_sync (); + SET_EXPR_LOCATION (sync_expr, + cp_lexer_peek_token (parser->lexer)->location); + finish_expr_stmt (sync_expr); + } + else + error_at (input_location, "_Cilk_sync cannot be used without enabling " + "Cilk Plus"); + cp_lexer_consume_token (parser->lexer); + break; + case RID_BUILTIN_SHUFFLE: { vec<tree, va_gc> *vec; diff --git a/gcc/cp/parser.h b/gcc/cp/parser.h index edd4e6e..e26e350 100644 --- a/gcc/cp/parser.h +++ b/gcc/cp/parser.h @@ -301,6 +301,7 @@ typedef struct GTY(()) cp_parser { #define IN_OMP_FOR 8 #define IN_IF_STMT 16 #define IN_CILK_SIMD_FOR 32 +#define IN_CILK_SPAWN 64 unsigned char in_statement; /* TRUE if we are presently parsing the body of a switch statement. diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 01b2d44..2c64a71 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -13762,6 +13762,13 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl, error ("use %<...%> to expand argument pack"); RETURN (error_mark_node); + case CILK_SPAWN_STMT: + cfun->calls_cilk_spawn = 1; + RETURN (build_cilk_spawn (EXPR_LOCATION (t), RECUR (CILK_SPAWN_FN (t)))); + + case CILK_SYNC_STMT: + RETURN (build_cilk_sync ()); + case COMPOUND_EXPR: tmp = RECUR (TREE_OPERAND (t, 0)); if (tmp == NULL_TREE) diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 7c1b18e..63f50fb 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -10429,6 +10429,8 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags) return false; return true; + case CILK_SYNC_STMT: + case CILK_SPAWN_STMT: case ARRAY_NOTATION_REF: return false; diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 74fc4d7..01afbac 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -6166,6 +6166,17 @@ cp_build_compound_expr (tree lhs, tree rhs, tsubst_flags_t complain) if (lhs == error_mark_node || rhs == error_mark_node) return error_mark_node; + if (flag_enable_cilkplus + && (TREE_CODE (lhs) == CILK_SPAWN_STMT + || TREE_CODE (rhs) == CILK_SPAWN_STMT)) + { + location_t loc = (EXPR_HAS_LOCATION (lhs) ? EXPR_LOCATION (lhs) + : EXPR_LOCATION (rhs)); + error_at (loc, + "spawned function call cannot be part of a comma expression"); + return error_mark_node; + } + if (TREE_CODE (rhs) == TARGET_EXPR) { /* If the rhs is a TARGET_EXPR, then build the compound @@ -8290,6 +8301,13 @@ check_return_expr (tree retval, bool *no_warning) *no_warning = false; + if (flag_enable_cilkplus && retval && TREE_CODE (retval) == CILK_SPAWN_STMT) + { + error_at (EXPR_LOCATION (retval), "use of %<_Cilk_spawn%> in a return " + "statement is not allowed"); + return NULL_TREE; + } + /* A `volatile' function is one that isn't supposed to return, ever. (This is a G++ extension, used to get better code for functions that call the `volatile' function.) */ diff --git a/gcc/gimplify.c b/gcc/gimplify.c index 2e8c657..8bcce22 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -2204,12 +2204,6 @@ gimplify_call_expr (tree *expr_p, gimple_seq *pre_p, bool want_value) if (! EXPR_HAS_LOCATION (*expr_p)) SET_EXPR_LOCATION (*expr_p, input_location); - if (fn_contains_cilk_spawn_p (cfun) - && lang_hooks.cilkplus.cilk_detect_spawn_and_unwrap (expr_p) - && !seen_error ()) - return (enum gimplify_status) - lang_hooks.cilkplus.gimplify_cilk_spawn (expr_p, pre_p, NULL); - /* This may be a call to a builtin function. Builtin function calls may be transformed into different @@ -4427,12 +4421,6 @@ gimplify_modify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, gcc_assert (TREE_CODE (*expr_p) == MODIFY_EXPR || TREE_CODE (*expr_p) == INIT_EXPR); - - if (fn_contains_cilk_spawn_p (cfun) - && lang_hooks.cilkplus.cilk_detect_spawn_and_unwrap (expr_p) - && !seen_error ()) - return (enum gimplify_status) - lang_hooks.cilkplus.gimplify_cilk_spawn (expr_p, pre_p, post_p); /* Trying to simplify a clobber using normal logic doesn't work, so handle it here. */ @@ -7383,19 +7371,6 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, } break; - case CILK_SPAWN_STMT: - gcc_assert - (fn_contains_cilk_spawn_p (cfun) - && lang_hooks.cilkplus.cilk_detect_spawn_and_unwrap (expr_p)); - if (!seen_error ()) - { - ret = (enum gimplify_status) - lang_hooks.cilkplus.gimplify_cilk_spawn (expr_p, pre_p, - post_p); - break; - } - /* If errors are seen, then just process it as a CALL_EXPR. */ - case CALL_EXPR: ret = gimplify_call_expr (expr_p, pre_p, fallback != fb_none); diff --git a/gcc/langhooks-def.h b/gcc/langhooks-def.h index 411cf74..b7be472 100644 --- a/gcc/langhooks-def.h +++ b/gcc/langhooks-def.h @@ -214,18 +214,6 @@ extern tree lhd_make_node (enum tree_code); #define LANG_HOOKS_OMP_CLAUSE_DTOR hook_tree_tree_tree_null #define LANG_HOOKS_OMP_FINISH_CLAUSE hook_void_tree -extern void lhd_install_body_with_frame_cleanup (tree, tree); -extern bool lhd_cilk_detect_spawn (tree *); -#define LANG_HOOKS_CILKPLUS_DETECT_SPAWN_AND_UNWRAP lhd_cilk_detect_spawn -#define LANG_HOOKS_CILKPLUS_FRAME_CLEANUP lhd_install_body_with_frame_cleanup -#define LANG_HOOKS_CILKPLUS_GIMPLIFY_SPAWN lhd_gimplify_expr - -#define LANG_HOOKS_CILKPLUS { \ - LANG_HOOKS_CILKPLUS_DETECT_SPAWN_AND_UNWRAP, \ - LANG_HOOKS_CILKPLUS_FRAME_CLEANUP, \ - LANG_HOOKS_CILKPLUS_GIMPLIFY_SPAWN \ -} - #define LANG_HOOKS_DECLS { \ LANG_HOOKS_GLOBAL_BINDINGS_P, \ LANG_HOOKS_PUSHDECL, \ @@ -303,7 +291,6 @@ extern void lhd_end_section (void); LANG_HOOKS_TREE_DUMP_INITIALIZER, \ LANG_HOOKS_DECLS, \ LANG_HOOKS_FOR_TYPES_INITIALIZER, \ - LANG_HOOKS_CILKPLUS, \ LANG_HOOKS_LTO, \ LANG_HOOKS_GET_INNERMOST_GENERIC_PARMS, \ LANG_HOOKS_GET_INNERMOST_GENERIC_ARGS, \ diff --git a/gcc/langhooks.c b/gcc/langhooks.c index 7fe349d..6766ee5 100644 --- a/gcc/langhooks.c +++ b/gcc/langhooks.c @@ -676,18 +676,3 @@ lhd_end_section (void) saved_section = NULL; } } - -/* Empty function that is replaced with appropriate language dependent - frame cleanup function for _Cilk_spawn. */ - -void -lhd_install_body_with_frame_cleanup (tree, tree) -{ -} - -/* Empty function to handle cilk_valid_spawn. */ -bool -lhd_cilk_detect_spawn (tree *) -{ - return false; -} diff --git a/gcc/langhooks.h b/gcc/langhooks.h index 9539e7d..5a5c8b6 100644 --- a/gcc/langhooks.h +++ b/gcc/langhooks.h @@ -139,23 +139,6 @@ struct lang_hooks_for_types tree (*reconstruct_complex_type) (tree, tree); }; -/* Language hooks related to Cilk Plus. */ - -struct lang_hooks_for_cilkplus -{ - /* Returns true if the expression passed in has a spawned function call. */ - bool (*cilk_detect_spawn_and_unwrap) (tree *); - - /* Function to add the clean up functions after spawn. The reason why it is - language dependent is because in C++, it must handle exceptions. */ - void (*install_body_with_frame_cleanup) (tree, tree); - - /* Function to gimplify a spawned function call. Returns enum gimplify - status, but as mentioned in a previous comment, we can't see that type - here, so just return an int. */ - int (*gimplify_cilk_spawn) (tree *, gimple_seq *, gimple_seq *); -}; - /* Language hooks related to decls and the symbol table. */ struct lang_hooks_for_decls @@ -424,8 +407,6 @@ struct lang_hooks struct lang_hooks_for_decls decls; struct lang_hooks_for_types types; - - struct lang_hooks_for_cilkplus cilkplus; struct lang_hooks_for_lto lto; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 0de1112..e57eaf0 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,15 @@ +2013-12-11 Balaji V. Iyer <balaji.v.iyer@intel.com> + + * g++.dg/cilk-plus/CK/catch_exc.cc: New test case. + * g++.dg/cilk-plus/CK/const_spawn.cc: Likewise. + * g++.dg/cilk-plus/CK/fib-opr-overload.cc: Likewise. + * g++.dg/cilk-plus/CK/fib-tplt.cc: Likewise. + * g++.dg/cilk-plus/CK/lambda_spawns.cc: Likewise. + * g++.dg/cilk-plus/CK/lambda_spawns_tplt.cc: Likewise. + * g++.dg/cilk-plus/cilk-plus.exp: Added support to run Cilk Keywords + test stored in c-c++-common. Also, added the Cilk runtime's library + to the ld_library_path. + 2013-12-11 Bernd Edlinger <bernd.edlinger@hotmail.de> PR middle-end/59134 diff --git a/gcc/testsuite/g++.dg/cilk-plus/CK/catch_exc.cc b/gcc/testsuite/g++.dg/cilk-plus/CK/catch_exc.cc new file mode 100644 index 0000000..0633d19 --- /dev/null +++ b/gcc/testsuite/g++.dg/cilk-plus/CK/catch_exc.cc @@ -0,0 +1,67 @@ +/* { dg-options "-fcilkplus" } */ +/* { dg-do run { target i?86-*-* x86_64-*-* arm*-*-* } } */ +/* { dg-options "-fcilkplus -lcilkrts" { target { i?86-*-* x86_64-*-* arm*-*-* } } } */ + +#include <assert.h> +#include <unistd.h> +#if HAVE_IO +#include <cstdio> +#include <cilk/cilk_api.h> +#endif +#include <cstdlib> + + +void func(int volatile* steal_me) +{ + while (! (*steal_me)) + { + usleep(2000); + } +#if HAVE_IO + printf("Foo executing on %d\n", __cilkrts_get_worker_number()); +#endif + throw 5; +} + +void my_test() +{ + volatile int steal_me = 0; + + try + { + _Cilk_spawn func(&steal_me); +#if HAVE_IO + printf("Continuation executing on %d\n", + __cilkrts_get_worker_number()); +#endif + steal_me = 1; + _Cilk_sync; + goto bad; + } + + catch (int x) + { +#if HAVE_IO + printf("We caught x = %d\n", x); +#endif + assert(x == 5); + } + if (0) + { + bad: +#if HAVE_IO + printf("We should not be here!\n"); +#endif + __builtin_abort (); + } +} + + +int main() +{ + my_test(); +#if HAVE_IO + printf("PASSED\n"); +#endif + return 0; +} diff --git a/gcc/testsuite/g++.dg/cilk-plus/CK/const_spawn.cc b/gcc/testsuite/g++.dg/cilk-plus/CK/const_spawn.cc new file mode 100644 index 0000000..1ea473f --- /dev/null +++ b/gcc/testsuite/g++.dg/cilk-plus/CK/const_spawn.cc @@ -0,0 +1,78 @@ +/* { dg-options "-fcilkplus" } */ +/* { dg-do run { target i?86-*-* x86_64-*-* arm*-*-* } } */ +/* { dg-options "-fcilkplus -lcilkrts" { target { i?86-*-* x86_64-*-* arm*-*-* } } } */ + +class Rectangle +{ + int area_val, h, w; + public: + Rectangle (int, int); + Rectangle (int, int, int); + ~Rectangle (); + int area (); +}; +Rectangle::~Rectangle () +{ + h = 0; + w = 0; + area_val = 0; +} +Rectangle::Rectangle (int height, int width) +{ + h = height; + w = width; + area_val = 0; +} + +Rectangle::Rectangle (int height, int width, int area_orig) +{ + h = height; + w = width; + area_val = area_orig; +} + +int Rectangle::area() +{ + return (area_val += (h*w)); +} + +/* Spawning constructor. */ +int main1 (void) +{ + Rectangle r = _Cilk_spawn Rectangle (4, 3); + return r.area(); +} + +/* Spawning constructor 2. */ +int main2 (void) +{ + Rectangle r (_Cilk_spawn Rectangle (4, 3)); + return r.area(); +} + +/* Spawning copy constructor. */ +int main3 (void) +{ + Rectangle r = _Cilk_spawn Rectangle (4, 3, 2); + return r.area (); +} + +/* Spawning copy constructor 2. */ +int main4 (void) +{ + Rectangle r ( _Cilk_spawn Rectangle (4, 3, 2)); + return r.area(); +} + +int main (void) +{ + if (main1 () != 12) + __builtin_abort (); + if (main2 () != 12) + __builtin_abort (); + if (main3 () != 14) + __builtin_abort (); + if (main4() != 14) + __builtin_abort (); + return 0; +} diff --git a/gcc/testsuite/g++.dg/cilk-plus/CK/fib-opr-overload.cc b/gcc/testsuite/g++.dg/cilk-plus/CK/fib-opr-overload.cc new file mode 100644 index 0000000..6af4a36 --- /dev/null +++ b/gcc/testsuite/g++.dg/cilk-plus/CK/fib-opr-overload.cc @@ -0,0 +1,94 @@ +/* { dg-options "-fcilkplus" } */ +/* { dg-do run { target i?86-*-* x86_64-*-* arm*-*-* } } */ +/* { dg-options "-fcilkplus -lcilkrts" { target { i?86-*-* x86_64-*-* arm*-*-* } } } */ + +#if HAVE_IO +#include <iostream> +#endif + +class Some_Struct +{ + int calculated_value; + short some_unused_value; +public: + Some_Struct () { + this->calculated_value = 0; + } + Some_Struct (int value) { + this->calculated_value = value; + } + Some_Struct operator=(Some_Struct f) { + this->calculated_value = f.calculated_value; + return *this; + } + bool operator!=(Some_Struct f) { + return (this->calculated_value != f.calculated_value); + } + Some_Struct operator+(Some_Struct &f) { + Some_Struct z; + z.calculated_value = this->calculated_value + f.calculated_value; + return z; + } + Some_Struct operator-(int x) { + Some_Struct z; + z.calculated_value = this->calculated_value - x; + return z; + } + bool operator<(int x) { + return (this->calculated_value < x); + } + int get_calculated_value () { + return this->calculated_value; + } +}; + + +template <class T> +T fibonacci_serial (T f) +{ + if (f < 2) + return f; + T a = fibonacci_serial (f-1); + T b = fibonacci_serial (f-2); + return (a+b); +} + +template <class T> +T fibonacci (T f) +{ + if (f < 2) + return f; + T a = _Cilk_spawn fibonacci (f-1); + T b = fibonacci (f-2); + _Cilk_sync; + return (a+b); +} + +int main (void) +{ + Some_Struct f (40), f_serial(40); + f = fibonacci (f); + f_serial = fibonacci_serial (f_serial); + + if (f != f_serial) + __builtin_abort (); + + int t = 40, t_serial = 40; + t = fibonacci (t); + t_serial = fibonacci_serial (t_serial); + if (t != t_serial) + __builtin_abort (); + + short s = 20, s_serial = 20; + s = fibonacci (s); + s_serial = fibonacci_serial (s_serial); + if (s != s_serial) + __builtin_abort (); + +#if HAVE_IO + std::cout << "Fib_Parallel (40) = " << f.get_calculated_value() << std::endl; + std::cout << "Fib_Serial (40) = " << f_serial.get_calculated_value() + << std::endl; +#endif + return 0; +} diff --git a/gcc/testsuite/g++.dg/cilk-plus/CK/fib-tplt.cc b/gcc/testsuite/g++.dg/cilk-plus/CK/fib-tplt.cc new file mode 100644 index 0000000..dbc2da8 --- /dev/null +++ b/gcc/testsuite/g++.dg/cilk-plus/CK/fib-tplt.cc @@ -0,0 +1,53 @@ +/* { dg-options "-fcilkplus" } */ +/* { dg-do run { target i?86-*-* x86_64-*-* arm*-*-* } } */ +/* { dg-options "-fcilkplus -lcilkrts" { target { i?86-*-* x86_64-*-* arm*-*-*-* } } } */ + +struct fib_struct +{ + int x; + int *y; + int z[3]; + struct fib_struct *ptr_next; + struct fib_struct operator+(struct fib_struct &other) { + struct fib_struct z ; + z.x = (*this).x + (other.x); + return z; + } + struct fib_struct operator-(int other) { + struct fib_struct z ; + z.x = this->x - other; + return z; + } + bool operator<(int number) { + return (this->x < number); + } + +}; + +template <typename T> +T fib (T z) { + if (z < 2) return z; + T a = _Cilk_spawn fib<T>(z - 1); + T b = fib<T>(z - 2); + T c = a + b; + return (a+b); +} + + +int sfib(int x) +{ + if (x < 2) return x; + int a = sfib(x-1); + int b = sfib(x-2); + return (a+b); +} + +int main () { + int z = 30; + int parallel_fib = fib<int>(z); + int serial_fib = sfib(z); + if (serial_fib != parallel_fib) + __builtin_abort (); + + return 0; +} diff --git a/gcc/testsuite/g++.dg/cilk-plus/CK/lambda_spawns.cc b/gcc/testsuite/g++.dg/cilk-plus/CK/lambda_spawns.cc new file mode 100644 index 0000000..7448d1a --- /dev/null +++ b/gcc/testsuite/g++.dg/cilk-plus/CK/lambda_spawns.cc @@ -0,0 +1,236 @@ +/* { dg-options "-fcilkplus" } */ +/* { dg-do run { target i?86-*-* x86_64-*-* arm*-*-* } } */ +/* { dg-options "-std=c++11 -fcilkplus -lcilkrts" { target { i?86-*-* x86_64-*-* arm*-*-* } } } */ +#define FIRST_NUMBER 5 +#define SECOND_NUMBER 3 +#define HAVE_IO 0 +#if HAVE_IO +#include <stdio.h> +#endif + +#include <stdlib.h> + +int global_var; + +void foo1(int *array, int size) +{ +#if HAVE_IO + for (int ii = 0; ii < size; ii++) + printf("%2d\t", array[ii]); + printf("\n"); + fflush (stdout); +#else + if (size != 2) + __builtin_abort (); + if (array[0] != FIRST_NUMBER) + __builtin_abort (); + if (array[1] != SECOND_NUMBER) + __builtin_abort (); +#endif + global_var++; +} +void foo1_c(const int *array, int size) +{ +#if HAVE_IO + for (int ii = 0; ii < size; ii++) + printf("%2d\t", array[ii]); + printf("\n"); + fflush (stdout); +#else + if (size != 2) + __builtin_abort (); + if (array[0] != FIRST_NUMBER) + __builtin_abort (); + if (array[1] != SECOND_NUMBER) + __builtin_abort (); +#endif + global_var++; +} + + +int main2 (int argc) { + int A[2] = {FIRST_NUMBER, SECOND_NUMBER}; + int B[2] = {FIRST_NUMBER, SECOND_NUMBER}; + int main_size = argc+1; /* We know argc is 1, and so 1+1 = 2. */ + int q = 0; + + global_var = 0; + auto func0 = [=](){ foo1_c(A, 2); }; + _Cilk_spawn func0(); + foo1 (A, 2); + _Cilk_sync; + if (global_var != 2) + return (++q); + + global_var = 0; + auto func1 = [=](int *Aa){ foo1(Aa, 2); }; + _Cilk_spawn func1 (A); + foo1 (A, 2); + _Cilk_sync; + if (global_var != 2) + return (++q); + + global_var = 0; + auto func2 = [=](int *Aa, int size){ foo1(Aa, size); }; + _Cilk_spawn func2 (A, 2); + foo1 (A, 2); + _Cilk_sync; + if (global_var != 2) + return (++q); + + global_var = 0; + auto func3 = [=](int *Aa, int size){ int new_size = (size % 2 + 2); + foo1(Aa, size); }; + _Cilk_spawn func3 (A, 2); + foo1 (A, 2); + _Cilk_sync; + if (global_var != 2) + return (++q); + + global_var = 0; + auto func4 = [](int *Aa){ foo1(Aa, 2); }; + _Cilk_spawn func4 (A); + foo1 (A, 2); + _Cilk_sync; + if (global_var != 2) + return (++q); + + global_var = 0; + auto func5 = [](int *Aa, int size){ foo1(Aa, size); }; + _Cilk_spawn func5 (A, 2); + foo1 (A, 2); + _Cilk_sync; + if (global_var != 2) + return (++q); + + global_var = 0; + auto func6 = [&](int *Aa){ foo1(Aa, 2); }; + _Cilk_spawn func6 (A); + foo1 (A, 2); + _Cilk_sync; + if (global_var != 2) + return (++q); + + global_var = 0; + auto func7 = [&](int *Aa, int size){ foo1(Aa, size); }; + _Cilk_spawn func7 (A, 2); + foo1 (A, 2); + _Cilk_sync; + if (global_var != 2) + return (++q); + + global_var = 0; + auto func8 = [&](){ foo1(A, 2); }; + _Cilk_spawn func8 (); + foo1 (A, 2); + _Cilk_sync; + if (global_var != 2) + return (++q); + + global_var = 0; + /* We ignore the first param here and pass in A from the outer fn. */ + auto func9 = [&](int *Aa, int size){ foo1(A, size); }; + _Cilk_spawn func9 (A, 2); + foo1 (A, 2); + _Cilk_sync; + if (global_var != 2) + return (++q); + + global_var = 0; + auto func10 = [=](){ foo1_c(A, main_size); }; + _Cilk_spawn func10 (); + foo1 (A, 2); + _Cilk_sync; + if (global_var != 2) + return (++q); + + global_var = 0; + auto func11 = [&](){ foo1(A, main_size); }; + _Cilk_spawn func11 (); + foo1 (A, 2); + _Cilk_sync; + if (global_var != 2) + return (++q); + + global_var = 0; + /* We ignore the first & second param here and pass in A from the + outer fn. */ + auto func12 = [&](int *Aa, int size){ foo1(A, main_size); }; + _Cilk_spawn func12 (A, 2); + foo1 (A, 2); + _Cilk_sync; + if (global_var != 2) + return (++q); + + global_var = 0; + _Cilk_spawn [&](int *Aa){ foo1(Aa, 2); }(A); + foo1 (A, 2); + _Cilk_sync; + if (global_var != 2) + return (++q); + + global_var = 0; + _Cilk_spawn [&](int *Aa, int size){ foo1(Aa, size); }(A, 2); + foo1 (A, 2); + _Cilk_sync; + if (global_var != 2) + return (++q); + + global_var = 0; + _Cilk_spawn [=](int *Aa){ foo1(Aa, 2); }(A); + foo1 (A, 2); + _Cilk_sync; + if (global_var != 2) + return (++q); + + global_var = 0; + _Cilk_spawn [=](int *Aa, int size){ foo1(Aa, size); }(A, 2); + foo1 (A, 2); + _Cilk_sync; + if (global_var != 2) + return (++q); + + global_var = 0; + /* We ignore the first param here. */ + _Cilk_spawn [=](int *Aa, int size){ foo1_c(A, size); }(A, 2); + foo1 (A, 2); + _Cilk_sync; + if (global_var != 2) + return (++q); + + global_var = 0; + /* We ignore the first and second param here. */ + _Cilk_spawn [=](int *Aa, int size){ foo1_c(A, size); }(B, 2); + foo1 (A, 2); + _Cilk_sync; + if (global_var != 2) + return (++q); + + global_var = 0; + _Cilk_spawn [&](){ foo1(A, 2); }(); + [&](){ foo1(A, 2); }(); + _Cilk_sync; + if (global_var != 2) + return (++q); + + global_var = 0; + _Cilk_spawn [=](){ foo1_c (A, main_size); }(); + foo1 (A, 2); + _Cilk_sync; + if (global_var != 2) + return (++q); + + global_var = 0; + _Cilk_spawn [&](){ foo1(A, main_size); }(); + [&](){ foo1(A, 2); }(); + _Cilk_sync; + if (global_var != 2) + return (++q); + + return q; +} + +int main (void) +{ + return main2 (1); +} diff --git a/gcc/testsuite/g++.dg/cilk-plus/CK/lambda_spawns_tplt.cc b/gcc/testsuite/g++.dg/cilk-plus/CK/lambda_spawns_tplt.cc new file mode 100644 index 0000000..2667f5a --- /dev/null +++ b/gcc/testsuite/g++.dg/cilk-plus/CK/lambda_spawns_tplt.cc @@ -0,0 +1,173 @@ +/* { dg-options "-fcilkplus" } */ +/* { dg-do run { target i?86-*-* x86_64-*-* arm*-*-* } } */ +/* { dg-options "-std=c++11 -fcilkplus -lcilkrts" { target { i?86-*-* x86_64-*-* arm*-*-* } } } */ + +#define FIRST_NUMBER 5 +#define SECOND_NUMBER 3 +#define HAVE_IO 0 +#if HAVE_IO +#include <stdio.h> +#endif + +#include <stdlib.h> + +template <class T> +void foo1(T *array, int size) +{ +#if HAVE_IO + for (int ii = 0; ii < size; ii++) + printf("%2d\t", (int)array[ii]); + printf("\n"); + fflush (stdout); +#else + if (size != 2) + __builtin_abort (); + if (array[0] != FIRST_NUMBER) + __builtin_abort (); + if (array[1] != SECOND_NUMBER) + __builtin_abort (); +#endif +} +template <class T> +void foo1_c(const T *array, int size) +{ +#if HAVE_IO + for (int ii = 0; ii < size; ii++) + printf("%2d\t", (int)array[ii]); + printf("\n"); + fflush (stdout); +#else + if (size != 2) + __builtin_abort (); + if (array[0] != FIRST_NUMBER) + __builtin_abort (); + if (array[1] != SECOND_NUMBER) + __builtin_abort (); +#endif +} +template <class T> +int main2 (int argc, char **argv) { + T A[2] = {FIRST_NUMBER, SECOND_NUMBER}; + int main_size = argc+1; /* We know argc is 1, and so 1+1 = 2. */ + auto func0 = [=](){ foo1_c(A, 2); }; + _Cilk_spawn func0(); + foo1 (A, 2); + _Cilk_sync; + + auto func1 = [=](T *Aa){ foo1(Aa, 2); }; + _Cilk_spawn func1 (A); + foo1 (A, 2); + _Cilk_sync; + + auto func2 = [=](T *Aa, int size){ foo1(Aa, size); }; + _Cilk_spawn func2 (A, 2); + foo1 (A, 2); + _Cilk_sync; + + auto func3 = [=](T *Aa, int size){ int new_size = (size % 2 + 2); + foo1(Aa, size); }; + _Cilk_spawn func3 (A, 2); + foo1 (A, 2); + _Cilk_sync; + + auto func4 = [](T *Aa){ foo1(Aa, 2); }; + _Cilk_spawn func4 (A); + foo1 (A, 2); + _Cilk_sync; + + auto func5 = [](T *Aa, int size){ foo1(Aa, size); }; + _Cilk_spawn func5 (A, 2); + foo1 (A, 2); + _Cilk_sync; + + auto func6 = [&](T *Aa){ foo1(Aa, 2); }; + _Cilk_spawn func6 (A); + foo1 (A, 2); + _Cilk_sync; + + auto func7 = [&](T *Aa, int size){ foo1(Aa, size); }; + _Cilk_spawn func7 (A, 2); + foo1 (A, 2); + _Cilk_sync; + + auto func8 = [&](){ foo1(A, 2); }; + _Cilk_spawn func8 (); + foo1 (A, 2); + _Cilk_sync; + + /* We ignore the first param here and pass in A from the outer fn. */ + auto func9 = [&](T *Aa, int size){ foo1(A, size); }; + _Cilk_spawn func9 (A, 2); + foo1 (A, 2); + _Cilk_sync; + + auto func10 = [=](){ foo1_c(A, main_size); }; + _Cilk_spawn func10 (); + foo1 (A, 2); + _Cilk_sync; + + auto func11 = [&](){ foo1(A, main_size); }; + _Cilk_spawn func11 (); + foo1 (A, 2); + _Cilk_sync; + + /* We ignore the first & second param here and pass in A from the + outer fn. */ + auto func12 = [&](T *Aa, int size){ foo1(A, main_size); }; + _Cilk_spawn func12 (A, 2); + foo1 (A, 2); + _Cilk_sync; + + _Cilk_spawn [&](T *Aa){ foo1(Aa, 2); }(A); + foo1 (A, 2); + _Cilk_sync; + + _Cilk_spawn [&](T *Aa, int size){ foo1(Aa, size); }(A, 2); + foo1 (A, 2); + _Cilk_sync; + + _Cilk_spawn [=](T *Aa){ foo1(Aa, 2); }(A); + foo1 (A, 2); + _Cilk_sync; + + _Cilk_spawn [=](T *Aa, int size){ foo1(Aa, size); }(A, 2); + foo1 (A, 2); + _Cilk_sync; + + /* We ignore the first param here. */ + _Cilk_spawn [=](T *Aa, int size){ foo1_c(A, size); }(A, 2); + foo1 (A, 2); + _Cilk_sync; + + /* We ignore the first and second param here. */ + _Cilk_spawn [=](T *Aa, int size){ foo1_c(A, main_size); }(A, 2); + foo1 (A, 2); + _Cilk_sync; + + _Cilk_spawn [&](){ foo1(A, 2); }(); + [&](){ foo1(A, 2); }(); + _Cilk_sync; + + _Cilk_spawn [=](){ foo1_c(A, main_size); }(); + foo1 (A, 2); + _Cilk_sync; + + _Cilk_spawn [&](){ foo1(A, main_size); }(); + [&](){ foo1(A, 2); }(); + _Cilk_sync; + + return 0; +} + +int main (void) +{ + int argc = 1; + char **argv = NULL; + int x = 1, y = 1, z = 1, q = 1, p = 1; + x = main2<char>(argc,argv); + y = main2<short>(argc,argv); + z = main2<int>(argc,argv); + p = main2<long>(argc,argv); + q = main2<long long>(argc,argv); + return (x+y+z+p+q); +} diff --git a/gcc/testsuite/g++.dg/cilk-plus/cilk-plus.exp b/gcc/testsuite/g++.dg/cilk-plus/cilk-plus.exp index 707d17e..36c8111 100644 --- a/gcc/testsuite/g++.dg/cilk-plus/cilk-plus.exp +++ b/gcc/testsuite/g++.dg/cilk-plus/cilk-plus.exp @@ -22,6 +22,14 @@ if { ![check_effective_target_cilkplus] } { return; } +verbose "$tool $libdir" 1 +set library_var "[get_multilibs]" +# Pointing the ld_library_path to the Cilk Runtime library binaries. +set ld_library_path "$[get_multilibs]/libcilkrts/.libs" + +set ALWAYS_CFLAGS "" +lappend ALWAYS_CFLAGS "-L${library_var}/libcilkrts/.libs" + dg-init # Run the tests that are shared with C. g++-dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/PS/*.c]] "" @@ -63,4 +71,23 @@ dg-runtest [lsort [glob -nocomplain $srcdir/g++.dg/cilk-plus/AN/*.cc]] " -g -O3 dg-runtest [lsort [glob -nocomplain $srcdir/g++.dg/cilk-plus/AN/*.cc]] " -O3 -ftree-vectorize -fcilkplus -g" " " dg-finish +dg-init +dg-runtest [lsort [glob -nocomplain $srcdir/g++.dg/cilk-plus/CK/*.cc]] " -fcilkplus $ALWAYS_CFLAGS" " " +dg-runtest [lsort [glob -nocomplain $srcdir/g++.dg/cilk-plus/CK/*.cc]] " -O1 -fcilkplus $ALWAYS_CFLAGS" " " +dg-runtest [lsort [glob -nocomplain $srcdir/g++.dg/cilk-plus/CK/*.cc]] " -O2 -fcilkplus $ALWAYS_CFLAGS" " " +dg-runtest [lsort [glob -nocomplain $srcdir/g++.dg/cilk-plus/CK/*.cc]] " -O3 -fcilkplus $ALWAYS_CFLAGS" " " +dg-runtest [lsort [glob -nocomplain $srcdir/g++.dg/cilk-plus/CK/*.cc]] " -g -fcilkplus $ALWAYS_CFLAGS" " " +dg-runtest [lsort [glob -nocomplain $srcdir/g++.dg/cilk-plus/CK/*.cc]] " -g -O2 -fcilkplus $ALWAYS_CFLAGS" " " +dg-runtest [lsort [glob -nocomplain $srcdir/g++.dg/cilk-plus/CK/*.cc]] " -g -O3 -fcilkplus $ALWAYS_CFLAGS" " " +dg-finish + +dg-init +dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/CK/*.c]] " -fcilkplus $ALWAYS_CFLAGS" " " +dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/CK/*.c]] " -O1 -fcilkplus $ALWAYS_CFLAGS" " " +dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/CK/*.c]] " -O2 -fcilkplus $ALWAYS_CFLAGS" " " +dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/CK/*.c]] " -O3 -fcilkplus $ALWAYS_CFLAGS" " " +dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/CK/*.c]] " -g -fcilkplus" " " +dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/CK/*.c]] " -g -O2 -fcilkplus $ALWAYS_CFLAGS" " " +dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/CK/*.c]] " -g -O3 -fcilkplus $ALWAYS_CFLAGS" " " +dg-finish unset TEST_EXTRA_LIBS |