From patchwork Mon Nov 25 15:50:16 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Iyer, Balaji V" X-Patchwork-Id: 294024 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 730E82C00BC for ; Tue, 26 Nov 2013 02:50:42 +1100 (EST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :to:cc:subject:date:message-id:references:in-reply-to :content-type:mime-version; q=dns; s=default; b=kHsrflOptpl8G2nw TdaJOF7GAwuO1AUR4w4fKjyYhUEeg1sdARH79moNyY71/jU/hvCt0uyWqdYgjjMx o6QeNobELr7a9yg5Ag9SD/Mqcbv+b8F1+EhkN9svOXJevIZ0b7RTtKpSkPlTTcpf m5eIddfSD2HWuvFPB2NNJYpdeR4= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :to:cc:subject:date:message-id:references:in-reply-to :content-type:mime-version; s=default; bh=1mDGsYk0IhUPWPKBch68DY RyJT8=; b=JOTpV+6EHeUhiRF/chygvTr55UOa8VGN8KcYPxIrIPcVUd3TJvpNOc FsdkiaVYwJt4ZBAP7ttFv9Fv0uJb1KxNOWyvMRMd771fBm9taR1SZQp8O1eL2pwR QWiMl6Zkig16E9hleRVOQ3HPKmQjQFEL/T1UBdP5FbqBaAUruZ7nw= Received: (qmail 10397 invoked by alias); 25 Nov 2013 15:50:32 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 10385 invoked by uid 89); 25 Nov 2013 15:50:31 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=0.8 required=5.0 tests=AWL, BAYES_50, RDNS_NONE, SPF_PASS, URIBL_BLOCKED autolearn=no version=3.3.2 X-HELO: mga09.intel.com Received: from Unknown (HELO mga09.intel.com) (134.134.136.24) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Mon, 25 Nov 2013 15:50:28 +0000 Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by orsmga102.jf.intel.com with ESMTP; 25 Nov 2013 07:46:42 -0800 X-ExtLoop1: 1 Received: from fmsmsx107.amr.corp.intel.com ([10.19.9.54]) by fmsmga001.fm.intel.com with ESMTP; 25 Nov 2013 07:50:16 -0800 Received: from fmsmsx101.amr.corp.intel.com ([169.254.1.227]) by FMSMSX107.amr.corp.intel.com ([169.254.9.137]) with mapi id 14.03.0123.003; Mon, 25 Nov 2013 07:50:15 -0800 From: "Iyer, Balaji V" To: Jason Merrill , "gcc-patches@gcc.gnu.org" CC: Jeff Law Subject: RE: _Cilk_spawn and _Cilk_sync for C++ Date: Mon, 25 Nov 2013 15:50:16 +0000 Message-ID: References: <528E57DE.90900@redhat.com> <528F7D81.4000308@redhat.com> In-Reply-To: <528F7D81.4000308@redhat.com> MIME-Version: 1.0 X-IsSubscribed: yes Hi Jason, Please see my responses below > -----Original Message----- > From: Jason Merrill [mailto:jason@redhat.com] > Sent: Friday, November 22, 2013 10:51 AM > To: Iyer, Balaji V; gcc-patches@gcc.gnu.org > Cc: Jeff Law > Subject: Re: _Cilk_spawn and _Cilk_sync for C++ > > On 11/21/2013 05:40 PM, Iyer, Balaji V wrote: > > +/* Returns a TRY_CATCH_EXPR that will encapsulate BODY, EXCEPT_DATA > and > > + EXCEPT_FLAG. */ > > + > > +tree > > +create_cilk_try_catch (tree except_flag, tree except_data, tree body) > > +{ > > + tree catch_list = alloc_stmt_list (); > > + append_to_statement_list (except_flag, &catch_list); > > + append_to_statement_list (except_data, &catch_list); > > + 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 (EXPR_LOCATION (body), > 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 (EXPR_LOCATION (body), > TRY_CATCH_EXPR, > > + body, catch_list); > > + return try_catch_expr; > > +} > > I had in mind something less cilk-specific: a function that takes two tree > operands, one for the body and one for the throwing path. > Basically, make catch_list a parameter and move the first two appends back > into the calling function. > This is fixed as you suggested. > > The reason is that, when you have something like this: > > > > _Cilk_spawn [=] { } (); > > > > I need to capture the function call (which in this case is the whole function) > and throw it into a nested function. The nested function implementation is > shared with C. If the function is stored in a variable then I can just send that > out to the nested function. I have added another constraint to make sure the > function is a spawning function, this way we can reduce more cases were > they are stored to a variable. The reason why I added this check in > finish_call_expr is that it seemed to be most straight-forward for me and > only place where I could do with least disruption (code-changes). > > It looks like you're transforming any > > [...] {...} (...); > > into > > auto lambda = [...]{...}; > lambda(...); > > which has significantly different semantics, particularly in terms of the > lifetime of the lambda object. In some of the Cilk online documentation, I > see: > > > When spawning named lambda functions, be careful that the lifespan of > the lambda extends at least until the next sync, or else the destructor for the > lambda will race with the spawned call. For example: > > double i = g(); > > if (some condition) { > > // named lambda with value capture of i > > auto f = [=i]() { double d = sin(i); f(d); }; > > cilk_spawn f(); > > } // Ouch! destructor for f is in parallel with spawned call. > > This would seem to apply even more to unnamed lambda functions, since > normally they would be destroyed at the end of the full-expression, which > must always be before the sync. Does the Intel compiler implicitly extend > the lifetime of a lambda called by cilk spawn? In any case, we really don't > want to do this for all calls to unnamed lambdas just because we turned on > cilk mode. > I have fixed this issue. My function to map the variable's context from the spawner to the spawn helper function was going into the lambda function. I made it stop by adding a language specific copy_tree_body (basically stop going into the lambda function's body for C++ and for the rest of the times just use copy_tree_body_r, no code duplicating is done between the two) that and it works fine now. The fixed patch is attached and here are the fixed ChangeLogs: gcc/c-family/ChangeLog 2013-11-25 Balaji V. Iyer * cilk.c (cilk_outline): Replaced a call to copy_tree_body_r with the language specific one. gcc/c/ChangeLog 2013-11-25 Balaji V. Iyer * c-objc-common.h (LANG_HOOKS_CILKPLUS_CILK_SPEC_COPY_BODY): New define. gcc/ChangeLog 2013-11-25 Balaji V. Iyer * langhooks.h (lang_hooks_for_cilkplus::cilk_specific_copy_tree_body): New field. * langhooks-def.h (LANG_HOOKS_CILKPLUS::LANG_HOOKS_CILKPLUS_CILK_SPEC_COPY_BODY): Likewise. (LANG_HOOKS_CILKPLUS_CILK_SPEC_COPY_BODY): New #define. gcc/cp/ChangeLog 2013-11-25 Balaji V. Iyer * cp-tree.h (cilk_valid_spawn): New prototype. (gimplify_cilk_spawn): Likewise. (cp_cilk_install_body_wframe_cleanup): Likewise. (cilk_create_lambda_fn_tmp_var): 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. (cp_cilk_install_body_wframe_cleanup): Likewise. (is_lambda_function): Likewise. (cp_cilk_copy_tree_body_r): Likewise. * except.c (create_try_catch_expr): Likewise. * parser.h (IN_CILK_SPAWN): New #define. * cp-objcp-common.h (LANG_HOOKS_CILKPLUS_GIMPLIFY_SPAWN): Likewise. * cp-objcp-common.h (LANG_HOOKS_CILKPLUS_CILK_SPEC_COPY_BODY): Likewise. (LANG_HOOKS_CILKPLUS_DETECT_SPAWN_AND_UNWRAP): Likewise. (LANG_HOOKS_CILKPLUS_FRAME_CLEANUP): Likewise. * 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. gcc/testsuite/ChangeLog 2013-11-25 Balaji V. Iyer * 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. So, is this patch Ok to install? Thanks, Balaji V. Iyer. > Jason diff --git a/gcc/c-family/cilk.c b/gcc/c-family/cilk.c index 165348f..925a2c1 100644 --- a/gcc/c-family/cilk.c +++ b/gcc/c-family/cilk.c @@ -510,7 +510,16 @@ cilk_outline (tree inner_fn, tree *stmt_p, struct wrapper_data *wd) pointer_map_traverse (wd->decl_map, nested ? for_local_cb : wrapper_local_cb, &id); - walk_tree (stmt_p, copy_tree_body_r, &id, NULL); + /* When you are walking through all the trees and copying them, there is no + reason to copy the lambda function body that is spawned in C++. + For everything else (_Cilk_for body for C/C++), just do the normal copying, + i.e. call copy_tree_body_r. In C, the cilk_specific_copy_tree_body is + defined to copy_tree_body_r in c-objc-common.h file. */ + if (wd->type == CILK_BLOCK_FOR) + walk_tree (stmt_p, copy_tree_body_r, (void *) &id, NULL); + else + walk_tree (stmt_p, lang_hooks.cilkplus.cilk_specific_copy_tree_body, + (void *) &id, NULL); /* See if this function can throw or calls something that should not be spawned. The exception part is only necessary if diff --git a/gcc/c/c-objc-common.h b/gcc/c/c-objc-common.h index 6ae7b3e..adab71b 100644 --- a/gcc/c/c-objc-common.h +++ b/gcc/c/c-objc-common.h @@ -108,6 +108,9 @@ along with GCC; see the file COPYING3. If not see #undef LANG_HOOKS_CILKPLUS_GIMPLIFY_SPAWN #define LANG_HOOKS_CILKPLUS_GIMPLIFY_SPAWN gimplify_cilk_spawn +#undef LANG_HOOKS_CILKPLUS_CILK_SPEC_COPY_BODY +#define LANG_HOOKS_CILKPLUS_CILK_SPEC_COPY_BODY copy_tree_body_r + #undef LANG_HOOKS_CILKPLUS_FRAME_CLEANUP #define LANG_HOOKS_CILKPLUS_FRAME_CLEANUP c_cilk_install_body_w_frame_cleanup diff --git a/gcc/cp/cp-cilkplus.c b/gcc/cp/cp-cilkplus.c index 5c1090a..414f71e 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,105 @@ 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; +} + +/* Returns true if the FUNCTION_DECL in call_exp, A CALL_EXPR tree is a + lambda function. */ + +static bool +is_lambda_fn_p (tree call_exp) +{ + tree call_fn = CALL_EXPR_FN (call_exp); + if (TREE_CODE (call_fn) == ADDR_EXPR) + call_fn = TREE_OPERAND (call_fn, 0); + if (call_fn && LAMBDA_FUNCTION_P (call_fn)) + return true; + return false; +} + +/* Helper function for walk_tree. This function will call copy_tree_body_r + for all the sub_trees except the first parameter of a lambda function. */ + +tree +cp_cilk_copy_tree_body_r (tree *tp, int *walk_subtrees, void *data) +{ + if (TREE_CODE (*tp) == CALL_EXPR) + { + int nargs = call_expr_nargs (*tp); + int start = 0; + if (cxx_dialect >= cxx0x && is_lambda_fn_p (*tp)) + start = 1; + for (int ii = start; ii < nargs; ii++) + walk_tree (&CALL_EXPR_ARG ((*tp), ii), copy_tree_body_r, data, NULL); + /* No need to visit *TP's subtrees since we have done the necessary + ones above. */ + *walk_subtrees = 0; + } + else + walk_tree (tp, copy_tree_body_r, data, NULL); + return NULL_TREE; +} + +/* Installs BODY into function FNDECL with appropriate exception handling + code. */ + +void +cp_cilk_install_body_wframe_cleanup (tree fndecl, tree orig_body) +{ + 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); + 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-objcp-common.h b/gcc/cp/cp-objcp-common.h index ee22423..eb81cb2 100644 --- a/gcc/cp/cp-objcp-common.h +++ b/gcc/cp/cp-objcp-common.h @@ -154,4 +154,17 @@ 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 +#undef LANG_HOOKS_CILKPLUS_CILK_SPEC_COPY_BODY +#define LANG_HOOKS_CILKPLUS_CILK_SPEC_COPY_BODY cp_cilk_copy_tree_body_r + +#undef LANG_HOOKS_CILKPLUS_GIMPLIFY_SPAWN +#define LANG_HOOKS_CILKPLUS_GIMPLIFY_SPAWN gimplify_cilk_spawn + +#undef LANG_HOOKS_CILKPLUS_DETECT_SPAWN_AND_UNWRAP +#define LANG_HOOKS_CILKPLUS_DETECT_SPAWN_AND_UNWRAP \ + cilk_detect_spawn_and_unwrap + +#undef LANG_HOOKS_CILKPLUS_FRAME_CLEANUP +#define LANG_HOOKS_CILKPLUS_FRAME_CLEANUP cp_cilk_install_body_wframe_cleanup + #endif /* GCC_CP_OBJCP_COMMON */ diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 4e26bd5..9d9f4be 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -5355,6 +5355,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); @@ -6179,11 +6180,19 @@ extern void vtv_build_vtable_verify_fndecl (void); /* In cp-cilkplus.c. */ extern bool cpp_validate_cilk_plus_loop (tree); +extern void cp_cilk_install_body_wframe_cleanup (tree, tree); +extern tree cp_cilk_copy_tree_body_r (tree *, int *, void *); /* In cp/cp-array-notations.c */ 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); +extern int gimplify_cilk_spawn (tree *, gimple_seq *, + gimple_seq *); + /* -- end of C++ */ #endif /* ! GCC_CP_TREE_H */ diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 7d9d5df..64c09d1 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -54,6 +54,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 { @@ -13866,6 +13867,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 ac2128d..e8e6383 100644 --- a/gcc/cp/except.c +++ b/gcc/cp/except.c @@ -1339,4 +1339,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); + gcc_assert (TREE_CODE (catch_list) == STATEMENT_LIST); + 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 27f1054..0f9b29b 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -5622,6 +5622,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); @@ -5766,6 +5767,70 @@ 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 + { + /* Break or continue statements within this primary expression + is not allowed. */ + saved_in_statement = parser->in_statement; + parser->in_statement = IN_CILK_SPAWN; + } + /* We set this here so that finish_call_expr can set lambda to a var. + if it is not done so. */ + 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); + if (parser->in_statement & IN_CILK_SPAWN) + parser->in_statement = parser->in_statement & ~IN_CILK_SPAWN; + break; + case RID_BUILTIN_SHUFFLE: { vec *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 3bc8ccb..1b34434 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -13758,6 +13758,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 81394fa..a07b0ef 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -10415,6 +10415,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 bff7f17..f42ea63 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -6159,6 +6159,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 @@ -8283,6 +8294,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/langhooks-def.h b/gcc/langhooks-def.h index 411cf74..ca24f06 100644 --- a/gcc/langhooks-def.h +++ b/gcc/langhooks-def.h @@ -220,8 +220,13 @@ extern bool lhd_cilk_detect_spawn (tree *); #define LANG_HOOKS_CILKPLUS_FRAME_CLEANUP lhd_install_body_with_frame_cleanup #define LANG_HOOKS_CILKPLUS_GIMPLIFY_SPAWN lhd_gimplify_expr +/* We do not need a empty function for the cilk-specific becuase they will + automatically checked for NULL before calling. */ +#define LANG_HOOKS_CILKPLUS_CILK_SPEC_COPY_BODY NULL + #define LANG_HOOKS_CILKPLUS { \ LANG_HOOKS_CILKPLUS_DETECT_SPAWN_AND_UNWRAP, \ + LANG_HOOKS_CILKPLUS_CILK_SPEC_COPY_BODY, \ LANG_HOOKS_CILKPLUS_FRAME_CLEANUP, \ LANG_HOOKS_CILKPLUS_GIMPLIFY_SPAWN \ } diff --git a/gcc/langhooks.h b/gcc/langhooks.h index 9539e7d..56b52be 100644 --- a/gcc/langhooks.h +++ b/gcc/langhooks.h @@ -146,6 +146,10 @@ struct lang_hooks_for_cilkplus /* Returns true if the expression passed in has a spawned function call. */ bool (*cilk_detect_spawn_and_unwrap) (tree *); + /* Cilk specific copy tree body used by C++ because we need a way to bypass + the first argument of a lambda function for a _Cilk_spawn. */ + tree (*cilk_specific_copy_tree_body) (tree *, int *, void *); + /* 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); 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 +#include +#if HAVE_IO +#include +#include +#endif +#include + + +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 +#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 +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 +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 +T fib (T z) { + if (z < 2) return z; + T a = _Cilk_spawn fib(z - 1); + T b = fib(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(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 +#endif + +#include + +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 +#endif + +#include + +template +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 +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 +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(argc,argv); + y = main2(argc,argv); + z = main2(argc,argv); + p = main2(argc,argv); + q = main2(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 fa9246c..90faca4 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]] "" @@ -56,3 +64,23 @@ dg-runtest [lsort [glob -nocomplain $srcdir/g++.dg/cilk-plus/AN/*.cc]] " -g -O2 dg-runtest [lsort [glob -nocomplain $srcdir/g++.dg/cilk-plus/AN/*.cc]] " -g -O3 -fcilkplus" " " 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