From patchwork Fri Dec 6 04:38:54 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: 297570 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 B112A2C0082 for ; Fri, 6 Dec 2013 15:39:23 +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=xJLfZ35Bs3snBu1y UVoI5YluyxkGna0K5BGqIbtGQ6FpzJ9RibIJKcr0dgHVFBtvTdrtGkYiORsh8Nh2 0jDioYnuqaouzbA/QI0D4poboFdepb0/1jUVQhWy9cXSSSu+q8yD0bx2GV0mciS+ 8XBqGwMdljFfxKGNvt8Ghj7Hlh4= 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=1maYnH4aDmyAM0jW5aYVdp 8dpjk=; b=ai9k7f1tzzJnUCH2DeC9mGAGYHNOBkyEUVepCjSKmtcpMogntb7aIq zQzgWSMtuRp0CtkaU+ULl69UUDsR2ou99JiJQqS/GoI4dCbf4q8v2uFFGpUs5qic G5Tr4zFrEmSPn4eBmNsQS37bj1IiUXwue/2lp0c26qQ/k8kl+mUcs= Received: (qmail 32415 invoked by alias); 6 Dec 2013 04:39:15 -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 32405 invoked by uid 89); 6 Dec 2013 04:39:14 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=4.9 required=5.0 tests=AWL, BAYES_50, KAM_STOCKTIP, SPF_PASS, UNSUBSCRIBE_BODY 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; Fri, 06 Dec 2013 04:39:07 +0000 Received: from orsmga001.jf.intel.com ([10.7.209.18]) by orsmga101.jf.intel.com with ESMTP; 05 Dec 2013 20:38:57 -0800 X-ExtLoop1: 1 Received: from fmsmsx103.amr.corp.intel.com ([10.19.9.34]) by orsmga001.jf.intel.com with ESMTP; 05 Dec 2013 20:38:55 -0800 Received: from fmsmsx111.amr.corp.intel.com (10.18.116.5) by FMSMSX103.amr.corp.intel.com (10.19.9.34) with Microsoft SMTP Server (TLS) id 14.3.123.3; Thu, 5 Dec 2013 20:38:55 -0800 Received: from fmsmsx101.amr.corp.intel.com ([169.254.1.227]) by fmsmsx111.amr.corp.intel.com ([169.254.2.158]) with mapi id 14.03.0123.003; Thu, 5 Dec 2013 20:38:55 -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: Fri, 6 Dec 2013 04:38:54 +0000 Message-ID: References: <528E57DE.90900@redhat.com> <528F7D81.4000308@redhat.com> <52962F1A.8090205@redhat.com> <5296407C.40907@redhat.com> <52969B3A.9070506@redhat.com> <52974EF1.8000702@redhat.com> <529D0757.3040405@redhat.com> <529E5764.1000003@redhat.com> <529FAEF8.1090207@redhat.com> <529FB194.5090003@redhat.com> In-Reply-To: <529FB194.5090003@redhat.com> MIME-Version: 1.0 X-IsSubscribed: yes Hi Jason, Attached, please find a fixed patch. I have fixed all the issues you have mentioned (make the C++ use the normal copy_body_r, used the init_p value that comes out of stabilize_expr and removed the unsetting of IN_CILK_SPAWN during the _CIlk_sync keyword parsing in parser.c). I'm also attaching the Change logs with the email. Is it OK for trunk? It passes all the tests for C and C++ in my x86_64 SUSE box. Thanks, Balaji V. Iyer. > -----Original Message----- > From: Jason Merrill [mailto:jason@redhat.com] > Sent: Wednesday, December 4, 2013 5:50 PM > To: Iyer, Balaji V; gcc-patches@gcc.gnu.org > Cc: Jeff Law > Subject: Re: _Cilk_spawn and _Cilk_sync for C++ > > On 12/04/2013 05:42 PM, Iyer, Balaji V wrote: > >> I had in mind that the declaration would be in c-common.h, but each > >> front end would have a different definition in the front end > >> directory, kind of like how all front ends need to define "convert". > > > > I didn't know it was an OK thing to do. > > I think it's OK for c-common interfaces, but not for back end interfaces. > > Jason > diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h index 1df9e99..a014c7c 100644 --- a/gcc/c-family/c-common.h +++ b/gcc/c-family/c-common.h @@ -1378,8 +1378,8 @@ extern vec *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); @@ -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/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..8c7f61e 100644 --- a/gcc/c-family/cilk.c +++ b/gcc/c-family/cilk.c @@ -38,45 +38,6 @@ along with GCC; see the file COPYING3. If not see #include "diagnostic.h" #include "cilk.h" -enum add_variable_type { - /* Reference to previously-defined variable. */ - ADD_READ, - /* Definition of a new variable in inner-scope. */ - ADD_BIND, - /* Write to possibly previously-defined variable. */ - ADD_WRITE -}; - -enum cilk_block_type { - /* Indicates a _Cilk_spawn block. 30 was an arbitary number picked for - ease of debugging. */ - CILK_BLOCK_SPAWN = 30, - /* Indicates _Cilk_for statement block. */ - CILK_BLOCK_FOR -}; - -struct wrapper_data -{ - /* Kind of function to be created. */ - enum cilk_block_type type; - /* Signature of helper function. */ - tree fntype; - /* Containing function. */ - tree context; - /* Disposition of all variables in the inner statement. */ - struct pointer_map_t *decl_map; - /* True if this function needs a static chain. */ - bool nested; - /* Arguments to be passed to wrapper function, currently a list. */ - tree arglist; - /* Argument types, a list. */ - tree argtypes; - /* Incoming parameters. */ - tree parms; - /* Outer BLOCK object. */ - tree block; -}; - static void extract_free_variables (tree, struct wrapper_data *, enum add_variable_type); static HOST_WIDE_INT cilk_wrapper_count; @@ -477,7 +438,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 +473,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 +514,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 +691,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 +835,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 +995,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 +1156,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 +1181,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/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); +} diff --git a/gcc/cilk.h b/gcc/cilk.h index 99b4d78..b4ee61d 100644 --- a/gcc/cilk.h +++ b/gcc/cilk.h @@ -99,4 +99,44 @@ fn_contains_cilk_spawn_p (function *f) return (flag_enable_cilkplus && (f->calls_cilk_spawn || f->cilk_frame_decl != NULL_TREE)); } + +enum add_variable_type { + /* Reference to previously-defined variable. */ + ADD_READ, + /* Definition of a new variable in inner-scope. */ + ADD_BIND, + /* Write to possibly previously-defined variable. */ + ADD_WRITE +}; + +enum cilk_block_type { + /* Indicates a _Cilk_spawn block. 30 was an arbitary number picked for + ease of debugging. */ + CILK_BLOCK_SPAWN = 30, + /* Indicates _Cilk_for statement block. */ + CILK_BLOCK_FOR +}; + +struct wrapper_data +{ + /* Kind of function to be created. */ + enum cilk_block_type type; + /* Signature of helper function. */ + tree fntype; + /* Containing function. */ + tree context; + /* Disposition of all variables in the inner statement. */ + struct pointer_map_t *decl_map; + /* True if this function needs a static chain. */ + bool nested; + /* Arguments to be passed to wrapper function, currently a list. */ + tree arglist; + /* Argument types, a list. */ + tree argtypes; + /* Incoming parameters. */ + tree parms; + /* Outer BLOCK object. */ + tree block; +}; + #endif diff --git a/gcc/cp/cp-cilkplus.c b/gcc/cp/cp-cilkplus.c index 5c1090a..5d8beb9 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,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 +call_to_lambda_fn_p (tree call_exp) +{ + if (cxx_dialect < cxx0x) + return false; + if (TREE_CODE (call_exp) != CALL_EXPR) + return false; + tree call_fn = get_callee_fndecl (call_exp); + 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 +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); + tree pre_body = NULL_TREE; + if (call_to_lambda_fn_p (orig_body)) + 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, pre_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-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 bd4ead7..d82a1df 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 *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/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 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 diff --git a/libcilkrts/Makefile.am b/libcilkrts/Makefile.am index 56bc9eb..d252087 100644 --- a/libcilkrts/Makefile.am +++ b/libcilkrts/Makefile.am @@ -38,7 +38,7 @@ ACLOCAL_AMFLAGS = -I .. -I ../config # Compiler and linker flags. GENERAL_FLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/runtime -I$(top_srcdir)/runtime/config/$(config_dir) -DIN_CILK_RUNTIME=1 -GENERAL_FLAGS += -D_Cilk_spawn="" -D_Cilk_sync="" -D_Cilk_for=for +# GENERAL_FLAGS += -D_Cilk_spawn="" -D_Cilk_sync="" -D_Cilk_for=for # Enable Intel Cilk Plus extension GENERAL_FLAGS += -fcilkplus diff --git a/libcilkrts/Makefile.in b/libcilkrts/Makefile.in index 5066bef..94902e1 100644 --- a/libcilkrts/Makefile.in +++ b/libcilkrts/Makefile.in @@ -342,12 +342,12 @@ AUTOMAKE_OPTIONS = foreign ACLOCAL_AMFLAGS = -I .. -I ../config # Compiler and linker flags. +# GENERAL_FLAGS += -D_Cilk_spawn="" -D_Cilk_sync="" -D_Cilk_for=for # Enable Intel Cilk Plus extension GENERAL_FLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/runtime \ -I$(top_srcdir)/runtime/config/$(config_dir) \ - -DIN_CILK_RUNTIME=1 -D_Cilk_spawn="" -D_Cilk_sync="" \ - -D_Cilk_for=for -fcilkplus + -DIN_CILK_RUNTIME=1 -fcilkplus AM_CFLAGS = $(GENERAL_FLAGS) -std=c99 AM_CPPFLAGS = $(GENERAL_FLAGS) AM_LDFLAGS = -lpthread diff --git a/libcilkrts/configure.ac b/libcilkrts/configure.ac index 30fac99..2a095de 100644 --- a/libcilkrts/configure.ac +++ b/libcilkrts/configure.ac @@ -31,8 +31,8 @@ # WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. -AC_INIT([Cilk Runtime Library], [2.0], [cilk@intel.com]) AC_PREREQ([2.64]) +AC_INIT([Cilk Runtime Library], [2.0], [cilk@intel.com]) # Needed to define ${target}. Needs to be very early to avoid annoying # warning about calling AC_ARG_PROGRAM before AC_CANONICAL_SYSTEM diff --git a/libcilkrts/runtime/symbol_test.c b/libcilkrts/runtime/symbol_test.c index 1113ecd..8291d36 100644 --- a/libcilkrts/runtime/symbol_test.c +++ b/libcilkrts/runtime/symbol_test.c @@ -41,6 +41,7 @@ * will cause a linker error. */ +#define _Cilk_for for extern void* __cilkrts_global_state; void *volatile p;