From patchwork Thu Nov 28 04:05:49 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: 294765 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 0BD612C04BC for ; Thu, 28 Nov 2013 15:07:26 +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=csqfcoBhJ/05uxXU 0UQ/wfVFmkaqjO0fiBKs6r/KwiVXSdbeCN/Svz7uU9EEXBL5sdo16Kymb66C0X8m RxM032Pc8uzA8kmWHshGXK7Z3XVl3fVypZ+mXfr7l7xt3pGkSfJVOP2Z+TIvZTqG zaHyceZOIz7RR1ejSiAUEVpgHIA= 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=/dah0wuosVPauY+tn6Wj7X TTQmw=; b=A2AptLAuzrUmt17T+AjmaOhvZBQ3kZ1ff25bzrxITQ3nlryJ6qPAZ8 MJgS+JMBxo9wRSSRAAiwkfCRSCkM3T06GNKvkZosAKGTmuuDspMskQd2Jz29pVsH m/3mytAVDeHfcz84/MxAPsJCBjx5TMnD1sNP25neamO3dEgG0m7wk= Received: (qmail 18470 invoked by alias); 28 Nov 2013 04:06:50 -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 18459 invoked by uid 89); 28 Nov 2013 04:06:49 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=2.1 required=5.0 tests=AWL, BAYES_99, RDNS_NONE, SPF_PASS, URIBL_BLOCKED autolearn=no version=3.3.2 X-HELO: mga02.intel.com Received: from Unknown (HELO mga02.intel.com) (134.134.136.20) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Thu, 28 Nov 2013 04:05:59 +0000 Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by orsmga101.jf.intel.com with ESMTP; 27 Nov 2013 20:05:51 -0800 X-ExtLoop1: 1 Received: from fmsmsx103.amr.corp.intel.com ([10.19.9.34]) by fmsmga001.fm.intel.com with ESMTP; 27 Nov 2013 20:05:50 -0800 Received: from fmsmsx151.amr.corp.intel.com (10.19.17.220) by FMSMSX103.amr.corp.intel.com (10.19.9.34) with Microsoft SMTP Server (TLS) id 14.3.123.3; Wed, 27 Nov 2013 20:05:50 -0800 Received: from fmsmsx101.amr.corp.intel.com ([169.254.1.227]) by FMSMSX151.amr.corp.intel.com ([169.254.7.202]) with mapi id 14.03.0123.003; Wed, 27 Nov 2013 20:05:50 -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: Thu, 28 Nov 2013 04:05:49 +0000 Message-ID: References: <528E57DE.90900@redhat.com> <528F7D81.4000308@redhat.com> <52962F1A.8090205@redhat.com> <5296407C.40907@redhat.com> <52969B3A.9070506@redhat.com> In-Reply-To: <52969B3A.9070506@redhat.com> MIME-Version: 1.0 X-IsSubscribed: yes > -----Original Message----- > From: Jason Merrill [mailto:jason@redhat.com] > Sent: Wednesday, November 27, 2013 8:24 PM > To: Iyer, Balaji V; gcc-patches@gcc.gnu.org > Cc: Jeff Law > Subject: Re: _Cilk_spawn and _Cilk_sync for C++ > > On 11/27/2013 05:59 PM, Iyer, Balaji V wrote: > > Well, if I use copy_tree_body_r for C and C++, in lambda functions, it > asserts in varasm.c. The main reason I see that, the copy_tree_body_r walks > into the closure and then maps the variables from the lambda function from > the spawner to the helper function. > > It walks into the initializer for the closure object, yes. And gets confused by > the initializer in the > > _Cilk_spawn [=](int *Aa, int size){ foo1_c(A, size); }(B, 2); > > case. The initializer for the closure is a CONSTRUCTOR which contains a > reference to A, and that is running into trouble because > extract_free_variables doesn't walk into CONSTRUCTORs. You probably > want to switch a lot of your tree walking functions to use walk_tree directly > rather than try to keep up with all the different kinds of expressions yourself. Found the bug. I was not utilizing the stabilize_expr's output correctly. Here is the fixed patch. I have removed the function pointer and the lang_hooks addition. It now just uses copy_tree_body_r for C and C++. It passes all the tests for C and C++ on my x86_64 box. Is this Ok for trunk? Here are the ChangeLog entries: gcc/c-family/ChangeLog 2013-11-27 Balaji V. Iyer * cilk.c (cilk_outline): Made this function non-static. * c-common.h (cilk_outline): New prototype. (c_cilk_install_body_with_frame_cleanup): Added a new parameter. gcc/ChangeLog 2013-11-27 Balaji V. Iyer * langhooks.h (lang_hooks_for_cilkplus::install_body_with_frame_cleanup): Added new parameter. gcc/cp/ChangeLog 2013-11-27 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. * 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-27 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. Thanks, Balaji V. Iyer. diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h index 664e928..f46008f --- a/gcc/c-family/c-common.h +++ b/gcc/c-family/c-common.h @@ -1379,7 +1379,7 @@ extern vec *fix_sec_implicit_args 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 void c_cilk_install_body_w_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); @@ -1387,5 +1387,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 *, struct wrapper_data *); #endif /* ! GCC_C_COMMON_H */ diff --git a/gcc/c-family/cilk.c b/gcc/c-family/cilk.c index c85b5f2..537a07b 100644 --- a/gcc/c-family/cilk.c +++ b/gcc/c-family/cilk.c @@ -477,7 +477,7 @@ 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 +void cilk_outline (tree inner_fn, tree *stmt_p, struct wrapper_data *wd) { const tree outer_fn = wd->context; @@ -512,8 +512,8 @@ 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,9 @@ 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); + lang_hooks.cilkplus.install_body_with_frame_cleanup (fndecl, stmt, + (void *) wd); gcc_assert (DECL_SAVED_TREE (fndecl)); pop_cfun_to (outer); @@ -879,7 +878,7 @@ cilk_install_body_pedigree_operations (tree frame_ptr) spawn-helper and BODY is the newly created body for FNDECL. */ void -c_cilk_install_body_w_frame_cleanup (tree fndecl, tree body) +c_cilk_install_body_w_frame_cleanup (tree fndecl, tree body, void *wd) { tree list = alloc_stmt_list (); tree frame = make_cilk_frame (fndecl); @@ -894,6 +893,10 @@ c_cilk_install_body_w_frame_cleanup (tree fndecl, tree body) 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 *) wd); + 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); diff --git a/gcc/cp/cp-cilkplus.c b/gcc/cp/cp-cilkplus.c index 5c1090a..480823d --- 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,90 @@ 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) +{ + if (TREE_CODE (call_exp) != CALL_EXPR) + return false; + 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; +} + +/* 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 +cp_cilk_install_body_wframe_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); + tree pre_body = NULL_TREE; + if (is_lambda_fn_p (orig_body)) + stabilize_expr (orig_body, &pre_body); + else + pre_body = orig_body; + cilk_outline (fndecl, &pre_body, (struct wrapper_data *) wd); + orig_body = fold_build_cleanup_point_expr (void_type_node, orig_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..77a66c3 100644 --- a/gcc/cp/cp-objcp-common.h +++ b/gcc/cp/cp-objcp-common.h @@ -154,4 +154,14 @@ 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_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 1fc4b59..109110b 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); @@ -6180,11 +6181,17 @@ 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, 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 9508131..5e3c301 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 { @@ -13883,6 +13884,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..8ecac62 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); + 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 d7092cc..2069e4c 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,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 b58c755..8672129 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 d871c4d..4f637fb 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -10417,6 +10417,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 a4da037..fd8eac1 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -6164,6 +6164,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 @@ -8288,6 +8299,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..e3c34d9 100644 --- a/gcc/langhooks-def.h +++ b/gcc/langhooks-def.h @@ -214,7 +214,7 @@ 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 void lhd_install_body_with_frame_cleanup (tree, tree, void *); 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 diff --git a/gcc/langhooks.c b/gcc/langhooks.c index 7fe349d..ef6d82d 100644 --- a/gcc/langhooks.c +++ b/gcc/langhooks.c @@ -681,7 +681,7 @@ lhd_end_section (void) frame cleanup function for _Cilk_spawn. */ void -lhd_install_body_with_frame_cleanup (tree, tree) +lhd_install_body_with_frame_cleanup (tree, tree, void *) { } diff --git a/gcc/langhooks.h b/gcc/langhooks.h index 9539e7d..80bfa66 100644 --- a/gcc/langhooks.h +++ b/gcc/langhooks.h @@ -148,7 +148,7 @@ struct lang_hooks_for_cilkplus /* 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); + void (*install_body_with_frame_cleanup) (tree, tree, void *); /* Function to gimplify a spawned function call. Returns enum gimplify status, but as mentioned in a previous comment, we can't see that type 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 a66ec44..a4328d0 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]] "" @@ -62,4 +70,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