From patchwork Fri Aug 29 14:36:17 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Zamyatin, Igor" X-Patchwork-Id: 384262 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)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 64C1114011E for ; Sat, 30 Aug 2014 00:40:08 +1000 (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 :content-transfer-encoding:mime-version; q=dns; s=default; b=pxb 0kLMfNdeCmRpSqrVKPv9fpnwtnn0Syv6fLGyceFfi0wEOOJ9Gyj5fBM0//PE51T2 +UlwCfmgm8MAcXp+9NHkDpMC7P0Gj2rbPyKfLQRu7kSOW7QGmJ96CaE+EcKOTml3 sX7Ne5Lg7ORVs0KGtHkVAWnRGYXC7pF7lGbx7KGU= 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 :content-transfer-encoding:mime-version; s=default; bh=qadL5hiFi Zx4nylKuPOqWxhW3Cw=; b=WfIPr1KGJSuUUAnHqpUZnTQhf6FWnY6pOOWCCY44e qDcPj0F0hLfKJxvQnmk+YQ8WduU5brrq5d8Aak8/Bgx2tfNlxGEmp5i5hmIRNVWf I3346AU2WACna1OMqW7QdYhFbnoOqyVHekE4v/NGdgM8BZryp8pZk46JWfVEGyB4 wE= Received: (qmail 16557 invoked by alias); 29 Aug 2014 14:39:55 -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 16541 invoked by uid 89); 29 Aug 2014 14:39:54 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-0.6 required=5.0 tests=AWL, BAYES_50, RP_MATCHES_RCVD, SPF_PASS autolearn=ham version=3.3.2 X-HELO: mga01.intel.com Received: from mga01.intel.com (HELO mga01.intel.com) (192.55.52.88) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Fri, 29 Aug 2014 14:39:41 +0000 Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by fmsmga101.fm.intel.com with ESMTP; 29 Aug 2014 07:39:33 -0700 X-ExtLoop1: 1 Received: from irsmsx103.ger.corp.intel.com ([163.33.3.157]) by fmsmga001.fm.intel.com with ESMTP; 29 Aug 2014 07:37:51 -0700 Received: from irsmsx109.ger.corp.intel.com (163.33.3.23) by IRSMSX103.ger.corp.intel.com (163.33.3.157) with Microsoft SMTP Server (TLS) id 14.3.195.1; Fri, 29 Aug 2014 15:36:18 +0100 Received: from irsmsx101.ger.corp.intel.com ([169.254.1.194]) by IRSMSX109.ger.corp.intel.com ([169.254.13.200]) with mapi id 14.03.0195.001; Fri, 29 Aug 2014 15:36:18 +0100 From: "Zamyatin, Igor" To: "GCC Patches (gcc-patches@gcc.gnu.org)" CC: "Jakub Jelinek (jakub@redhat.com)" Subject: [PATCH, Cilk+] CIlk_for enabling in the compiler Date: Fri, 29 Aug 2014 14:36:17 +0000 Message-ID: <0EFAB2BDD0F67E4FB6CCC8B9F87D756969B22535@IRSMSX101.ger.corp.intel.com> MIME-Version: 1.0 X-IsSubscribed: yes Hi! The patch is another attempt to enable Cilk_for (see eg https://www.cilkplus.org/sites/default/files/open_specifications/Intel_Cilk_plus_lang_spec_1.2.htm) in the GCC compiler. Bootstrapped and regtested on x86_64. Is it ok for the trunk? Thanks, Igor Changelogs: gcc/ 2014-08-29 Jakub Jelinek Balaji V. Iyer * cilk-builtins.def (__cilkrts_cilk_for_32): New. (__cilkrts_cilk_for_64): Likewise. * cilk-common.c (declare_cilk_for_builtin): New function. (cilk_init_builtins): Declare __cilkrts_cilk_for_32 and __cilkrts_cilk_for_64 bultins. * cilk.h (enum cilk_tree_index): Added CILK_TI_F_LOOP_32 and CILK_TI_F_LOOP_64. (cilk_for_32_fndecl): New define. (cilk_for_64_fndecl): Likewise. * gimple-pretty-print.c (dump_gimple_omp_for): Correct hadling of GF_OMP_FOR_KIND_CILKFOR cases; Added NE_EXPR case. * gimple.h (enum gf_mask): Added GF_OMP_FOR_KIND_CILKFOR; adjusted GF_OMP_FOR_KIND_MASK, GF_OMP_FOR_SIMD, GF_OMP_FOR_COMBINED, GF_OMP_FOR_COMBINED_INTO. * gimplify.c (gimplify_scan_omp_clauses): Added OMP_CLAUSE__CILK_FOR_COUNT_ case. (gimplify_adjust_omp_clauses): Ditto. (gimplify_omp_for): Added CILK_FOR case. (gimplify_expr): Ditto. * omp-low.c: Include cilk.h. (extract_omp_for_data): Set appropriate kind for GF_OMP_FOR_KIND_CILKFOR; added check for GF_OMP_FOR_KIND_CILKFOR. (scan_sharing_clauses): Added OMP_CLAUSE__CILK_FOR_COUNT_ cases. (create_omp_child_function_name): Added second argument to handle cilk_for case. (cilk_for_check_loop_diff_type): New function. (expand_cilk_for_call): Likewise. (expand_cilk_for): Likewise. (create_omp_child_function): Set cilk_for_count; handle the cases when it is true; call create_omp_child_function_name with second argument. (expand_omp_taskreg): Set is_cilk_for and handle cases when it's true. (expand_omp_for): Handle case of GF_OMP_FOR_KIND_CILKFOR. * tree-core.h (omp_clause_code): Added OMP_CLAUSE__CILK_FOR_COUNT_. * tree-nested.c (convert_nonlocal_omp_clauses): Added OMP_CLAUSE__CILK_FOR_COUNT_ case. (convert_local_omp_clauses): Ditto. * tree-pretty-print.c (dump_omp_clause): Added OMP_CLAUSE__CILK_FOR_COUNT_ and OMP_CLAUSE_SCHEDULE_CILKFOR cases. (dump_generic_node): Added CILK_FOR case. * tree.c (omp_clause_num_ops): New element OMP_CLAUSE__CILK_FOR_COUNT_ (1). (omp_clause_code_name): New element _Cilk_for_count_. (walk_tree_1): Added OMP_CLAUSE__CILK_FOR_COUNT_ case. * tree.def: Add tree code for CILK_FOR. c/ 2014-08-29 Jakub Jelinek Balaji V. Iyer * c-parser.c (c_parser_cilk_for): New function. (c_parser_cilk_grainsize): Likewise. (c_get_temp_regvar): Likewise. (c_parser_statement_after_labels): Added RID_CILK_FOR case. (c_parser_pragma): Added PRAGMA_CILK_GRAINSIZE case. (c_parser_omp_for_loop): Added CILK_FOR and CILK_SIMD checks. * c-typeck.c (c_finish_omp_clauses): Added OMP_CLAUSE__CILK_FOR_COUNT_ case. cp/ 2014-08-29 Jakub Jelinek Balaji V. Iyer * cp-cilkplus.c (cpp_validate_cilk_plus_loop_aux): Loc definition simplified. * parser.c (cp_parser_cilk_for): New function. (cp_parser_cilk_grainsize): Likewise. (cp_parser_statement): Added RID_CILK_FOR case. (cp_parser_omp_for_cond): Added CILK_FOR check. (cp_parser_omp_for_loop_init): Change function argument to accept tree_code instead just a bool flag; change the check to use that tree_code; check for initialization declaration in case of Cilk_for. (cp_parser_omp_for_loop): Added checks for CILK_FOR and RID_CILK_FOR; changed call to cp_parser_omp_for_loop_init according new arguments' list. (cp_parser_pragma): Added PRAGMA_CILK_GRAINSIZE case. * pt.c (tsubst_expr): Added CILK_FOR case. * semantics.c: Include convert.h. (finish_omp_clauses): Properly handle OMP_CLAUSE_SCHEDULE_CILKFOR case; added OMP_CLAUSE__CILK_FOR_COUNT_. (handle_omp_for_class_iterator): New argument lastp and its usage; added NE_EXPR case. (finish_omp_for): Changed call to handle_omp_for_class_iterator according new arguments' list; in case of Cilk_for save very first decl and create empty stmt_list block; use block to build correct statement tree. c-family/ 2014-08-29 Jakub Jelinek Balaji V. Iyer * c-cilkplus.c (cilk_for_number_of_iterations): New function. * c-common.c (c_common_reswords): Added _Cilk_for. * c-common.h (enum rid): Added RID_CILK_FOR. (cilk_for_number_of_iterations): Add declaration. * c-omp.c (c_finish_omp_for): Added checks for CILK_SIMD and CILK_FOR. * c-pragma.c (init_pragma): Register "grainsize" pragma. * c-pragma.h (enum pragma_kind): Add PRAGMA_CILK_GRAINSIZE. testsuite/ 014-08-29 Jakub Jelinek Balaji V. Iyer * c-c++-common/cilk-plus/CK/cilk-fors.c: New test. * c-c++-common/cilk-plus/CK/cilk-for-2.c: New test. * c-c++-common/cilk-plus/CK/cilk-for-3.c: New test. * c-c++-common/cilk-plus/CK/cilk_for_errors.c: New test. * c-c++-common/cilk-plus/CK/cilk_for_grain.c: New test. * c-c++-common/cilk-plus/CK/cilk_for_grain_errors.c: New test. * c-c++-common/cilk-plus/CK/cilk_for_ptr_iter.c: New test. * c-c++-common/cilk-plus/CK/nested_cilk_for.c: New test. * g++.dg/cilk-plus/CK/cf3.cc: New test. * g++.dg/cilk-plus/CK/cilk-for-tplt.cc: New test. * g++.dg/cilk-plus/CK/for1.cc: New test. * g++.dg/cilk-plus/CK/stl_iter.cc: New test. * g++.dg/cilk-plus/CK/stl_rev_iter.cc: New test. * g++.dg/cilk-plus/CK/stl_test.cc: New test. diff --git a/gcc/c-family/c-cilkplus.c b/gcc/c-family/c-cilkplus.c index 1a16f66..131da0b 100644 --- a/gcc/c-family/c-cilkplus.c +++ b/gcc/c-family/c-cilkplus.c @@ -91,3 +91,136 @@ c_finish_cilk_clauses (tree clauses) } return clauses; } + +/* Calculate number of iterations of CILK_FOR. */ + +tree +cilk_for_number_of_iterations (tree cilk_for) +{ + tree t, v, n1, n2, step, type, init, cond, incr, itype; + enum tree_code cond_code; + location_t loc = EXPR_LOCATION (cilk_for); + + init = TREE_VEC_ELT (OMP_FOR_INIT (cilk_for), 0); + v = TREE_OPERAND (init, 0); + cond = TREE_VEC_ELT (OMP_FOR_COND (cilk_for), 0); + incr = TREE_VEC_ELT (OMP_FOR_INCR (cilk_for), 0); + type = TREE_TYPE (v); + + gcc_assert (TREE_CODE (TREE_TYPE (v)) == INTEGER_TYPE + || TREE_CODE (TREE_TYPE (v)) == POINTER_TYPE); + n1 = TREE_OPERAND (init, 1); + cond_code = TREE_CODE (cond); + n2 = TREE_OPERAND (cond, 1); + switch (cond_code) + { + case LT_EXPR: + case GT_EXPR: + case NE_EXPR: + break; + case LE_EXPR: + if (POINTER_TYPE_P (TREE_TYPE (n2))) + n2 = fold_build_pointer_plus_hwi_loc (loc, n2, 1); + else + n2 = fold_build2_loc (loc, PLUS_EXPR, TREE_TYPE (n2), n2, + build_int_cst (TREE_TYPE (n2), 1)); + cond_code = LT_EXPR; + break; + case GE_EXPR: + if (POINTER_TYPE_P (TREE_TYPE (n2))) + n2 = fold_build_pointer_plus_hwi_loc (loc, n2, -1); + else + n2 = fold_build2_loc (loc, MINUS_EXPR, TREE_TYPE (n2), n2, + build_int_cst (TREE_TYPE (n2), 1)); + cond_code = GT_EXPR; + break; + default: + gcc_unreachable (); + } + + step = NULL_TREE; + switch (TREE_CODE (incr)) + { + case PREINCREMENT_EXPR: + case POSTINCREMENT_EXPR: + step = build_int_cst (TREE_TYPE (v), 1); + break; + case PREDECREMENT_EXPR: + case POSTDECREMENT_EXPR: + step = build_int_cst (TREE_TYPE (v), -1); + break; + case MODIFY_EXPR: + t = TREE_OPERAND (incr, 1); + gcc_assert (TREE_OPERAND (t, 0) == v); + switch (TREE_CODE (t)) + { + case PLUS_EXPR: + step = TREE_OPERAND (t, 1); + break; + case POINTER_PLUS_EXPR: + step = fold_convert (ssizetype, TREE_OPERAND (t, 1)); + break; + case MINUS_EXPR: + step = TREE_OPERAND (t, 1); + step = fold_build1_loc (loc, NEGATE_EXPR, TREE_TYPE (step), step); + break; + default: + gcc_unreachable (); + } + break; + default: + gcc_unreachable (); + } + + itype = type; + if (POINTER_TYPE_P (itype)) + itype = signed_type_for (itype); + if (cond_code == NE_EXPR) + { + /* For NE_EXPR, we need to find out if the iterator increases + or decreases from whether step is positive or negative. */ + tree stype = itype; + if (TYPE_UNSIGNED (stype)) + stype = signed_type_for (stype); + cond = fold_build2_loc (loc, GE_EXPR, boolean_type_node, + fold_convert_loc (loc, stype, step), + build_int_cst (stype, 0)); + t = fold_build3_loc (loc, COND_EXPR, itype, cond, + build_int_cst (itype, -1), + build_int_cst (itype, 1)); + } + else + t = build_int_cst (itype, (cond_code == LT_EXPR ? -1 : 1)); + t = fold_build2_loc (loc, PLUS_EXPR, itype, + fold_convert_loc (loc, itype, step), t); + t = fold_build2_loc (loc, PLUS_EXPR, itype, t, + fold_convert_loc (loc, itype, n2)); + t = fold_build2_loc (loc, MINUS_EXPR, itype, t, + fold_convert_loc (loc, itype, n1)); + if (TYPE_UNSIGNED (itype) && cond_code == GT_EXPR) + t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype, + fold_build1_loc (loc, NEGATE_EXPR, itype, t), + fold_build1_loc (loc, NEGATE_EXPR, itype, + fold_convert_loc (loc, itype, + step))); + else if (TYPE_UNSIGNED (itype) && cond_code == NE_EXPR) + { + tree t1 + = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype, t, + fold_convert_loc (loc, itype, step)); + tree t2 + = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype, + fold_build1_loc (loc, NEGATE_EXPR, itype, t), + fold_build1_loc (loc, NEGATE_EXPR, itype, + fold_convert_loc (loc, itype, + step))); + t = fold_build3_loc (loc, COND_EXPR, itype, cond, t1, t2); + } + else + t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype, t, + fold_convert_loc (loc, itype, step)); + cond = fold_build2_loc (loc, cond_code, boolean_type_node, n1, n2); + t = fold_build3_loc (loc, COND_EXPR, itype, cond, t, + build_int_cst (itype, 0)); + return t; +} diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c index 58b9763..16cc5f6 100644 --- a/gcc/c-family/c-common.c +++ b/gcc/c-family/c-common.c @@ -418,6 +418,7 @@ const struct c_common_resword c_common_reswords[] = { "_Complex", RID_COMPLEX, 0 }, { "_Cilk_spawn", RID_CILK_SPAWN, 0 }, { "_Cilk_sync", RID_CILK_SYNC, 0 }, + { "_Cilk_for", RID_CILK_FOR, 0 }, { "_Imaginary", RID_IMAGINARY, D_CONLY }, { "_Decimal32", RID_DFLOAT32, D_CONLY | D_EXT }, { "_Decimal64", RID_DFLOAT64, D_CONLY | D_EXT }, diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h index d1cc810..993a97b 100644 --- a/gcc/c-family/c-common.h +++ b/gcc/c-family/c-common.h @@ -149,7 +149,7 @@ enum rid RID_CONSTEXPR, RID_DECLTYPE, RID_NOEXCEPT, RID_NULLPTR, RID_STATIC_ASSERT, /* Cilk Plus keywords. */ - RID_CILK_SPAWN, RID_CILK_SYNC, + RID_CILK_SPAWN, RID_CILK_SYNC, RID_CILK_FOR, /* Objective-C ("AT" reserved words - they are only keywords when they follow '@') */ @@ -1395,4 +1395,5 @@ extern tree create_cilk_function_exit (tree, bool, bool); extern tree cilk_install_body_pedigree_operations (tree); extern void cilk_outline (tree, tree *, void *); extern bool contains_cilk_spawn_stmt (tree); +extern tree cilk_for_number_of_iterations (tree); #endif /* ! GCC_C_COMMON_H */ diff --git a/gcc/c-family/c-omp.c b/gcc/c-family/c-omp.c index 6a0e419..d6ca3df 100644 --- a/gcc/c-family/c-omp.c +++ b/gcc/c-family/c-omp.c @@ -396,7 +396,7 @@ c_finish_omp_for (location_t locus, enum tree_code code, tree declv, bool fail = false; int i; - if (code == CILK_SIMD + if ((code == CILK_SIMD || code == CILK_FOR) && !c_check_cilk_loop (locus, TREE_VEC_ELT (declv, 0))) fail = true; @@ -515,7 +515,10 @@ c_finish_omp_for (location_t locus, enum tree_code code, tree declv, || TREE_CODE (cond) == EQ_EXPR) { if (!INTEGRAL_TYPE_P (TREE_TYPE (decl))) - cond_ok = false; + { + if (code != CILK_SIMD && code != CILK_FOR) + cond_ok = false; + } else if (operand_equal_p (TREE_OPERAND (cond, 1), TYPE_MIN_VALUE (TREE_TYPE (decl)), 0)) @@ -526,7 +529,7 @@ c_finish_omp_for (location_t locus, enum tree_code code, tree declv, 0)) TREE_SET_CODE (cond, TREE_CODE (cond) == NE_EXPR ? LT_EXPR : GE_EXPR); - else if (code != CILK_SIMD) + else if (code != CILK_SIMD && code != CILK_FOR) cond_ok = false; } } diff --git a/gcc/c-family/c-pragma.c b/gcc/c-family/c-pragma.c index 804f37c..da928b2 100644 --- a/gcc/c-family/c-pragma.c +++ b/gcc/c-family/c-pragma.c @@ -1405,6 +1405,11 @@ init_pragma (void) if (!flag_preprocess_only) cpp_register_deferred_pragma (parse_in, "GCC", "ivdep", PRAGMA_IVDEP, false, false); + + if (flag_cilkplus && !flag_preprocess_only) + cpp_register_deferred_pragma (parse_in, "cilk", "grainsize", + PRAGMA_CILK_GRAINSIZE, true, false); + #ifdef HANDLE_PRAGMA_PACK_WITH_EXPANSION c_register_pragma_with_expansion (0, "pack", handle_pragma_pack); #else diff --git a/gcc/c-family/c-pragma.h b/gcc/c-family/c-pragma.h index 6f1bf74..b9f09ba 100644 --- a/gcc/c-family/c-pragma.h +++ b/gcc/c-family/c-pragma.h @@ -55,6 +55,9 @@ typedef enum pragma_kind { /* Top level clause to handle all Cilk Plus pragma simd clauses. */ PRAGMA_CILK_SIMD, + /* This pragma handles setting of grainsize for a _Cilk_for. */ + PRAGMA_CILK_GRAINSIZE, + PRAGMA_GCC_PCH_PREPROCESS, PRAGMA_IVDEP, diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c index 34f1e47..03c6830 100644 --- a/gcc/c/c-parser.c +++ b/gcc/c/c-parser.c @@ -1264,9 +1264,11 @@ static bool c_parser_objc_diagnose_bad_element_prefix /* Cilk Plus supporting routines. */ static void c_parser_cilk_simd (c_parser *); +static void c_parser_cilk_for (c_parser *, tree); static bool c_parser_cilk_verify_simd (c_parser *, enum pragma_context); static tree c_parser_array_notation (location_t, c_parser *, tree, tree); static tree c_parser_cilk_clause_vectorlength (c_parser *, tree, bool); +static void c_parser_cilk_grainsize (c_parser *); /* Parse a translation unit (C90 6.7, C99 6.9). @@ -4895,6 +4897,16 @@ c_parser_statement_after_labels (c_parser *parser) case RID_FOR: c_parser_for_statement (parser, false); break; + case RID_CILK_FOR: + if (!flag_cilkplus) + { + error_at (c_parser_peek_token (parser)->location, + "-fcilkplus must be enabled to use %<_Cilk_for%>"); + c_parser_skip_to_end_of_block_or_statement (parser); + } + else + c_parser_cilk_for (parser, integer_zero_node); + break; case RID_CILK_SYNC: c_parser_consume_token (parser); c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>"); @@ -9582,6 +9594,23 @@ c_parser_pragma (c_parser *parser, enum pragma_context context) c_parser_consume_pragma (parser); c_parser_cilk_simd (parser); return false; + case PRAGMA_CILK_GRAINSIZE: + if (!flag_cilkplus) + { + warning (0, "%<#pragma grainsize%> ignored because -fcilkplus is not" + " enabled"); + c_parser_skip_until_found (parser, CPP_PRAGMA_EOL, NULL); + return false; + } + if (context == pragma_external) + { + error_at (c_parser_peek_token (parser)->location, + "%<#pragma grainsize%> must be inside a function"); + c_parser_skip_until_found (parser, CPP_PRAGMA_EOL, NULL); + return false; + } + c_parser_cilk_grainsize (parser); + return false; default: if (id < PRAGMA_FIRST_EXTERNAL) @@ -11715,11 +11744,18 @@ c_parser_omp_for_loop (location_t loc, c_parser *parser, enum tree_code code, condv = make_tree_vec (collapse); incrv = make_tree_vec (collapse); - if (!c_parser_next_token_is_keyword (parser, RID_FOR)) + if (code != CILK_FOR + && !c_parser_next_token_is_keyword (parser, RID_FOR)) { c_parser_error (parser, "for statement expected"); return NULL; } + if (code == CILK_FOR + && !c_parser_next_token_is_keyword (parser, RID_CILK_FOR)) + { + c_parser_error (parser, "_Cilk_for statement expected"); + return NULL; + } for_loc = c_parser_peek_token (parser)->location; c_parser_consume_token (parser); @@ -11797,7 +11833,7 @@ c_parser_omp_for_loop (location_t loc, c_parser *parser, enum tree_code code, case LE_EXPR: break; case NE_EXPR: - if (code == CILK_SIMD) + if (code == CILK_SIMD || code == CILK_FOR) break; /* FALLTHRU. */ default: @@ -13890,8 +13926,48 @@ c_parser_cilk_all_clauses (c_parser *parser) return c_finish_cilk_clauses (clauses); } -/* Main entry point for parsing Cilk Plus <#pragma simd> for - loops. */ +/* This function helps parse the grainsize pragma for a _Cilk_for statement. + Here is the correct syntax of this pragma: + #pragma cilk grainsize = + */ + +static void +c_parser_cilk_grainsize (c_parser *parser) +{ + extern tree convert_to_integer (tree, tree); + + /* consume the 'grainsize' keyword. */ + c_parser_consume_pragma (parser); + + if (c_parser_require (parser, CPP_EQ, "expected %<=%>") != 0) + { + struct c_expr g_expr = c_parser_binary_expression (parser, NULL, NULL); + if (g_expr.value == error_mark_node) + { + c_parser_skip_to_pragma_eol (parser); + return; + } + tree grain = convert_to_integer (long_integer_type_node, + c_fully_fold (g_expr.value, false, + NULL)); + c_parser_skip_to_pragma_eol (parser); + c_token *token = c_parser_peek_token (parser); + if (token && token->type == CPP_KEYWORD + && token->keyword == RID_CILK_FOR) + { + if (grain == NULL_TREE || grain == error_mark_node) + grain = integer_zero_node; + c_parser_cilk_for (parser, grain); + } + else + warning (0, "%<#pragma cilk grainsize%> is not followed by " + "%<_Cilk_for%>"); + } + else + c_parser_skip_to_pragma_eol (parser); +} + +/* Main entry point for parsing Cilk Plus <#pragma simd> for loops. */ static void c_parser_cilk_simd (c_parser *parser) @@ -13903,6 +13979,105 @@ c_parser_cilk_simd (c_parser *parser) block = c_end_compound_stmt (loc, block, true); add_stmt (block); } + +/* Create an artificial decl with TYPE and emit initialization of it with + INIT. */ + +static tree +c_get_temp_regvar (tree type, tree init) +{ + location_t loc = EXPR_LOCATION (init); + tree decl = build_decl (loc, VAR_DECL, NULL_TREE, type); + DECL_ARTIFICIAL (decl) = 1; + DECL_IGNORED_P (decl) = 1; + pushdecl (decl); + tree t = build2 (INIT_EXPR, type, decl, init); + add_stmt (t); + return decl; +} + +/* Main entry point for parsing Cilk Plus _Cilk_for loops. + GRAIN is the grain value passed in through pragma or 0. */ + +static void +c_parser_cilk_for (c_parser *parser, tree grain) +{ + tree clauses = build_omp_clause (EXPR_LOCATION (grain), OMP_CLAUSE_SCHEDULE); + OMP_CLAUSE_SCHEDULE_KIND (clauses) = OMP_CLAUSE_SCHEDULE_CILKFOR; + OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (clauses) = grain; + clauses = c_finish_omp_clauses (clauses); + + tree block = c_begin_compound_stmt (true); + tree sb = push_stmt_list (); + location_t loc = c_parser_peek_token (parser)->location; + tree omp_for = c_parser_omp_for_loop (loc, parser, CILK_FOR, clauses, NULL); + sb = pop_stmt_list (sb); + + if (omp_for) + { + tree omp_par = make_node (OMP_PARALLEL); + TREE_TYPE (omp_par) = void_type_node; + OMP_PARALLEL_CLAUSES (omp_par) = NULL_TREE; + tree bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL); + TREE_SIDE_EFFECTS (bind) = 1; + BIND_EXPR_BODY (bind) = sb; + OMP_PARALLEL_BODY (omp_par) = bind; + if (OMP_FOR_PRE_BODY (omp_for)) + { + add_stmt (OMP_FOR_PRE_BODY (omp_for)); + OMP_FOR_PRE_BODY (omp_for) = NULL_TREE; + } + tree init = TREE_VEC_ELT (OMP_FOR_INIT (omp_for), 0); + tree decl = TREE_OPERAND (init, 0); + tree cond = TREE_VEC_ELT (OMP_FOR_COND (omp_for), 0); + tree incr = TREE_VEC_ELT (OMP_FOR_INCR (omp_for), 0); + tree t = TREE_OPERAND (cond, 1), c, clauses = NULL_TREE; + if (TREE_CODE (t) != INTEGER_CST) + { + TREE_OPERAND (cond, 1) = c_get_temp_regvar (TREE_TYPE (t), t); + c = build_omp_clause (input_location, OMP_CLAUSE_FIRSTPRIVATE); + OMP_CLAUSE_DECL (c) = TREE_OPERAND (cond, 1); + OMP_CLAUSE_CHAIN (c) = clauses; + clauses = c; + } + if (TREE_CODE (incr) == MODIFY_EXPR) + { + t = TREE_OPERAND (TREE_OPERAND (incr, 1), 1); + if (TREE_CODE (t) != INTEGER_CST) + { + TREE_OPERAND (TREE_OPERAND (incr, 1), 1) + = c_get_temp_regvar (TREE_TYPE (t), t); + c = build_omp_clause (input_location, OMP_CLAUSE_FIRSTPRIVATE); + OMP_CLAUSE_DECL (c) = TREE_OPERAND (TREE_OPERAND (incr, 1), 1); + OMP_CLAUSE_CHAIN (c) = clauses; + clauses = c; + } + } + t = TREE_OPERAND (init, 1); + if (TREE_CODE (t) != INTEGER_CST) + { + TREE_OPERAND (init, 1) = c_get_temp_regvar (TREE_TYPE (t), t); + c = build_omp_clause (input_location, OMP_CLAUSE_FIRSTPRIVATE); + OMP_CLAUSE_DECL (c) = TREE_OPERAND (init, 1); + OMP_CLAUSE_CHAIN (c) = clauses; + clauses = c; + } + c = build_omp_clause (input_location, OMP_CLAUSE_PRIVATE); + OMP_CLAUSE_DECL (c) = decl; + OMP_CLAUSE_CHAIN (c) = clauses; + clauses = c; + c = build_omp_clause (input_location, OMP_CLAUSE__CILK_FOR_COUNT_); + OMP_CLAUSE_OPERAND (c, 0) + = cilk_for_number_of_iterations (omp_for); + OMP_CLAUSE_CHAIN (c) = clauses; + OMP_PARALLEL_CLAUSES (omp_par) = c_finish_omp_clauses (c); + add_stmt (omp_par); + } + + block = c_end_compound_stmt (loc, block, true); + add_stmt (block); +} + /* Parse a transaction attribute (GCC Extension). diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c index a7de8f3..da71ab2 100644 --- a/gcc/c/c-typeck.c +++ b/gcc/c/c-typeck.c @@ -12229,6 +12229,7 @@ c_finish_omp_clauses (tree clauses) case OMP_CLAUSE_SECTIONS: case OMP_CLAUSE_TASKGROUP: case OMP_CLAUSE_PROC_BIND: + case OMP_CLAUSE__CILK_FOR_COUNT_: pc = &OMP_CLAUSE_CHAIN (c); continue; diff --git a/gcc/cilk-builtins.def b/gcc/cilk-builtins.def index 9f3240a..bf319d5 100644 --- a/gcc/cilk-builtins.def +++ b/gcc/cilk-builtins.def @@ -31,3 +31,5 @@ DEF_CILK_BUILTIN_STUB (BUILT_IN_CILK_SYNC, "__cilkrts_sync") DEF_CILK_BUILTIN_STUB (BUILT_IN_CILK_LEAVE_FRAME, "__cilkrts_leave_frame") DEF_CILK_BUILTIN_STUB (BUILT_IN_CILK_POP_FRAME, "__cilkrts_pop_frame") DEF_CILK_BUILTIN_STUB (BUILT_IN_CILK_SAVE_FP, "__cilkrts_save_fp_ctrl_state") +DEF_CILK_BUILTIN_STUB (BUILT_IN_CILK_FOR_32, "__cilkrts_cilk_for_32") +DEF_CILK_BUILTIN_STUB (BUILT_IN_CILK_FOR_64, "__cilkrts_cilk_for_64") diff --git a/gcc/cilk-common.c b/gcc/cilk-common.c index a6a1aa2..35c47e1 100644 --- a/gcc/cilk-common.c +++ b/gcc/cilk-common.c @@ -105,6 +105,27 @@ install_builtin (const char *name, tree fntype, enum built_in_function code, return fndecl; } +/* Returns a FUNCTION_DECL of type TYPE whose name is *NAME. */ + +static tree +declare_cilk_for_builtin (const char *name, tree type, + enum built_in_function code) +{ + tree cb, ft, fn; + + cb = build_function_type_list (void_type_node, + ptr_type_node, type, type, + NULL_TREE); + cb = build_pointer_type (cb); + ft = build_function_type_list (void_type_node, + cb, ptr_type_node, type, + integer_type_node, NULL_TREE); + fn = install_builtin (name, ft, code, false); + TREE_NOTHROW (fn) = 0; + + return fn; +} + /* Creates and initializes all the built-in Cilk keywords functions and three structures: __cilkrts_stack_frame, __cilkrts_pedigree and __cilkrts_worker. Detailed information about __cilkrts_stack_frame and @@ -119,7 +140,7 @@ cilk_init_builtins (void) uint64_t rank; struct __cilkrts_pedigree *parent; } */ - + tree pedigree_type = lang_hooks.types.make_type (RECORD_TYPE); tree pedigree_ptr = build_pointer_type (pedigree_type); tree field = add_field ("rank", uint64_type_node, NULL_TREE); @@ -131,7 +152,7 @@ cilk_init_builtins (void) lang_hooks.types.register_builtin_type (pedigree_type, "__cilkrts_pedigree_t"); cilk_pedigree_type_decl = pedigree_type; - + /* Build the Cilk Stack Frame: struct __cilkrts_stack_frame { uint32_t flags; @@ -212,7 +233,7 @@ cilk_init_builtins (void) tree sysdep_t = lang_hooks.types.make_type (RECORD_TYPE); finish_builtin_struct (sysdep_t, "__cilkrts_worker_sysdep_state", NULL_TREE, NULL_TREE); - + field = add_field ("tail", fptr_vol_ptr_vol, NULL_TREE); cilk_trees[CILK_TI_WORKER_TAIL] = field; field = add_field ("head", fptr_vol_ptr_vol, field); @@ -234,16 +255,16 @@ cilk_init_builtins (void) tree fptr_arglist = tree_cons (NULL_TREE, frame_ptr, void_list_node); tree fptr_fun = build_function_type (void_type_node, fptr_arglist); - + /* void __cilkrts_enter_frame_1 (__cilkrts_stack_frame *); */ cilk_enter_fndecl = install_builtin ("__cilkrts_enter_frame_1", fptr_fun, BUILT_IN_CILK_ENTER_FRAME, false); /* void __cilkrts_enter_frame_fast_1 (__cilkrts_stack_frame *); */ cilk_enter_fast_fndecl = - install_builtin ("__cilkrts_enter_frame_fast_1", fptr_fun, + install_builtin ("__cilkrts_enter_frame_fast_1", fptr_fun, BUILT_IN_CILK_ENTER_FRAME_FAST, false); - + /* void __cilkrts_pop_frame (__cilkrts_stack_frame *); */ cilk_pop_fndecl = install_builtin ("__cilkrts_pop_frame", fptr_fun, BUILT_IN_CILK_POP_FRAME, false); @@ -261,14 +282,22 @@ cilk_init_builtins (void) BUILT_IN_CILK_DETACH, false); /* __cilkrts_rethrow (struct stack_frame *); */ - cilk_rethrow_fndecl = install_builtin ("__cilkrts_rethrow", fptr_fun, + cilk_rethrow_fndecl = install_builtin ("__cilkrts_rethrow", fptr_fun, BUILT_IN_CILK_RETHROW, false); TREE_NOTHROW (cilk_rethrow_fndecl) = 0; /* __cilkrts_save_fp_ctrl_state (__cilkrts_stack_frame *); */ - cilk_save_fp_fndecl = install_builtin ("__cilkrts_save_fp_ctrl_state", + cilk_save_fp_fndecl = install_builtin ("__cilkrts_save_fp_ctrl_state", fptr_fun, BUILT_IN_CILK_SAVE_FP, false); + /* __cilkrts_cilk_for_32 (...); */ + cilk_for_32_fndecl = declare_cilk_for_builtin ("__cilkrts_cilk_for_32", + unsigned_intSI_type_node, + BUILT_IN_CILK_FOR_32); + /* __cilkrts_cilk_for_64 (...); */ + cilk_for_64_fndecl = declare_cilk_for_builtin ("__cilkrts_cilk_for_64", + unsigned_intDI_type_node, + BUILT_IN_CILK_FOR_64); } /* Get the appropriate frame arguments for CALL that is of type CALL_EXPR. */ diff --git a/gcc/cilk.h b/gcc/cilk.h index ae96f53..1fee929 100644 --- a/gcc/cilk.h +++ b/gcc/cilk.h @@ -40,6 +40,9 @@ enum cilk_tree_index { CILK_TI_F_POP, /* __cilkrts_pop_frame (...). */ CILK_TI_F_RETHROW, /* __cilkrts_rethrow (...). */ CILK_TI_F_SAVE_FP, /* __cilkrts_save_fp_ctrl_state (...). */ + CILK_TI_F_LOOP_32, /* __cilkrts_cilk_for_32 (...). */ + CILK_TI_F_LOOP_64, /* __cilkrts_cilk_for_64 (...). */ + /* __cilkrts_stack_frame struct fields. */ CILK_TI_FRAME_FLAGS, /* stack_frame->flags. */ CILK_TI_FRAME_PARENT, /* stack_frame->parent. */ @@ -77,6 +80,8 @@ extern GTY (()) tree cilk_trees[CILK_TI_MAX]; #define cilk_rethrow_fndecl cilk_trees[CILK_TI_F_RETHROW] #define cilk_pop_fndecl cilk_trees[CILK_TI_F_POP] #define cilk_save_fp_fndecl cilk_trees[CILK_TI_F_SAVE_FP] +#define cilk_for_32_fndecl cilk_trees[CILK_TI_F_LOOP_32] +#define cilk_for_64_fndecl cilk_trees[CILK_TI_F_LOOP_64] #define cilk_worker_type_fndecl cilk_trees[CILK_TI_WORKER_TYPE] #define cilk_frame_type_decl cilk_trees[CILK_TI_FRAME_TYPE] diff --git a/gcc/cp/cp-cilkplus.c b/gcc/cp/cp-cilkplus.c index daa9b8e..565dd40 100644 --- a/gcc/cp/cp-cilkplus.c +++ b/gcc/cp/cp-cilkplus.c @@ -42,12 +42,11 @@ static tree cpp_validate_cilk_plus_loop_aux (tree *tp, int *walk_subtrees, void *data) { bool *valid = (bool *) data; - location_t loc = EXPR_HAS_LOCATION (*tp) ? EXPR_LOCATION (*tp) : - UNKNOWN_LOCATION; if (!tp || !*tp) return NULL_TREE; + location_t loc = EXPR_LOCATION (*tp); if (TREE_CODE (*tp) == THROW_EXPR) { error_at (loc, "throw expressions are not allowed inside loops " @@ -142,4 +141,3 @@ cilk_install_body_with_frame_cleanup (tree fndecl, tree orig_body, void *wd) append_to_statement_list (build_stmt (loc, TRY_FINALLY_EXPR, body, dtor), &list); } - diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index ad99cab..05fa86a 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -239,6 +239,8 @@ static tree cp_literal_operator_id static void cp_parser_cilk_simd (cp_parser *, cp_token *); +static tree cp_parser_cilk_for + (cp_parser *, tree); static bool cp_parser_omp_declare_reduction_exprs (tree, cp_parser *); static tree cp_parser_cilk_simd_vectorlength @@ -9532,6 +9534,18 @@ cp_parser_statement (cp_parser* parser, tree in_statement_expr, statement = cp_parser_iteration_statement (parser, false); break; + case RID_CILK_FOR: + if (!flag_cilkplus) + { + error_at (cp_lexer_peek_token (parser->lexer)->location, + "-fcilkplus must be enabled to use %<_Cilk_for%>"); + cp_lexer_consume_token (parser->lexer); + statement = error_mark_node; + } + else + statement = cp_parser_cilk_for (parser, integer_zero_node); + break; + case RID_BREAK: case RID_CONTINUE: case RID_RETURN: @@ -29222,7 +29236,7 @@ cp_parser_omp_for_cond (cp_parser *parser, tree decl, enum tree_code code) case LE_EXPR: break; case NE_EXPR: - if (code == CILK_SIMD) + if (code == CILK_SIMD || code == CILK_FOR) break; /* Fall through: OpenMP disallows NE_EXPR. */ default: @@ -29337,15 +29351,12 @@ cp_parser_omp_for_incr (cp_parser *parser, tree decl) /* Parse the initialization statement of either an OpenMP for loop or a Cilk Plus for loop. - PARSING_OPENMP is true if parsing OpenMP, or false if parsing Cilk - Plus. - Return true if the resulting construct should have an OMP_CLAUSE_PRIVATE added to it. */ static bool cp_parser_omp_for_loop_init (cp_parser *parser, - bool parsing_openmp, + enum tree_code code, tree &this_pre_body, vec *for_block, tree &init, @@ -29408,7 +29419,7 @@ cp_parser_omp_for_loop_init (cp_parser *parser, if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN)) { - if (parsing_openmp) + if (code != CILK_SIMD && code != CILK_FOR) error ("parenthesized initialization is not allowed in " "OpenMP % loop"); else @@ -29480,6 +29491,9 @@ cp_parser_omp_for_loop_init (cp_parser *parser, cp_id_kind idk; /* If parsing a type specifier sequence failed, then this MUST be a simple expression. */ + if (code == CILK_FOR) + error ("%<_Cilk_for%> allows expression instead of declaration only " + "in C, not in C++"); cp_parser_parse_tentatively (parser); decl = cp_parser_primary_expression (parser, false, false, false, &idk); @@ -29548,11 +29562,18 @@ cp_parser_omp_for_loop (cp_parser *parser, enum tree_code code, tree clauses, bool add_private_clause = false; location_t loc; - if (!cp_lexer_next_token_is_keyword (parser->lexer, RID_FOR)) + if (code != CILK_FOR + && !cp_lexer_next_token_is_keyword (parser->lexer, RID_FOR)) { cp_parser_error (parser, "for statement expected"); return NULL; } + if (code == CILK_FOR + && !cp_lexer_next_token_is_keyword (parser->lexer, RID_CILK_FOR)) + { + cp_parser_error (parser, "_Cilk_for statement expected"); + return NULL; + } loc = cp_lexer_consume_token (parser->lexer)->location; if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN)) @@ -29562,8 +29583,7 @@ cp_parser_omp_for_loop (cp_parser *parser, enum tree_code code, tree clauses, this_pre_body = push_stmt_list (); add_private_clause - |= cp_parser_omp_for_loop_init (parser, - /*parsing_openmp=*/code != CILK_SIMD, + |= cp_parser_omp_for_loop_init (parser, code, this_pre_body, for_block, init, decl, real_decl); @@ -29733,7 +29753,7 @@ cp_parser_omp_for_loop (cp_parser *parser, enum tree_code code, tree clauses, /* Note that we saved the original contents of this flag when we entered the structured block, and so we don't need to re-save it here. */ - if (code == CILK_SIMD) + if (code == CILK_SIMD || code == CILK_FOR) parser->in_statement = IN_CILK_SIMD_FOR; else parser->in_statement = IN_OMP_FOR; @@ -31692,6 +31712,36 @@ cp_parser_initial_pragma (cp_token *first_token) cp_lexer_get_preprocessor_token (NULL, first_token); } +/* Parses the grainsize pragma for the _Cilk_for statement. + Syntax: + #pragma cilk grainsize = . */ + +static void +cp_parser_cilk_grainsize (cp_parser *parser, cp_token *pragma_tok) +{ + if (cp_parser_require (parser, CPP_EQ, RT_EQ)) + { + tree exp = cp_parser_binary_expression (parser, false, false, + PREC_NOT_OPERATOR, NULL); + cp_parser_skip_to_pragma_eol (parser, pragma_tok); + if (!exp || exp == error_mark_node) + { + error_at (pragma_tok->location, "invalid grainsize for _Cilk_for"); + return; + } + + /* Make sure the next token is _Cilk_for, it is invalid otherwise. */ + if (cp_lexer_next_token_is_keyword (parser->lexer, RID_CILK_FOR)) + cp_parser_cilk_for (parser, exp); + else + warning_at (cp_lexer_peek_token (parser->lexer)->location, 0, + "%<#pragma cilk grainsize%> is not followed by " + "%<_Cilk_for%>"); + return; + } + cp_parser_skip_to_pragma_eol (parser, pragma_tok); +} + /* Normal parsing of a pragma token. Here we can (and must) use the regular lexer. */ @@ -31874,6 +31924,27 @@ cp_parser_pragma (cp_parser *parser, enum pragma_context context) cp_parser_cilk_simd (parser, pragma_tok); return true; + case PRAGMA_CILK_GRAINSIZE: + if (context == pragma_external) + { + error_at (pragma_tok->location, + "%<#pragma cilk grainsize%> must be inside a function"); + break; + } + + /* Ignore the pragma if Cilk Plus is not enabled. */ + if (flag_cilkplus) + { + cp_parser_cilk_grainsize (parser, pragma_tok); + return true; + } + else + { + error_at (pragma_tok->location, "-fcilkplus must be enabled to use " + "%<#pragma cilk grainsize%>"); + break; + } + default: gcc_assert (id >= PRAGMA_FIRST_EXTERNAL); c_invoke_pragma_handler (id); @@ -31960,10 +32031,10 @@ cp_parser_cilk_simd_vectorlength (cp_parser *parser, tree clauses, if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN)) return error_mark_node; - + expr = cp_parser_constant_expression (parser, false, NULL); expr = maybe_constant_value (expr); - + /* If expr == error_mark_node, then don't emit any errors nor create a clause. if any of the above functions returns error mark node then they would have emitted an error message. */ @@ -32197,7 +32268,7 @@ cp_parser_cilk_simd (cp_parser *parser, cp_token *pragma_token) if (clauses == error_mark_node) return; - + if (cp_lexer_next_token_is_not_keyword (parser->lexer, RID_FOR)) { error_at (cp_lexer_peek_token (parser->lexer)->location, @@ -32212,7 +32283,35 @@ cp_parser_cilk_simd (cp_parser *parser, cp_token *pragma_token) cpp_validate_cilk_plus_loop (OMP_FOR_BODY (ret)); cp_parser_end_omp_structured_block (parser, save); add_stmt (finish_omp_structured_block (sb)); - return; +} + +/* Main entry-point for parsing Cilk Plus _Cilk_for + loops. The return value is error_mark_node + when errors happen and CILK_FOR tree on success. */ + +static tree +cp_parser_cilk_for (cp_parser *parser, tree grain) +{ + if (cp_lexer_next_token_is_not_keyword (parser->lexer, RID_CILK_FOR)) + gcc_unreachable (); + + tree sb = begin_omp_structured_block (); + int save = cp_parser_begin_omp_structured_block (parser); + + tree clauses = build_omp_clause (EXPR_LOCATION (grain), OMP_CLAUSE_SCHEDULE); + OMP_CLAUSE_SCHEDULE_KIND (clauses) = OMP_CLAUSE_SCHEDULE_CILKFOR; + OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (clauses) = grain; + clauses = finish_omp_clauses (clauses); + + tree ret = cp_parser_omp_for_loop (parser, CILK_FOR, clauses, NULL); + if (ret) + cpp_validate_cilk_plus_loop (ret); + else + ret = error_mark_node; + + cp_parser_end_omp_structured_block (parser, save); + add_stmt (finish_omp_structured_block (sb)); + return ret; } /* Create an identifier for a generic parameter type (a synthesized diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index eac837f..5ea5a58 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -14012,6 +14012,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl, case OMP_FOR: case OMP_SIMD: case CILK_SIMD: + case CILK_FOR: case OMP_DISTRIBUTE: { tree clauses, body, pre_body; diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 168bde8..01748da 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -49,6 +49,7 @@ along with GCC; see the file COPYING3. If not see #include "bitmap.h" #include "omp-low.h" #include "builtins.h" +#include "convert.h" static bool verify_constant (tree, bool, bool *, bool *); #define VERIFY_CONSTANT(X) \ @@ -5424,6 +5425,8 @@ finish_omp_clauses (tree clauses) else if (t == error_mark_node) remove = true; else if (!type_dependent_expression_p (t) + && (OMP_CLAUSE_SCHEDULE_KIND (c) + != OMP_CLAUSE_SCHEDULE_CILKFOR) && !INTEGRAL_TYPE_P (TREE_TYPE (t))) { error ("schedule chunk size expression must be integral"); @@ -5433,7 +5436,19 @@ finish_omp_clauses (tree clauses) { t = mark_rvalue_use (t); if (!processing_template_decl) - t = fold_build_cleanup_point_expr (TREE_TYPE (t), t); + { + if (OMP_CLAUSE_SCHEDULE_KIND (c) + == OMP_CLAUSE_SCHEDULE_CILKFOR) + { + t = convert_to_integer (long_integer_type_node, t); + if (t == error_mark_node) + { + remove = true; + break; + } + } + t = fold_build_cleanup_point_expr (TREE_TYPE (t), t); + } OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (c) = t; } break; @@ -5734,6 +5749,7 @@ finish_omp_clauses (tree clauses) case OMP_CLAUSE_SECTIONS: case OMP_CLAUSE_TASKGROUP: case OMP_CLAUSE_PROC_BIND: + case OMP_CLAUSE__CILK_FOR_COUNT_: break; case OMP_CLAUSE_INBRANCH: @@ -6053,7 +6069,7 @@ finish_omp_task (tree clauses, tree body) static bool handle_omp_for_class_iterator (int i, location_t locus, tree declv, tree initv, tree condv, tree incrv, tree *body, - tree *pre_body, tree clauses) + tree *pre_body, tree clauses, tree *lastp) { tree diff, iter_init, iter_incr = NULL, last; tree incr_var = NULL, orig_pre_body, orig_body, c; @@ -6073,6 +6089,7 @@ handle_omp_for_class_iterator (int i, location_t locus, tree declv, tree initv, case GE_EXPR: case LT_EXPR: case LE_EXPR: + case NE_EXPR: if (TREE_OPERAND (cond, 1) == iter) cond = build2 (swap_tree_comparison (TREE_CODE (cond)), TREE_TYPE (cond), iter, TREE_OPERAND (cond, 0)); @@ -6285,6 +6302,7 @@ handle_omp_for_class_iterator (int i, location_t locus, tree declv, tree initv, TREE_VEC_ELT (initv, i) = init; TREE_VEC_ELT (condv, i) = cond; TREE_VEC_ELT (incrv, i) = incr; + *lastp = last; return false; } @@ -6301,7 +6319,8 @@ finish_omp_for (location_t locus, enum tree_code code, tree declv, tree initv, tree condv, tree incrv, tree body, tree pre_body, tree clauses) { tree omp_for = NULL, orig_incr = NULL; - tree decl, init, cond, incr; + tree decl = NULL, init, cond, incr, orig_decl = NULL_TREE, block = NULL_TREE; + tree last = NULL_TREE; location_t elocus; int i; @@ -6431,8 +6450,11 @@ finish_omp_for (location_t locus, enum tree_code code, tree declv, tree initv, "iteration variable %qE", decl); return NULL; } + if (code == CILK_FOR && i == 0) + orig_decl = decl; if (handle_omp_for_class_iterator (i, locus, declv, initv, condv, - incrv, &body, &pre_body, clauses)) + incrv, &body, &pre_body, + clauses, &last)) return NULL; continue; } @@ -6485,11 +6507,18 @@ finish_omp_for (location_t locus, enum tree_code code, tree declv, tree initv, if (IS_EMPTY_STMT (pre_body)) pre_body = NULL; + if (code == CILK_FOR && !processing_template_decl) + block = push_stmt_list (); + omp_for = c_finish_omp_for (locus, code, declv, initv, condv, incrv, body, pre_body); if (omp_for == NULL) - return NULL; + { + if (block) + pop_stmt_list (block); + return NULL; + } for (i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INCR (omp_for)); i++) { @@ -6523,8 +6552,117 @@ finish_omp_for (location_t locus, enum tree_code code, tree declv, tree initv, if (orig_incr) TREE_VEC_ELT (OMP_FOR_INCR (omp_for), i) = TREE_VEC_ELT (orig_incr, i); } - if (omp_for != NULL) - OMP_FOR_CLAUSES (omp_for) = clauses; + OMP_FOR_CLAUSES (omp_for) = clauses; + + if (block) + { + tree omp_par = make_node (OMP_PARALLEL); + TREE_TYPE (omp_par) = void_type_node; + OMP_PARALLEL_CLAUSES (omp_par) = NULL_TREE; + tree bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL); + TREE_SIDE_EFFECTS (bind) = 1; + BIND_EXPR_BODY (bind) = pop_stmt_list (block); + OMP_PARALLEL_BODY (omp_par) = bind; + if (OMP_FOR_PRE_BODY (omp_for)) + { + add_stmt (OMP_FOR_PRE_BODY (omp_for)); + OMP_FOR_PRE_BODY (omp_for) = NULL_TREE; + } + init = TREE_VEC_ELT (OMP_FOR_INIT (omp_for), 0); + decl = TREE_OPERAND (init, 0); + cond = TREE_VEC_ELT (OMP_FOR_COND (omp_for), 0); + incr = TREE_VEC_ELT (OMP_FOR_INCR (omp_for), 0); + tree t = TREE_OPERAND (cond, 1), c, clauses, *pc; + clauses = OMP_FOR_CLAUSES (omp_for); + OMP_FOR_CLAUSES (omp_for) = NULL_TREE; + for (pc = &clauses; *pc; ) + if (OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_SCHEDULE) + { + gcc_assert (OMP_FOR_CLAUSES (omp_for) == NULL_TREE); + OMP_FOR_CLAUSES (omp_for) = *pc; + *pc = OMP_CLAUSE_CHAIN (*pc); + OMP_CLAUSE_CHAIN (OMP_FOR_CLAUSES (omp_for)) = NULL_TREE; + } + else + { + gcc_assert (OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_FIRSTPRIVATE); + pc = &OMP_CLAUSE_CHAIN (*pc); + } + if (TREE_CODE (t) != INTEGER_CST) + { + TREE_OPERAND (cond, 1) = get_temp_regvar (TREE_TYPE (t), t); + c = build_omp_clause (input_location, OMP_CLAUSE_FIRSTPRIVATE); + OMP_CLAUSE_DECL (c) = TREE_OPERAND (cond, 1); + OMP_CLAUSE_CHAIN (c) = clauses; + clauses = c; + } + if (TREE_CODE (incr) == MODIFY_EXPR) + { + t = TREE_OPERAND (TREE_OPERAND (incr, 1), 1); + if (TREE_CODE (t) != INTEGER_CST) + { + TREE_OPERAND (TREE_OPERAND (incr, 1), 1) + = get_temp_regvar (TREE_TYPE (t), t); + c = build_omp_clause (input_location, OMP_CLAUSE_FIRSTPRIVATE); + OMP_CLAUSE_DECL (c) = TREE_OPERAND (TREE_OPERAND (incr, 1), 1); + OMP_CLAUSE_CHAIN (c) = clauses; + clauses = c; + } + } + t = TREE_OPERAND (init, 1); + if (TREE_CODE (t) != INTEGER_CST) + { + TREE_OPERAND (init, 1) = get_temp_regvar (TREE_TYPE (t), t); + c = build_omp_clause (input_location, OMP_CLAUSE_FIRSTPRIVATE); + OMP_CLAUSE_DECL (c) = TREE_OPERAND (init, 1); + OMP_CLAUSE_CHAIN (c) = clauses; + clauses = c; + } + if (orig_decl && orig_decl != decl) + { + c = build_omp_clause (input_location, OMP_CLAUSE_FIRSTPRIVATE); + OMP_CLAUSE_DECL (c) = orig_decl; + OMP_CLAUSE_CHAIN (c) = clauses; + clauses = c; + } + if (last) + { + c = build_omp_clause (input_location, OMP_CLAUSE_FIRSTPRIVATE); + OMP_CLAUSE_DECL (c) = last; + OMP_CLAUSE_CHAIN (c) = clauses; + clauses = c; + } + c = build_omp_clause (input_location, OMP_CLAUSE_PRIVATE); + OMP_CLAUSE_DECL (c) = decl; + OMP_CLAUSE_CHAIN (c) = clauses; + clauses = c; + c = build_omp_clause (input_location, OMP_CLAUSE__CILK_FOR_COUNT_); + OMP_CLAUSE_OPERAND (c, 0) + = cilk_for_number_of_iterations (omp_for); + OMP_CLAUSE_CHAIN (c) = clauses; + OMP_PARALLEL_CLAUSES (omp_par) = finish_omp_clauses (c); + add_stmt (omp_par); + return omp_par; + } + else if (code == CILK_FOR && processing_template_decl) + { + tree c, clauses = OMP_FOR_CLAUSES (omp_for); + if (orig_decl && orig_decl != decl) + { + c = build_omp_clause (input_location, OMP_CLAUSE_FIRSTPRIVATE); + OMP_CLAUSE_DECL (c) = orig_decl; + OMP_CLAUSE_CHAIN (c) = clauses; + clauses = c; + } + if (last) + { + c = build_omp_clause (input_location, OMP_CLAUSE_FIRSTPRIVATE); + OMP_CLAUSE_DECL (c) = last; + OMP_CLAUSE_CHAIN (c) = clauses; + clauses = c; + } + OMP_FOR_CLAUSES (omp_for) = clauses; + } return omp_for; } diff --git a/gcc/gimple-pretty-print.c b/gcc/gimple-pretty-print.c index 283aca2..60b56b0 100644 --- a/gcc/gimple-pretty-print.c +++ b/gcc/gimple-pretty-print.c @@ -1135,6 +1135,9 @@ dump_gimple_omp_for (pretty_printer *buffer, gimple gs, int spc, int flags) case GF_OMP_FOR_KIND_DISTRIBUTE: kind = " distribute"; break; + case GF_OMP_FOR_KIND_CILKFOR: + kind = " _Cilk_for"; + break; default: gcc_unreachable (); } @@ -1169,16 +1172,24 @@ dump_gimple_omp_for (pretty_printer *buffer, gimple gs, int spc, int flags) case GF_OMP_FOR_KIND_DISTRIBUTE: pp_string (buffer, "#pragma omp distribute"); break; + case GF_OMP_FOR_KIND_CILKFOR: + break; default: gcc_unreachable (); } - dump_omp_clauses (buffer, gimple_omp_for_clauses (gs), spc, flags); + if (gimple_omp_for_kind (gs) != GF_OMP_FOR_KIND_CILKFOR) + dump_omp_clauses (buffer, gimple_omp_for_clauses (gs), spc, flags); for (i = 0; i < gimple_omp_for_collapse (gs); i++) { if (i) spc += 2; - newline_and_indent (buffer, spc); - pp_string (buffer, "for ("); + if (gimple_omp_for_kind (gs) == GF_OMP_FOR_KIND_CILKFOR) + pp_string (buffer, "_Cilk_for ("); + else + { + newline_and_indent (buffer, spc); + pp_string (buffer, "for ("); + } dump_generic_node (buffer, gimple_omp_for_index (gs, i), spc, flags, false); pp_string (buffer, " = "); @@ -1203,6 +1214,9 @@ dump_gimple_omp_for (pretty_printer *buffer, gimple gs, int spc, int flags) case GE_EXPR: pp_greater_equal (buffer); break; + case NE_EXPR: + pp_string (buffer, "!="); + break; default: gcc_unreachable (); } @@ -1221,6 +1235,8 @@ dump_gimple_omp_for (pretty_printer *buffer, gimple gs, int spc, int flags) if (!gimple_seq_empty_p (gimple_omp_body (gs))) { + if (gimple_omp_for_kind (gs) == GF_OMP_FOR_KIND_CILKFOR) + dump_omp_clauses (buffer, gimple_omp_for_clauses (gs), spc, flags); newline_and_indent (buffer, spc + 2); pp_left_brace (buffer); pp_newline (buffer); diff --git a/gcc/gimple.h b/gcc/gimple.h index 51814ba..ec41585 100644 --- a/gcc/gimple.h +++ b/gcc/gimple.h @@ -92,15 +92,16 @@ enum gf_mask { GF_CALL_INTERNAL = 1 << 6, GF_CALL_CTRL_ALTERING = 1 << 7, GF_OMP_PARALLEL_COMBINED = 1 << 0, - GF_OMP_FOR_KIND_MASK = (1 << 2) - 1, + GF_OMP_FOR_KIND_MASK = 7 << 0, GF_OMP_FOR_KIND_FOR = 0, GF_OMP_FOR_KIND_DISTRIBUTE = 1, + GF_OMP_FOR_KIND_CILKFOR = 2, /* Flag for SIMD variants of OMP_FOR kinds. */ - GF_OMP_FOR_SIMD = 1 << 1, + GF_OMP_FOR_SIMD = 1 << 2, GF_OMP_FOR_KIND_SIMD = GF_OMP_FOR_SIMD | 0, GF_OMP_FOR_KIND_CILKSIMD = GF_OMP_FOR_SIMD | 1, - GF_OMP_FOR_COMBINED = 1 << 2, - GF_OMP_FOR_COMBINED_INTO = 1 << 3, + GF_OMP_FOR_COMBINED = 1 << 3, + GF_OMP_FOR_COMBINED_INTO = 1 << 4, GF_OMP_TARGET_KIND_MASK = (1 << 2) - 1, GF_OMP_TARGET_KIND_REGION = 0, GF_OMP_TARGET_KIND_DATA = 1, diff --git a/gcc/gimplify.c b/gcc/gimplify.c index 658c5d2..0ebc24c 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -6208,6 +6208,7 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p, case OMP_CLAUSE_THREAD_LIMIT: case OMP_CLAUSE_DIST_SCHEDULE: case OMP_CLAUSE_DEVICE: + case OMP_CLAUSE__CILK_FOR_COUNT_: if (gimplify_expr (&OMP_CLAUSE_OPERAND (c, 0), pre_p, NULL, is_gimple_val, fb_rvalue) == GS_ERROR) remove = true; @@ -6584,6 +6585,7 @@ gimplify_adjust_omp_clauses (gimple_seq *pre_p, tree *list_p) case OMP_CLAUSE_PROC_BIND: case OMP_CLAUSE_SAFELEN: case OMP_CLAUSE_DEPEND: + case OMP_CLAUSE__CILK_FOR_COUNT_: break; default: @@ -7056,6 +7058,7 @@ gimplify_omp_for (tree *expr_p, gimple_seq *pre_p) case OMP_FOR: kind = GF_OMP_FOR_KIND_FOR; break; case OMP_SIMD: kind = GF_OMP_FOR_KIND_SIMD; break; case CILK_SIMD: kind = GF_OMP_FOR_KIND_CILKSIMD; break; + case CILK_FOR: kind = GF_OMP_FOR_KIND_CILKFOR; break; case OMP_DISTRIBUTE: kind = GF_OMP_FOR_KIND_DISTRIBUTE; break; default: gcc_unreachable (); @@ -8128,6 +8131,7 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, case OMP_FOR: case OMP_SIMD: case CILK_SIMD: + case CILK_FOR: case OMP_DISTRIBUTE: ret = gimplify_omp_for (expr_p, pre_p); break; diff --git a/gcc/omp-low.c b/gcc/omp-low.c index 9d1cd2c..22a8fca 100644 --- a/gcc/omp-low.c +++ b/gcc/omp-low.c @@ -70,6 +70,7 @@ along with GCC; see the file COPYING3. If not see #include "ipa-prop.h" #include "tree-nested.h" #include "tree-eh.h" +#include "cilk.h" /* Lowering of OpenMP parallel and workshare constructs proceeds in two @@ -313,6 +314,8 @@ extract_omp_for_data (gimple for_stmt, struct omp_for_data *fd, fd->have_ordered = false; fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC; fd->chunk_size = NULL_TREE; + if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_CILKFOR) + fd->sched_kind = OMP_CLAUSE_SCHEDULE_CILKFOR; collapse_iter = NULL; collapse_count = NULL; @@ -392,7 +395,9 @@ extract_omp_for_data (gimple for_stmt, struct omp_for_data *fd, break; case NE_EXPR: gcc_assert (gimple_omp_for_kind (for_stmt) - == GF_OMP_FOR_KIND_CILKSIMD); + == GF_OMP_FOR_KIND_CILKSIMD + || (gimple_omp_for_kind (for_stmt) + == GF_OMP_FOR_KIND_CILKFOR)); break; case LE_EXPR: if (POINTER_TYPE_P (TREE_TYPE (loop->n2))) @@ -1604,6 +1609,7 @@ scan_sharing_clauses (tree clauses, omp_context *ctx) case OMP_CLAUSE_SCHEDULE: case OMP_CLAUSE_DIST_SCHEDULE: case OMP_CLAUSE_DEPEND: + case OMP_CLAUSE__CILK_FOR_COUNT_: if (ctx->outer) scan_omp_op (&OMP_CLAUSE_OPERAND (c, 0), ctx->outer); break; @@ -1812,6 +1818,7 @@ scan_sharing_clauses (tree clauses, omp_context *ctx) case OMP_CLAUSE__LOOPTEMP_: case OMP_CLAUSE_TO: case OMP_CLAUSE_FROM: + case OMP_CLAUSE__CILK_FOR_COUNT_: break; default: @@ -1835,13 +1842,39 @@ scan_sharing_clauses (tree clauses, omp_context *ctx) scan_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c), ctx); } -/* Create a new name for omp child function. Returns an identifier. */ +/* Create a new name for omp child function. Returns an identifier. If + IS_CILK_FOR is true then the suffix for the child function is + "_cilk_for_fn." */ static tree -create_omp_child_function_name (bool task_copy) +create_omp_child_function_name (bool task_copy, bool is_cilk_for) { - return (clone_function_name (current_function_decl, - task_copy ? "_omp_cpyfn" : "_omp_fn")); + if (is_cilk_for) + return clone_function_name (current_function_decl, "_cilk_for_fn"); + return clone_function_name (current_function_decl, + task_copy ? "_omp_cpyfn" : "_omp_fn"); +} + +/* Returns the type of the induction variable for the child function for + _Cilk_for and the types for _high and _low variables based on TYPE. */ + +static tree +cilk_for_check_loop_diff_type (tree type) +{ + if (TYPE_PRECISION (type) <= TYPE_PRECISION (uint32_type_node)) + { + if (TYPE_UNSIGNED (type)) + return uint32_type_node; + else + return integer_type_node; + } + else + { + if (TYPE_UNSIGNED (type)) + return uint64_type_node; + else + return long_long_integer_type_node; + } } /* Build a decl for the omp child function. It'll not contain a body @@ -1852,15 +1885,28 @@ create_omp_child_function (omp_context *ctx, bool task_copy) { tree decl, type, name, t; - name = create_omp_child_function_name (task_copy); + tree cilk_for_count + = (flag_cilkplus && gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL) + ? find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt), + OMP_CLAUSE__CILK_FOR_COUNT_) : NULL_TREE; + tree cilk_var_type = NULL_TREE; + + name = create_omp_child_function_name (task_copy, + cilk_for_count != NULL_TREE); if (task_copy) type = build_function_type_list (void_type_node, ptr_type_node, ptr_type_node, NULL_TREE); + else if (cilk_for_count) + { + type = TREE_TYPE (OMP_CLAUSE_OPERAND (cilk_for_count, 0)); + cilk_var_type = cilk_for_check_loop_diff_type (type); + type = build_function_type_list (void_type_node, ptr_type_node, + cilk_var_type, cilk_var_type, NULL_TREE); + } else type = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE); - decl = build_decl (gimple_location (ctx->stmt), - FUNCTION_DECL, name, type); + decl = build_decl (gimple_location (ctx->stmt), FUNCTION_DECL, name, type); if (!task_copy) ctx->cb.dst_fn = decl; @@ -1904,13 +1950,42 @@ create_omp_child_function (omp_context *ctx, bool task_copy) DECL_CONTEXT (t) = decl; DECL_RESULT (decl) = t; - t = build_decl (DECL_SOURCE_LOCATION (decl), - PARM_DECL, get_identifier (".omp_data_i"), ptr_type_node); + /* _Cilk_for's child function requires two extra parameters called + __low and __high that are set the by Cilk runtime when it calls this + function. */ + if (cilk_for_count) + { + t = build_decl (DECL_SOURCE_LOCATION (decl), + PARM_DECL, get_identifier ("__high"), cilk_var_type); + DECL_ARTIFICIAL (t) = 1; + DECL_NAMELESS (t) = 1; + DECL_ARG_TYPE (t) = ptr_type_node; + DECL_CONTEXT (t) = current_function_decl; + TREE_USED (t) = 1; + DECL_CHAIN (t) = DECL_ARGUMENTS (decl); + DECL_ARGUMENTS (decl) = t; + + t = build_decl (DECL_SOURCE_LOCATION (decl), + PARM_DECL, get_identifier ("__low"), cilk_var_type); + DECL_ARTIFICIAL (t) = 1; + DECL_NAMELESS (t) = 1; + DECL_ARG_TYPE (t) = ptr_type_node; + DECL_CONTEXT (t) = current_function_decl; + TREE_USED (t) = 1; + DECL_CHAIN (t) = DECL_ARGUMENTS (decl); + DECL_ARGUMENTS (decl) = t; + } + + tree data_name = get_identifier (".omp_data_i"); + t = build_decl (DECL_SOURCE_LOCATION (decl), PARM_DECL, data_name, + ptr_type_node); DECL_ARTIFICIAL (t) = 1; DECL_NAMELESS (t) = 1; DECL_ARG_TYPE (t) = ptr_type_node; DECL_CONTEXT (t) = current_function_decl; TREE_USED (t) = 1; + if (cilk_for_count) + DECL_CHAIN (t) = DECL_ARGUMENTS (decl); DECL_ARGUMENTS (decl) = t; if (!task_copy) ctx->receiver_decl = t; @@ -4382,6 +4457,44 @@ expand_parallel_call (struct omp_region *region, basic_block bb, false, GSI_CONTINUE_LINKING); } +/* Insert a function call whose name is FUNC_NAME with the information from + ENTRY_STMT into the basic_block BB. */ + +static void +expand_cilk_for_call (basic_block bb, gimple entry_stmt, + vec *ws_args) +{ + tree t, t1, t2; + gimple_stmt_iterator gsi; + vec *args; + + gcc_assert (vec_safe_length (ws_args) == 2); + tree func_name = (*ws_args)[0]; + tree grain = (*ws_args)[1]; + + tree clauses = gimple_omp_parallel_clauses (entry_stmt); + tree count = find_omp_clause (clauses, OMP_CLAUSE__CILK_FOR_COUNT_); + gcc_assert (count != NULL_TREE); + count = OMP_CLAUSE_OPERAND (count, 0); + + gsi = gsi_last_bb (bb); + t = gimple_omp_parallel_data_arg (entry_stmt); + if (t == NULL) + t1 = null_pointer_node; + else + t1 = build_fold_addr_expr (t); + t2 = build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt)); + + vec_alloc (args, 4); + args->quick_push (t2); + args->quick_push (t1); + args->quick_push (count); + args->quick_push (grain); + t = build_call_expr_loc_vec (UNKNOWN_LOCATION, func_name, args); + + force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, false, + GSI_CONTINUE_LINKING); +} /* Build the function call to GOMP_task to actually generate the task operation. BB is the block where to insert the code. */ @@ -4717,7 +4830,18 @@ expand_omp_taskreg (struct omp_region *region) entry_bb = region->entry; exit_bb = region->exit; - if (is_combined_parallel (region)) + bool is_cilk_for + = (flag_cilkplus + && gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL + && find_omp_clause (gimple_omp_parallel_clauses (entry_stmt), + OMP_CLAUSE__CILK_FOR_COUNT_) != NULL_TREE); + + if (is_cilk_for) + /* If it is a _Cilk_for statement, it is modelled *like* a parallel for, + and the inner statement contains the name of the built-in function + and grain. */ + ws_args = region->inner->ws_args; + else if (is_combined_parallel (region)) ws_args = region->ws_args; else ws_args = NULL; @@ -4929,7 +5053,9 @@ expand_omp_taskreg (struct omp_region *region) } /* Emit a library call to launch the children threads. */ - if (gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL) + if (is_cilk_for) + expand_cilk_for_call (new_bb, entry_stmt, ws_args); + else if (gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL) expand_parallel_call (region, new_bb, entry_stmt, ws_args); else expand_task_call (new_bb, entry_stmt); @@ -6621,6 +6747,191 @@ expand_omp_for_static_chunk (struct omp_region *region, } } +/* A subroutine of expand_omp_for. Generate code for _Cilk_for loop. + Given parameters: + for (V = N1; V cond N2; V += STEP) BODY; + + where COND is "<" or ">" or "!=", we generate pseudocode + + for (ind_var = low; ind_var < high; ind_var++) + { + V = n1 + (ind_var * STEP) + + + } + + In the above pseudocode, low and high are function parameters of the + child function. In the function below, we are inserting a temp. + variable that will be making a call to two OMP functions that will not be + found in the body of _Cilk_for (since OMP_FOR cannot be mixed + with _Cilk_for). These functions are replaced with low and high + by the function that handles taskreg. */ + + +static void +expand_cilk_for (struct omp_region *region, struct omp_for_data *fd) +{ + bool broken_loop = region->cont == NULL; + basic_block entry_bb = region->entry; + basic_block cont_bb = region->cont; + + gcc_assert (EDGE_COUNT (entry_bb->succs) == 2); + gcc_assert (broken_loop + || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest); + basic_block l0_bb = FALLTHRU_EDGE (entry_bb)->dest; + basic_block l1_bb, l2_bb; + + if (!broken_loop) + { + gcc_assert (BRANCH_EDGE (cont_bb)->dest == l0_bb); + gcc_assert (EDGE_COUNT (cont_bb->succs) == 2); + l1_bb = split_block (cont_bb, last_stmt (cont_bb))->dest; + l2_bb = BRANCH_EDGE (entry_bb)->dest; + } + else + { + BRANCH_EDGE (entry_bb)->flags &= ~EDGE_ABNORMAL; + l1_bb = split_edge (BRANCH_EDGE (entry_bb)); + l2_bb = single_succ (l1_bb); + } + basic_block exit_bb = region->exit; + basic_block l2_dom_bb = NULL; + + gimple_stmt_iterator gsi = gsi_last_bb (entry_bb); + + /* Below statements until the "tree high_val = ..." are pseudo statements + used to pass information to be used by expand_omp_taskreg. + low_val and high_val will be replaced by the __low and __high + parameter from the child function. + + The call_exprs part is a place-holder, it is mainly used + to distinctly identify to the top-level part that this is + where we should put low and high (reasoning given in header + comment). */ + + tree child_fndecl + = gimple_omp_parallel_child_fn (last_stmt (region->outer->entry)); + tree t, low_val = NULL_TREE, high_val = NULL_TREE; + for (t = DECL_ARGUMENTS (child_fndecl); t; t = TREE_CHAIN (t)) + { + if (!strcmp (IDENTIFIER_POINTER (DECL_NAME (t)), "__high")) + high_val = t; + else if (!strcmp (IDENTIFIER_POINTER (DECL_NAME (t)), "__low")) + low_val = t; + } + gcc_assert (low_val && high_val); + + tree type = TREE_TYPE (low_val); + tree ind_var = create_tmp_reg (type, "__cilk_ind_var"); + gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR); + + /* Not needed in SSA form right now. */ + gcc_assert (!gimple_in_ssa_p (cfun)); + if (l2_dom_bb == NULL) + l2_dom_bb = l1_bb; + + tree n1 = low_val; + tree n2 = high_val; + + gimple stmt = gimple_build_assign (ind_var, n1); + + /* Replace the GIMPLE_OMP_FOR statement. */ + gsi_replace (&gsi, stmt, true); + + if (!broken_loop) + { + /* Code to control the increment goes in the CONT_BB. */ + gsi = gsi_last_bb (cont_bb); + stmt = gsi_stmt (gsi); + gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE); + stmt = gimple_build_assign_with_ops (PLUS_EXPR, ind_var, ind_var, + build_one_cst (type)); + + /* Replace GIMPLE_OMP_CONTINUE. */ + gsi_replace (&gsi, stmt, true); + } + + /* Emit the condition in L1_BB. */ + gsi = gsi_after_labels (l1_bb); + t = fold_build2 (MULT_EXPR, TREE_TYPE (fd->loop.step), + fold_convert (TREE_TYPE (fd->loop.step), ind_var), + fd->loop.step); + if (POINTER_TYPE_P (TREE_TYPE (fd->loop.n1))) + t = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (fd->loop.n1), + fd->loop.n1, fold_convert (sizetype, t)); + else + t = fold_build2 (PLUS_EXPR, TREE_TYPE (fd->loop.n1), + fd->loop.n1, fold_convert (TREE_TYPE (fd->loop.n1), t)); + t = fold_convert (TREE_TYPE (fd->loop.v), t); + expand_omp_build_assign (&gsi, fd->loop.v, t); + + /* The condition is always '<' since the runtime will fill in the low + and high values. */ + stmt = gimple_build_cond (LT_EXPR, ind_var, n2, NULL_TREE, NULL_TREE); + gsi_insert_before (&gsi, stmt, GSI_SAME_STMT); + + /* Remove GIMPLE_OMP_RETURN. */ + gsi = gsi_last_bb (exit_bb); + gsi_remove (&gsi, true); + + /* Connect the new blocks. */ + remove_edge (FALLTHRU_EDGE (entry_bb)); + + edge e, ne; + if (!broken_loop) + { + remove_edge (BRANCH_EDGE (entry_bb)); + make_edge (entry_bb, l1_bb, EDGE_FALLTHRU); + + e = BRANCH_EDGE (l1_bb); + ne = FALLTHRU_EDGE (l1_bb); + e->flags = EDGE_TRUE_VALUE; + } + else + { + single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU; + + ne = single_succ_edge (l1_bb); + e = make_edge (l1_bb, l0_bb, EDGE_TRUE_VALUE); + + } + ne->flags = EDGE_FALSE_VALUE; + e->probability = REG_BR_PROB_BASE * 7 / 8; + ne->probability = REG_BR_PROB_BASE / 8; + + set_immediate_dominator (CDI_DOMINATORS, l1_bb, entry_bb); + set_immediate_dominator (CDI_DOMINATORS, l2_bb, l2_dom_bb); + set_immediate_dominator (CDI_DOMINATORS, l0_bb, l1_bb); + + if (!broken_loop) + { + struct loop *loop = alloc_loop (); + loop->header = l1_bb; + loop->latch = cont_bb; + add_loop (loop, l1_bb->loop_father); + loop->safelen = INT_MAX; + } + + /* Pick the correct library function based on the precision of the + induction variable type. */ + tree lib_fun = NULL_TREE; + if (TYPE_PRECISION (type) == 32) + lib_fun = cilk_for_32_fndecl; + else if (TYPE_PRECISION (type) == 64) + lib_fun = cilk_for_64_fndecl; + else + gcc_unreachable (); + + gcc_assert (fd->sched_kind == OMP_CLAUSE_SCHEDULE_CILKFOR); + + /* WS_ARGS contains the library function flavor to call: + __libcilkrts_cilk_for_64 or __libcilkrts_cilk_for_32), and the + user-defined grain value. If the user does not define one, then zero + is passed in by the parser. */ + vec_alloc (region->ws_args, 2); + region->ws_args->quick_push (lib_fun); + region->ws_args->quick_push (fd->chunk_size); +} /* A subroutine of expand_omp_for. Generate code for a simd non-worksharing loop. Given parameters: @@ -6964,6 +7275,8 @@ expand_omp_for (struct omp_region *region, gimple inner_stmt) if (gimple_omp_for_kind (fd.for_stmt) & GF_OMP_FOR_SIMD) expand_omp_simd (region, &fd); + else if (gimple_omp_for_kind (fd.for_stmt) == GF_OMP_FOR_KIND_CILKFOR) + expand_cilk_for (region, &fd); else if (fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC && !fd.have_ordered) { diff --git a/gcc/testsuite/c-c++-common/cilk-plus/CK/cilk-for-2.c b/gcc/testsuite/c-c++-common/cilk-plus/CK/cilk-for-2.c new file mode 100644 index 0000000..fd30667 --- /dev/null +++ b/gcc/testsuite/c-c++-common/cilk-plus/CK/cilk-for-2.c @@ -0,0 +1,393 @@ +/* { dg-do run { target { i?86-*-* x86_64-*-* } } } */ +/* { dg-options "-fcilkplus" } */ +/* { dg-additional-options "-std=gnu99" { target c } } */ +/* { dg-additional-options "-lcilkrts" { target { i?86-*-* x86_64-*-* } } } */ + +int msk; + +#define BODY \ + do { \ + int j = (i >= 30U) ? 30 : i; \ + if (__atomic_fetch_or (&msk, 1 << j, __ATOMIC_RELAXED) & (1 << j)) \ + __builtin_abort (); \ + } while (0) +#define TEST(x) if (msk != (x)) __builtin_abort (); msk = 0 + +__attribute__((noinline, noclone)) void +test (int seven, int three, int two, int minustwo, int ten, + int zero, int eleven, int six, int one, int threealt, + unsigned long int sevenUL, unsigned long int threeUL, + unsigned long int twoUL, unsigned long int minustwoUL, + unsigned long int tenUL, unsigned long int zeroUL, + unsigned long int elevenUL, unsigned long int sixUL, + unsigned long int oneUL, unsigned long int threealtUL) +{ + _Cilk_for (int i = seven; i < three; ++i) + __builtin_abort (); + _Cilk_for (int i = seven; i <= three; ++i) + __builtin_abort (); + _Cilk_for (int i = three; i != threealt; ++i) + __builtin_abort (); + _Cilk_for (int i = seven; i < three; i += two) + __builtin_abort (); + _Cilk_for (int i = seven; i <= three; i += two) + __builtin_abort (); + _Cilk_for (int i = three; i != threealt; i += two) + __builtin_abort (); + _Cilk_for (int i = seven; i < three; i -= minustwo) + __builtin_abort (); + _Cilk_for (int i = seven; i <= three; i -= minustwo) + __builtin_abort (); + _Cilk_for (int i = three; i != threealt; i -= minustwo) + __builtin_abort (); + _Cilk_for (int i = three; i > seven; --i) + __builtin_abort (); + _Cilk_for (int i = three; i >= seven; i--) + __builtin_abort (); + _Cilk_for (int i = three; i != threealt; i--) + __builtin_abort (); + _Cilk_for (int i = three; i > seven; i -= two) + __builtin_abort (); + _Cilk_for (int i = three; i >= seven; i -= two) + __builtin_abort (); + _Cilk_for (int i = three; i != threealt; i -= two) + __builtin_abort (); + _Cilk_for (int i = three; i > seven; i += minustwo) + __builtin_abort (); + _Cilk_for (int i = three; i >= seven; i += minustwo) + __builtin_abort (); + _Cilk_for (int i = three; i != threealt; i += minustwo) + __builtin_abort (); + _Cilk_for (int i = three; i < seven; ++i) + BODY; + TEST (0x78); + _Cilk_for (int i = three; i <= seven; i++) + BODY; + TEST (0xf8); + _Cilk_for (int i = three; i != seven; i++) + BODY; + TEST (0x78); + _Cilk_for (int i = zero; i < ten; i += two) + BODY; + TEST (0x155); + _Cilk_for (int i = zero; i <= ten; i += two) + BODY; + TEST (0x555); + _Cilk_for (int i = zero; i != ten; i += two) + BODY; + TEST (0x155); + _Cilk_for (int i = zero; i < ten; i -= minustwo) + BODY; + TEST (0x155); + _Cilk_for (int i = zero; i <= ten; i -= minustwo) + BODY; + TEST (0x555); + _Cilk_for (int i = zero; i != ten; i -= minustwo) + BODY; + TEST (0x155); + _Cilk_for (int i = six; i > two; --i) + BODY; + TEST (0x78); + _Cilk_for (int i = seven; i >= three; i--) + BODY; + TEST (0xf8); + _Cilk_for (int i = seven; i != three; i--) + BODY; + TEST (0xf0); + _Cilk_for (int i = eleven; i > one; i += minustwo) + BODY; + TEST (0xaa8); + _Cilk_for (int i = eleven; i >= two; i += minustwo) + BODY; + TEST (0xaa8); + _Cilk_for (int i = eleven; i != one; i += minustwo) + BODY; + TEST (0xaa8); + _Cilk_for (int i = eleven; i > one; i -= two) + BODY; + TEST (0xaa8); + _Cilk_for (int i = eleven; i >= two; i -= two) + BODY; + TEST (0xaa8); + _Cilk_for (int i = eleven; i != one; i -= two) + BODY; + TEST (0xaa8); + _Cilk_for (unsigned long int i = sevenUL; i < threeUL; ++i) + __builtin_abort (); + _Cilk_for (unsigned long int i = sevenUL; i <= threeUL; ++i) + __builtin_abort (); + _Cilk_for (unsigned long int i = threeUL; i != threealtUL; ++i) + __builtin_abort (); + _Cilk_for (unsigned long int i = sevenUL; i < threeUL; i += twoUL) + __builtin_abort (); + _Cilk_for (unsigned long int i = sevenUL; i <= threeUL; i += twoUL) + __builtin_abort (); + _Cilk_for (unsigned long int i = threeUL; i != threealtUL; i += twoUL) + __builtin_abort (); + _Cilk_for (unsigned long int i = sevenUL; i < threeUL; i -= minustwoUL) + __builtin_abort (); + _Cilk_for (unsigned long int i = sevenUL; i <= threeUL; i -= minustwoUL) + __builtin_abort (); + _Cilk_for (unsigned long int i = threeUL; i != threealtUL; i -= minustwoUL) + __builtin_abort (); + _Cilk_for (unsigned long int i = threeUL; i > sevenUL; --i) + __builtin_abort (); + _Cilk_for (unsigned long int i = threeUL; i >= sevenUL; i--) + __builtin_abort (); + _Cilk_for (unsigned long int i = threeUL; i != threealtUL; i--) + __builtin_abort (); + _Cilk_for (unsigned long int i = threeUL; i > sevenUL; i -= twoUL) + __builtin_abort (); + _Cilk_for (unsigned long int i = threeUL; i >= sevenUL; i -= twoUL) + __builtin_abort (); + _Cilk_for (unsigned long int i = threeUL; i != threealtUL; i -= twoUL) + __builtin_abort (); + _Cilk_for (unsigned long int i = threeUL; i > sevenUL; i += minustwoUL) + __builtin_abort (); + _Cilk_for (unsigned long int i = threeUL; i >= sevenUL; i += minustwoUL) + __builtin_abort (); + _Cilk_for (unsigned long int i = threeUL; i != threealtUL; i += minustwoUL) + __builtin_abort (); + _Cilk_for (unsigned long int i = threeUL; i < sevenUL; ++i) + BODY; + TEST (0x78); + _Cilk_for (unsigned long int i = threeUL; i <= sevenUL; i++) + BODY; + TEST (0xf8); + _Cilk_for (unsigned long int i = threeUL; i != sevenUL; i++) + BODY; + TEST (0x78); + _Cilk_for (unsigned long int i = zeroUL; i < tenUL; i += twoUL) + BODY; + TEST (0x155); + _Cilk_for (unsigned long int i = zeroUL; i <= tenUL; i += twoUL) + BODY; + TEST (0x555); + _Cilk_for (unsigned long int i = zeroUL; i != tenUL; i += twoUL) + BODY; + TEST (0x155); + _Cilk_for (unsigned long int i = zeroUL; i < tenUL; i -= minustwoUL) + BODY; + TEST (0x155); + _Cilk_for (unsigned long int i = zeroUL; i <= tenUL; i -= minustwoUL) + BODY; + TEST (0x555); + _Cilk_for (unsigned long int i = zeroUL; i != tenUL; i -= minustwoUL) + BODY; + TEST (0x155); + _Cilk_for (unsigned long int i = sixUL; i > twoUL; --i) + BODY; + TEST (0x78); + _Cilk_for (unsigned long int i = sevenUL; i >= threeUL; i--) + BODY; + TEST (0xf8); + _Cilk_for (unsigned long int i = sevenUL; i != threeUL; i--) + BODY; + TEST (0xf0); + _Cilk_for (unsigned long int i = elevenUL; i > oneUL; i += minustwoUL) + BODY; + TEST (0xaa8); + _Cilk_for (unsigned long int i = elevenUL; i >= twoUL; i += minustwoUL) + BODY; + TEST (0xaa8); + _Cilk_for (unsigned long int i = elevenUL; i != oneUL; i += minustwoUL) + BODY; + TEST (0xaa8); + _Cilk_for (unsigned long int i = elevenUL; i > oneUL; i -= twoUL) + BODY; + TEST (0xaa8); + _Cilk_for (unsigned long int i = elevenUL; i >= twoUL; i -= twoUL) + BODY; + TEST (0xaa8); + _Cilk_for (unsigned long int i = elevenUL; i != oneUL; i -= twoUL) + BODY; + TEST (0xaa8); +} + +int +main () +{ + _Cilk_for (int i = 7; i < 3; ++i) + __builtin_abort (); + _Cilk_for (int i = 7; i <= 3; ++i) + __builtin_abort (); + _Cilk_for (int i = 3; i != 3; ++i) + __builtin_abort (); + _Cilk_for (int i = 7; i < 3; i += 2) + __builtin_abort (); + _Cilk_for (int i = 7; i <= 3; i += 2) + __builtin_abort (); + _Cilk_for (int i = 3; i != 3; i += 2) + __builtin_abort (); + _Cilk_for (int i = 7; i < 3; i -= -2) + __builtin_abort (); + _Cilk_for (int i = 7; i <= 3; i -= -2) + __builtin_abort (); + _Cilk_for (int i = 3; i != 3; i -= -2) + __builtin_abort (); + _Cilk_for (int i = 3; i > 7; --i) + __builtin_abort (); + _Cilk_for (int i = 3; i >= 7; i--) + __builtin_abort (); + _Cilk_for (int i = 3; i != 3; i--) + __builtin_abort (); + _Cilk_for (int i = 3; i > 7; i -= 2) + __builtin_abort (); + _Cilk_for (int i = 3; i >= 7; i -= 2) + __builtin_abort (); + _Cilk_for (int i = 3; i != 3; i -= 2) + __builtin_abort (); + _Cilk_for (int i = 3; i > 7; i += -2) + __builtin_abort (); + _Cilk_for (int i = 3; i >= 7; i += -2) + __builtin_abort (); + _Cilk_for (int i = 3; i != 3; i += -2) + __builtin_abort (); + _Cilk_for (int i = 3; i < 7; ++i) + BODY; + TEST (0x78); + _Cilk_for (int i = 3; i <= 7; i++) + BODY; + TEST (0xf8); + _Cilk_for (int i = 3; i != 7; i++) + BODY; + TEST (0x78); + _Cilk_for (int i = 0; i < 10; i += 2) + BODY; + TEST (0x155); + _Cilk_for (int i = 0; i <= 10; i += 2) + BODY; + TEST (0x555); + _Cilk_for (int i = 0; i != 10; i += 2) + BODY; + TEST (0x155); + _Cilk_for (int i = 0; i < 10; i -= -2) + BODY; + TEST (0x155); + _Cilk_for (int i = 0; i <= 10; i -= -2) + BODY; + TEST (0x555); + _Cilk_for (int i = 0; i != 10; i -= -2) + BODY; + TEST (0x155); + _Cilk_for (int i = 6; i > 2; --i) + BODY; + TEST (0x78); + _Cilk_for (int i = 7; i >= 3; i--) + BODY; + TEST (0xf8); + _Cilk_for (int i = 7; i != 3; i--) + BODY; + TEST (0xf0); + _Cilk_for (int i = 11; i > 1; i += -2) + BODY; + TEST (0xaa8); + _Cilk_for (int i = 11; i >= 2; i += -2) + BODY; + TEST (0xaa8); + _Cilk_for (int i = 11; i != 1; i += -2) + BODY; + TEST (0xaa8); + _Cilk_for (int i = 11; i > 1; i -= 2) + BODY; + TEST (0xaa8); + _Cilk_for (int i = 11; i >= 2; i -= 2) + BODY; + TEST (0xaa8); + _Cilk_for (int i = 11; i != 1; i -= 2) + BODY; + TEST (0xaa8); + _Cilk_for (unsigned long int i = 7UL; i < 3UL; ++i) + __builtin_abort (); + _Cilk_for (unsigned long int i = 7UL; i <= 3UL; ++i) + __builtin_abort (); + _Cilk_for (unsigned long int i = 3UL; i != 3UL; ++i) + __builtin_abort (); + _Cilk_for (unsigned long int i = 7UL; i < 3UL; i += 2UL) + __builtin_abort (); + _Cilk_for (unsigned long int i = 7UL; i <= 3UL; i += 2UL) + __builtin_abort (); + _Cilk_for (unsigned long int i = 3UL; i != 3UL; i += 2UL) + __builtin_abort (); + _Cilk_for (unsigned long int i = 7UL; i < 3UL; i -= -2UL) + __builtin_abort (); + _Cilk_for (unsigned long int i = 7UL; i <= 3UL; i -= -2UL) + __builtin_abort (); + _Cilk_for (unsigned long int i = 3UL; i != 3UL; i -= -2UL) + __builtin_abort (); + _Cilk_for (unsigned long int i = 3UL; i > 7UL; --i) + __builtin_abort (); + _Cilk_for (unsigned long int i = 3UL; i >= 7UL; i--) + __builtin_abort (); + _Cilk_for (unsigned long int i = 3UL; i != 3UL; i--) + __builtin_abort (); + _Cilk_for (unsigned long int i = 3UL; i > 7UL; i -= 2UL) + __builtin_abort (); + _Cilk_for (unsigned long int i = 3UL; i >= 7UL; i -= 2UL) + __builtin_abort (); + _Cilk_for (unsigned long int i = 3UL; i != 3UL; i -= 2UL) + __builtin_abort (); + _Cilk_for (unsigned long int i = 3UL; i > 7UL; i += -2UL) + __builtin_abort (); + _Cilk_for (unsigned long int i = 3UL; i >= 7UL; i += -2UL) + __builtin_abort (); + _Cilk_for (unsigned long int i = 3UL; i != 3UL; i += -2UL) + __builtin_abort (); + _Cilk_for (unsigned long int i = 3UL; i < 7UL; ++i) + BODY; + TEST (0x78); + _Cilk_for (unsigned long int i = 3UL; i <= 7UL; i++) + BODY; + TEST (0xf8); + _Cilk_for (unsigned long int i = 3UL; i != 7UL; i++) + BODY; + TEST (0x78); + _Cilk_for (unsigned long int i = 0UL; i < 10UL; i += 2UL) + BODY; + TEST (0x155); + _Cilk_for (unsigned long int i = 0UL; i <= 10UL; i += 2UL) + BODY; + TEST (0x555); + _Cilk_for (unsigned long int i = 0UL; i != 10UL; i += 2UL) + BODY; + TEST (0x155); + _Cilk_for (unsigned long int i = 0UL; i < 10UL; i -= -2UL) + BODY; + TEST (0x155); + _Cilk_for (unsigned long int i = 0UL; i <= 10UL; i -= -2UL) + BODY; + TEST (0x555); + _Cilk_for (unsigned long int i = 0UL; i != 10UL; i -= -2UL) + BODY; + TEST (0x155); + _Cilk_for (unsigned long int i = 6UL; i > 2UL; --i) + BODY; + TEST (0x78); + _Cilk_for (unsigned long int i = 7UL; i >= 3UL; i--) + BODY; + TEST (0xf8); + _Cilk_for (unsigned long int i = 7UL; i != 3UL; i--) + BODY; + TEST (0xf0); + _Cilk_for (unsigned long int i = 11UL; i > 1UL; i += -2UL) + BODY; + TEST (0xaa8); + _Cilk_for (unsigned long int i = 11UL; i >= 2UL; i += -2UL) + BODY; + TEST (0xaa8); + _Cilk_for (unsigned long int i = 11UL; i != 1UL; i += -2UL) + BODY; + TEST (0xaa8); + _Cilk_for (unsigned long int i = 11UL; i > 1UL; i -= 2UL) + BODY; + TEST (0xaa8); + _Cilk_for (unsigned long int i = 11UL; i >= 2UL; i -= 2UL) + BODY; + TEST (0xaa8); + _Cilk_for (unsigned long int i = 11UL; i != 1UL; i -= 2UL) + BODY; + TEST (0xaa8); + test (7, 3, 2, -2, 10, 0, 11, 6, 1, 3, + 7UL, 3UL, 2UL, -2UL, 10UL, 0UL, 11UL, 6UL, 1UL, 3UL); + return 0; +} diff --git a/gcc/testsuite/c-c++-common/cilk-plus/CK/cilk-for-3.c b/gcc/testsuite/c-c++-common/cilk-plus/CK/cilk-for-3.c new file mode 100644 index 0000000..04c1635 --- /dev/null +++ b/gcc/testsuite/c-c++-common/cilk-plus/CK/cilk-for-3.c @@ -0,0 +1,19 @@ +/* { dg-do compile } */ +/* { dg-options "-fcilkplus" } */ +/* { dg-additional-options "-std=gnu99" { target c } } */ + +void bar (int *, int *, int *, int *); +void baz (char **, char **, char **, int *); + +void +foo () +{ + int a, b, c; + char *d, *e; + bar (0, &a, &b, &c); + _Cilk_for (int i = a; i < b; i += c) + bar (&i, &a, &b, &c); + baz (0, &d, &e, &c); + _Cilk_for (char *p = d; p != e; p += c) + baz (&p, &d, &e, &c); +} diff --git a/gcc/testsuite/c-c++-common/cilk-plus/CK/cilk-fors.c b/gcc/testsuite/c-c++-common/cilk-plus/CK/cilk-fors.c new file mode 100644 index 0000000..0a8f046 --- /dev/null +++ b/gcc/testsuite/c-c++-common/cilk-plus/CK/cilk-fors.c @@ -0,0 +1,87 @@ +/* { dg-do run { target { i?86-*-* x86_64-*-* } } } */ +/* { dg-options "-fcilkplus" } */ +/* { dg-additional-options "-std=gnu99" { target c } } */ +/* { dg-additional-options "-lcilkrts" { target { i?86-*-* x86_64-*-* } } } */ + +#if HAVE_IO +#include +#endif + +static void check (int *Array, int start, int end, int incr, int value) +{ + int ii = 0; + for (ii = start; ii < end; ii = ii + incr) + if (Array[ii] != value) + __builtin_abort (); +#if HAVE_IO + printf ("Passed\n"); +#endif +} + +static void check_reverse (int *Array, int start, int end, int incr, int value) +{ + int ii = 0; + for (ii = start; ii >= end; ii = ii - incr) + if (Array[ii] != value) + __builtin_abort (); +#if HAVE_IO + printf ("Passed\n"); +#endif +} + + +int main (void) +{ + int Array[10]; + int x = 9, y = 0, z = 3; + + + _Cilk_for (int ii = 0; ii < 10; ii++) + Array[ii] = 1133; + check (Array, 0, 10, 1, 1133); + + _Cilk_for (int ii = 0; ii < 10; ++ii) + Array[ii] = 3311; + check (Array, 0, 10, 1, 3311); + + _Cilk_for (int ii = 9; ii > -1; ii--) + Array[ii] = 4433; + check_reverse (Array, 9, 0, 1, 4433); + + _Cilk_for (int ii = 9; ii > -1; --ii) + Array[ii] = 9988; + check_reverse (Array, 9, 0, 1, 9988); + + _Cilk_for (int ii = 0; ii < 10; ++ii) + Array[ii] = 3311; + check (Array, 0, 10, 1, 3311); + + _Cilk_for (int ii = 0; ii < 10; ii += 2) + Array[ii] = 1328; + check (Array, 0, 10, 2, 1328); + + _Cilk_for (int ii = 9; ii >= 0; ii -= 2) + Array[ii] = 1738; + check_reverse (Array, 9, 0, 2, 1738); + + + _Cilk_for (int ii = 0; ii < 10; ii++) + { + if (ii % 2) + Array[ii] = 1343; + else + Array[ii] = 3413; + } + + check (Array, 1, 10, 2, 1343); + check (Array, 0, 10, 2, 3413); + + _Cilk_for (short cc = 0; cc < 10; cc++) + Array[cc] = 1343; + check (Array, 0, 10, 1,1343); + + _Cilk_for (short cc = 9; cc >= 0; cc--) + Array[cc] = 1348; + check_reverse (Array, 9, 0, 1, 1348); + return 0; +} diff --git a/gcc/testsuite/c-c++-common/cilk-plus/CK/cilk_for_errors.c b/gcc/testsuite/c-c++-common/cilk-plus/CK/cilk_for_errors.c new file mode 100644 index 0000000..60a9e7d --- /dev/null +++ b/gcc/testsuite/c-c++-common/cilk-plus/CK/cilk_for_errors.c @@ -0,0 +1,53 @@ +/* { dg-do compile } */ +/* { dg-options "-fcilkplus" } */ +/* { dg-additional-options "-std=c99" { target c } } */ + + +int main (void) +{ + int q = 0, ii = 0, jj = 0; + + _Cilk_for (int ii; ii < 10; ii++) /* { dg-error "is not initialized" "" { target c } } */ + /* { dg-error "expected" "" { target c++ } 10 } */ + q = 5; + + _Cilk_for (; ii < 10; ii++) /* { dg-error "expected iteration declaration" } */ + q = 2; + + _Cilk_for (int ii = 0; ; ii++) /* { dg-error "missing controlling predicate" } */ + q = 2; + + _Cilk_for (int ii = 0; ii < 10, jj < 10; ii++) /* { dg-error "expected ';' before ',' token" "" { target c } } */ + /* { dg-error "invalid controlling predicate" "" { target c++ } 20 } */ + q = 5; + + _Cilk_for (int ii = 0; ii < 10; ) /* { dg-error "missing increment" } */ + q = 5; + + _Cilk_for (int ii = 0, jj = 0; ii < 10; ii++) /* { dg-error "expected|invalid" } */ + q = 5; + + _Cilk_for (volatile int vii = 0; vii < 10; vii++) /* { dg-error "iteration variable cannot be volatile" } */ + q = 5; + + _Cilk_for (static int sii = 0; sii < 10; sii++) /* { dg-error "static|expected|declared|expression" } */ + q = 5; + + _Cilk_for (float fii = 3.47; fii < 5.23; fii++) /* { dg-error "invalid type for iteration variable" } */ + q = 5; + + _Cilk_for (int ii = 0; 10 > jj; ii++) /* { dg-error "invalid controlling predicate" } */ + q = 5; + + _Cilk_for (int ii = 0; ii < 10; ii >> 1) /* { dg-error "invalid increment expression" } */ + q = 5; + + _Cilk_for (int ii = 10; ii >= 0; ii--) /* This is OK! */ + q = 5; + + _Cilk_for (int ii; ii < 10; ii++) /* { dg-error "is not initialized" "" { target c } } */ + /* { dg-error "expected" "" { target c++ } 48 } */ + q = 5; + + return 0; +} diff --git a/gcc/testsuite/c-c++-common/cilk-plus/CK/cilk_for_grain.c b/gcc/testsuite/c-c++-common/cilk-plus/CK/cilk_for_grain.c new file mode 100644 index 0000000..ec02613 --- /dev/null +++ b/gcc/testsuite/c-c++-common/cilk-plus/CK/cilk_for_grain.c @@ -0,0 +1,35 @@ +/* { dg-do run { target { i?86-*-* x86_64-*-* } } } */ +/* { dg-options "-fcilkplus" } */ +/* { dg-additional-options "-std=gnu99" { target c } } */ +/* { dg-additional-options "-lcilkrts" { target { i?86-*-* x86_64-*-* } } } */ + + +int grain_value = 2; +int main (void) +{ + int Array1[200], Array1_Serial[200]; + + for (int ii = 0; ii < 200; ii++) + { + Array1_Serial[ii] = 2; + Array1[ii] = 1; + } + +#pragma cilk grainsize = 2 + _Cilk_for (int ii = 0; ii < 200; ii++) + Array1[ii] = 2; + + for (int ii = 0; ii < 200; ii++) + if (Array1[ii] != Array1_Serial[ii]) + return (ii+1); + +#pragma cilk grainsize = grain_value + _Cilk_for (int ii = 0; ii < 200; ii++) + Array1[ii] = 2; + + for (int ii = 0; ii < 200; ii++) + if (Array1[ii] != Array1_Serial[ii]) + return (ii+1); + + return 0; +} diff --git a/gcc/testsuite/c-c++-common/cilk-plus/CK/cilk_for_grain_errors.c b/gcc/testsuite/c-c++-common/cilk-plus/CK/cilk_for_grain_errors.c new file mode 100644 index 0000000..214c6be --- /dev/null +++ b/gcc/testsuite/c-c++-common/cilk-plus/CK/cilk_for_grain_errors.c @@ -0,0 +1,48 @@ +/* { dg-do compile } */ +/* { dg-options "-fcilkplus -Wunknown-pragmas" } */ +/* { dg-additional-options "-std=c99" { target c } } */ + + +char Array1[26]; + +#pragma cilk grainsize = 2 /* { dg-error "must be inside a function" } */ + +int main(int argc, char **argv) +{ +/* This is OK. */ +#pragma cilk grainsize = 2 + _Cilk_for (int ii = 0; ii < 10; ii++) + Array1[ii] = 0; + +#pragma cilk grainsize 2 /* { dg-error "expected '=' before numeric constant" } */ + _Cilk_for (int ii = 0; ii < 10; ii++) + Array1[ii] = 0; + +#pragma cilk grainsiz = 2 /* { dg-warning "ignoring #pragma cilk grainsiz" } */ + _Cilk_for (int ii = 0; ii < 10; ii++) + Array1[ii] = 0; + + +/* This is OK, it will do a type conversion to long int. */ +#pragma cilk grainsize = 0.5 + _Cilk_for (int ii = 0; ii < 10; ii++) + Array1[ii] = 0; + +#pragma cilk grainsize = 1 + while (Array1[5] != 0) /* { dg-warning "is not followed by" } */ + { + /* Blah */ + } + +#pragma cilk grainsize = 1 + int q = 0; /* { dg-warning "is not followed by" } */ + _Cilk_for (q = 0; q < 10; q++) /* { dg-error "allows expression instead of declaration" "" { target c++ } } */ + Array1[q] = 5; + + while (Array1[5] != 0) + { + /* Blah */ + } + + return 0; +} diff --git a/gcc/testsuite/c-c++-common/cilk-plus/CK/cilk_for_ptr_iter.c b/gcc/testsuite/c-c++-common/cilk-plus/CK/cilk_for_ptr_iter.c new file mode 100644 index 0000000..f4a1f4c --- /dev/null +++ b/gcc/testsuite/c-c++-common/cilk-plus/CK/cilk_for_ptr_iter.c @@ -0,0 +1,35 @@ +/* { dg-do run { target { i?86-*-* x86_64-*-* } } } */ +/* { dg-options "-fcilkplus" } */ +/* { dg-additional-options "-std=gnu99" { target c } } */ +/* { dg-additional-options "-lcilkrts" { target { i?86-*-* x86_64-*-* } } } */ + + + +/* loop control variable must have integer, pointer or class type + +*/ + +#define ARRAY_SIZE 10000 +int a[ARRAY_SIZE]; + +int main(void) +{ + int ii = 0; + + for (ii =0; ii < ARRAY_SIZE; ii++) + a[ii] = 5; + _Cilk_for(int *aa = a; aa < a + ARRAY_SIZE; aa++) + *aa = 0; + for (ii = 0; ii < ARRAY_SIZE; ii++) + if (a[ii] != 0) + __builtin_abort (); + + _Cilk_for (int *aa = a; aa < a + ARRAY_SIZE; aa = aa + 2) + *aa = 4; + + for (ii = 0; ii < ARRAY_SIZE; ii = ii + 2) + if (a[ii] != 4) + __builtin_abort (); + + return 0; +} diff --git a/gcc/testsuite/c-c++-common/cilk-plus/CK/nested_cilk_for.c b/gcc/testsuite/c-c++-common/cilk-plus/CK/nested_cilk_for.c new file mode 100644 index 0000000..3daaca9 --- /dev/null +++ b/gcc/testsuite/c-c++-common/cilk-plus/CK/nested_cilk_for.c @@ -0,0 +1,79 @@ +/* { dg-do run { target { i?86-*-* x86_64-*-* } } } */ +/* { dg-options "-fcilkplus" } */ +/* { dg-additional-options "-std=gnu99" { target c } } */ +/* { dg-additional-options "-lcilkrts" { target { i?86-*-* x86_64-*-* } } } */ + +#if HAVE_IO +#include +#endif + +int main (void) +{ + int Array[10][10]; + + + for (int ii = 0; ii < 10; ii++) + for (int jj = 0; jj < 10; jj++) + { + Array[ii][jj] = 0; + } + + _Cilk_for (int ii = 0; ii < 10; ii++) + _Cilk_for (int jj = 0; jj < 5; jj++) + Array[ii][jj] = 5; + + for (int ii = 0; ii < 10; ii++) + for (int jj = 0; jj < 5; jj++) + if (Array[ii][jj] != 5) +#if HAVE_IO + printf("Array[%d][%d] = %d\n", ii, jj, Array[ii][jj]); +#else + __builtin_abort (); +#endif + + + /* One goes up and one goes down. */ + _Cilk_for (int ii = 0; ii < 10; ii++) + _Cilk_for (int jj = 9; jj >= 0; jj--) + Array[ii][jj] = 7; + + for (int ii = 0; ii < 10; ii++) + for (int jj = 9; jj >= 0; jj--) + if (Array[ii][jj] != 7) +#if HAVE_IO + printf("Array[%d][%d] = %d\n", ii, jj, Array[ii][jj]); +#else + __builtin_abort (); +#endif + + /* different step sizes. */ + _Cilk_for (int ii = 0; ii < 10; ii++) + _Cilk_for (int jj = 0; jj < 10; jj += 2) + Array[ii][jj] = 9; + + for (int ii = 0; ii < 10; ii++) + for (int jj = 0; jj < 10; jj += 2) + if (Array[ii][jj] != 9) +#if HAVE_IO + printf("Array[%d][%d] = %d\n", ii, jj, Array[ii][jj]); +#else + __builtin_abort (); +#endif + + /* different step sizes. */ + _Cilk_for (int ii = 0; ii < 10; ii += 2) + _Cilk_for (int jj = 5; jj < 9; jj++) + Array[ii][jj] = 11; + + for (int ii = 0; ii < 10; ii += 2) + for (int jj = 5; jj < 9; jj++) + if (Array[ii][jj] != 11) +#if HAVE_IO + printf("Array[%d][%d] = %d\n", ii, jj, Array[ii][jj]); +#else + __builtin_abort (); +#endif + + return 0; +} + diff --git a/gcc/testsuite/g++.dg/cilk-plus/CK/cf3.cc b/gcc/testsuite/g++.dg/cilk-plus/CK/cf3.cc new file mode 100644 index 0000000..8d88c5f --- /dev/null +++ b/gcc/testsuite/g++.dg/cilk-plus/CK/cf3.cc @@ -0,0 +1,96 @@ +/* { dg-options "-fcilkplus" } */ + +typedef __PTRDIFF_TYPE__ ptrdiff_t; + +template +class I +{ +public: + typedef ptrdiff_t difference_type; + I (); + ~I (); + I (T *); + I (const I &); + T &operator * (); + T *operator -> (); + T &operator [] (const difference_type &) const; + I &operator = (const I &); + I &operator ++ (); + I operator ++ (int); + I &operator -- (); + I operator -- (int); + I &operator += (const difference_type &); + I &operator -= (const difference_type &); + I operator + (const difference_type &) const; + I operator - (const difference_type &) const; + template friend bool operator == (I &, I &); + template friend bool operator == (const I &, const I &); + template friend bool operator < (I &, I &); + template friend bool operator < (const I &, const I &); + template friend bool operator <= (I &, I &); + template friend bool operator <= (const I &, const I &); + template friend bool operator > (I &, I &); + template friend bool operator > (const I &, const I &); + template friend bool operator >= (I &, I &); + template friend bool operator >= (const I &, const I &); + template friend typename I::difference_type operator - (I &, I &); + template friend typename I::difference_type operator - (const I &, const I &); + template friend I operator + (typename I::difference_type , const I &); +private: + T *p; +}; +template I::I () : p (0) {} +template I::~I () {} +template I::I (T *x) : p (x) {} +template I::I (const I &x) : p (x.p) {} +template T &I::operator * () { return *p; } +template T *I::operator -> () { return p; } +template T &I::operator [] (const difference_type &x) const { return p[x]; } +template I &I::operator = (const I &x) { p = x.p; return *this; } +template I &I::operator ++ () { ++p; return *this; } +template I I::operator ++ (int) { return I (p++); } +template I &I::operator -- () { --p; return *this; } +template I I::operator -- (int) { return I (p--); } +template I &I::operator += (const difference_type &x) { p += x; return *this; } +template I &I::operator -= (const difference_type &x) { p -= x; return *this; } +template I I::operator + (const difference_type &x) const { return I (p + x); } +template I I::operator - (const difference_type &x) const { return I (p - x); } +template bool operator == (I &x, I &y) { return x.p == y.p; } +template bool operator == (const I &x, const I &y) { return x.p == y.p; } +template bool operator != (I &x, I &y) { return !(x == y); } +template bool operator != (const I &x, const I &y) { return !(x == y); } +template bool operator < (I &x, I &y) { return x.p < y.p; } +template bool operator < (const I &x, const I &y) { return x.p < y.p; } +template bool operator <= (I &x, I &y) { return x.p <= y.p; } +template bool operator <= (const I &x, const I &y) { return x.p <= y.p; } +template bool operator > (I &x, I &y) { return x.p > y.p; } +template bool operator > (const I &x, const I &y) { return x.p > y.p; } +template bool operator >= (I &x, I &y) { return x.p >= y.p; } +template bool operator >= (const I &x, const I &y) { return x.p >= y.p; } +template typename I::difference_type operator - (I &x, I &y) { return x.p - y.p; } +template typename I::difference_type operator - (const I &x, const I &y) { return x.p - y.p; } +template I operator + (typename I::difference_type x, const I &y) { return I (x + y.p); } + +template +class J +{ +public: + J(const I &x, const I &y) : b (x), e (y) {} + const I &begin (); + const I &end (); +private: + I b, e; +}; + +template const I &J::begin () { return b; } +template const I &J::end () { return e; } + +template +void baz (I &i); + +void +foo (J j) +{ + _Cilk_for (I i = j.begin (); i < j.end (); i += 2) + baz (i); +} diff --git a/gcc/testsuite/g++.dg/cilk-plus/CK/cilk-for-tplt.cc b/gcc/testsuite/g++.dg/cilk-plus/CK/cilk-for-tplt.cc new file mode 100644 index 0000000..ff9a324 --- /dev/null +++ b/gcc/testsuite/g++.dg/cilk-plus/CK/cilk-for-tplt.cc @@ -0,0 +1,25 @@ +/* { dg-do run { target { i?86-*-* x86_64-*-* } } } */ +/* { dg-options "-fcilkplus" } */ +/* { dg-options "-lcilkrts" { target { i?86-*-* x86_64-*-* } } } */ + +#define SIZE 100 +#define CHECK_VALUE 5 + +template +int func (T start, T end) +{ + int Array[SIZE]; + _Cilk_for (T ii = 0; ii < end; ii++) + Array[ii] = CHECK_VALUE; + + for (T ii = 0; ii < end; ii++) + if (Array[ii] != CHECK_VALUE) + __builtin_abort (); + + return 0; +} + +int main (void) +{ + return func (0, 100) + func (0, 100); +} diff --git a/gcc/testsuite/g++.dg/cilk-plus/CK/for1.cc b/gcc/testsuite/g++.dg/cilk-plus/CK/for1.cc new file mode 100644 index 0000000..d2243ac --- /dev/null +++ b/gcc/testsuite/g++.dg/cilk-plus/CK/for1.cc @@ -0,0 +1,376 @@ +/* { dg-do run { target { i?86-*-* x86_64-*-* } } } */ +/* { dg-options "-fcilkplus" } */ +/* { dg-additional-options "-lcilkrts" { target { i?86-*-* x86_64-*-* } } } */ + +#if HAVE_IO +#include +#endif + +typedef __PTRDIFF_TYPE__ ptrdiff_t; +extern "C" void abort (); + +template +class I +{ +public: + typedef ptrdiff_t difference_type; + I (); + ~I (); + I (T *); + I (const I &); + T &operator * (); + T *operator -> (); + T &operator [] (const difference_type &) const; + I &operator = (const I &); + I &operator ++ (); + I operator ++ (int); + I &operator -- (); + I operator -- (int); + I &operator += (const difference_type &); + I &operator -= (const difference_type &); + I operator + (const difference_type &) const; + I operator - (const difference_type &) const; + template friend bool operator == (I &, I &); + template friend bool operator == (const I &, const I &); + template friend bool operator < (I &, I &); + template friend bool operator < (const I &, const I &); + template friend bool operator <= (I &, I &); + template friend bool operator <= (const I &, const I &); + template friend bool operator > (I &, I &); + template friend bool operator > (const I &, const I &); + template friend bool operator >= (I &, I &); + template friend bool operator >= (const I &, const I &); + template friend typename I::difference_type operator - (I &, I &); + template friend typename I::difference_type operator - (const I &, const I &); + template friend I operator + (typename I::difference_type , const I &); +private: + T *p; +}; +template I::I () : p (0) {} +template I::~I () {} +template I::I (T *x) : p (x) {} +template I::I (const I &x) : p (x.p) {} +template T &I::operator * () { return *p; } +template T *I::operator -> () { return p; } +template T &I::operator [] (const difference_type &x) const { return p[x]; } +template I &I::operator = (const I &x) { p = x.p; return *this; } +template I &I::operator ++ () { ++p; return *this; } +template I I::operator ++ (int) { return I (p++); } +template I &I::operator -- () { --p; return *this; } +template I I::operator -- (int) { return I (p--); } +template I &I::operator += (const difference_type &x) { p += x; return *this; } +template I &I::operator -= (const difference_type &x) { p -= x; return *this; } +template I I::operator + (const difference_type &x) const { return I (p + x); } +template I I::operator - (const difference_type &x) const { return I (p - x); } +template bool operator == (I &x, I &y) { return x.p == y.p; } +template bool operator == (const I &x, const I &y) { return x.p == y.p; } +template bool operator != (I &x, I &y) { return !(x == y); } +template bool operator != (const I &x, const I &y) { return !(x == y); } +template bool operator < (I &x, I &y) { return x.p < y.p; } +template bool operator < (const I &x, const I &y) { return x.p < y.p; } +template bool operator <= (I &x, I &y) { return x.p <= y.p; } +template bool operator <= (const I &x, const I &y) { return x.p <= y.p; } +template bool operator > (I &x, I &y) { return x.p > y.p; } +template bool operator > (const I &x, const I &y) { return x.p > y.p; } +template bool operator >= (I &x, I &y) { return x.p >= y.p; } +template bool operator >= (const I &x, const I &y) { return x.p >= y.p; } +template typename I::difference_type operator - (I &x, I &y) { return x.p - y.p; } +template typename I::difference_type operator - (const I &x, const I &y) { return x.p - y.p; } +template I operator + (typename I::difference_type x, const I &y) { return I (x + y.p); } + +template +class J +{ +public: + J(const I &x, const I &y) : b (x), e (y) {} + const I &begin (); + const I &end (); +private: + I b, e; +}; + +template const I &J::begin () { return b; } +template const I &J::end () { return e; } + +int results[2000]; + +template +void +baz (I &i) +{ + if (*i < 0 || *i >= 2000) + { +#if HAVE_IO + printf ("*i(%d) is < 0 or >= 2000\n", *i); + fflush (stdout); +#endif + __builtin_abort (); + } + else + results[*i]++; +} + +void +f1 (const I &x, const I &y) +{ + _Cilk_for (I i = x; i <= y; i += 6) + { + baz (i); + } + +#if HAVE_IO + printf("===== Starting F1 =========\n"); + for (I i = x; i <= y; i+= 6) { + printf("Result[%4d] = %2d\n", *i, results[*i]); + fflush (stdout); + } +#endif +} + +void +f2 (const I &x, const I &y) +{ + _Cilk_for (I i = x; i < y - 1; i += 2) + baz (i); + +#if HAVE_IO + printf("===== Starting F2 =========\n"); + for (int ii = 0; ii < 1998; ii += 2) { + printf("Result[%4d] = %2d\n", ii, results[ii]); + fflush (stdout); + } +#endif +} + +template +void +f3 (const I &x, const I &y) +{ + _Cilk_for (I i = x; i <= y; i += 1) + baz (i); +#if HAVE_IO + printf("===== Starting F3 =========\n"); + for (int ii = 20; ii < 1987; ii += 1) { + printf("Result[%4d] = %2d\n", ii, results[ii]); + fflush (stdout); + } + +#endif +} + +template +void +f4 (const I &x, const I &y) +{ + _Cilk_for (I i = x + (2000 - 64); i > y + 10; --i) + baz (i); +#if HAVE_IO + printf("===== Starting F3 =========\n"); + for (I i = x + (2000 - 64); i > y + 10; --i) { + printf("Result[%4d] = %2d\n", *i, results[*i]); + fflush (stdout); + } +#endif +} +void +f5 (const I &x, const I &y) +{ + _Cilk_for (I i = x + 2000 - 64; i > y + 10; i -= 10) + baz (i); +#if HAVE_IO + for (I i = x + 2000 - 64; i > y + 10; i -= 10) { + printf("Result[%4d] = %2d\n", *i, results[*i]); + fflush (stdout); + } +#endif +} + +template +void +f6 (const I &x, const I &y) +{ + _Cilk_for (I i = x + 2000 - 64; i > y + 10; i -= 10) + { + I j = i + N; + baz (j); + } +#if HAVE_IO + for (I i = x + 2000 - 64; i > y + 10; i = i - 12 + 2) + { + I j = i + N; + printf("Result[%4d] = %2d\n", *j, results[*j]); + fflush (stdout); + } +#endif +} +template +void +f7 (I ii, const I &x, const I &y) +{ + _Cilk_for (I i = x - 10; i <= y + 10; i += N) + baz (i); +#if HAVE_IO + for (I i = x - 10; i <= y + 10; i += N) + { + printf("Result[%4d] = %2d\n", *i, results[*i]); + fflush (stdout); + } +#endif +} + +template +void +f8 (J j) +{ + _Cilk_for (I i = j.begin (); i <= j.end () + N; i += 2) + baz (i); +#if HAVE_IO + for (I i = j.begin (); i <= j.end () + N; i += 2) { + printf("Result[%4d] = %2d\n", *i, results[*i]); + fflush (stdout); + } +#endif + +} + +template +void +f9 (const I &x, const I &y) +{ + _Cilk_for (I i = x; i <= y; i += N) + baz (i); +#if HAVE_IO + for (I i = x; i <= y; i = i + N) + { + printf("Result[%4d] = %2d\n", *i, results[*i]); + fflush (stdout); + } +#endif +} + +template +void +f10 (const I &x, const I &y) +{ + _Cilk_for (I i = x; i > y; i += N) + baz (i); +#if HAVE_IO + for (I i = x; i > y; i = i + N) { + printf("Result[%4d] = %2d\n", *i, results[*i]); + fflush (stdout); + } +#endif +} + +template +void +f11 (const T &x, const T &y) +{ + _Cilk_for (T i = x; i <= y; i += 3) + baz (i); + +#if HAVE_IO + for (T i = x; i <= y; i += 3) { + printf("Result[%4d] = %2d\n", *i, results[*i]); + fflush (stdout); + } +#endif + T j = y + 3; + baz (j); + +} + +template +void +f12 (const T &x, const T &y) +{ + _Cilk_for (T i = x; i > y; --i) + baz (i); +#if HAVE_IO + for (T i = x; i > y; --i) { + printf("Result[%4d] = %2d\n", *i, results[*i]); + fflush (stdout); + } +#endif +} +template +struct K +{ + template + static void + f13 (const T &x, const T &y) + { + _Cilk_for (T i = x; i <= y + N; i += N) + baz (i); +#if HAVE_IO + for (T i = x; i < y+N; i += N) { + printf("Result[%4d] = %2d\n", *i, results[*i]); + fflush (stdout); + } +#endif + } +}; + +#define check(expr) \ + for (int i = 0; i < 2000; i++) \ + if (expr) \ + { \ + if (results[i] != 1) { \ + __builtin_abort (); \ + } \ + results[i] = 0; \ + } \ + else if (results[i]) \ + abort () + +int +main () +{ + int a[2000]; + long b[2000]; + for (int i = 0; i < 2000; i++) + { + a[i] = i; + b[i] = i; + } + f1 (&a[10], &a[1990]); + check (i >= 10 && i <= 1990 && (i - 10) % 6 == 0); + f2 (&a[0], &a[1999]); + check (i < 1998 && (i & 1) == 0); + f3 (&a[20], &a[1837]); + check (i >= 20 && i <= 1837); + f4 (&a[0], &a[30]); + check (i > 40 && i <= 2000 - 64); + + f5 (&a[0], &a[100]); + check (i >= 116 && i <= 2000 - 64 && (i - 116) % 10 == 0); + f6<-10> (&a[10], &a[110]); + check (i >= 116 && i <= 2000 - 64 && (i - 116) % 10 == 0); + + f7<6> (I (), &a[12], &a[1800]); + check (i >= 2 && i <= 1808 && (i - 2) % 6 == 0); + + f8<121> (J (&a[14], &a[1803])); + check (i >= 14 && i <= 1924 && (i & 1) == 0); + f9 (&a[33], &a[1967]); + check (i >= 33 && i <= 1967 && (i - 33) % 7 == 0); + f10 (&a[1939], &a[17]); + check (i >= 21 && i <= 1939 && (i - 21) % 7 == 0); + f11 > (&a[16], &a[1981]); + check (i >= 16 && i <= 1984 && (i - 16) % 3 == 0); + f12 > (&a[1761], &a[37]); + check (i > 37 && i <= 1761); + K<5>::f13 > (&a[1], &a[1935]); + check (i >= 1 && i <= 1936 && (i - 1) % 5 == 0); + f9 (&b[33], &b[1967]); + check (i >= 33 && i <= 1967 && (i - 33) % 7 == 0); + f10 (&b[1939], &b[17]); + check (i >= 21 && i <= 1939 && (i - 21) % 7 == 0); + f11 > (&b[16], &b[1981]); + check (i >= 16 && i <= 1984 && (i - 16) % 3 == 0); + f12 > (&b[1761], &b[37]); + check (i > 37 && i <= 1761); + K<5>::f13 > (&b[1], &b[1935]); + check (i >= 1 && i <= 1936 && (i - 1) % 5 == 0); + return 0; +} diff --git a/gcc/testsuite/g++.dg/cilk-plus/CK/stl_iter.cc b/gcc/testsuite/g++.dg/cilk-plus/CK/stl_iter.cc new file mode 100644 index 0000000..d68ee7b --- /dev/null +++ b/gcc/testsuite/g++.dg/cilk-plus/CK/stl_iter.cc @@ -0,0 +1,50 @@ +/* { dg-do run { target { i?86-*-* x86_64-*-* } } } */ +/* { dg-options "-fcilkplus" } */ +/* { dg-options "-lcilkrts" { target { i?86-*-* x86_64-*-* } } } */ + +#include +#include +#include +#include + +using namespace std; + + +int main(void) +{ +vector array; +vector array_serial; + +for (int ii = -1; ii < 10; ii++) +{ + array.push_back(ii); + array_serial.push_back (ii); +} +_Cilk_for (vector::iterator iter = array.begin(); iter != array.end(); + iter++) +{ + if (*iter == 6) + *iter = 13; +} +for (vector::iterator iter = array_serial.begin(); + iter != array_serial.end(); iter++) +{ + if (*iter == 6) + *iter = 13; +} +sort (array.begin(), array.end()); +sort (array_serial.begin(), array_serial.end()); + +vector ::iterator iter = array.begin (); +vector ::iterator iter_serial = array_serial.begin (); + +while (iter != array.end () && iter_serial != array_serial.end ()) +{ + if (*iter != *iter_serial) + __builtin_abort (); + iter++; + iter_serial++; +} + +return 0; +} diff --git a/gcc/testsuite/g++.dg/cilk-plus/CK/stl_rev_iter.cc b/gcc/testsuite/g++.dg/cilk-plus/CK/stl_rev_iter.cc new file mode 100644 index 0000000..6eee0d9 --- /dev/null +++ b/gcc/testsuite/g++.dg/cilk-plus/CK/stl_rev_iter.cc @@ -0,0 +1,68 @@ +/* { dg-do run { target { i?86-*-* x86_64-*-* } } } */ +/* { dg-options "-fcilkplus" } */ +/* { dg-options "-lcilkrts" { target { i?86-*-* x86_64-*-* } } } */ + + +#include +#include +#include +#include + +using namespace std; + + +int main(void) +{ +vector array,array_serial; + +for (int ii = -1; ii < 10; ii++) +{ + array.push_back(ii); + array_serial.push_back(ii); +} +_Cilk_for (vector::reverse_iterator iter4 = array.rbegin(); + iter4 != array.rend(); iter4++) +{ + if (*iter4 == 0x8) { + *iter4 = 9; + } +} + +_Cilk_for (vector::reverse_iterator iter4 = array_serial.rbegin(); + iter4 != array_serial.rend(); iter4++) +{ + if (*iter4 == 0x8) { + *iter4 = 9; + } +} +_Cilk_for (vector::reverse_iterator iter2 = array.rbegin(); + iter2 != array.rend(); + iter2 += 1) +{ + if ((*iter2 == 0x4) || (*iter2 == 0x7)) { + *iter2 = 0x3; + } +} +for (vector::reverse_iterator iter2 = array_serial.rbegin(); + iter2 != array_serial.rend(); + iter2 += 1) +{ + if ((*iter2 == 0x4) || (*iter2 == 0x7)) { + *iter2 = 0x3; + } +} +sort (array.begin(), array.end()); +sort (array_serial.begin(), array_serial.end()); + +vector ::iterator iter = array.begin (); +vector ::iterator iter_serial = array_serial.begin (); +while (iter != array.end () && iter_serial != array_serial.end ()) +{ + if (*iter != *iter_serial) + __builtin_abort (); + iter++; + iter_serial++; +} + +return 0; +} diff --git a/gcc/testsuite/g++.dg/cilk-plus/CK/stl_test.cc b/gcc/testsuite/g++.dg/cilk-plus/CK/stl_test.cc new file mode 100644 index 0000000..84518f3 --- /dev/null +++ b/gcc/testsuite/g++.dg/cilk-plus/CK/stl_test.cc @@ -0,0 +1,50 @@ +/* { dg-do run { target { i?86-*-* x86_64-*-* } } } */ +/* { dg-options "-fcilkplus" } */ +/* { dg-options "-lcilkrts" { target { i?86-*-* x86_64-*-* } } } */ + + +#include +#include +#include +#include +#include +#include + +using namespace std; + + +int main(int argc, char **argv) +{ + vector number_list, number_list_serial; + int new_number = 0; + int no_elements = 0; + + if (argc != 2) + { + no_elements = 10; + } + + + number_list.clear(); + number_list_serial.clear(); + for (int ii = 0; ii < no_elements; ii++) + { + number_list.push_back(new_number); + number_list_serial.push_back(new_number); + } + + _Cilk_for (int jj = 0; jj < no_elements; jj++) + { + number_list[jj] = jj + no_elements; + } + for (int jj = 0; jj < no_elements; jj++) + { + number_list_serial[jj] = jj + no_elements; + } + + for (int jj = 0; jj < no_elements; jj++) + if (number_list_serial[jj] != number_list[jj]) + __builtin_abort (); + + return 0; +} diff --git a/gcc/tree-core.h b/gcc/tree-core.h index 9e9ca8c..0761f95 100644 --- a/gcc/tree-core.h +++ b/gcc/tree-core.h @@ -334,7 +334,11 @@ enum omp_clause_code { OMP_CLAUSE_TASKGROUP, /* Internally used only clause, holding SIMD uid. */ - OMP_CLAUSE__SIMDUID_ + OMP_CLAUSE__SIMDUID_, + + /* Internally used only clause, holding _Cilk_for # of iterations + on OMP_PARALLEL. */ + OMP_CLAUSE__CILK_FOR_COUNT_ }; #undef DEFTREESTRUCT @@ -351,6 +355,7 @@ enum omp_clause_schedule_kind { OMP_CLAUSE_SCHEDULE_GUIDED, OMP_CLAUSE_SCHEDULE_AUTO, OMP_CLAUSE_SCHEDULE_RUNTIME, + OMP_CLAUSE_SCHEDULE_CILKFOR, OMP_CLAUSE_SCHEDULE_LAST }; diff --git a/gcc/tree-nested.c b/gcc/tree-nested.c index 6ca594d..a378a02 100644 --- a/gcc/tree-nested.c +++ b/gcc/tree-nested.c @@ -1115,6 +1115,7 @@ convert_nonlocal_omp_clauses (tree *pclauses, struct walk_stmt_info *wi) case OMP_CLAUSE_NUM_TEAMS: case OMP_CLAUSE_THREAD_LIMIT: case OMP_CLAUSE_SAFELEN: + case OMP_CLAUSE__CILK_FOR_COUNT_: wi->val_only = true; wi->is_lhs = false; convert_nonlocal_reference_op (&OMP_CLAUSE_OPERAND (clause, 0), @@ -1744,6 +1745,7 @@ convert_local_omp_clauses (tree *pclauses, struct walk_stmt_info *wi) case OMP_CLAUSE_NUM_TEAMS: case OMP_CLAUSE_THREAD_LIMIT: case OMP_CLAUSE_SAFELEN: + case OMP_CLAUSE__CILK_FOR_COUNT_: wi->val_only = true; wi->is_lhs = false; convert_local_reference_op (&OMP_CLAUSE_OPERAND (clause, 0), &dummy, diff --git a/gcc/tree-pretty-print.c b/gcc/tree-pretty-print.c index aee0331..ce0c655 100644 --- a/gcc/tree-pretty-print.c +++ b/gcc/tree-pretty-print.c @@ -361,6 +361,13 @@ dump_omp_clause (pretty_printer *buffer, tree clause, int spc, int flags) pp_right_paren (buffer); break; + case OMP_CLAUSE__CILK_FOR_COUNT_: + pp_string (buffer, "_Cilk_for_count_("); + dump_generic_node (buffer, OMP_CLAUSE_OPERAND (clause, 0), + spc, flags, false); + pp_right_paren (buffer); + break; + case OMP_CLAUSE_NOWAIT: pp_string (buffer, "nowait"); break; @@ -411,6 +418,9 @@ dump_omp_clause (pretty_printer *buffer, tree clause, int spc, int flags) case OMP_CLAUSE_SCHEDULE_AUTO: pp_string (buffer, "auto"); break; + case OMP_CLAUSE_SCHEDULE_CILKFOR: + pp_string (buffer, "cilk-for grain"); + break; default: gcc_unreachable (); } @@ -2421,6 +2431,12 @@ dump_generic_node (pretty_printer *buffer, tree node, int spc, int flags, pp_string (buffer, "#pragma simd"); goto dump_omp_loop; + case CILK_FOR: + /* This label points one line after dumping the clauses. + For _Cilk_for the clauses are dumped after the _Cilk_for (...) + parameters are printed out. */ + goto dump_omp_loop_cilk_for; + case OMP_DISTRIBUTE: pp_string (buffer, "#pragma omp distribute"); goto dump_omp_loop; @@ -2449,18 +2465,22 @@ dump_generic_node (pretty_printer *buffer, tree node, int spc, int flags, dump_omp_loop: dump_omp_clauses (buffer, OMP_FOR_CLAUSES (node), spc, flags); + dump_omp_loop_cilk_for: if (!(flags & TDF_SLIM)) { int i; if (OMP_FOR_PRE_BODY (node)) { - newline_and_indent (buffer, spc + 2); + if (TREE_CODE (node) == CILK_FOR) + pp_string (buffer, " "); + else + newline_and_indent (buffer, spc + 2); pp_left_brace (buffer); spc += 4; newline_and_indent (buffer, spc); dump_generic_node (buffer, OMP_FOR_PRE_BODY (node), - spc, flags, false); + spc, flags, false); } if (OMP_FOR_INIT (node)) { @@ -2468,8 +2488,12 @@ dump_generic_node (pretty_printer *buffer, tree node, int spc, int flags, for (i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (node)); i++) { spc += 2; - newline_and_indent (buffer, spc); - pp_string (buffer, "for ("); + if (TREE_CODE (node) != CILK_FOR || OMP_FOR_PRE_BODY (node)) + newline_and_indent (buffer, spc); + if (TREE_CODE (node) == CILK_FOR) + pp_string (buffer, "_Cilk_for ("); + else + pp_string (buffer, "for ("); dump_generic_node (buffer, TREE_VEC_ELT (OMP_FOR_INIT (node), i), spc, flags, false); @@ -2483,6 +2507,8 @@ dump_generic_node (pretty_printer *buffer, tree node, int spc, int flags, spc, flags, false); pp_right_paren (buffer); } + if (TREE_CODE (node) == CILK_FOR) + dump_omp_clauses (buffer, OMP_FOR_CLAUSES (node), spc, flags); } if (OMP_FOR_BODY (node)) { diff --git a/gcc/tree.c b/gcc/tree.c index 33922a0..d1d67ef 100644 --- a/gcc/tree.c +++ b/gcc/tree.c @@ -281,6 +281,7 @@ unsigned const char omp_clause_num_ops[] = 0, /* OMP_CLAUSE_SECTIONS */ 0, /* OMP_CLAUSE_TASKGROUP */ 1, /* OMP_CLAUSE__SIMDUID_ */ + 1, /* OMP_CLAUSE__CILK_FOR_COUNT_ */ }; const char * const omp_clause_code_name[] = @@ -324,7 +325,8 @@ const char * const omp_clause_code_name[] = "parallel", "sections", "taskgroup", - "_simduid_" + "_simduid_", + "_Cilk_for_count_" }; @@ -11041,6 +11043,7 @@ walk_tree_1 (tree *tp, walk_tree_fn func, void *data, case OMP_CLAUSE_SIMDLEN: case OMP_CLAUSE__LOOPTEMP_: case OMP_CLAUSE__SIMDUID_: + case OMP_CLAUSE__CILK_FOR_COUNT_: WALK_SUBTREE (OMP_CLAUSE_OPERAND (*tp, 0)); /* FALLTHRU */ diff --git a/gcc/tree.def b/gcc/tree.def index 84ffe93..bd39e4b 100644 --- a/gcc/tree.def +++ b/gcc/tree.def @@ -1064,6 +1064,10 @@ DEFTREECODE (OMP_SIMD, "omp_simd", tcc_statement, 6) Operands like for OMP_FOR. */ DEFTREECODE (CILK_SIMD, "cilk_simd", tcc_statement, 6) +/* Cilk Plus - _Cilk_for (..) + Operands like for OMP_FOR. */ +DEFTREECODE (CILK_FOR, "cilk_for", tcc_statement, 6) + /* OpenMP - #pragma omp distribute [clause1 ... clauseN] Operands like for OMP_FOR. */ DEFTREECODE (OMP_DISTRIBUTE, "omp_distribute", tcc_statement, 6)