From patchwork Mon Nov 18 03:19:09 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: 291932 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 496442C00C7 for ; Mon, 18 Nov 2013 14:19:46 +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:content-type:mime-version; q=dns; s=default; b=UBb8Upv0BBAfGN1p3zvBMmE5wgbkPTedh+uaX/slR/jgutmQBI CHahXzF3yMlKuZnaQtoWxo4Z1m6QTXTwSHnMdwDgqWxh/7MX8bTHQ2Pw/yUw2JDs zOS5vMV2dEig8xnJvYgki1RUN5FEcx7ybeKq+uoztG6EWInYo44nOgSPs= 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:content-type:mime-version; s= default; bh=0/qUHZuMAh6XzKHsEclZ5IDENzM=; b=kXBL8sVzxC4+0TuNmwpJ CCYxDkIOVQy7FeyNne6TeikgmL4XwEwK/EFGl6XhpnPuMqlX4bGUZzDyJCT2QHbY j/C9ZA6kl4MTvJQFssr7i0K5QNkhefb3q8C2B3SaCpMN/CRargmtPJoy+fkAyd/p x/K0F8BA1TU2QwU6/MH2EsY= Received: (qmail 10164 invoked by alias); 18 Nov 2013 03:19:35 -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 10151 invoked by uid 89); 18 Nov 2013 03:19:33 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=1.4 required=5.0 tests=AWL, BAYES_80, RDNS_NONE, SPF_PASS, URIBL_BLOCKED autolearn=no version=3.3.2 X-HELO: mga09.intel.com Received: from Unknown (HELO mga09.intel.com) (134.134.136.24) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Mon, 18 Nov 2013 03:19:30 +0000 Received: from orsmga002.jf.intel.com ([10.7.209.21]) by orsmga102.jf.intel.com with ESMTP; 17 Nov 2013 19:15:37 -0800 X-ExtLoop1: 1 Received: from fmsmsx106.amr.corp.intel.com ([10.19.9.37]) by orsmga002.jf.intel.com with ESMTP; 17 Nov 2013 19:19:09 -0800 Received: from FMSMSX109.amr.corp.intel.com (10.18.116.9) by FMSMSX106.amr.corp.intel.com (10.19.9.37) with Microsoft SMTP Server (TLS) id 14.3.123.3; Sun, 17 Nov 2013 19:19:09 -0800 Received: from fmsmsx101.amr.corp.intel.com ([169.254.1.227]) by FMSMSX109.amr.corp.intel.com ([169.254.5.37]) with mapi id 14.03.0123.003; Sun, 17 Nov 2013 19:19:09 -0800 From: "Iyer, Balaji V" To: "gcc-patches@gcc.gnu.org" CC: "Jason Merrill (jason@redhat.com)" , Jeff Law Subject: _Cilk_spawn and _Cilk_sync for C++ Date: Mon, 18 Nov 2013 03:19:09 +0000 Message-ID: MIME-Version: 1.0 X-IsSubscribed: yes Hello Jason et al., Mike Stump mentioned that my _Cilk_spawn and _Cilk_sync for C++ may have been lost in the email pile. So, attached is an updated _Cilk_spawn and _Cilk_sync for C++ patch. Is this Ok to install? Here are the ChangeLog entries (they shouldn't have changed since the last submission): gcc/cp/ChangeLog 2013-11-17 Balaji V. Iyer * Make-lang.in (CXX_AND_OBJCXX_OBJS): Added cp/cp-cilk.o. * cp-cilk.c: New file. * 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. * decl.c (finish_function): Insert Cilk function-calls when a _Cilk_spawn is used in a function. * except.c (do_begin_catch): Made the function non-static. (do_end_catch): Likewise. * parser.c (cp_parser_postfix_expression): Added RID_CILK_SPAWN and RID_CILK_SYNC cases. * parser.h (IN_CILK_SPAWN): New #define. * cp-objcp-common.h (LANG_HOOKS_CILKPLUS_GIMPLIFY_SPAWN): 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. (finish_call_expr): Stored the lambda function to a variable when Cilk Plus is enabled. * 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-17 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.j diff --git a/gcc/cp/Make-lang.in b/gcc/cp/Make-lang.in index 424f2e6..e046ee3 100644 --- a/gcc/cp/Make-lang.in +++ b/gcc/cp/Make-lang.in @@ -77,7 +77,7 @@ CXX_AND_OBJCXX_OBJS = cp/call.o cp/decl.o cp/expr.o cp/pt.o cp/typeck2.o \ cp/search.o cp/semantics.o cp/tree.o cp/repo.o cp/dump.o cp/optimize.o \ cp/mangle.o cp/cp-objcp-common.o cp/name-lookup.o cp/cxx-pretty-print.o \ cp/cp-cilkplus.o \ - cp/cp-gimplify.o cp/cp-array-notation.o cp/lambda.o \ + cp/cp-gimplify.o cp/cp-array-notation.o cp/lambda.o cp/cp-cilk.o \ cp/vtable-class-hierarchy.o $(CXX_C_OBJS) # Language-specific object files for C++. diff --git a/gcc/cp/cp-cilk.c b/gcc/cp/cp-cilk.c new file mode 100644 index 0000000..0da95e8 --- /dev/null +++ b/gcc/cp/cp-cilk.c @@ -0,0 +1,118 @@ +/* Functions to handle Cilk keywords support in C++. + Copyright (C) 2011-2013 Free Software Foundation, Inc. + Contributed by Balaji V. Iyer , + Intel Corporation. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GCC; see the file COPYING3. If not see + . */ + +#include "config.h" +#include "system.h" +#include "coretypes.h" +#include "cp-tree.h" +#include "tree-iterator.h" +#include "cilk.h" + +/* Sets the EXCEPTION bit (0x10) in the FRAME.flags field. */ + +static tree +set_cilk_except_flag (tree frame) +{ + tree flags = cilk_dot (frame, CILK_TI_FRAME_FLAGS, 0); + + flags = build2 (MODIFY_EXPR, void_type_node, flags, + build2 (BIT_IOR_EXPR, TREE_TYPE (flags), flags, + build_int_cst (TREE_TYPE (flags), + CILK_FRAME_EXCEPTING))); + return flags; +} + +/* Sets the frame.EXCEPT_DATA field to the head of the exception pointer. */ + +static tree +set_cilk_except_data (tree frame) +{ + tree except_data = cilk_dot (frame, CILK_TI_FRAME_EXCEPTION, 0); + tree uresume_fn = builtin_decl_implicit (BUILT_IN_EH_POINTER); + tree ret_expr; + uresume_fn = build_call_expr (uresume_fn, 1, + build_int_cst (integer_type_node, 0)); + ret_expr = build2 (MODIFY_EXPR, void_type_node, except_data, uresume_fn); + return ret_expr; +} + +/* Installs BODY into function FNDECL with appropriate exception handling + code. */ + +void +cp_cilk_install_body_wframe_cleanup (tree fndecl, tree orig_body) +{ + tree frame = make_cilk_frame (fndecl); + tree dtor = create_cilk_function_exit (frame, false, false); + extern tree do_begin_catch (void); + extern tree do_end_catch (tree); + add_local_decl (cfun, frame); + + tree list = alloc_stmt_list (); + DECL_SAVED_TREE (fndecl) = list; + tree fptr = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (frame)), frame); + tree body = cilk_install_body_pedigree_operations (fptr); + gcc_assert (TREE_CODE (body) == STATEMENT_LIST); + tree detach_expr = build_call_expr (cilk_detach_fndecl, 1, fptr); + append_to_statement_list (detach_expr, &body); + append_to_statement_list (orig_body, &body); + + if (flag_exceptions) + { + tree catch_list = alloc_stmt_list (); + tree except_flag = set_cilk_except_flag (frame); + tree except_data = set_cilk_except_data (frame); + append_to_statement_list (except_flag, &catch_list); + append_to_statement_list (except_data, &catch_list); + append_to_statement_list (do_begin_catch (), &catch_list); + append_to_statement_list (build_throw (NULL_TREE), &catch_list); + tree catch_tf_expr = build_stmt (EXPR_LOCATION (body), TRY_FINALLY_EXPR, + catch_list, do_end_catch (NULL_TREE)); + catch_list = build2 (CATCH_EXPR, void_type_node, NULL_TREE, + catch_tf_expr); + tree try_catch_expr = build_stmt (EXPR_LOCATION (body), TRY_CATCH_EXPR, + body, catch_list); + tree try_finally_expr = build_stmt (EXPR_LOCATION (body), + TRY_FINALLY_EXPR, + try_catch_expr, dtor); + append_to_statement_list (try_finally_expr, &list); + } + else + append_to_statement_list (build_stmt (EXPR_LOCATION (body), + TRY_FINALLY_EXPR, body, dtor), &list); +} + +/* Returns a local variable of type VAR_DECL to store LAMBDA_FN. */ + +tree +cilk_create_lambda_fn_tmp_var (tree lambda_fn) +{ + tree return_var = build_decl (EXPR_LOCATION (lambda_fn), VAR_DECL, NULL_TREE, + make_auto ()); + TREE_USED (return_var) = 1; + TREE_ADDRESSABLE (return_var) = 1; + DECL_CONTEXT (return_var) = current_function_decl; + DECL_INITIAL (return_var) = NULL_TREE; + DECL_SEEN_IN_BIND_EXPR_P (return_var) = 1; + cp_finish_decl (return_var, lambda_fn, false, NULL_TREE, LOOKUP_NORMAL); + add_local_decl (cfun, return_var); + return return_var; +} 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 4e26bd5..351158e 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -6184,6 +6184,14 @@ 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); +extern int gimplify_cilk_spawn (tree *, gimple_seq *, + gimple_seq *); + +/* In cp/cp-cilk.c */ +extern void cp_cilk_install_body_wframe_cleanup (tree, tree); +extern tree cilk_create_lambda_fn_tmp_var (tree); /* -- end of C++ */ #endif /* ! GCC_CP_TREE_H */ diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 7d9d5df..64c09d1 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -54,6 +54,7 @@ along with GCC; see the file COPYING3. If not see #include "splay-tree.h" #include "plugin.h" #include "cgraph.h" +#include "cilk.h" /* Possible cases of bad specifiers type used by bad_specifiers. */ enum bad_spec_place { @@ -13866,6 +13867,9 @@ finish_function (int flags) /* If we're saving up tree structure, tie off the function now. */ DECL_SAVED_TREE (fndecl) = pop_stmt_list (DECL_SAVED_TREE (fndecl)); + if (fn_contains_cilk_spawn_p (cfun) && !processing_template_decl) + cfun->cilk_frame_decl = insert_cilk_frame (fndecl); + finish_fname_decls (); /* If this function can't throw any exceptions, remember that. */ diff --git a/gcc/cp/except.c b/gcc/cp/except.c index ac2128d..80ccfc8 100644 --- a/gcc/cp/except.c +++ b/gcc/cp/except.c @@ -34,9 +34,9 @@ along with GCC; see the file COPYING3. If not see static void push_eh_cleanup (tree); static tree prepare_eh_type (tree); -static tree do_begin_catch (void); +tree do_begin_catch (void); static int dtor_nothrow (tree); -static tree do_end_catch (tree); +tree do_end_catch (tree); static bool decl_is_java_type (tree decl, int err); static void initialize_handler_parm (tree, tree); static tree do_allocate_exception (tree); @@ -181,7 +181,7 @@ do_get_exception_ptr (void) /* Build up a call to __cxa_begin_catch, to tell the runtime that the exception has been handled. */ -static tree +tree do_begin_catch (void) { tree fn; @@ -228,7 +228,7 @@ dtor_nothrow (tree type) /* Build up a call to __cxa_end_catch, to destroy the exception object for the current catch block if no others are currently using it. */ -static tree +tree do_end_catch (tree type) { tree fn, cleanup; diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 27f1054..29be9a8 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -5622,6 +5622,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p, cp_id_kind idk = CP_ID_KIND_NONE; tree postfix_expression = NULL_TREE; bool is_member_access = false; + int saved_in_statement = -1; /* Peek at the next token. */ token = cp_lexer_peek_token (parser->lexer); @@ -5766,6 +5767,67 @@ 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; + } + 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; + } + 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; + cfun->calls_cilk_spawn = 1; + } + break; + } + + case RID_CILK_SYNC: + if (flag_enable_cilkplus) + { + tree sync_expr = build_cilk_sync (); + SET_EXPR_LOCATION (sync_expr, + cp_lexer_peek_token (parser->lexer)->location); + finish_expr_stmt (sync_expr); + } + else + error_at (input_location, "_Cilk_sync cannot be used without enabling " + "Cilk Plus"); + cp_lexer_consume_token (parser->lexer); + if (parser->in_statement & IN_CILK_SPAWN) + parser->in_statement = parser->in_statement & ~IN_CILK_SPAWN; + break; + case RID_BUILTIN_SHUFFLE: { vec *vec; diff --git a/gcc/cp/parser.h b/gcc/cp/parser.h index edd4e6e..e26e350 100644 --- a/gcc/cp/parser.h +++ b/gcc/cp/parser.h @@ -301,6 +301,7 @@ typedef struct GTY(()) cp_parser { #define IN_OMP_FOR 8 #define IN_IF_STMT 16 #define IN_CILK_SIMD_FOR 32 +#define IN_CILK_SPAWN 64 unsigned char in_statement; /* TRUE if we are presently parsing the body of a switch statement. diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 3bc8ccb..1b34434 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -13758,6 +13758,13 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl, error ("use %<...%> to expand argument pack"); RETURN (error_mark_node); + case CILK_SPAWN_STMT: + cfun->calls_cilk_spawn = 1; + RETURN (build_cilk_spawn (EXPR_LOCATION (t), RECUR (CILK_SPAWN_FN (t)))); + + case CILK_SYNC_STMT: + RETURN (build_cilk_sync ()); + case COMPOUND_EXPR: tmp = RECUR (TREE_OPERAND (t, 0)); if (tmp == NULL_TREE) diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 81394fa..5d68250 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -2121,6 +2121,14 @@ finish_call_expr (tree fn, vec **args, bool disallow_virtual, gcc_assert (!TYPE_P (fn)); + /* When Cilk Plus is enabled, the lambda function need to be stored to + a variable because if the function is spawned, then we need some kind + of a handle. */ + if (flag_enable_cilkplus && cxx_dialect >= cxx0x + && TREE_CODE (fn) != VAR_DECL && TREE_CODE (fn) != OVERLOAD + && TREE_CODE (fn) != FUNCTION_DECL) + fn = cilk_create_lambda_fn_tmp_var (fn); + orig_fn = fn; if (processing_template_decl) @@ -10415,9 +10423,15 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags) return false; return true; + case CILK_SYNC_STMT: case ARRAY_NOTATION_REF: return false; + case CILK_SPAWN_STMT: + if (!potential_constant_expression_1 (CILK_SPAWN_FN (t), true, flags)) + return false; + return true; + case FMA_EXPR: case VEC_PERM_EXPR: for (i = 0; i < 3; ++i) diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index bff7f17..f42ea63 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -6159,6 +6159,17 @@ cp_build_compound_expr (tree lhs, tree rhs, tsubst_flags_t complain) if (lhs == error_mark_node || rhs == error_mark_node) return error_mark_node; + if (flag_enable_cilkplus + && (TREE_CODE (lhs) == CILK_SPAWN_STMT + || TREE_CODE (rhs) == CILK_SPAWN_STMT)) + { + location_t loc = (EXPR_HAS_LOCATION (lhs) ? EXPR_LOCATION (lhs) + : EXPR_LOCATION (rhs)); + error_at (loc, + "spawned function call cannot be part of a comma expression"); + return error_mark_node; + } + if (TREE_CODE (rhs) == TARGET_EXPR) { /* If the rhs is a TARGET_EXPR, then build the compound @@ -8283,6 +8294,13 @@ check_return_expr (tree retval, bool *no_warning) *no_warning = false; + if (flag_enable_cilkplus && retval && TREE_CODE (retval) == CILK_SPAWN_STMT) + { + error_at (EXPR_LOCATION (retval), "use of %<_Cilk_spawn%> in a return " + "statement is not allowed"); + return NULL_TREE; + } + /* A `volatile' function is one that isn't supposed to return, ever. (This is a G++ extension, used to get better code for functions that call the `volatile' function.) */ diff --git a/gcc/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..a358973 --- /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..aeceda1 --- /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..39ed4ee --- /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..bf16f1e --- /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..818bca0 --- /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 + + +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..17c0fa5 --- /dev/null +++ b/gcc/testsuite/g++.dg/cilk-plus/CK/lambda_spawns_tplt.cc @@ -0,0 +1,173 @@ +/* { dg-options "-fcilkplus" } */ +/* { dg-do run { target i?86-*-* x86_64-*-* arm*-*-* } } */ +/* { dg-options "-std=c++11 -fcilkplus -lcilkrts" { target { i?86-*-* x86_64-*-* arm*-*-* } } } */ + +#define FIRST_NUMBER 5 +#define SECOND_NUMBER 3 +#define HAVE_IO 0 +#if HAVE_IO +#include +#endif + +#include + +template +void foo1(T *array, int size) +{ +#if HAVE_IO + for (int ii = 0; ii < size; ii++) + printf("%2d\t", (int)array[ii]); + printf("\n"); + fflush (stdout); +#else + if (size != 2) + __builtin_abort (); + if (array[0] != FIRST_NUMBER) + __builtin_abort (); + if (array[1] != SECOND_NUMBER) + __builtin_abort (); +#endif +} +template +void foo1_c(const T *array, int size) +{ +#if HAVE_IO + for (int ii = 0; ii < size; ii++) + printf("%2d\t", (int)array[ii]); + printf("\n"); + fflush (stdout); +#else + if (size != 2) + __builtin_abort (); + if (array[0] != FIRST_NUMBER) + __builtin_abort (); + if (array[1] != SECOND_NUMBER) + __builtin_abort (); +#endif +} +template +int main2 (int argc, char **argv) { + T A[2] = {FIRST_NUMBER, SECOND_NUMBER}; + int main_size = argc+1; /* We know argc is 1, and so 1+1 = 2. */ + auto func0 = [=](){ foo1_c(A, 2); }; + _Cilk_spawn func0(); + foo1 (A, 2); + _Cilk_sync; + + auto func1 = [=](T *Aa){ foo1(Aa, 2); }; + _Cilk_spawn func1 (A); + foo1 (A, 2); + _Cilk_sync; + + auto func2 = [=](T *Aa, int size){ foo1(Aa, size); }; + _Cilk_spawn func2 (A, 2); + foo1 (A, 2); + _Cilk_sync; + + auto func3 = [=](T *Aa, int size){ int new_size = (size % 2 + 2); + foo1(Aa, size); }; + _Cilk_spawn func3 (A, 2); + foo1 (A, 2); + _Cilk_sync; + + auto func4 = [](T *Aa){ foo1(Aa, 2); }; + _Cilk_spawn func4 (A); + foo1 (A, 2); + _Cilk_sync; + + auto func5 = [](T *Aa, int size){ foo1(Aa, size); }; + _Cilk_spawn func5 (A, 2); + foo1 (A, 2); + _Cilk_sync; + + auto func6 = [&](T *Aa){ foo1(Aa, 2); }; + _Cilk_spawn func6 (A); + foo1 (A, 2); + _Cilk_sync; + + auto func7 = [&](T *Aa, int size){ foo1(Aa, size); }; + _Cilk_spawn func7 (A, 2); + foo1 (A, 2); + _Cilk_sync; + + auto func8 = [&](){ foo1(A, 2); }; + _Cilk_spawn func8 (); + foo1 (A, 2); + _Cilk_sync; + + /* We ignore the first param here and pass in A from the outer fn. */ + auto func9 = [&](T *Aa, int size){ foo1(A, size); }; + _Cilk_spawn func9 (A, 2); + foo1 (A, 2); + _Cilk_sync; + + auto func10 = [=](){ foo1_c(A, main_size); }; + _Cilk_spawn func10 (); + foo1 (A, 2); + _Cilk_sync; + + auto func11 = [&](){ foo1(A, main_size); }; + _Cilk_spawn func11 (); + foo1 (A, 2); + _Cilk_sync; + + /* We ignore the first & second param here and pass in A from the + outer fn. */ + auto func12 = [&](T *Aa, int size){ foo1(A, main_size); }; + _Cilk_spawn func12 (A, 2); + foo1 (A, 2); + _Cilk_sync; + + _Cilk_spawn [&](T *Aa){ foo1(Aa, 2); }(A); + foo1 (A, 2); + _Cilk_sync; + + _Cilk_spawn [&](T *Aa, int size){ foo1(Aa, size); }(A, 2); + foo1 (A, 2); + _Cilk_sync; + + _Cilk_spawn [=](T *Aa){ foo1(Aa, 2); }(A); + foo1 (A, 2); + _Cilk_sync; + + _Cilk_spawn [=](T *Aa, int size){ foo1(Aa, size); }(A, 2); + foo1 (A, 2); + _Cilk_sync; + + /* We ignore the first param here. */ + _Cilk_spawn [=](T *Aa, int size){ foo1_c(A, size); }(A, 2); + foo1 (A, 2); + _Cilk_sync; + + /* We ignore the first and second param here. */ + _Cilk_spawn [=](T *Aa, int size){ foo1_c(A, main_size); }(A, 2); + foo1 (A, 2); + _Cilk_sync; + + _Cilk_spawn [&](){ foo1(A, 2); }(); + [&](){ foo1(A, 2); }(); + _Cilk_sync; + + _Cilk_spawn [=](){ foo1_c(A, main_size); }(); + foo1 (A, 2); + _Cilk_sync; + + _Cilk_spawn [&](){ foo1(A, main_size); }(); + [&](){ foo1(A, 2); }(); + _Cilk_sync; + + return 0; +} + +int main (void) +{ + int argc = 1; + char **argv = NULL; + int x = 1, y = 1, z = 1, q = 1, p = 1; + x = main2(argc,argv); + y = main2(argc,argv); + z = main2(argc,argv); + p = main2(argc,argv); + q = main2(argc,argv); + return (x+y+z+p+q); +} diff --git a/gcc/testsuite/g++.dg/cilk-plus/cilk-plus.exp b/gcc/testsuite/g++.dg/cilk-plus/cilk-plus.exp index fa9246c..27412e8 100644 --- a/gcc/testsuite/g++.dg/cilk-plus/cilk-plus.exp +++ b/gcc/testsuite/g++.dg/cilk-plus/cilk-plus.exp @@ -22,6 +22,11 @@ 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" + dg-init # Run the tests that are shared with C. g++-dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/PS/*.c]] "" @@ -56,3 +61,29 @@ dg-runtest [lsort [glob -nocomplain $srcdir/g++.dg/cilk-plus/AN/*.cc]] " -g -O2 dg-runtest [lsort [glob -nocomplain $srcdir/g++.dg/cilk-plus/AN/*.cc]] " -g -O3 -fcilkplus" " " dg-runtest [lsort [glob -nocomplain $srcdir/g++.dg/cilk-plus/AN/*.cc]] " -O3 -ftree-vectorize -fcilkplus -g" " " dg-finish + +dg-init +dg-runtest [lsort [glob -nocomplain $srcdir/g++.dg/cilk-plus/CK/*.cc]] " -fcilkplus" " " +dg-runtest [lsort [glob -nocomplain $srcdir/g++.dg/cilk-plus/CK/*.cc]] " -O1 -fcilkplus" " " +dg-runtest [lsort [glob -nocomplain $srcdir/g++.dg/cilk-plus/CK/*.cc]] " -O2 -fcilkplus" " " +dg-runtest [lsort [glob -nocomplain $srcdir/g++.dg/cilk-plus/CK/*.cc]] " -O3 -fcilkplus" " " +dg-runtest [lsort [glob -nocomplain $srcdir/g++.dg/cilk-plus/CK/*.cc]] " -g -fcilkplus" " " +dg-runtest [lsort [glob -nocomplain $srcdir/g++.dg/cilk-plus/CK/*.cc]] " -g -O1 -fcilkplus" " " +dg-runtest [lsort [glob -nocomplain $srcdir/g++.dg/cilk-plus/CK/*.cc]] " -g -O2 -ftree-vectorize -fcilkplus" " " +dg-runtest [lsort [glob -nocomplain $srcdir/g++.dg/cilk-plus/CK/*.cc]] " -g -O3 -fcilkplus" " " +dg-finish + +dg-init +dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/CK/*.c]] " -fcilkplus" " " +dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/CK/*.c]] " -O1 -fcilkplus" " " +dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/CK/*.c]] " -O2 -fcilkplus" " " +dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/CK/*.c]] " -O3 -fcilkplus" " " +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 -O1 -fcilkplus" " " +dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/CK/*.c]] " -g -O2 -ftree-vectorize -fcilkplus" " " +dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/CK/*.c]] " -g -O3 -fcilkplus" " " +dg-finish