From patchwork Mon Jun 17 18:29:23 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Iyer, Balaji V" X-Patchwork-Id: 252033 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 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client CN "localhost", Issuer "www.qmailtoaster.com" (not verified)) by ozlabs.org (Postfix) with ESMTPS id BF5DD2C00B1 for ; Tue, 18 Jun 2013 04:29:54 +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:references:in-reply-to :content-type:mime-version; q=dns; s=default; b=HGpFKjFrGr1qTaIt rU8T/698bI/K+Zz1efT8CqT1UR0T1HPaXHf9uWNTIm3C/veek+L+LA0HBvhAncTJ AOzB62tD96lPELjUeFujLUuzYPoTQQSffnqmFesivV4Mi4MGyGf4JVDYPO4SONFW b40srQoz9w6ApfVua+WevBXkZX0= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :to:cc:subject:date:message-id:references:in-reply-to :content-type:mime-version; s=default; bh=kveb0uMUh+QeovjJsfbgCs m8tLM=; b=vl11qjCa3VF29+fXOXRCP/uSAjRPuh8VvpoPSXrCPwL0MjRUXpgX4E T73senY/b2i8FownjwY1NQNYzrKvjVHsXH0QzUytGjYTZ383jiklWuqVOPWR27i0 tLa1u3SNFMhcsRqUsPQVIT2hAu233TVYwsJIXdwGacrgTxBLLgg2g= Received: (qmail 9760 invoked by alias); 17 Jun 2013 18:29:45 -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 9749 invoked by uid 89); 17 Jun 2013 18:29:44 -0000 X-Spam-SWARE-Status: No, score=-6.3 required=5.0 tests=AWL, BAYES_00, KHOP_THREADED, RCVD_IN_HOSTKARMA_W, RCVD_IN_HOSTKARMA_WL, RP_MATCHES_RCVD, SPF_PASS, TW_BJ, TW_JC, TW_TM autolearn=ham version=3.3.1 Received: from mga03.intel.com (HELO mga03.intel.com) (143.182.124.21) by sourceware.org (qpsmtpd/0.84/v0.84-167-ge50287c) with ESMTP; Mon, 17 Jun 2013 18:29:37 +0000 Received: from azsmga001.ch.intel.com ([10.2.17.19]) by azsmga101.ch.intel.com with ESMTP; 17 Jun 2013 11:29:30 -0700 X-ExtLoop1: 1 Received: from fmsmsx103.amr.corp.intel.com ([10.19.9.34]) by azsmga001.ch.intel.com with ESMTP; 17 Jun 2013 11:29:28 -0700 Received: from fmsmsx113.amr.corp.intel.com (10.18.116.7) by FMSMSX103.amr.corp.intel.com (10.19.9.34) with Microsoft SMTP Server (TLS) id 14.3.123.3; Mon, 17 Jun 2013 11:29:28 -0700 Received: from fmsmsx101.amr.corp.intel.com ([169.254.1.114]) by FMSMSX113.amr.corp.intel.com ([169.254.4.208]) with mapi id 14.03.0123.003; Mon, 17 Jun 2013 11:29:27 -0700 From: "Iyer, Balaji V" To: Richard Henderson CC: Aldy Hernandez , "gcc-patches@gcc.gnu.org" , "Jason Merrill (jason@redhat.com)" Subject: RE: [PATCH] Cilk Plus Array Notation for C++ Date: Mon, 17 Jun 2013 18:29:23 +0000 Message-ID: References: <51B8A2FA.2020404@redhat.com> <51B9EF1D.9060505@redhat.com> <51B9F0EA.50709@redhat.com> <51BF4222.3050107@redhat.com> In-Reply-To: <51BF4222.3050107@redhat.com> MIME-Version: 1.0 > > In hindsight, I could have for __sec_reduce_max and __sec_reduce_min. > > I was more familiar with conditional expression. Out of curiosity, is > > there a big performance benefit of using max/min expr over conditional? > > There can be. The COND->MIN/MAX transformation is not done without the - > ffinite-math-only component of -ffast-math. I.e. we don't try the transform > when NaNs are a possibility. > > So, yes, you probably should generate MIN/MAX_EXPR right from the start. Hi Richard et al., Here is a fixed patch using MIN_EXPR and MAX_EXPR instead of conditionals. Here are the ChangeLog entries (there should be no changes from the previous thread). Is this OK for trunk? gcc/cp/ChangeLog 2013-06-17 Balaji V. Iyer * call.c (convert_like_real): Added a check if array notation is present in expression. If so, then no conversion of arguments is necessary. (build_over_call): Likewise. * typeck.c (cp_build_function_call_vec): Likewise. (convert_for_assignment): Likewise. (cp_build_array_ref): Reject array notations with a rank greater than 1 as an array's index. (cp_build_binary_op): If array notations are preent in op, then call find_correct_array_notation_type. (cp_build_addr_expr_1): Handle ARRAY_NOTATION_REF similar to ARRAY_REF. * cp-array-notation.c: New file. * cp-objcp-common.c (cp_common_init_ts): Marked ARRAY_NOTATION_REF tree as typed. * cp-tree.h (fix_array_notation_exprs): New prototype. * semantics.c (finish_return_stmt): Reject array notations as return value. (cxx_eval_constant_expression): Added ARRAY_NOTATION_REF case. (potential_constant_expression_1): Likewise. * tree.c (lvalue_kind): Likewise. * error.c (dump_decl): Likewise. (dump_expr): Likewise. * pt.c (ARRAY_NOTATION_REF): Likewise. (type_unification_real): Do not unify any arguments if array notations are found in arg. (instantiate_decl): Added a check for array notaitons inside the function body. If so, then expand them. * parser.c (cp_parser_array_notation): New function. (cp_parser_postfix_open_square_expression): Added a check for colons inside square braces. If found, then handle the array access as an array notation access. Also, disable auto-correction from a single colon to scope when Cilk Plus is enabled. (cp_parser_compound_statement): Added a check for array notations inside the statement. If found, then expand them. (cp_parser_ctor_initializer_opt_and_function_body): Likewise. (cp_parser_function_definition_after_declarator): Likewise. (cp_parser_selection_statement): Searched for array notations inside condition. If so, then emit an error. (cp_parser_iteration_statement): Likewise. (cp_parser_direct_declarator): Reject array notations inside a variable or array declaration. * Make-lang.in (CXX_AND_OBJCXX_OBJS): Added cp/cp-array-notation.o. gcc/testsuite/ChangeLog 2013-06-17 Balaji V. Iyer * c-c++-common/cilk-plus/AN/if_test_errors.c (main): Made certain errors specific to C, if necessary. Also added new error hooks for C++. * c-c++-common/cilk-plus/AN/misc.c (main): Likewise. * c-c++-common/cilk-plus/AN/parser_errors.c (main): Likewise. * c-c++-common/cilk-plus/AN/parser_errors2.c (main): Likewise. * c-c++-common/cilk-plus/AN/parser_errors3.c (main): Likewise. * c-c++-common/cilk-plus/AN/pr57541.c (main): Likewise. * c-c++-common/cilk-plus/AN/parser_errors4.c (main): In addition to the same changes as parser_errors3.c, spaces were added between colons to not confuse C++ parser with 2 colons as scope. * c-c++-common/cilk-plus/AN/vla.c: Make this test C specific. * g++.dg/cilk-plus/AN/array_test1_tplt.cc: New test. * g++.dg/cilk-plus/AN/array_test2_tplt.cc: Likewise. * g++.dg/cilk-plus/AN/array_test_ND_tplt.cc: Likewise. * g++.dg/cilk-plus/AN/braced_list.cc: Likewise. * g++.dg/cilk-plus/AN/builtin_fn_custom_tplt.cc: Likewise. * g++.dg/cilk-plus/AN/builtin_fn_mutating_tplt.cc: Likewise. * g++.dg/cilk-plus/AN/fp_triplet_values_tplt.c: Likewise. * g++.dg/cilk-plus/AN/preincr_test.cc: Likewise. * g++.dg/cilk-plus/AN/postincr_test.cc: Likewise. * g++.dg/cilk-plus/cilk-plus.exp: New script. * gcc/testsuite/g++.dg/dg.exp: Included Cilk Plus C++ tests in the list. Thanks, Balaji V. Iyer. > > > r~ diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog old mode 100644 new mode 100755 index 1b58ba0..0b11a75 Binary files a/gcc/cp/ChangeLog and b/gcc/cp/ChangeLog differ diff --git a/gcc/cp/Make-lang.in b/gcc/cp/Make-lang.in index df8ed3e..6e80bcf 100644 --- a/gcc/cp/Make-lang.in +++ b/gcc/cp/Make-lang.in @@ -80,7 +80,7 @@ CXX_AND_OBJCXX_OBJS = cp/call.o cp/decl.o cp/expr.o cp/pt.o cp/typeck2.o \ cp/typeck.o cp/cvt.o cp/except.o cp/friend.o cp/init.o cp/method.o \ cp/search.o cp/semantics.o cp/tree.o cp/repo.o cp/dump.o cp/optimize.o \ cp/mangle.o cp/cp-objcp-common.o cp/name-lookup.o cp/cxx-pretty-print.o \ - cp/cp-gimplify.o $(CXX_C_OBJS) + cp/cp-gimplify.o cp/cp-array-notation.o $(CXX_C_OBJS) # Language-specific object files for C++. CXX_OBJS = cp/cp-lang.o c-family/stub-objc.o $(CXX_AND_OBJCXX_OBJS) @@ -266,6 +266,9 @@ CXX_PRETTY_PRINT_H = cp/cxx-pretty-print.h $(C_PRETTY_PRINT_H) cp/lex.o: cp/lex.c $(CXX_TREE_H) $(TM_H) $(FLAGS_H) \ $(C_PRAGMA_H) input.h cp/operators.def $(TM_P_H) \ c-family/c-objc.h +cp/cp-array-notation.o: cp/cp-array-notation.c $(CONFIG_H) $(SYSTEM_H) \ + coretypes.h $(TREE_H) $(CXX_TREE_H) $(DIAGNOSTIC_H) tree-iterator.h vec.h \ + $(GIMPLE_H) c-family/array-notation-common.o $(C_COMMON_H) cp/cp-lang.o: cp/cp-lang.c $(CXX_TREE_H) $(TM_H) debug.h langhooks.h \ $(LANGHOOKS_DEF_H) $(C_COMMON_H) gtype-cp.h gt-cp-cp-lang.h \ cp/cp-objcp-common.h $(EXPR_H) $(TARGET_H) $(CXX_PARSER_H) diff --git a/gcc/cp/call.c b/gcc/cp/call.c index dfd061a..64be41f 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -5858,9 +5858,15 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum, break; } - if (permerror (loc, "invalid conversion from %qT to %qT", - TREE_TYPE (expr), totype) - && fn) + if (flag_enable_cilkplus + && (contains_array_notation_expr (expr) + || contains_array_notation_expr (fn))) + /* If we are using array notations, we fix them up at a later stage + and we will do these checks then. */ + ; + else if (permerror (loc, "invalid conversion from %qT to %qT", + TREE_TYPE (expr), totype) + && fn) inform (DECL_SOURCE_LOCATION (fn), "initializing argument %P of %qD", argnum, fn); @@ -6890,12 +6896,20 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain) } } - val = convert_like_with_context (conv, arg, fn, i-is_method, - conversion_warning - ? complain - : complain & (~tf_warning)); + /* If the function call is builtin array notation function then no need + to do any type conversion. */ + if (flag_enable_cilkplus + && is_cilkplus_reduce_builtin (fn) != BUILT_IN_NONE) + val = arg; + else + { + val = convert_like_with_context (conv, arg, fn, i-is_method, + conversion_warning + ? complain + : complain & (~tf_warning)); - val = convert_for_arg_passing (type, val, complain); + val = convert_for_arg_passing (type, val, complain); + } if (val == error_mark_node) return error_mark_node; else diff --git a/gcc/cp/cp-array-notation.c b/gcc/cp/cp-array-notation.c new file mode 100755 index 0000000..da701e7 --- /dev/null +++ b/gcc/cp/cp-array-notation.c @@ -0,0 +1,1740 @@ +/* This file is part of the Intel(R) Cilk(TM) Plus support + It contains routines to handle Array Notation expression + handling routines in the C++ Compiler. + Copyright (C) 2013 Free Software Foundation, Inc. + Contributed by Balaji V. Iyer , + Intel Corporation + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GCC; see the file COPYING3. If not see + . */ + +/* The Array Notation Transformation Technique: + + An array notation expression has 4 major components: + 1. The array name + 2. Start Index + 3. Number of elements we need to acess (we call it length) + 4. Stride + + So, if we have something like A[0:5:2], we are accessing A[0], A[2], A[4], + A[6] and A[8]. The user is responsible to make sure the access length does + not step outside the array's size. + + In this section, I highlight the overall method on how array notations are + broken up into C/C++ code. Almost all the functions follows this step: + + Let's say the user has used the array notation in a statement like this: + + A[St1:Ln:Str1] = B[St2:Ln:Str2] + + + where St{1,2} = Starting index, Ln = Number of elements we need to access, + and Str{1,2} = the stride. + Note: The length of both the array notation expressions must be the same. + + The above expression is broken into the following: + + for (Tmp_Var = 0; Tmp_Var < Ln; Tmp_Var++) + A[St1 + Tmp_Var * Str1] = B[St1 + Tmp_Var * Str2] + ; +*/ + +#include "config.h" +#include "system.h" +#include "coretypes.h" +#include "tree.h" +#include "cp-tree.h" +#include "c-family/c-common.h" +#include "diagnostic.h" +#include "tree-iterator.h" +#include "vec.h" +#include "gimple.h" + +/* Creates a FOR_STMT with INIT, COND, INCR and BODY as the initializer, + condition, increment expression and the loop-body, respectively. */ + +static void +create_an_loop (tree init, tree cond, tree incr, tree body) +{ + tree for_stmt; + + finish_expr_stmt (init); + for_stmt = begin_for_stmt (NULL_TREE, NULL_TREE); + finish_for_init_stmt (for_stmt); + finish_for_cond (cond, for_stmt); + finish_for_expr (incr, for_stmt); + finish_expr_stmt (body); + finish_for_stmt (for_stmt); +} + +/* Returns true if there is a length mismatch among exprssions that are at the + same dimension and one the same side of the equal sign. The Array notation + lengths (LIST) is passed in as a 2D vector of trees. */ + +static bool +cp_length_mismatch_in_expr_p (location_t loc, vec >list) +{ + size_t ii, jj; + tree start = NULL_TREE; + HOST_WIDE_INT l_start, l_node; + + size_t x = list.length (); + size_t y = list[0].length (); + + for (jj = 0; jj < y; jj++) + { + start = NULL_TREE; + for (ii = 0; ii < x; ii++) + { + if (!start) + start = list[ii][jj]; + else if (TREE_CODE (start) == INTEGER_CST) + { + /* If start is a INTEGER, and list[ii][jj] is an integer then + check if they are equal. If they are not equal then return + true. */ + if (TREE_CODE (list[ii][jj]) == INTEGER_CST) + { + l_node = int_cst_value (list[ii][jj]); + l_start = int_cst_value (start); + if (absu_hwi (l_start) != absu_hwi (l_node)) + { + error_at (loc, "length mismatch in expression"); + return true; + } + } + } + else + /* We set the start node as the current node just in case it turns + out to be an integer. */ + start = list[ii][jj]; + } + } + return false; +} + +/* If *VALUE is not a constant integer, then this function replaces it with + a variable to make it loop invariant for array notations. */ + +static inline void +make_triplet_val_inv (location_t loc, tree *value, tsubst_flags_t cry) +{ + tree var; + if (TREE_CODE (*value) != INTEGER_CST + && TREE_CODE (*value) != PARM_DECL + && TREE_CODE (*value) != VAR_DECL) + { + var = build_decl (loc, VAR_DECL, NULL_TREE, integer_type_node); + finish_expr_stmt (build_x_modify_expr (loc, var, NOP_EXPR, *value, cry)); + *value = var; + } +} + +/* Extracts all the array notation triplet information from LIST and stores them + in a 2-D arrays (size x rank) of START, LENGTH and STRIDE, holding the + starting index, length, and stride, respectively. In addition, it also + sets two bool arrays IS_VECTOR and COUNT_DOWN indicating whether a certain + value at a certain field is a vector or not. */ + +static inline void +extract_an_triplets (vec *list, vec > *value, + vec > *start, vec > *length, + vec > *stride, vec > *is_vector, + vec > *count_down, size_t size, size_t rank) +{ + vec > array_exprs = vNULL; + + start->safe_grow_cleared (size); + length->safe_grow_cleared (size); + stride->safe_grow_cleared (size); + value->safe_grow_cleared (size); + array_exprs.safe_grow_cleared (size); + is_vector->safe_grow_cleared (size); + count_down->safe_grow_cleared (size); + + for (size_t ii = 0; ii < size; ii++) + for (size_t jj = 0; jj < rank; jj++) + { + array_exprs[ii].safe_push (NULL_TREE); + (*start)[ii].safe_push (NULL_TREE); + (*value)[ii].safe_push (NULL_TREE); + (*length)[ii].safe_push (NULL_TREE); + (*stride)[ii].safe_push (NULL_TREE); + (*is_vector)[ii].safe_push (false); + (*count_down)[ii].safe_push (false); + } + for (size_t ii = 0; ii < size; ii++) + { + size_t jj = 0; + tree ii_tree = (*list)[ii]; + while (ii_tree) + { + if (TREE_CODE (ii_tree) == ARRAY_NOTATION_REF) + { + array_exprs[ii][jj] = ii_tree; + jj++; + ii_tree = ARRAY_NOTATION_ARRAY (ii_tree); + } + else if (TREE_CODE (ii_tree) == ARRAY_REF) + ii_tree = TREE_OPERAND (ii_tree, 0); + else if (TREE_CODE (ii_tree) == VAR_DECL + || TREE_CODE (ii_tree) == CALL_EXPR + || TREE_CODE (ii_tree) == PARM_DECL) + break; + else + gcc_unreachable (); + } + } + for (size_t ii = 0; ii < size; ii++) + if (TREE_CODE ((*list)[ii]) == ARRAY_NOTATION_REF) + for (size_t jj = 0; jj < rank; jj++) + if (TREE_CODE (array_exprs[ii][jj]) == ARRAY_NOTATION_REF) + { + tree ii_tree = array_exprs[ii][jj]; + (*is_vector)[ii][jj] = true; + (*value)[ii][jj] = ARRAY_NOTATION_ARRAY (ii_tree); + (*start)[ii][jj] = ARRAY_NOTATION_START (ii_tree); + (*length)[ii][jj] = fold_build1 (CONVERT_EXPR, integer_type_node, + ARRAY_NOTATION_LENGTH (ii_tree)); + (*stride)[ii][jj] = fold_build1 (CONVERT_EXPR, integer_type_node, + ARRAY_NOTATION_STRIDE (ii_tree)); + } +} + +/* Returns a vector of size RANK that contains an array ref that is derived from + array notation triplet parameters stored in VALUE, START, STRIDE. IS_VECTOR + is used to check if the data stored at its corresponding location is an + array notation. VAR is the induction variable passed in by the caller. + + For example: For an array notation A[5:10:2], the vector start will be + of size 1 holding '5', stride of same size as start but holding the value of + as 2, is_vector as true and count_down as false. Let's assume VAR is 'x' + This function returns a vector of size 1 with the following data: + A[5 + (x * 2)] . +*/ + +static vec * +create_array_refs (location_t loc, vec > value, + vec > start, vec > stride, + vec > is_vector, vec var, + vec > count_down, size_t size, size_t rank) +{ + enum tree_code code = PLUS_EXPR; + tree ind_mult, ind_incr; + vec *array_operand = NULL; + for (size_t ii = 0; ii < size; ii++) + if (is_vector[ii][0]) + { + tree array_opr = value[ii][rank-1]; + for (int s_jj = rank -1; s_jj >= 0; s_jj--) + { + tree str = NULL_TREE, v = NULL_TREE, st = NULL_TREE; + + /* If stride and start are of same type and the induction var + is not, convert induction variable to stride's type. */ + if (TREE_TYPE (start[ii][s_jj]) == TREE_TYPE (stride[ii][s_jj]) + && TREE_TYPE (stride[ii][s_jj]) != TREE_TYPE (var[s_jj])) + { + st = start[ii][s_jj]; + str = stride[ii][s_jj]; + v = build_c_cast (loc, TREE_TYPE (str), var[s_jj]); + } + else if (TREE_TYPE (start[ii][s_jj]) != TREE_TYPE (stride[ii][s_jj])) + { + /* If we reach here, then the stride and start are of + different types, and so it doesn't really matter what + the induction variable type is, convert everything to + integer. The reason why we pick an integer + instead of something like size_t is because the stride + and length can be + or -. */ + st = build_c_cast (loc, integer_type_node, start[ii][s_jj]); + str = build_c_cast (loc, integer_type_node, stride[ii][s_jj]); + v = build_c_cast (loc, integer_type_node, var[s_jj]); + } + else + { + st = start[ii][s_jj]; + str = stride[ii][s_jj]; + v = var[s_jj]; + } + + if (count_down[ii][s_jj]) + code = MINUS_EXPR; + else + code = PLUS_EXPR; + + ind_mult = build2 (MULT_EXPR, TREE_TYPE (v), v, str); + ind_incr = build2 (code, TREE_TYPE (v), st, ind_mult); + /* Array [ start_index + (induction_var * stride)] */ + array_opr = grok_array_decl (loc, array_opr, ind_incr, false); + } + vec_safe_push (array_operand, array_opr); + } + else + vec_safe_push (array_operand, integer_one_node); + return array_operand; +} + +/* Populates the INCR and CMP vectors with the increment (of type POSTINCREMENT + or POSTDECREMENT) and comparison (of TYPE GT_EXPR or LT_EXPR) expressions, + using data from LENGTH, COUNT_DOWN, and VAR. INCR and CMP vectors are of + size RANK. */ + +static void +create_cmp_and_incr (location_t loc, vec var, vec > length, + vec *incr, vec *cmp, + vec > count_down, size_t rank, + tsubst_flags_t complain) +{ + enum tree_code incr_code, comp_code; + cmp->safe_grow_cleared (rank); + incr->safe_grow_cleared (rank); + for (size_t ii = 0; ii < rank; ii++) + { + if (count_down[0][ii]) + { + incr_code = POSTDECREMENT_EXPR; + comp_code = GT_EXPR; + } + else + { + incr_code = POSTINCREMENT_EXPR; + comp_code = LT_EXPR; + } + (*incr)[ii] = build_x_unary_op (loc, incr_code, var[ii], complain); + (*cmp)[ii] = build_x_binary_op (loc, comp_code, var[ii], + TREE_CODE (var[ii]), length[0][ii], + TREE_CODE (length[0][ii]), NULL, complain); + } +} + +/* Replaces all the __sec_implicit_arg functions in LIST with the induction + variable stored in VAR at the appropriate location pointed by the + __sec_implicit_arg's first parameter. Emits an error if the parameter is not + between 0 and RANK. */ + +vec * +fix_sec_implicit_args (location_t loc, vec *list, vec var, + size_t rank, tree orig_stmt) +{ + vec *array_operand = NULL; + for (size_t ii = 0; ii < vec_safe_length (list); ii++) + if (TREE_CODE ((*list)[ii]) == CALL_EXPR + && TREE_CODE (CALL_EXPR_FN ((*list)[ii])) == ADDR_EXPR + && is_sec_implicit_index_fn (CALL_EXPR_FN ((*list)[ii]))) + { + int idx = extract_sec_implicit_index_arg (loc, (*list)[ii]); + if (idx < (int) rank && idx >= 0) + vec_safe_push (array_operand, var[idx]); + else if (idx == -1) + /* In this case, the returning function would have emitted an + error thus it is not necessary to do so again. */ + return NULL; + else + { + error_at (loc, "__sec_implicit_index argument %d must be " + "less than the rank of %qE", idx, orig_stmt); + return NULL; + } + } + else + /* Save the existing value into the array operand. */ + vec_safe_push (array_operand, (*list)[ii]); + return array_operand; +} + +/* Clear (i.e. deallocate) all the temporary vectors required to expand + array notation expressions. */ + +static inline void +clear_all_an_vectors (vec > *value, vec > *start, + vec > *length, vec > *stride, + vec > *is_vector, vec > *count_down, + vec *incr, vec *cmp, vec *ind_init, + vec *var) +{ + value->release (); + start->release (); + length->release (); + stride->release (); + is_vector->release (); + count_down->release (); + incr->release (); + cmp->release (); + ind_init->release (); + var->release (); +} + +/* Replaces all the scalar expressions in *NODE. Returns a STATEMENT LIST that + holds the NODE along with the variables that hold the results of the + invariant expressions. */ + +static tree +replace_invariant_exprs (tree *node) +{ + size_t ix = 0; + tree node_list = NULL_TREE; + tree t = NULL_TREE, new_var = NULL_TREE, new_node; + struct inv_list data; + + data.list_values = NULL; + data.replacement = NULL; + data.additional_tcodes = NULL; + cp_walk_tree (node, find_inv_trees, (void *) &data, NULL); + + if (vec_safe_length (data.list_values)) + { + node_list = push_stmt_list (); + for (ix = 0; vec_safe_iterate (data.list_values, ix, &t); ix++) + { + if (processing_template_decl || !TREE_TYPE (t)) + new_var = build_min_nt_loc (EXPR_LOCATION (t), VAR_DECL, NULL_TREE, + NULL_TREE); + else + new_var = build_decl (EXPR_LOCATION (t), VAR_DECL, NULL_TREE, + TREE_TYPE (t)); + gcc_assert (new_var != NULL_TREE && new_var != error_mark_node); + new_node = build_x_modify_expr (EXPR_LOCATION (t), new_var, NOP_EXPR, + t, tf_warning_or_error); + finish_expr_stmt (new_node); + vec_safe_push (data.replacement, new_var); + } + cp_walk_tree (node, replace_inv_trees, (void *) &data, NULL); + node_list = pop_stmt_list (node_list); + } + return node_list; +} + +/* Replace array notation's built-in function passed in AN_BUILTIN_FN with + the appropriate loop and computation (all stored in variable LOOP of type + tree node). The output of the function function is always a scalar and that + result is returned in *NEW_VAR. *NEW_VAR is NULL_TREE if the function is + __sec_reduce_mutating. */ + +static tree +expand_sec_reduce_builtin (tree an_builtin_fn, tree *new_var) +{ + tree new_var_type = NULL_TREE, func_parm, new_yes_expr, new_no_expr; + tree array_ind_value = NULL_TREE, new_no_ind, new_yes_ind, new_no_list; + tree new_yes_list, new_cond_expr, new_expr = NULL_TREE; + tree new_var_init = NULL_TREE, new_exp_init = NULL_TREE; + vec *array_list = NULL, *array_operand = NULL; + size_t list_size = 0, rank = 0, ii = 0; + vec array_var = vNULL, expr_incr = vNULL, compare_expr = vNULL; + vec ind_init = vNULL; + vec > array_value = vNULL, array_stride = vNULL, + array_length = vNULL, array_start = vNULL; + tree body, an_init, loop_with_init = alloc_stmt_list (); + tree array_op0, comp_node = NULL_TREE; + tree call_fn = NULL_TREE, identity_value = NULL_TREE; + vec > count_down = vNULL, array_vector = vNULL; + tree init = NULL_TREE, cond_init = NULL_TREE; + enum tree_code code = NOP_EXPR; + location_t location = UNKNOWN_LOCATION; + + enum built_in_function an_type = + is_cilkplus_reduce_builtin (CALL_EXPR_FN (an_builtin_fn)); + + if (an_type == BUILT_IN_NONE) + return NULL_TREE; + + if (an_type != BUILT_IN_CILKPLUS_SEC_REDUCE + && an_type != BUILT_IN_CILKPLUS_SEC_REDUCE_MUTATING) + func_parm = CALL_EXPR_ARG (an_builtin_fn, 0); + else + { + call_fn = CALL_EXPR_ARG (an_builtin_fn, 2); + + /* We need to do this because we are "faking" the builtin function types, + so the compiler does a bunch of typecasts and this will get rid of + all that! */ + while (TREE_CODE (call_fn) == CONVERT_EXPR + || TREE_CODE (call_fn) == NOP_EXPR) + call_fn = TREE_OPERAND (call_fn, 0); + + if (TREE_CODE (call_fn) != OVERLOAD + && TREE_CODE (call_fn) != FUNCTION_DECL) + call_fn = TREE_OPERAND (call_fn, 0); + identity_value = CALL_EXPR_ARG (an_builtin_fn, 0); + func_parm = CALL_EXPR_ARG (an_builtin_fn, 1); + + /* We need to do this because we are "faking" the builtin function types + so the compiler does a bunch of typecasts and this will get rid of + all that! */ + while (TREE_CODE (identity_value) == CONVERT_EXPR + || TREE_CODE (identity_value) == NOP_EXPR) + identity_value = TREE_OPERAND (identity_value, 0); + } + while (TREE_CODE (func_parm) == CONVERT_EXPR + || TREE_CODE (func_parm) == NOP_EXPR) + func_parm = TREE_OPERAND (func_parm, 0); + + location = EXPR_LOCATION (an_builtin_fn); + + /* Note about using find_rank (): If find_rank returns false, then it must + have already reported an error, thus we just return an error_mark_node + without any doing any error emission. */ + if (!find_rank (location, an_builtin_fn, an_builtin_fn, true, &rank)) + return error_mark_node; + if (rank == 0) + return an_builtin_fn; + else if (rank > 1 + && (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND + || an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MIN_IND)) + { + error_at (location, "__sec_reduce_min_ind or __sec_reduce_max_ind cannot " + "have arrays with dimension greater than 1"); + return error_mark_node; + } + + extract_array_notation_exprs (func_parm, true, &array_list); + list_size = vec_safe_length (array_list); + switch (an_type) + { + case BUILT_IN_CILKPLUS_SEC_REDUCE_ADD: + case BUILT_IN_CILKPLUS_SEC_REDUCE_MUL: + case BUILT_IN_CILKPLUS_SEC_REDUCE_MAX: + case BUILT_IN_CILKPLUS_SEC_REDUCE_MIN: + new_var_type = TREE_TYPE ((*array_list)[0]); + break; + case BUILT_IN_CILKPLUS_SEC_REDUCE_ALL_ZERO: + case BUILT_IN_CILKPLUS_SEC_REDUCE_ANY_ZERO: + case BUILT_IN_CILKPLUS_SEC_REDUCE_ANY_NONZERO: + case BUILT_IN_CILKPLUS_SEC_REDUCE_ALL_NONZERO: + new_var_type = integer_type_node; + break; + case BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND: + case BUILT_IN_CILKPLUS_SEC_REDUCE_MIN_IND: + new_var_type = size_type_node; + break; + case BUILT_IN_CILKPLUS_SEC_REDUCE: + if (call_fn && identity_value) + new_var_type = TREE_TYPE ((*array_list)[0]); + break; + case BUILT_IN_CILKPLUS_SEC_REDUCE_MUTATING: + new_var_type = NULL_TREE; + break; + default: + gcc_unreachable (); + } + + if (new_var_type && TREE_CODE (new_var_type) == ARRAY_TYPE) + new_var_type = TREE_TYPE (new_var_type); + + ind_init.safe_grow_cleared (rank); + array_var.safe_grow_cleared (rank); + an_init = push_stmt_list (); + + /* Assign the array notation components to variable so that they can satisfy + the exec-once rule. */ + for (ii = 0; ii < list_size; ii++) + if (TREE_CODE ((*array_list)[ii]) == ARRAY_NOTATION_REF) + { + tree anode = (*array_list)[ii]; + make_triplet_val_inv (location, &ARRAY_NOTATION_START (anode), + tf_warning_or_error); + make_triplet_val_inv (location, &ARRAY_NOTATION_LENGTH (anode), + tf_warning_or_error); + make_triplet_val_inv (location, &ARRAY_NOTATION_STRIDE (anode), + tf_warning_or_error); + } + + extract_an_triplets (array_list, &array_value, &array_start, &array_length, + &array_stride, &array_vector, &count_down, list_size, + rank); + for (ii = 0; ii < rank; ii++) + { + array_var[ii] = build_decl (location, VAR_DECL, NULL_TREE, + TREE_TYPE (array_start[0][ii])); + ind_init[ii] = build_x_modify_expr + (location, array_var[ii], NOP_EXPR, + build_zero_cst (TREE_TYPE (array_var[ii])), tf_warning_or_error); + } + array_operand = create_array_refs (location, array_value, array_start, + array_stride, array_vector, array_var, + count_down, list_size, rank); + replace_array_notations (&func_parm, true, array_list, array_operand); + + if (!TREE_TYPE (func_parm)) + TREE_TYPE (func_parm) = TREE_TYPE ((*array_list)[0]); + + create_cmp_and_incr (location, array_var, array_length, &expr_incr, + &compare_expr, count_down, rank, tf_warning_or_error); + if (an_type != BUILT_IN_CILKPLUS_SEC_REDUCE_MUTATING) + { + if (processing_template_decl) + *new_var = build_decl (location, VAR_DECL, NULL_TREE, new_var_type); + else + *new_var = create_tmp_var (new_var_type, NULL); + } + else + /* We do not require a new variable for mutating. The "identity value" + itself is the variable. */ + *new_var = NULL_TREE; + + if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND + || an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MIN_IND) + { + array_ind_value = create_tmp_var (TREE_TYPE (func_parm), NULL); + gcc_assert (array_ind_value && (array_ind_value != error_mark_node)); + DECL_INITIAL (array_ind_value) = NULL_TREE; + pushdecl (array_ind_value); + } + + array_op0 = (*array_operand)[0]; + switch (an_type) + { + case BUILT_IN_CILKPLUS_SEC_REDUCE_ADD: + code = PLUS_EXPR; + init = ARITHMETIC_TYPE_P (new_var_type) ? build_zero_cst (new_var_type) + : integer_zero_node; + break; + case BUILT_IN_CILKPLUS_SEC_REDUCE_MUL: + code = MULT_EXPR; + init = ARITHMETIC_TYPE_P (new_var_type) ? build_one_cst (new_var_type) + : integer_one_node; + break; + case BUILT_IN_CILKPLUS_SEC_REDUCE_ANY_ZERO: + case BUILT_IN_CILKPLUS_SEC_REDUCE_ANY_NONZERO: + code = (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_ANY_ZERO) ? EQ_EXPR + : NE_EXPR; + init = build_zero_cst (new_var_type); + cond_init = build_one_cst (new_var_type); + comp_node = !ARITHMETIC_TYPE_P (TREE_TYPE (func_parm)) ? integer_zero_node + : build_zero_cst (TREE_TYPE (func_parm)); + break; + case BUILT_IN_CILKPLUS_SEC_REDUCE_ALL_ZERO: + case BUILT_IN_CILKPLUS_SEC_REDUCE_ALL_NONZERO: + code = (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_ALL_ZERO) ? NE_EXPR + : EQ_EXPR; + init = build_one_cst (new_var_type); + cond_init = build_zero_cst (new_var_type); + comp_node = !ARITHMETIC_TYPE_P (TREE_TYPE (func_parm)) ? integer_zero_node + : build_zero_cst (TREE_TYPE (func_parm)); + break; + case BUILT_IN_CILKPLUS_SEC_REDUCE_MAX: + code = MAX_EXPR; + init = TYPE_MIN_VALUE (new_var_type) ? TYPE_MIN_VALUE (new_var_type) + : func_parm; + break; + case BUILT_IN_CILKPLUS_SEC_REDUCE_MIN: + code = MIN_EXPR; + init = TYPE_MAX_VALUE (new_var_type) ? TYPE_MAX_VALUE (new_var_type) + : func_parm; + break; + case BUILT_IN_CILKPLUS_SEC_REDUCE_MIN_IND: + case BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND: + code = an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND ? LE_EXPR + : GE_EXPR; + init = array_var[0]; + case BUILT_IN_CILKPLUS_SEC_REDUCE: + init = identity_value; + break; + case BUILT_IN_CILKPLUS_SEC_REDUCE_MUTATING: + init = NULL_TREE; + break; + default: + gcc_unreachable (); + } + + if (init) + new_var_init = build_x_modify_expr (location, *new_var, NOP_EXPR, init, + tf_warning_or_error); + if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_ADD + || an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MUL) + new_expr = build_x_modify_expr (location, *new_var, code, func_parm, + tf_warning_or_error); + if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_ALL_ZERO + || an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_ALL_NONZERO + || an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_ANY_ZERO + || an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_ANY_NONZERO) + { + /* In all these cases, assume the false case is true and as soon as + we find a true case, set the true flag on and latch it in. */ + new_yes_expr = build_x_modify_expr (location, *new_var, NOP_EXPR, + cond_init, tf_warning_or_error); + new_no_expr = build_x_modify_expr (location, *new_var, NOP_EXPR, + *new_var, tf_warning_or_error); + new_cond_expr = build_x_binary_op + (location, code, func_parm, TREE_CODE (func_parm), comp_node, + TREE_CODE (comp_node), NULL, tf_warning_or_error); + new_expr = build_x_conditional_expr (location, new_cond_expr, + new_yes_expr, new_no_expr, + tf_warning_or_error); + } + if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MAX + || an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MIN) + { + new_cond_expr = build_x_binary_op + (location, code, *new_var, TREE_CODE (*new_var), func_parm, + TREE_CODE (func_parm), NULL, tf_warning_or_error); + new_expr = build_x_modify_expr (location, *new_var, NOP_EXPR, func_parm, + tf_warning_or_error); + } + if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND + || an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MIN_IND) + { + new_exp_init = build_x_modify_expr (location, array_ind_value, NOP_EXPR, + func_parm, tf_warning_or_error); + new_yes_expr = build_x_modify_expr (location, array_ind_value, NOP_EXPR, + func_parm, tf_warning_or_error); + new_no_expr = build_x_modify_expr (location, array_ind_value, NOP_EXPR, + array_ind_value, tf_warning_or_error); + if (list_size > 1) + new_yes_ind = build_x_modify_expr (location, *new_var, NOP_EXPR, + array_var[0], tf_warning_or_error); + else + new_yes_ind = build_x_modify_expr (location, *new_var, NOP_EXPR, + TREE_OPERAND (array_op0, 1), + tf_warning_or_error); + new_no_ind = build_x_modify_expr (location, *new_var, NOP_EXPR, *new_var, + tf_warning_or_error); + new_yes_list = alloc_stmt_list (); + append_to_statement_list (new_yes_ind, &new_yes_list); + append_to_statement_list (new_yes_expr, &new_yes_list); + + new_no_list = alloc_stmt_list (); + append_to_statement_list (new_no_ind, &new_no_list); + append_to_statement_list (new_no_expr, &new_no_list); + + new_cond_expr = build_x_binary_op (location, code, array_ind_value, + TREE_CODE (array_ind_value), func_parm, + TREE_CODE (func_parm), NULL, + tf_warning_or_error); + new_expr = build_x_conditional_expr (location, new_cond_expr, + new_yes_list, new_no_list, + tf_warning_or_error); + } + if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE + || an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MUTATING) + { + vec *func_args = make_tree_vector (); + if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE) + vec_safe_push (func_args, *new_var); + else + vec_safe_push (func_args, identity_value); + vec_safe_push (func_args, func_parm); + + new_expr = finish_call_expr (call_fn, &func_args, false, true, + tf_warning_or_error); + if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE) + new_expr = build_x_modify_expr (location, *new_var, NOP_EXPR, new_expr, + tf_warning_or_error); + } + + /* The reason we are putting initial variable twice is because the + new exp init below depends on this value being initialized. */ + for (ii = 0; ii < rank; ii++) + finish_expr_stmt (ind_init[ii]); + + if (an_type != BUILT_IN_CILKPLUS_SEC_REDUCE_MUTATING) + finish_expr_stmt (new_var_init); + + if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND + || an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MIN_IND) + finish_expr_stmt (new_exp_init); + + an_init = pop_stmt_list (an_init); + append_to_statement_list_force (an_init, &loop_with_init); + body = new_expr; + + for (ii = 0; ii < rank; ii++) + { + tree new_loop = push_stmt_list (); + create_an_loop (ind_init[ii], compare_expr[ii], expr_incr[ii], body); + body = pop_stmt_list (new_loop); + } + append_to_statement_list_force (body, &loop_with_init); + clear_all_an_vectors (&array_value, &array_start, &array_length, + &array_stride, &array_vector, &count_down, &expr_incr, + &compare_expr, &ind_init, &array_var); + return loop_with_init; +} + +/* Returns a loop with ARRAY_REF inside it with an appropriate modify expr. + The LHS and/or RHS will be array notation expressions that have a + MODIFYCODE. The location of the variable is specified by LOCATION. */ + +static tree +expand_an_in_modify_expr (location_t location, tree lhs, + enum tree_code modifycode, tree rhs, + tsubst_flags_t complain) +{ + tree array_expr_lhs = NULL_TREE, array_expr_rhs = NULL_TREE; + tree array_expr = NULL_TREE; + tree body = NULL_TREE; + vec lhs_var = vNULL, rhs_var = vNULL; + vec cond_expr = vNULL; + vec lhs_expr_incr = vNULL, rhs_expr_incr = vNULL; + vec lhs_ind_init = vNULL, rhs_ind_init = vNULL; + vec lhs_compare = vNULL, rhs_compare = vNULL; + vec *lhs_array_operand = NULL, *rhs_array_operand = NULL; + size_t lhs_rank = 0, rhs_rank = 0, ii = 0; + vec *rhs_list = NULL, *lhs_list = NULL; + size_t rhs_list_size = 0, lhs_list_size = 0; + tree new_modify_expr, new_var = NULL_TREE, builtin_loop, scalar_mods; + bool found_builtin_fn = false; + tree an_init, loop_with_init = alloc_stmt_list (); + vec > lhs_value = vNULL, lhs_start = vNULL, lhs_length = vNULL; + vec > lhs_stride = vNULL; + vec > rhs_value = vNULL, rhs_start = vNULL, rhs_length = vNULL; + vec > rhs_stride = vNULL; + vec > lhs_count_down = vNULL, rhs_count_down = vNULL; + vec > lhs_vector = vNULL, rhs_vector = vNULL; + + if (!find_rank (location, rhs, rhs, false, &rhs_rank)) + return error_mark_node; + extract_array_notation_exprs (rhs, false, &rhs_list); + rhs_list_size = vec_safe_length (rhs_list); + an_init = push_stmt_list (); + if (rhs_rank) + { + scalar_mods = replace_invariant_exprs (&rhs); + if (scalar_mods) + finish_expr_stmt (scalar_mods); + } + for (ii = 0; ii < rhs_list_size; ii++) + { + tree rhs_node = (*rhs_list)[ii]; + if (TREE_CODE (rhs_node) == CALL_EXPR) + { + builtin_loop = expand_sec_reduce_builtin (rhs_node, &new_var); + if (builtin_loop == error_mark_node) + return error_mark_node; + else if (builtin_loop) + { + finish_expr_stmt (builtin_loop); + found_builtin_fn = true; + if (new_var) + { + vec *rhs_sub_list = NULL, *new_var_list = NULL; + vec_safe_push (rhs_sub_list, rhs_node); + vec_safe_push (new_var_list, new_var); + replace_array_notations (&rhs, false, rhs_sub_list, + new_var_list); + } + } + } + } + lhs_rank = 0; + rhs_rank = 0; + if (!find_rank (location, lhs, lhs, true, &lhs_rank) + || !find_rank (location, rhs, rhs, true, &rhs_rank)) + { + pop_stmt_list (an_init); + return error_mark_node; + } + + /* If both are scalar, then the only reason why we will get this far is if + there is some array notations inside it and was using a builtin array + notation functions. If so, we have already broken those guys up and now + a simple build_x_modify_expr would do. */ + if (lhs_rank == 0 && rhs_rank == 0) + { + if (found_builtin_fn) + { + new_modify_expr = build_x_modify_expr (location, lhs, + modifycode, rhs, complain); + finish_expr_stmt (new_modify_expr); + pop_stmt_list (an_init); + return an_init; + } + else + { + pop_stmt_list (an_init); + return NULL_TREE; + } + } + + /* If for some reason location is not set, then find if LHS or RHS has + location info. If so, then use that so we atleast have an idea. */ + if (location == UNKNOWN_LOCATION) + { + if (EXPR_LOCATION (lhs) != UNKNOWN_LOCATION) + location = EXPR_LOCATION (lhs); + else if (EXPR_LOCATION (rhs) != UNKNOWN_LOCATION) + location = EXPR_LOCATION (rhs); + } + + /* We need this when we have a scatter issue. */ + extract_array_notation_exprs (lhs, true, &lhs_list); + rhs_list = NULL; + extract_array_notation_exprs (rhs, true, &rhs_list); + rhs_list_size = vec_safe_length (rhs_list); + lhs_list_size = vec_safe_length (lhs_list); + + if (lhs_rank == 0 && rhs_rank != 0) + { + if (location == UNKNOWN_LOCATION && EXPR_HAS_LOCATION (rhs)) + location = EXPR_LOCATION (rhs); + error_at (location, "%qD cannot be scalar when %qD is not", lhs, rhs); + return error_mark_node; + } + if (lhs_rank != 0 && rhs_rank != 0 && lhs_rank != rhs_rank) + { + error_at (location, "rank mismatch between %qE and %qE", lhs, rhs); + return error_mark_node; + } + + /* Assign the array notation components to variable so that they can satisfy + the execute-once rule. */ + for (ii = 0; ii < lhs_list_size; ii++) + { + tree anode = (*lhs_list)[ii]; + make_triplet_val_inv (location, &ARRAY_NOTATION_START (anode), complain); + make_triplet_val_inv (location, &ARRAY_NOTATION_LENGTH (anode), complain); + make_triplet_val_inv (location, &ARRAY_NOTATION_STRIDE (anode), complain); + } + for (ii = 0; ii < rhs_list_size; ii++) + if ((*rhs_list)[ii] && TREE_CODE ((*rhs_list)[ii]) == ARRAY_NOTATION_REF) + { + tree aa = (*rhs_list)[ii]; + make_triplet_val_inv (location, &ARRAY_NOTATION_START (aa), complain); + make_triplet_val_inv (location, &ARRAY_NOTATION_LENGTH (aa), complain); + make_triplet_val_inv (location, &ARRAY_NOTATION_STRIDE (aa), complain); + } + + lhs_var.safe_grow_cleared (lhs_rank); + lhs_ind_init.safe_grow_cleared (lhs_rank); + if (rhs_rank) + { + rhs_var.safe_grow_cleared (rhs_rank); + rhs_ind_init.safe_grow_cleared (rhs_rank); + } + + cond_expr.safe_grow_cleared (MAX (lhs_rank, rhs_rank)); + + extract_an_triplets (lhs_list, &lhs_value, &lhs_start, &lhs_length, + &lhs_stride, &lhs_vector, &lhs_count_down, lhs_list_size, + lhs_rank); + if (rhs_list) + extract_an_triplets (rhs_list, &rhs_value, &rhs_start, &rhs_length, + &rhs_stride, &rhs_vector, &rhs_count_down, + rhs_list_size, rhs_rank); + + if (cp_length_mismatch_in_expr_p (EXPR_LOCATION (lhs), lhs_length) + || (rhs_list && cp_length_mismatch_in_expr_p (EXPR_LOCATION (rhs), + rhs_length))) + { + pop_stmt_list (an_init); + return error_mark_node; + } + if (lhs_list_size > 0 && rhs_list_size > 0 && lhs_rank > 0 && rhs_rank > 0 + && TREE_CODE (lhs_length[0][0]) == INTEGER_CST + && rhs_length[0][0] && TREE_CODE (rhs_length[0][0]) == INTEGER_CST) + { + HOST_WIDE_INT l_length = int_cst_value (lhs_length[0][0]); + HOST_WIDE_INT r_length = int_cst_value (rhs_length[0][0]); + if (absu_hwi (l_length) != absu_hwi (r_length)) + { + error_at (location, "length mismatch between LHS and RHS"); + pop_stmt_list (an_init); + return error_mark_node; + } + } + for (ii = 0; ii < lhs_rank; ii++) + if (lhs_start[0][ii] && TREE_TYPE (lhs_start[0][ii])) + lhs_var[ii] = build_decl (location, VAR_DECL, NULL_TREE, + TREE_TYPE (lhs_start[0][ii])); + else + lhs_var[ii] = build_decl (location, VAR_DECL, NULL_TREE, + integer_type_node); + if (rhs_list_size > 0) + { + rhs_array_operand = fix_sec_implicit_args (location, rhs_list, lhs_var, + lhs_rank, lhs); + if (!rhs_array_operand) + return error_mark_node; + } + replace_array_notations (&rhs, true, rhs_list, rhs_array_operand); + rhs_list_size = 0; + rhs_list = NULL; + extract_array_notation_exprs (rhs, true, &rhs_list); + rhs_list_size = vec_safe_length (rhs_list); + + for (ii = 0; ii < lhs_rank; ii++) + if (lhs_vector[0][ii]) + { + lhs_ind_init[ii] = build_x_modify_expr + (location, lhs_var[ii], NOP_EXPR, + build_zero_cst (TREE_TYPE (lhs_var[ii])), complain); + } + for (ii = 0; ii < rhs_rank; ii++) + { + /* When we have a polynomial, we assume that the indices are of type + integer. */ + rhs_var[ii] = build_decl (location, VAR_DECL, NULL_TREE, + TREE_TYPE (rhs_start[0][ii])); + rhs_ind_init[ii] = build_x_modify_expr + (location, rhs_var[ii], NOP_EXPR, + build_zero_cst (TREE_TYPE (rhs_var[ii])), complain); + } + + if (lhs_rank) + { + lhs_array_operand = create_array_refs (location, lhs_value, lhs_start, + lhs_stride, lhs_vector, lhs_var, + lhs_count_down, lhs_list_size, + lhs_rank); + replace_array_notations (&lhs, true, lhs_list, lhs_array_operand); + } + + if (rhs_array_operand) + vec_safe_truncate (rhs_array_operand, 0); + if (rhs_rank) + { + rhs_array_operand = create_array_refs (location, rhs_value, rhs_start, + rhs_stride, rhs_vector, rhs_var, + rhs_count_down, rhs_list_size, + rhs_rank); + /* Replace all the array refs created by the above function because this + variable is blown away by the fix_sec_implicit_args function below. */ + replace_array_notations (&rhs, true, rhs_list, rhs_array_operand); + vec_safe_truncate (rhs_array_operand , 0); + rhs_array_operand = fix_sec_implicit_args (location, rhs_list, rhs_var, + rhs_rank, rhs); + if (!rhs_array_operand) + return error_mark_node; + replace_array_notations (&rhs, true, rhs_list, rhs_array_operand); + } + + array_expr_rhs = rhs; + array_expr_lhs = lhs; + + array_expr = build_x_modify_expr (location, array_expr_lhs, modifycode, + array_expr_rhs, complain); + create_cmp_and_incr (location, lhs_var, lhs_length, &lhs_expr_incr, + &lhs_compare, lhs_count_down, lhs_rank, complain); + if (rhs_rank) + create_cmp_and_incr (location, rhs_var, rhs_length, &rhs_expr_incr, + &rhs_compare, rhs_count_down, rhs_rank, complain); + + for (ii = 0; ii < MAX (rhs_rank, lhs_rank); ii++) + if (ii < lhs_rank && ii < rhs_rank) + cond_expr[ii] = build_x_binary_op + (location, TRUTH_ANDIF_EXPR, lhs_compare[ii], + TREE_CODE (lhs_compare[ii]), rhs_compare[ii], + TREE_CODE (rhs_compare[ii]), NULL, complain); + else if (ii < lhs_rank && ii >= rhs_rank) + cond_expr[ii] = lhs_compare[ii]; + else + /* No need to compare ii < rhs_rank && ii >= lhs_rank because valid Array + notation expression cannot RHS's rank cannot be greater than LHS. */ + gcc_unreachable (); + + an_init = pop_stmt_list (an_init); + append_to_statement_list_force (an_init, &loop_with_init); + body = array_expr; + for (ii = 0; ii < MAX (lhs_rank, rhs_rank); ii++) + { + tree incr_list = alloc_stmt_list (); + tree init_list = alloc_stmt_list (); + tree new_loop = push_stmt_list (); + + if (lhs_rank) + { + append_to_statement_list_force (lhs_ind_init[ii], &init_list); + append_to_statement_list_force (lhs_expr_incr[ii], &incr_list); + } + if (rhs_rank) + { + append_to_statement_list_force (rhs_ind_init[ii], &init_list); + append_to_statement_list_force (rhs_expr_incr[ii], &incr_list); + } + create_an_loop (init_list, cond_expr[ii], incr_list, body); + body = pop_stmt_list (new_loop); + } + append_to_statement_list (body, &loop_with_init); + + clear_all_an_vectors (&lhs_value, &lhs_start, &lhs_length, &lhs_stride, + &lhs_vector, &lhs_count_down, &lhs_expr_incr, + &lhs_compare, &lhs_ind_init, &lhs_var); + if (rhs_rank) + clear_all_an_vectors (&rhs_value, &rhs_start, &rhs_length, &rhs_stride, + &rhs_vector, &rhs_count_down, &rhs_expr_incr, + &rhs_compare, &rhs_ind_init, &rhs_var); + cond_expr.release (); + return loop_with_init; +} + +/* Helper function for expand_conditonal_array_notations. Encloses the + conditional statement passed in ORIG_STMT with a loop around it and replaces + the condition in STMT with a ARRAY_REF tree-node to the array. The condition + must have a ARRAY_NOTATION_REF tree. */ + +static tree +cp_expand_cond_array_notations (tree orig_stmt) +{ + vec *array_list = NULL, *array_operand = NULL; + size_t list_size = 0; + size_t rank = 0, ii = 0; + tree an_init, body, stmt = NULL_TREE; + vec > array_value = vNULL, array_stride = vNULL; + vec > array_length = vNULL, array_start = vNULL; + vec compare_expr = vNULL, array_var = vNULL, expr_incr = vNULL; + vec ind_init = vNULL; + tree builtin_loop, new_var = NULL_TREE; + vec > count_down = vNULL, array_vector = vNULL; + tree loop_with_init = alloc_stmt_list (); + tsubst_flags_t complain = tf_warning_or_error; + location_t location = UNKNOWN_LOCATION; + + if (TREE_CODE (orig_stmt) == COND_EXPR) + { + size_t cond_rank = 0, yes_rank = 0, no_rank = 0; + tree yes_expr = COND_EXPR_THEN (orig_stmt); + tree no_expr = COND_EXPR_ELSE (orig_stmt); + tree cond = COND_EXPR_COND (orig_stmt); + if (!find_rank (EXPR_LOCATION (cond), cond, cond, true, &cond_rank) + || !find_rank (EXPR_LOCATION (yes_expr), yes_expr, yes_expr, true, + &yes_rank) + || find_rank (EXPR_LOCATION (no_expr), no_expr, no_expr, true, + &no_rank)) + return error_mark_node; + if (cond_rank != 0 && cond_rank != yes_rank && yes_rank != 0) + { + error_at (EXPR_LOCATION (yes_expr), "rank mismatch with controlling" + " expression of parent if-statement"); + return error_mark_node; + } + else if (cond_rank != 0 && cond_rank != no_rank && no_rank != 0) + { + error_at (EXPR_LOCATION (no_expr), "rank mismatch with controlling " + "expression of parent if-statement"); + return error_mark_node; + } + } + else if (TREE_CODE (orig_stmt) == IF_STMT) + { + size_t cond_rank = 0, yes_rank = 0, no_rank = 0; + tree yes_expr = THEN_CLAUSE (orig_stmt); + tree no_expr = ELSE_CLAUSE (orig_stmt); + tree cond = IF_COND (orig_stmt); + if (!find_rank (EXPR_LOCATION (cond), cond, cond, true, &cond_rank) + || (yes_expr + && !find_rank (EXPR_LOCATION (yes_expr), yes_expr, yes_expr, true, + &yes_rank)) + || (no_expr + && !find_rank (EXPR_LOCATION (no_expr), no_expr, no_expr, true, + &no_rank))) + return error_mark_node; + if (cond_rank != 0 && cond_rank != yes_rank && yes_rank != 0) + { + error_at (EXPR_LOCATION (yes_expr), "rank mismatch with controlling" + " expression of parent if-statement"); + return error_mark_node; + } + else if (cond_rank != 0 && cond_rank != no_rank && no_rank != 0) + { + error_at (EXPR_LOCATION (no_expr), "rank mismatch with controlling " + "expression of parent if-statement"); + return error_mark_node; + } + } + + if (!find_rank (EXPR_LOCATION (orig_stmt), orig_stmt, orig_stmt, true, + &rank)) + return error_mark_node; + if (rank == 0) + return orig_stmt; + + extract_array_notation_exprs (orig_stmt, false, &array_list); + stmt = alloc_stmt_list (); + for (ii = 0; ii < vec_safe_length (array_list); ii++) + { + tree array_node = (*array_list)[ii]; + if (TREE_CODE (array_node) == CALL_EXPR + || TREE_CODE (array_node) == AGGR_INIT_EXPR) + { + builtin_loop = expand_sec_reduce_builtin (array_node, &new_var); + if (builtin_loop == error_mark_node) + finish_expr_stmt (error_mark_node); + else if (new_var) + { + vec *sub_list = NULL, *new_var_list = NULL; + vec_safe_push (sub_list, array_node); + vec_safe_push (new_var_list, new_var); + replace_array_notations (&orig_stmt, false, sub_list, + new_var_list); + append_to_statement_list_force (builtin_loop, &stmt); + } + } + } + append_to_statement_list_force (orig_stmt, &stmt); + rank = 0; + array_list = NULL; + if (!find_rank (EXPR_LOCATION (stmt), stmt, stmt, true, &rank)) + return error_mark_node; + if (rank == 0) + return stmt; + + extract_array_notation_exprs (stmt, true, &array_list); + list_size = vec_safe_length (array_list); + if (list_size == 0) + return stmt; + + location = EXPR_LOCATION (orig_stmt); + list_size = vec_safe_length (array_list); + + compare_expr.safe_grow_cleared (rank); + expr_incr.safe_grow_cleared (rank); + expr_incr.safe_grow_cleared (rank); + array_var.safe_grow_cleared (rank); + ind_init.safe_grow_cleared (rank); + an_init = push_stmt_list (); + + /* Assign the array notation components to variable so that they can satisfy + the exec-once rule. */ + for (ii = 0; ii < list_size; ii++) + { + tree anode = (*array_list)[ii]; + make_triplet_val_inv (location, &ARRAY_NOTATION_START (anode), complain); + make_triplet_val_inv (location, &ARRAY_NOTATION_LENGTH (anode), complain); + make_triplet_val_inv (location, &ARRAY_NOTATION_STRIDE (anode), complain); + } + + extract_an_triplets (array_list, &array_value, &array_start, &array_length, + &array_stride, &array_vector, &count_down, list_size, + rank); + for (ii = 0; ii < rank; ii++) + { + if (TREE_TYPE (array_start[0][ii]) + && TREE_CODE (TREE_TYPE (array_start[0][ii])) != TEMPLATE_TYPE_PARM) + { + array_var[ii] = build_decl (location, VAR_DECL, NULL_TREE, + TREE_TYPE (array_start[0][ii])); + ind_init[ii] = build_x_modify_expr + (location, array_var[ii], NOP_EXPR, + build_zero_cst (TREE_TYPE (array_var[ii])), tf_warning_or_error); + } + else + { + array_var[ii] = build_min_nt_loc (location, VAR_DECL, + NULL_TREE, NULL_TREE); + ind_init[ii] = build_x_modify_expr (location, array_var[ii], + NOP_EXPR, + integer_zero_node, 1); + } + } + array_operand = create_array_refs (location, array_value, array_start, + array_stride, array_vector, array_var, + count_down, list_size, rank); + replace_array_notations (&stmt, true, array_list, array_operand); + + create_cmp_and_incr (location, array_var, array_length, &expr_incr, + &compare_expr, count_down, rank, complain); + an_init = pop_stmt_list (an_init); + append_to_statement_list_force (an_init, &loop_with_init); + body = stmt; + + for (ii = 0; ii < rank; ii++) + { + tree new_loop = push_stmt_list (); + create_an_loop (ind_init[ii], compare_expr[ii], expr_incr[ii], body); + body = pop_stmt_list (new_loop); + } + append_to_statement_list_force (body, &loop_with_init); + clear_all_an_vectors (&array_value, &array_start, &array_length, + &array_stride, &array_vector, &count_down, &expr_incr, + &compare_expr, &ind_init, &array_var); + return loop_with_init; +} + +/* Transforms array notations inside unary expression ORIG_STMT with an + appropriate loop and ARRAY_REF (and returns all this as a super-tree called + LOOP). */ + +static tree +expand_unary_array_notation_exprs (tree orig_stmt) +{ + vec *array_list = NULL, *array_operand = NULL; + size_t list_size = 0, rank = 0, ii = 0; + tree body; + tree builtin_loop, stmt = NULL_TREE, new_var = NULL_TREE; + location_t location = EXPR_LOCATION (orig_stmt); + tree an_init, loop_with_init = alloc_stmt_list (); + vec > array_value = vNULL, array_stride = vNULL; + vec ind_init = vNULL; + vec > array_length = vNULL, array_start = vNULL; + vec compare_expr = vNULL, array_var = vNULL, expr_incr = vNULL; + vec > count_down = vNULL, array_vector = vNULL; + + if (!find_rank (location, orig_stmt, orig_stmt, true, &rank)) + return error_mark_node; + if (rank == 0) + return orig_stmt; + + extract_array_notation_exprs (orig_stmt, false, &array_list); + list_size = vec_safe_length (array_list); + location = EXPR_LOCATION (orig_stmt); + stmt = NULL_TREE; + for (ii = 0; ii < list_size; ii++) + { + tree list_node = (*array_list)[ii]; + if (TREE_CODE (list_node) == CALL_EXPR + || TREE_CODE (list_node) == AGGR_INIT_EXPR) + { + builtin_loop = expand_sec_reduce_builtin (list_node, &new_var); + if (builtin_loop == error_mark_node) + return error_mark_node; + else if (builtin_loop) + { + vec *sub_list = NULL, *new_var_list = NULL; + stmt = alloc_stmt_list (); + append_to_statement_list_force (builtin_loop, &stmt); + vec_safe_push (sub_list, list_node); + vec_safe_push (new_var_list, new_var); + replace_array_notations (&orig_stmt, false, sub_list, + new_var_list); + } + } + } + if (stmt != NULL_TREE) + append_to_statement_list_force (finish_expr_stmt (orig_stmt), &stmt); + else + stmt = orig_stmt; + rank = 0; + list_size = 0; + array_list = NULL; + extract_array_notation_exprs (stmt, true, &array_list); + list_size = vec_safe_length (array_list); + + if (!find_rank (EXPR_LOCATION (stmt), stmt, stmt, true, &rank)) + return error_mark_node; + if (rank == 0 || list_size == 0) + return stmt; + + compare_expr.safe_grow_cleared (rank); + expr_incr.safe_grow_cleared (rank); + expr_incr.safe_grow_cleared (rank); + array_var.safe_grow_cleared (rank); + ind_init.safe_grow_cleared (rank); + an_init = push_stmt_list (); + + /* Assign the array notation components to variable so that they can satisfy + the exec-once rule. */ + for (ii = 0; ii < list_size; ii++) + { + tree array_node = (*array_list)[ii]; + make_triplet_val_inv (location, &ARRAY_NOTATION_START (array_node), + tf_warning_or_error); + make_triplet_val_inv (location, &ARRAY_NOTATION_LENGTH (array_node), + tf_warning_or_error); + make_triplet_val_inv (location, &ARRAY_NOTATION_STRIDE (array_node), + tf_warning_or_error); + } + extract_an_triplets (array_list, &array_value, &array_start, &array_length, + &array_stride, &array_vector, &count_down, list_size, + rank); + for (ii = 0; ii < rank; ii++) + { + array_var[ii] = build_decl (location, VAR_DECL, NULL_TREE, + TREE_TYPE (array_start[0][ii])); + ind_init[ii] = build_x_modify_expr + (location, array_var[ii], NOP_EXPR, + build_zero_cst (TREE_TYPE (array_var[ii])), tf_warning_or_error); + } + array_operand = create_array_refs (location, array_value, array_start, + array_stride, array_vector, array_var, + count_down, list_size, rank); + replace_array_notations (&stmt, true, array_list, array_operand); + create_cmp_and_incr (location, array_var, array_length, &expr_incr, + &compare_expr, count_down, rank, tf_warning_or_error); + an_init = pop_stmt_list (an_init); + append_to_statement_list_force (an_init, &loop_with_init); + body = stmt; + + for (ii = 0; ii < rank; ii++) + { + tree new_loop = push_stmt_list (); + create_an_loop (ind_init[ii], compare_expr[ii], expr_incr[ii], body); + body = pop_stmt_list (new_loop); + } + append_to_statement_list_force (body, &loop_with_init); + clear_all_an_vectors (&array_value, &array_start, &array_length, + &array_stride, &array_vector, &count_down, &expr_incr, + &compare_expr, &ind_init, &array_var); + return loop_with_init; +} + +/* Expands the array notation's builtin reduction function in EXPR + (of type RETURN_EXPR) and returns a STATEMENT_LIST that contains a loop + with the builtin function expansion and a return statement at the end. */ + +static tree +expand_return_expr (tree expr) +{ + tree new_mod_list, new_var, new_mod, retval_expr; + location_t loc = EXPR_LOCATION (expr); + + if (TREE_CODE (expr) != RETURN_EXPR) + return expr; + + new_mod_list = alloc_stmt_list (); + retval_expr = TREE_OPERAND (expr, 0); + new_var = build_decl (loc, VAR_DECL, NULL_TREE, TREE_TYPE (retval_expr)); + new_mod = expand_an_in_modify_expr (loc, new_var, NOP_EXPR, + TREE_OPERAND (retval_expr, 1), + tf_warning_or_error); + TREE_OPERAND (retval_expr, 1) = new_var; + TREE_OPERAND (expr, 0) = retval_expr; + append_to_statement_list_force (new_mod, &new_mod_list); + append_to_statement_list_force (expr, &new_mod_list); + return new_mod_list; +} + +/* Expands ARRAY_NOTATION_REF and builtin functions in a compound statement, + STMT. Returns the STMT with expanded array notations. */ + +tree +expand_array_notation_exprs (tree t) +{ + enum tree_code code; + bool is_expr; + location_t loc = UNKNOWN_LOCATION; + + /* Skip empty subtrees. */ + if (!t) + return t; + + loc = EXPR_LOCATION (t); + + code = TREE_CODE (t); + is_expr = IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (code)); + switch (code) + { + case ERROR_MARK: + case IDENTIFIER_NODE: + case INTEGER_CST: + case REAL_CST: + case FIXED_CST: + case STRING_CST: + case BLOCK: + case PLACEHOLDER_EXPR: + case FIELD_DECL: + case VOID_TYPE: + case REAL_TYPE: + case SSA_NAME: + case LABEL_DECL: + case RESULT_DECL: + case VAR_DECL: + case PARM_DECL: + case NON_LVALUE_EXPR: + case NOP_EXPR: + case INIT_EXPR: + case ADDR_EXPR: + case ARRAY_REF: + case BIT_FIELD_REF: + case VECTOR_CST: + case COMPLEX_CST: + return t; + case MODIFY_EXPR: + if (contains_array_notation_expr (t)) + t = expand_an_in_modify_expr (loc, TREE_OPERAND (t, 0), NOP_EXPR, + TREE_OPERAND (t, 1), + tf_warning_or_error); + return t; + case MODOP_EXPR: + if (contains_array_notation_expr (t) && !processing_template_decl) + t = expand_an_in_modify_expr + (loc, TREE_OPERAND (t, 0), TREE_CODE (TREE_OPERAND (t, 1)), + TREE_OPERAND (t, 2), tf_warning_or_error); + return t; + case CONSTRUCTOR: + return t; + case BIND_EXPR: + { + BIND_EXPR_BODY (t) = + expand_array_notation_exprs (BIND_EXPR_BODY (t)); + return t; + } + case DECL_EXPR: + { + tree x = DECL_EXPR_DECL (t); + if (t && TREE_CODE (x) != FUNCTION_DECL) + if (DECL_INITIAL (x)) + t = expand_unary_array_notation_exprs (t); + return t; + } + case STATEMENT_LIST: + { + tree_stmt_iterator i; + for (i = tsi_start (t); !tsi_end_p (i); tsi_next (&i)) + *tsi_stmt_ptr (i) = + expand_array_notation_exprs (*tsi_stmt_ptr (i)); + return t; + } + + case OMP_PARALLEL: + case OMP_TASK: + case OMP_FOR: + case OMP_SINGLE: + case OMP_SECTION: + case OMP_SECTIONS: + case OMP_MASTER: + case OMP_ORDERED: + case OMP_CRITICAL: + case OMP_ATOMIC: + case OMP_CLAUSE: + case TARGET_EXPR: + case INTEGER_TYPE: + case ENUMERAL_TYPE: + case BOOLEAN_TYPE: + case POINTER_TYPE: + case ARRAY_TYPE: + case RECORD_TYPE: + case METHOD_TYPE: + return t; + case RETURN_EXPR: + if (contains_array_notation_expr (t)) + t = expand_return_expr (t); + return t; + case PREDECREMENT_EXPR: + case PREINCREMENT_EXPR: + case POSTDECREMENT_EXPR: + case POSTINCREMENT_EXPR: + case AGGR_INIT_EXPR: + case CALL_EXPR: + t = expand_unary_array_notation_exprs (t); + return t; + case CONVERT_EXPR: + case CLEANUP_POINT_EXPR: + case EXPR_STMT: + TREE_OPERAND (t, 0) = expand_array_notation_exprs (TREE_OPERAND (t, 0)); + /* It is not necessary to wrap error_mark_node in EXPR_STMT. */ + if (TREE_OPERAND (t, 0) == error_mark_node) + return TREE_OPERAND (t, 0); + return t; + case COND_EXPR: + t = cp_expand_cond_array_notations (t); + if (TREE_CODE (t) == COND_EXPR) + { + COND_EXPR_THEN (t) = + expand_array_notation_exprs (COND_EXPR_THEN (t)); + COND_EXPR_ELSE (t) = + expand_array_notation_exprs (COND_EXPR_ELSE (t)); + } + else + t = expand_array_notation_exprs (t); + return t; + + case SWITCH_EXPR: + t = cp_expand_cond_array_notations (t); + if (TREE_CODE (t) == SWITCH_EXPR) + SWITCH_BODY (t) = expand_array_notation_exprs (SWITCH_BODY (t)); + else + t = expand_array_notation_exprs (t); + return t; + case FOR_STMT: + + /* FIXME: Add a check for CILK_FOR_STMT here when we add Cilk tasking + keywords. */ + if (TREE_CODE (t) == FOR_STMT) + FOR_BODY (t) = expand_array_notation_exprs (FOR_BODY (t)); + else + t = expand_array_notation_exprs (t); + return t; + case IF_STMT: + t = cp_expand_cond_array_notations (t); + /* If the above function added some extra instructions above the original + if statement, then we can't assume it is still IF_STMT so we have to + check again. */ + if (TREE_CODE (t) == IF_STMT) + { + if (THEN_CLAUSE (t)) + THEN_CLAUSE (t) = expand_array_notation_exprs (THEN_CLAUSE (t)); + if (ELSE_CLAUSE (t)) + ELSE_CLAUSE (t) = expand_array_notation_exprs (ELSE_CLAUSE (t)); + } + else + t = expand_array_notation_exprs (t); + return t; + case SWITCH_STMT: + t = cp_expand_cond_array_notations (t); + /* If the above function added some extra instructions above the original + switch statement, then we can't assume it is still SWITCH_STMT so we + have to check again. */ + if (TREE_CODE (t) == SWITCH_STMT) + { + if (SWITCH_STMT_BODY (t)) + SWITCH_STMT_BODY (t) = + expand_array_notation_exprs (SWITCH_STMT_BODY (t)); + } + else + t = expand_array_notation_exprs (t); + return t; + case WHILE_STMT: + t = cp_expand_cond_array_notations (t); + /* If the above function added some extra instructions above the original + while statement, then we can't assume it is still WHILE_STMTso we + have to check again. */ + if (TREE_CODE (t) == WHILE_STMT) + { + if (WHILE_BODY (t)) + WHILE_BODY (t) = expand_array_notation_exprs (WHILE_BODY (t)); + } + else + t = expand_array_notation_exprs (t); + return t; + case DO_STMT: + t = cp_expand_cond_array_notations (t); + /* If the above function added some extra instructions above the original + do-while statement, then we can't assume it is still DO_STMT so we + have to check again. */ + if (TREE_CODE (t) == DO_STMT) + { + if (DO_BODY (t)) + DO_BODY (t) = expand_array_notation_exprs (DO_BODY (t)); + } + else + t = expand_array_notation_exprs (t); + return t; + default: + if (is_expr) + { + int i, len; + + /* Walk over all the sub-trees of this operand. */ + len = TREE_CODE_LENGTH (code); + + /* Go through the subtrees. We need to do this in forward order so + that the scope of a FOR_EXPR is handled properly. */ + for (i = 0; i < len; ++i) + TREE_OPERAND (t, i) = + expand_array_notation_exprs (TREE_OPERAND (t, i)); + } + return t; + } + return t; +} + +/* Given the base of an array (ARRAY), the START_INDEX, the number of elements + to be accessed (LENGTH) and the STRIDE, construct an ARRAY_NOTATION_REF tree + of type TYPE and return it. Restrictions on START_INDEX, LENGTH and STRIDE + are the same as that of index field passed into ARRAY_REF. The only + additional restriction is that, unlike index in ARRAY_REF, stride, length + and start_index cannot contain array notations. */ + +tree +build_array_notation_ref (location_t loc, tree array, tree start_index, + tree length, tree stride, tree type) +{ + tree array_ntn_expr = NULL_TREE; + + /* When dealing with templates, do the type checking at a later time. */ + if (processing_template_decl || !type) + { + if (!type && TREE_TYPE (array)) + type = TREE_TYPE (array); + array_ntn_expr = build_min_nt_loc (loc, ARRAY_NOTATION_REF, array, + start_index, length, stride, type, + NULL_TREE); + TREE_TYPE (array_ntn_expr) = type; + } + if (!stride) + { + if (TREE_CONSTANT (start_index) && TREE_CONSTANT (length) + && TREE_CODE (start_index) != VAR_DECL + && TREE_CODE (length) != VAR_DECL + && tree_int_cst_lt (length, start_index)) + stride = build_int_cst (TREE_TYPE (start_index), -1); + else + stride = build_int_cst (TREE_TYPE (start_index), 1); + } + + if (!cilkplus_an_triplet_types_ok_p (loc, start_index, length, stride, type)) + return error_mark_node; + + if (!processing_template_decl) + { + array_ntn_expr = build4 (ARRAY_NOTATION_REF, NULL_TREE, NULL_TREE, + NULL_TREE, NULL_TREE, NULL_TREE); + ARRAY_NOTATION_ARRAY (array_ntn_expr) = array; + ARRAY_NOTATION_START (array_ntn_expr) = start_index; + ARRAY_NOTATION_LENGTH (array_ntn_expr) = length; + ARRAY_NOTATION_STRIDE (array_ntn_expr) = stride; + if (type && (TREE_CODE (type) == ARRAY_TYPE + || TREE_CODE (type) == POINTER_TYPE)) + TREE_TYPE (array_ntn_expr) = TREE_TYPE (type); + else + TREE_TYPE (array_ntn_expr) = type; + } + SET_EXPR_LOCATION (array_ntn_expr, loc); + + return array_ntn_expr; +} + +/* Returns false if any of the Array notation triplet values: START_INDEX, + LENGTH and STRIDE, are not of integral type and have a rank greater than + zero. */ + +bool +cilkplus_an_triplet_types_ok_p (location_t loc, tree start_index, tree length, + tree stride, tree type) +{ + size_t stride_rank = 0, length_rank = 0, start_rank = 0; + if (!TREE_TYPE (start_index) || !INTEGRAL_TYPE_P (TREE_TYPE (start_index))) + { + error_at (loc, "start-index of array notation triplet is not an integer"); + return false; + } + if (!TREE_TYPE (length) || !INTEGRAL_TYPE_P (TREE_TYPE (length))) + { + error_at (loc, "length of array notation triplet is not an integer"); + return false; + } + if (!TREE_TYPE (stride) || !INTEGRAL_TYPE_P (TREE_TYPE (stride))) + { + error_at (loc, "stride of array notation triplet is not an integer"); + return false; + } + if (!TREE_CODE (type) == FUNCTION_TYPE) + { + error_at (loc, "array notations cannot be used with function type"); + return false; + } + while (type && (TREE_CODE (type) == POINTER_TYPE + || TREE_CODE (type) == ARRAY_TYPE)) + { + type = TREE_TYPE (type); + if (type && TREE_CODE (type) == FUNCTION_TYPE) + { + error_at (loc, "array notations cannot be used with function pointer" + " arrays"); + return false; + } + } + if (!find_rank (loc, start_index, start_index, false, &start_rank) + || !find_rank (loc, length, length, false, &length_rank) + || !find_rank (loc, stride, stride, false, &stride_rank)) + return false; + + if (start_rank != 0) + { + error_at (loc, "rank of an array notation triplet%'s start-index is not " + "zero"); + return false; + } + if (length_rank != 0) + { + error_at (loc, "rank of an array notation triplet%'s length is not zero"); + return false; + } + if (stride_rank != 0) + { + error_at (loc, "rank of array notation triplet%'s stride is not zero"); + return false; + } + return true; +} diff --git a/gcc/cp/cp-objcp-common.c b/gcc/cp/cp-objcp-common.c index bccd884..d301db0 100644 --- a/gcc/cp/cp-objcp-common.c +++ b/gcc/cp/cp-objcp-common.c @@ -321,6 +321,7 @@ cp_common_init_ts (void) MARK_TS_TYPED (USING_STMT); MARK_TS_TYPED (LAMBDA_EXPR); MARK_TS_TYPED (CTOR_INITIALIZER); + MARK_TS_TYPED (ARRAY_NOTATION_REF); } #include "gt-cp-cp-objcp-common.h" diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 2931ac5..76727ad 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -6121,6 +6121,10 @@ extern bool cxx_omp_privatize_by_reference (const_tree); extern void suggest_alternatives_for (location_t, tree); extern tree strip_using_decl (tree); +/* In cp/cp-array-notations.c */ +extern tree expand_array_notation_exprs (tree); +bool cilkplus_an_triplet_types_ok_p (location_t, tree, tree, tree, + tree); /* -- end of C++ */ #endif /* ! GCC_CP_TREE_H */ diff --git a/gcc/cp/error.c b/gcc/cp/error.c old mode 100644 new mode 100755 index a75fc4e..a8f52cd --- a/gcc/cp/error.c +++ b/gcc/cp/error.c @@ -1071,6 +1071,17 @@ dump_decl (tree t, int flags) pp_cxx_right_bracket (cxx_pp); break; + case ARRAY_NOTATION_REF: + dump_decl (ARRAY_NOTATION_ARRAY (t), flags | TFF_EXPR_IN_PARENS); + pp_cxx_left_bracket (cxx_pp); + dump_decl (ARRAY_NOTATION_START (t), flags | TFF_EXPR_IN_PARENS); + pp_string (cxx_pp, ":"); + dump_decl (ARRAY_NOTATION_LENGTH (t), flags | TFF_EXPR_IN_PARENS); + pp_string (cxx_pp, ":"); + dump_decl (ARRAY_NOTATION_STRIDE (t), flags | TFF_EXPR_IN_PARENS); + pp_cxx_right_bracket (cxx_pp); + break; + /* So that we can do dump_decl on an aggr type. */ case RECORD_TYPE: case UNION_TYPE: @@ -2057,6 +2068,17 @@ dump_expr (tree t, int flags) pp_cxx_right_bracket (cxx_pp); break; + case ARRAY_NOTATION_REF: + dump_expr (ARRAY_NOTATION_ARRAY (t), flags | TFF_EXPR_IN_PARENS); + pp_cxx_left_bracket (cxx_pp); + dump_expr (ARRAY_NOTATION_START (t), flags | TFF_EXPR_IN_PARENS); + pp_string (cxx_pp, ":"); + dump_expr (ARRAY_NOTATION_LENGTH (t), flags | TFF_EXPR_IN_PARENS); + pp_string (cxx_pp, ":"); + dump_expr (ARRAY_NOTATION_STRIDE (t), flags | TFF_EXPR_IN_PARENS); + pp_cxx_right_bracket (cxx_pp); + break; + case UNARY_PLUS_EXPR: dump_unary_op ("+", t, flags); break; diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c old mode 100644 new mode 100755 index d844d15..7bc9334 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -6060,6 +6060,170 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p, return error_mark_node; } +/* This function parses Cilk Plus array notations. The starting index is + passed in INIT_INDEX and the array name is passed in ARRAY_VALUE. If the + INIT_INDEX is NULL, then we have special case were the entire array is + accessed (e.g. A[:]). The return value of this function is a tree node + called VALUE_TREE of type ARRAY_NOTATION_REF. If some error occurred it + returns error_mark_node. */ + +static tree +cp_parser_array_notation (location_t loc, cp_parser *parser, tree init_index, + tree array_value) +{ + cp_token *token = NULL; + tree start_index = NULL_TREE, length_index = NULL_TREE, stride = NULL_TREE; + tree value_tree, type, array_type, array_type_domain; + double_int x; + bool saved_colon_corrects_to_scope_p = parser->colon_corrects_to_scope_p; + + if (!array_value || array_value == error_mark_node) + { + cp_parser_skip_to_end_of_statement (parser); + return error_mark_node; + } + + if (processing_template_decl) + { + array_type = TREE_TYPE (array_value); + type = TREE_TYPE (array_type); + } + else + { + array_type = TREE_TYPE (array_value); + gcc_assert (array_type); + type = array_type; + } + token = cp_lexer_peek_token (parser->lexer); + if (!token) + { + cp_parser_error (parser, "expected %<:%> or numeral"); + return error_mark_node; + } + else if (token->type == CPP_COLON) + { + if (!init_index) + { + /* If we are here, then we have a case like this A[:]. */ + cp_lexer_consume_token (parser->lexer); + + if (cp_lexer_peek_token (parser->lexer)->type != CPP_CLOSE_SQUARE) + { + cp_parser_error (parser, "expected %<]%>"); + cp_parser_skip_to_end_of_statement (parser); + return error_mark_node; + } + if (TREE_CODE (array_type) == RECORD_TYPE + || TREE_CODE (array_type) == POINTER_TYPE) + { + error_at (loc, "start-index and length fields necessary for " + "using array notations in pointers or records"); + cp_parser_skip_to_end_of_statement (parser); + return error_mark_node; + } + if (TREE_CODE (array_type) == ARRAY_TYPE) + { + tree subtype = TREE_TYPE (array_type); + while (subtype && TREE_CODE (subtype) == POINTER_TYPE) + { + /* This could be a function ptr. If so, then emit error. */ + subtype = TREE_TYPE (subtype); + if (subtype && TREE_CODE (subtype) == FUNCTION_TYPE) + { + error_at (loc, "array notations cannot be used with" + " function pointer arrays"); + cp_parser_skip_to_end_of_statement (parser); + return error_mark_node; + } + } + } + array_type_domain = TYPE_DOMAIN (array_type); + if (!array_type_domain) + { + error_at (loc, "start-index and length fields necessary for " + "using array notations in dimensionless arrays"); + cp_parser_skip_to_end_of_statement (parser); + return error_mark_node; + } + start_index = TYPE_MINVAL (array_type_domain); + start_index = fold_build1 (CONVERT_EXPR, ptrdiff_type_node, + start_index); + x = TREE_INT_CST (TYPE_MAXVAL (array_type_domain)); + x.low++; + length_index = double_int_to_tree (integer_type_node, x); + length_index = fold_build1 (CONVERT_EXPR, ptrdiff_type_node, + length_index); + stride = build_int_cst (integer_type_node, 1); + stride = fold_build1 (CONVERT_EXPR, ptrdiff_type_node, stride); + } + else if (init_index != error_mark_node) + { + /* If we hare here, then there are 2 possibilities: + 1. Array [ EXPR : EXPR ] + 2. Array [ EXPR : EXPR : EXPR ] + */ + start_index = init_index; + cp_lexer_consume_token (parser->lexer); + + saved_colon_corrects_to_scope_p = parser->colon_corrects_to_scope_p; + /* The ':' is used in array notation. Thus compiler cannot do scope + correction automatically. */ + parser->colon_corrects_to_scope_p = false; + length_index = cp_parser_expression (parser, false, NULL); + parser->colon_corrects_to_scope_p = saved_colon_corrects_to_scope_p; + if (!length_index || length_index == error_mark_node) + cp_parser_skip_to_end_of_statement (parser); + + if (cp_lexer_peek_token (parser->lexer)->type == CPP_COLON) + { + cp_lexer_consume_token (parser->lexer); + saved_colon_corrects_to_scope_p = + parser->colon_corrects_to_scope_p; + /* Disable correcting single colon correcting to scope. */ + parser->colon_corrects_to_scope_p = false; + stride = cp_parser_expression (parser, false, NULL); + parser->colon_corrects_to_scope_p = + saved_colon_corrects_to_scope_p; + if (!stride || stride == error_mark_node) + { + cp_parser_skip_to_end_of_statement (parser); + if (cp_lexer_peek_token (parser->lexer)->type + == CPP_CLOSE_SQUARE) + cp_lexer_consume_token (parser->lexer); + } + } + else + stride = build_one_cst (integer_type_node); + } + else + { + cp_parser_skip_to_end_of_statement (parser); + return error_mark_node; + } + } + + if (start_index == error_mark_node || length_index == error_mark_node + || stride == error_mark_node || !start_index || !length_index + || !stride) + { + if (cp_lexer_peek_token (parser->lexer)->type == CPP_CLOSE_SQUARE) + cp_lexer_consume_token (parser->lexer); + return error_mark_node; + } + cp_parser_require (parser, CPP_CLOSE_SQUARE, RT_CLOSE_SQUARE); + + /* We fold all 3 of the values to make things easier when we transform + them later. */ + start_index = fold (start_index); + length_index = fold (length_index); + stride = fold (stride); + + value_tree = build_array_notation_ref (input_location, array_value, + start_index, length_index, stride, + type); + return value_tree; +} + /* A subroutine of cp_parser_postfix_expression that also gets hijacked by cp_parser_builtin_offsetof. We're looking for @@ -6081,41 +6245,78 @@ cp_parser_postfix_open_square_expression (cp_parser *parser, /* Consume the `[' token. */ cp_lexer_consume_token (parser->lexer); - /* Parse the index expression. */ - /* ??? For offsetof, there is a question of what to allow here. If - offsetof is not being used in an integral constant expression context, - then we *could* get the right answer by computing the value at runtime. - If we are in an integral constant expression context, then we might - could accept any constant expression; hard to say without analysis. - Rather than open the barn door too wide right away, allow only integer - constant expressions here. */ - if (for_offsetof) - index = cp_parser_constant_expression (parser, false, NULL); + if (flag_enable_cilkplus + && cp_lexer_peek_token (parser->lexer)->type == CPP_COLON) + /* If we are here, then we have something like this: + ARRAY[:] + */ + postfix_expression = cp_parser_array_notation (loc, parser, NULL_TREE, + postfix_expression); else { - if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE)) + /* Here are have these options: + 1. ARRAY[EXPR] -- This is the normal array call. + 2. ARRAY[EXPR : EXPR] -- Array notation expr with default stride + of 1. + 3. ARRAY[EXPR : EXPR : EXPR] -- Array Notation with userdefined stride. + 4. Array[Braced List] -- This is handled by braced list. + */ + + /* Parse the index expression. */ + /* ??? For offsetof, there is a question of what to allow here. If + offsetof is not being used in an integral constant expression context, + then we *could* get the right answer by computing the value at runtime. + If we are in an integral constant expression context, then we might + could accept any constant expression; hard to say without analysis. + Rather than open the barn door too wide right away, allow only integer + constant expressions here. */ + if (for_offsetof) + index = cp_parser_constant_expression (parser, false, NULL); + else { - bool expr_nonconst_p; - maybe_warn_cpp0x (CPP0X_INITIALIZER_LISTS); - index = cp_parser_braced_list (parser, &expr_nonconst_p); + bool saved_colon_corrects_to_scope_p = + parser->colon_corrects_to_scope_p; + if (flag_enable_cilkplus) + parser->colon_corrects_to_scope_p = false; + if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE)) + { + bool expr_nonconst_p; + maybe_warn_cpp0x (CPP0X_INITIALIZER_LISTS); + index = cp_parser_braced_list (parser, &expr_nonconst_p); + if (flag_enable_cilkplus + && cp_lexer_peek_token (parser->lexer)->type == CPP_COLON) + { + error_at (cp_lexer_peek_token (parser->lexer)->location, + "braced list index is not allowed with array " + "notations"); + index = error_mark_node; + } + } + else + index = cp_parser_expression (parser, /*cast_p=*/false, NULL); + parser->colon_corrects_to_scope_p = saved_colon_corrects_to_scope_p; } + if (flag_enable_cilkplus + && cp_lexer_peek_token (parser->lexer)->type == CPP_COLON) + postfix_expression = cp_parser_array_notation (loc, parser, index, + postfix_expression); else - index = cp_parser_expression (parser, /*cast_p=*/false, NULL); - } - - /* Look for the closing `]'. */ - cp_parser_require (parser, CPP_CLOSE_SQUARE, RT_CLOSE_SQUARE); - - /* Build the ARRAY_REF. */ - postfix_expression = grok_array_decl (loc, postfix_expression, - index, decltype_p); + { + /* Look for the closing `]'. */ + cp_parser_require (parser, CPP_CLOSE_SQUARE, RT_CLOSE_SQUARE); - /* When not doing offsetof, array references are not permitted in - constant-expressions. */ - if (!for_offsetof - && (cp_parser_non_integral_constant_expression (parser, NIC_ARRAY_REF))) - postfix_expression = error_mark_node; + /* Build the ARRAY_REF. */ + postfix_expression = grok_array_decl (loc, postfix_expression, + index, decltype_p); + /* When not doing offsetof, array references are not permitted in + constant-expressions. */ + if (!for_offsetof + && (cp_parser_non_integral_constant_expression (parser, + NIC_ARRAY_REF))) + postfix_expression = error_mark_node; + } + } return postfix_expression; } @@ -9350,6 +9551,8 @@ cp_parser_compound_statement (cp_parser *parser, tree in_statement_expr, /* Consume the `}'. */ cp_parser_require (parser, CPP_CLOSE_BRACE, RT_CLOSE_BRACE); + if (flag_enable_cilkplus && contains_array_notation_expr (compound_stmt)) + compound_stmt = expand_array_notation_exprs (compound_stmt); return compound_stmt; } @@ -9542,6 +9745,14 @@ cp_parser_selection_statement (cp_parser* parser, bool *if_p) /* Now we're all done with the switch-statement. */ finish_switch_stmt (statement); + if (flag_enable_cilkplus + && contains_array_notation_expr (condition)) + { + error_at (EXPR_LOCATION (condition), + "array notations cannot be used as a condition for " + "switch statement"); + statement = error_mark_node; + } } return statement; @@ -10102,6 +10313,12 @@ cp_parser_iteration_statement (cp_parser* parser) parser->in_statement = in_statement; /* We're done with the while-statement. */ finish_while_stmt (statement); + if (flag_enable_cilkplus && contains_array_notation_expr (condition)) + { + error_at (EXPR_LOCATION (condition), "array notations cannot be " + "used as a condition for while statement"); + statement = error_mark_node; + } } break; @@ -10128,6 +10345,15 @@ cp_parser_iteration_statement (cp_parser* parser) cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN); /* Look for the `;'. */ cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON); + if (flag_enable_cilkplus + && contains_array_notation_expr (DO_COND (statement))) + { + error_at (EXPR_LOCATION (DO_COND (statement)), + "array notations cannot be used as a condition for a " + "do-while statement"); + statement = error_mark_node; + } + } break; @@ -10146,8 +10372,17 @@ cp_parser_iteration_statement (cp_parser* parser) cp_parser_already_scoped_statement (parser); parser->in_statement = in_statement; - /* We're done with the for-statement. */ - finish_for_stmt (statement); + if (flag_enable_cilkplus + && contains_array_notation_expr (FOR_COND (statement))) + { + error_at (EXPR_LOCATION (FOR_COND (statement)), + "array notations cannot be used in a condition for a " + "for-loop"); + statement = error_mark_node; + } + else + /* We're done with the for-statement. */ + finish_for_stmt (statement); } break; @@ -16722,30 +16957,53 @@ cp_parser_direct_declarator (cp_parser* parser, { bool non_constant_p; - bounds - = cp_parser_constant_expression (parser, - /*allow_non_constant=*/true, - &non_constant_p); - if (!non_constant_p) - /* OK */; - else if (error_operand_p (bounds)) - /* Already gave an error. */; - else if (!parser->in_function_body - || current_binding_level->kind == sk_function_parms) + if (flag_enable_cilkplus + && cp_lexer_next_token_is (parser->lexer, CPP_COLON)) { - /* Normally, the array bound must be an integral constant - expression. However, as an extension, we allow VLAs - in function scopes as long as they aren't part of a - parameter declaration. */ - cp_parser_error (parser, - "array bound is not an integer constant"); bounds = error_mark_node; + error_at (cp_lexer_peek_token (parser->lexer)->location, + "array notations cannot be used in declaration"); + cp_lexer_consume_token (parser->lexer); } - else if (processing_template_decl) + else { - /* Remember this wasn't a constant-expression. */ - bounds = build_nop (TREE_TYPE (bounds), bounds); - TREE_SIDE_EFFECTS (bounds) = 1; + bounds + = cp_parser_constant_expression (parser, + /*allow_non_constant=*/true, + &non_constant_p); + if (!non_constant_p) + /* OK */; + else if (error_operand_p (bounds)) + /* Already gave an error. */; + else if (!parser->in_function_body + || current_binding_level->kind == sk_function_parms) + { + /* Normally, the array bound must be an integral constant + expression. However, as an extension, we allow VLAs + in function scopes as long as they aren't part of a + parameter declaration. */ + cp_parser_error (parser, + "array bound is not an integer constant"); + bounds = error_mark_node; + } + else if (processing_template_decl) + { + /* Remember this wasn't a constant-expression. */ + bounds = build_nop (TREE_TYPE (bounds), bounds); + TREE_SIDE_EFFECTS (bounds) = 1; + } + if (flag_enable_cilkplus + && cp_lexer_next_token_is (parser->lexer, CPP_COLON)) + { + location_t loc = + cp_lexer_peek_token (parser->lexer)->location; + while (cp_lexer_next_token_is_not (parser->lexer, + CPP_CLOSE_SQUARE)) + cp_lexer_consume_token (parser->lexer); + error_at (loc, "array notations cannot be used in " + "declaration"); + bounds = error_mark_node; + } } } else @@ -18116,6 +18374,11 @@ cp_parser_ctor_initializer_opt_and_function_body (cp_parser *parser, cp_parser_function_body (parser, in_function_try_block); if (check_body_p) check_constexpr_ctor_body (last, list); + + /* Transform all array notations to the equivalent array refs and loop. */ + if (flag_enable_cilkplus && contains_array_notation_expr (body)) + body = expand_array_notation_exprs (body); + /* Finish the function body. */ finish_function_body (body); @@ -22095,6 +22358,12 @@ cp_parser_function_definition_after_declarator (cp_parser* parser, finish_lambda_scope (); + /* Expand all array notation expressions here. */ + if (flag_enable_cilkplus && current_function_decl + && contains_array_notation_expr (DECL_SAVED_TREE (current_function_decl))) + DECL_SAVED_TREE (current_function_decl) = + expand_array_notation_exprs (DECL_SAVED_TREE (current_function_decl)); + /* Finish the function. */ fn = finish_function ((ctor_initializer_p ? 1 : 0) | (inline_p ? 2 : 0)); diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c old mode 100644 new mode 100755 index 3602fcd..0a7d523 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -13740,6 +13740,20 @@ tsubst_copy_and_build (tree t, RECUR (TREE_OPERAND (t, 1)), complain|decltype_flag)); + case ARRAY_NOTATION_REF: + { + tree start_index, length, stride; + op1 = tsubst_non_call_postfix_expression (ARRAY_NOTATION_ARRAY (t), + args, complain, in_decl); + start_index = RECUR (ARRAY_NOTATION_START (t)); + length = RECUR (ARRAY_NOTATION_LENGTH (t)); + stride = RECUR (ARRAY_NOTATION_STRIDE (t)); + if (!cilkplus_an_triplet_types_ok_p (loc, start_index, length, stride, + TREE_TYPE (op1))) + RETURN (error_mark_node); + RETURN (build_array_notation_ref (EXPR_LOCATION (t), op1, start_index, + length, stride, TREE_TYPE (op1))); + } case SIZEOF_EXPR: if (PACK_EXPANSION_P (TREE_OPERAND (t, 0))) RETURN (tsubst_copy (t, args, complain, in_decl)); @@ -15712,6 +15726,9 @@ type_unification_real (tree tparms, arg = args[ia]; ++ia; + if (flag_enable_cilkplus && TREE_CODE (arg) == ARRAY_NOTATION_REF) + return 1; + if (unify_one_argument (tparms, targs, parm, arg, subr, strict, flags, explain_p)) return 1; @@ -19119,6 +19136,11 @@ instantiate_decl (tree d, int defer_ok, pointer_map_destroy (local_specializations); local_specializations = saved_local_specializations; + /* We expand all the array notation expressions here. */ + if (flag_enable_cilkplus + && contains_array_notation_expr (DECL_SAVED_TREE (d))) + DECL_SAVED_TREE (d) = expand_array_notation_exprs (DECL_SAVED_TREE (d)); + /* Finish the function. */ d = finish_function (0); expand_or_defer_fn (d); diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 0a700b7..f27a70d 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -779,6 +779,22 @@ finish_return_stmt (tree expr) tree r; bool no_warning; + if (flag_enable_cilkplus && contains_array_notation_expr (expr)) + { + size_t rank = 0; + + if (!find_rank (input_location, expr, expr, false, &rank)) + return error_mark_node; + + /* If the return expression contains array notatinos, then flag it as + error. */ + if (rank >= 1) + { + error_at (input_location, "array notation expression cannot be " + "used as a return value"); + return error_mark_node; + } + } expr = check_return_expr (expr, &no_warning); if (flag_openmp && !check_omp_return ()) @@ -8073,6 +8089,7 @@ cxx_eval_constant_expression (const constexpr_call *call, tree t, non_constant_p, overflow_p); break; + case ARRAY_NOTATION_REF: case ARRAY_REF: r = cxx_eval_array_reference (call, t, allow_non_constant, addr, non_constant_p, overflow_p); @@ -8884,6 +8901,7 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags) want_rval = true; /* Fall through. */ case ARRAY_REF: + case ARRAY_NOTATION_REF: case ARRAY_RANGE_REF: case MEMBER_REF: case DOTSTAR_EXPR: diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index 8524f6c..dd2fda4 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -141,6 +141,7 @@ lvalue_kind (const_tree ref) case INDIRECT_REF: case ARROW_EXPR: case ARRAY_REF: + case ARRAY_NOTATION_REF: case PARM_DECL: case RESULT_DECL: return clk_ordinary; diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c old mode 100644 new mode 100755 index 11ac85b..17f19c7 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -3005,6 +3005,22 @@ cp_build_array_ref (location_t loc, tree array, tree idx, return error_mark_node; } + /* If an array's index is an array notation, then its rank cannot be + greater than one. */ + if (flag_enable_cilkplus && contains_array_notation_expr (idx)) + { + size_t rank = 0; + + /* If find_rank returns false, then it should have reported an error, + thus it is unnecessary for repetition. */ + if (!find_rank (loc, idx, idx, true, &rank)) + return error_mark_node; + if (rank > 1) + { + error_at (loc, "rank of the array%'s index is greater than 1"); + return error_mark_node; + } + } if (TREE_TYPE (array) == error_mark_node || TREE_TYPE (idx) == error_mark_node) return error_mark_node; @@ -3477,8 +3493,12 @@ cp_build_function_call_vec (tree function, vec **params, params = &allocated; } - nargs = convert_arguments (parm_types, params, fndecl, LOOKUP_NORMAL, - complain); + if (flag_enable_cilkplus + && is_cilkplus_reduce_builtin (fndecl) != BUILT_IN_NONE) + nargs = (*params)->length (); + else + nargs = convert_arguments (parm_types, params, fndecl, LOOKUP_NORMAL, + complain); if (nargs < 0) return error_mark_node; @@ -3936,8 +3956,15 @@ cp_build_binary_op (location_t location, } } - type0 = TREE_TYPE (op0); - type1 = TREE_TYPE (op1); + if (flag_enable_cilkplus && contains_array_notation_expr (op0)) + type0 = find_correct_array_notation_type (op0); + else + type0 = TREE_TYPE (op0); + + if (flag_enable_cilkplus && contains_array_notation_expr (op1)) + type1 = find_correct_array_notation_type (op1); + else + type1 = TREE_TYPE (op1); /* The expression codes of the data types of the arguments tell us whether the arguments are integers, floating, pointers, etc. */ @@ -5140,6 +5167,13 @@ cp_build_addr_expr_1 (tree arg, bool strict_lvalue, tsubst_flags_t complain) gcc_assert (!identifier_p (arg) || !IDENTIFIER_OPNAME_P (arg)); + if (flag_enable_cilkplus && TREE_CODE (arg) == ARRAY_NOTATION_REF) + { + val = build_address (arg); + if (TREE_CODE (arg) == OFFSET_REF) + PTRMEM_OK_P (val) = PTRMEM_OK_P (arg); + return val; + } if (TREE_CODE (arg) == COMPONENT_REF && type_unknown_p (arg) && !really_overloaded_fn (TREE_OPERAND (arg, 1))) { @@ -7818,6 +7852,13 @@ convert_for_assignment (tree type, tree rhs, tree rhstype; enum tree_code coder; + /* If we are dealing with built-in array notation function then we don't need + to convert them. They will be broken up into modify exprs in future, + during which all these checks will be done. */ + if (flag_enable_cilkplus + && is_cilkplus_reduce_builtin (fndecl) != BUILT_IN_NONE) + return rhs; + /* Strip NON_LVALUE_EXPRs since we aren't using as an lvalue. */ if (TREE_CODE (rhs) == NON_LVALUE_EXPR) rhs = TREE_OPERAND (rhs, 0); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog old mode 100644 new mode 100755 diff --git a/gcc/testsuite/c-c++-common/cilk-plus/AN/if_test_errors.c b/gcc/testsuite/c-c++-common/cilk-plus/AN/if_test_errors.c index d17d8cf..579d396 100644 --- a/gcc/testsuite/c-c++-common/cilk-plus/AN/if_test_errors.c +++ b/gcc/testsuite/c-c++-common/cilk-plus/AN/if_test_errors.c @@ -18,19 +18,19 @@ int main (void) array2[:] = 5; else array2[:] = 10; - if (!(array[0:10:1] + array[0:10:1])) /* { dg-error "condition and the then-block" } */ - array2d[:][:] = 5; + if (!(array[0:10:1] + array[0:10:1])) /* { dg-error "condition and the then-block" "" { target c } } */ + array2d[:][:] = 5; /* { dg-error "rank mismatch with controlling expression of parent" "" { target c++ } } */ else array2[:] = 10; - if (!(array[0:10:1] + array[0:10:1])) /* { dg-error "condition and the else-block" } */ + if (!(array[0:10:1] + array[0:10:1])) /* { dg-error "condition and the else-block" "" { target c } } */ array2[:] = 5; else - array2d[:][:] = 10; + array2d[:][:] = 10; /* { dg-error "rank mismatch with controlling expression of parent" "" { target c++ } } */ - if (TwodArray[:][:] != 10) /* { dg-error "condition and the then-block" } */ - array2[:] = 10; + if (TwodArray[:][:] != 10) /* { dg-error "condition and the then-block" "" { target c } } */ + array2[:] = 10; /* { dg-error "rank mismatch with controlling expression of parent" "" { target c++ } } */ else array2[:] = 5; @@ -40,8 +40,8 @@ int main (void) array4[32][:][:][:] = 5; /* atoi(argv[1]) == 10, so it will convert all 10's to 5's */ - if (FourDArray[42][0:10:1][9:10:-1][0:5:2] != 10) /* { dg-error "condition and the then-block" } */ - array4[0:10:1][0:5:2][9:10:-1][0:5:2] = 10; + if (FourDArray[42][0:10:1][9:10:-1][0:5:2] != 10) /* { dg-error "condition and the then-block" "" { target c } } */ + array4[0:10:1][0:5:2][9:10:-1][0:5:2] = 10; /* { dg-error "rank mismatch with controlling expression of parent" "" { target c++ } } */ else array4[0:10:1][0:5:2][9:10:-1][0:5:2] = 5; diff --git a/gcc/testsuite/c-c++-common/cilk-plus/AN/misc.c b/gcc/testsuite/c-c++-common/cilk-plus/AN/misc.c index 35eb115..14421d9 100644 --- a/gcc/testsuite/c-c++-common/cilk-plus/AN/misc.c +++ b/gcc/testsuite/c-c++-common/cilk-plus/AN/misc.c @@ -73,13 +73,13 @@ int main (void) while (ii != array2[1:x:3][1:2:1]) /* { dg-error "array notations cannot be used as a condition for while statement" } */ x = 2; - do { /* { dg-error "array notations cannot be used as a condition for a do-while statement" } */ + do { /* { dg-error "array notations cannot be used as a condition for a do-while statement" "" { target c } } */ x = 3; - } while (ii != array2[:][:]); + } while (ii != array2[:][:]); /* { dg-error "array notations cannot be used as a condition for a do-while statement" "" { target c++ } } */ - do { /* { dg-error "array notations cannot be used as a condition for a do-while statement" } */ + do { /* { dg-error "array notations cannot be used as a condition for a do-while statement" "" { target c } } */ x = 2; - } while (ii != (x + array2[:][1:x:2]) + 2); + } while (ii != (x + array2[:][1:x:2]) + 2); /* { dg-error "array notations cannot be used as a condition for a do-while statement" "" { target c++ } } */ do { x += 3; diff --git a/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors.c b/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors.c old mode 100644 new mode 100755 index a0a3742..18816e0 --- a/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors.c +++ b/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors.c @@ -8,4 +8,4 @@ int main (void) array2[:] = array2[: ; /* { dg-error "expected ']'" } */ return 0; -} /* { dg-error "expected ';' before" } */ +} /* { dg-error "expected ';' before" "" { target c } } */ diff --git a/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors2.c b/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors2.c index 2e86b4f..4314090 100644 --- a/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors2.c +++ b/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors2.c @@ -5,7 +5,8 @@ int main (void) { int array[10][10], array2[10]; - array2[:] = array2[1:2:] ; /* { dg-error "expected expression before" } */ + array2[:] = array2[1:2:] ; /* { dg-error "expected expression before" "" { target c } } */ + /* { dg-error "expected primary-expression before" "" { target c++ } 8 } */ - return 0; /* { dg-error "expected ';' before" } */ + return 0; /* { dg-error "expected ';' before" "" { target c } } */ } diff --git a/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors3.c b/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors3.c index 34dfa16..47b5979 100644 --- a/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors3.c +++ b/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors3.c @@ -5,7 +5,8 @@ int main (void) { int array[10][10], array2[10]; - array2[:] = array2[1::] ; /* { dg-error "expected expression before" } */ + array2[:] = array2[1: :] ; /* { dg-error "expected expression before" "" { target c } } */ + /* { dg-error "expected primary-expression before" "" { target c++ } 8 } */ - return 0; /* { dg-error "expected ';' before" } */ + return 0; /* { dg-error "expected ';' before" "" { target c } } */ } diff --git a/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors4.c b/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors4.c index eba28a8..a0efc04 100644 --- a/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors4.c +++ b/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors4.c @@ -5,7 +5,7 @@ int main (void) { int array[10][10], array2[10]; - array2[:] = array2[::] ; /* { dg-error " expected ']' before ':' token" } */ + array2[:] = array2[ : : ] ; /* { dg-error " expected ']' before ':' token" } */ return 0; } diff --git a/gcc/testsuite/c-c++-common/cilk-plus/AN/pr57541.c b/gcc/testsuite/c-c++-common/cilk-plus/AN/pr57541.c index cabdb23..4c80c42 100755 --- a/gcc/testsuite/c-c++-common/cilk-plus/AN/pr57541.c +++ b/gcc/testsuite/c-c++-common/cilk-plus/AN/pr57541.c @@ -4,11 +4,14 @@ int A[10]; int main () { - char c = (char)N; /* { dg-error "undeclared" } */ + + /* C compiler uses the term "undeclared" whereas C++ compiler uses + "not declared". Thus, grepping for declared seem to be the easiest. */ + char c = (char)N; /* { dg-error "declared" } */ short s = (short)N; long l = (long)N; A[l:s:c]; } -/* { dg-message "note: each" "defined" { target *-*-* } 7 } */ +/* { dg-message "note: each" "defined" { target c } 7 } */ diff --git a/gcc/testsuite/c-c++-common/cilk-plus/AN/vla.c b/gcc/testsuite/c-c++-common/cilk-plus/AN/vla.c index 843745e..3b0777e 100644 --- a/gcc/testsuite/c-c++-common/cilk-plus/AN/vla.c +++ b/gcc/testsuite/c-c++-common/cilk-plus/AN/vla.c @@ -1,5 +1,5 @@ -/* { dg-do compile } */ -/* { dg-options "-fcilkplus -std=c99" } */ +/* { dg-do compile { target c } } */ +/* { dg-options "-fcilkplus -std=c99 -w" } */ int func (int x) { diff --git a/gcc/testsuite/g++.dg/cilk-plus/AN/array_test1_tplt.cc b/gcc/testsuite/g++.dg/cilk-plus/AN/array_test1_tplt.cc new file mode 100644 index 0000000..e9ee7ec --- /dev/null +++ b/gcc/testsuite/g++.dg/cilk-plus/AN/array_test1_tplt.cc @@ -0,0 +1,118 @@ +/* { dg-do run } */ +/* { dg-options "-fcilkplus" } */ + +#include +#include +#if HAVE_IO +#include +#endif +template int main2 (char **argv); + +int main (void) +{ + int x = 1, y = 1, z = 1; + char *array[2]; + array[0] = strdup ("a.out"); + array[1] = strdup ("5"); + x = main2 (array); + x += main2 (array); + y = main2 (array); + y += main2 (array); + y += main2 (array); + y += main2 (array); + z = main2 (array); + z += main2 (array); + y += main2 (array); + z += main2 (array); + + return x+y+z; +} +template +int main2 (char **argv) +{ + T array[10]; + int ii = 0, x = 2, z= 0 , y = 0; + + for (ii = 0; ii < 10; ii++) + array[ii] = 10; + + array[0:10:1] = (T)15; + + for (ii = 0; ii < 10; ii++) + if (array[ii] != (T)15) + return 1; + + + array[0:5:2] = (T)20; + + for (ii = 0; ii < 10; ii += 2) + if (array[ii] != (T)20) + return 2; + + + x = atoi(argv[1]); + z = (10-atoi(argv[1]))/atoi(argv[1]); + + array[x:5:z] = (T)50; + + for (ii = x; ii < 10; ii += z) + if (array[ii] != (T)50) + return 3; + + x = atoi(argv[1]); + z = (10-atoi(argv[1]))/atoi(argv[1]); /* (10 - 5) / 5 = 1 */ + y = 10-atoi(argv[1]); + + array[x:y:z] = (T)52; +#if HAVE_IO + for (ii = atoi ("5"); ii < (atoi ("5") + atoi ("5")); ii += atoi ("1")) + std::printf("%d\t", (int)array[ii]); + std::printf("\n"); +#endif + for (ii = x; ii < 10; ii += z) + if (array[ii] != (T)52) + return 4; + + + x = atoi(argv[1]); + z = (10-atoi(argv[1]))/atoi(argv[1]); + y = 10-atoi(argv[1]); + + array[x:y:((10-atoi(argv[1]))/atoi(argv[1]))] = (T)25; + + for (ii = x; ii < 10; ii += z) + if (array[ii] != (T)25) + return 5; + + x = atoi(argv[1]); + z = (10-atoi(argv[1]))/atoi(argv[1]); + y = 10-atoi(argv[1]); + + array[atoi(argv[1]):(10-atoi(argv[1])):((10-atoi(argv[1]))/atoi(argv[1]))] = + (T)14; + for (ii = x; ii < 10; ii += z) + if (array[ii] != (T)14) + return 6; + + + array[atoi("5"):5:1] = (T)65; + + for (ii = atoi ("5"); ii < 10; ii++) + if (array[ii] != (T)65) + return 7; + + + array[atoi("5"):atoi("5"):atoi("1")] = 99; + +#if HAVE_IO + for (ii = atoi ("5"); ii < (atoi ("5") + atoi ("5")); ii += atoi ("1")) + std::printf("%d\t", (int)array[ii]); + std::printf("\n"); +#endif + + for (ii = atoi ("5"); ii < (atoi ("5") + atoi ("5")); ii += atoi ("1")) + if (array[ii] != (T)99) + return 8; + + return 0; +} diff --git a/gcc/testsuite/g++.dg/cilk-plus/AN/array_test2_tplt.cc b/gcc/testsuite/g++.dg/cilk-plus/AN/array_test2_tplt.cc new file mode 100644 index 0000000..87c37e1 --- /dev/null +++ b/gcc/testsuite/g++.dg/cilk-plus/AN/array_test2_tplt.cc @@ -0,0 +1,141 @@ +/* { dg-do run } */ +/* { dg-options "-fcilkplus" } */ + +#include +#include +template int main2(char **argv); +int main(void) +{ + int x = 1, y = 1, z = 1, w = 1; + char *array[2]; + array[0] = strdup ("a.out"); + array[1] = strdup ("5"); + w = main2(array); + w += main2 (array); + x = main2 (array); + x += main2 (array); + y = main2 (array); + y += main2 (array); + z = main2 (array); + z += main2 (array); + z += main2 (array); + + return (w+x+y+z); +} + +template +int main2(char **argv) +{ + T array[10], array2[10]; + int ii = 0, x = 2, z= 0 , y = 0 ; + + for (ii = 0; ii < 10; ii++) + { + array[ii] = 10; + array2[ii] = 5000000; + } + + array2[0:10:1] = array[0:10:1]; + + for (ii = 0; ii < 10; ii++) + if (array2[ii] != array[ii]) + return 1; + + for (ii = 0; ii < 10; ii++) + { + array[ii] = 10; + array2[ii] = 5000000; + } + + array2[0:5:2] = array[0:5:2]; + + for (ii = 0; ii < 10; ii += 2) + if (array[ii] != array2[ii]) + return 2; + + for (ii = 0; ii < 10; ii++) + { + array[ii] = 10; + array2[ii] = 5000000; + } + x = atoi(argv[1]); + z = (10-atoi(argv[1]))/atoi(argv[1]); + + array2[x:5:z] = array[x:5:z]; + + for (ii = x; ii < 5; ii += z) + if (array2[ii] != array[ii]) + return 3; + + for (ii = 0; ii < 10; ii++) + { + array[ii] = 500; + array2[ii] = 1000000; + } + x = atoi(argv[1]); + z = (10-atoi(argv[1]))/atoi(argv[1]); + y = 10-atoi(argv[1]); + + array2[x:y:z] = array[x:y:z]; + for (ii = x; ii < 10; ii = ii + z) + if (array2[ii] != array[ii]) + return 4; + + for (ii = 0; ii < 10; ii++) + { + array[ii] = 500; + array2[ii] = 1000000; + } + x = atoi(argv[1]); + z = (10-atoi(argv[1]))/atoi(argv[1]); + y = 10-atoi(argv[1]); + + array[x:y:((10-atoi(argv[1]))/atoi(argv[1]))] = + array2[x:y:((10-atoi(argv[1]))/atoi(argv[1]))]; + + for (ii = x; ii < 10; ii += z) + if (array[ii] != array2[ii]) + return 6; + + + x = atoi(argv[1]); + z = (10-atoi(argv[1]))/atoi(argv[1]); + y = 10-atoi(argv[1]); + + for (ii = 0; ii < 10; ii++) + { + array[ii] = 500; + array2[ii] = 1000000; + } + + array[atoi(argv[1]):(10-atoi(argv[1])):((10-atoi(argv[1]))/atoi(argv[1]))] = + array2[atoi(argv[1]):(10-atoi(argv[1])):((10-atoi(argv[1]))/atoi(argv[1]))]; + for (ii = x; ii < 10; ii += z) + if (array[ii] != array2[ii]) + return 6; + + for (ii = 0; ii < 10; ii++) + { + array[ii] = 4; + array2[ii] = 2; + } + + array[atoi("5"):5:1] = array2[atoi("5"):5:1]; + + for (ii = atoi ("5"); ii < 10; ii++) + if (array[ii] != array2[ii]) + return 7; + + for (ii = 0; ii < 10; ii++) + { + array[ii] = 5; + array2[ii] = 1; + } + array[atoi("5"):atoi("5"):atoi("1")] = array2[atoi("5"):atoi("5"):atoi("1")]; + + for (ii = 5; ii < 10; ii++) + if (array2[ii] != array[ii]) + return 8; + + return 0; +} diff --git a/gcc/testsuite/g++.dg/cilk-plus/AN/array_test_ND_tplt.cc b/gcc/testsuite/g++.dg/cilk-plus/AN/array_test_ND_tplt.cc new file mode 100644 index 0000000..479ba13 --- /dev/null +++ b/gcc/testsuite/g++.dg/cilk-plus/AN/array_test_ND_tplt.cc @@ -0,0 +1,115 @@ +/* { dg-do run } */ +/* { dg-options "-fcilkplus" } */ + +#include +#include +template int main2(char **argv); + +int main(void) +{ + int x = 1, y=1, z=1, w = 1; + char *array[3]; + array[0] = strdup ("a.out"); + array[1] = strdup ("10"); + array[2] = strdup ("15"); + w = main2 (array); + w += main2 (array); + x = main2 (array); + x += main2 (array); + y = main2 (array); + y += main2 (array); + z = main2 (array); + z += main2 (array); + return x+y+z; +} + +template +int main2(char **argv) +{ + T array[10][15]; + T array_2[10][15]; + int ii = 0, jj = 0,x = 0, z= 1 , y = 10 ,argc = 3; + + + for (ii = 0; ii < 10; ii++) { + for (jj = 0; jj< 15; jj++) { + array[ii][jj] = ii+jj; + array_2[ii][jj] = 0; + } + } + array_2[0:5:2][0:5:3] = array[0:5:2][0:5:3] + 1 + 5 + array[0][5] + x; + + for (ii = 0; ii < 10; ii += 2) + { + for (jj = 0; jj < 15; jj += 3) + { + if (array_2[ii][jj] != array[ii][jj] + 1 + 5 + array[0][5] + x) + return 1; + } + } + + + for (ii = 0; ii < 10; ii++) { + for (jj = 0; jj< 15; jj++) { + array[ii][jj] = ii+jj; + array_2[ii][jj] = 0; + } + } + x = atoi(argv[1]); + y = atoi(argv[2]); + array_2[0:x:1][0:y:1] = array[0:x:1][0:y:1] + x + y + array[0:x:1][0:y:1]; + + for (ii = 0; ii < x; ii++) + { + for (jj = 0; jj < y; jj++) + { + if (array_2[ii][jj] != array[ii][jj] + x + y + array[ii][jj]) + return 2; + } + } + + for (ii = 0; ii < 10; ii++) { + for (jj = 0; jj< 15; jj++) { + array[ii][jj] = ii+jj; + array_2[ii][jj] = 0; + } + } + x = atoi(argv[1]); + y = atoi(argv[2]); + z = (20- atoi (argv[1]))/atoi(argv[1]); + /* (20-10)/10 evaluates to 1 all the time :-). */ + array_2[0:x:z][0:y:z] = array[0:x:z][0:y:z] + array[0:x:z][0:y:z] + y + z; + + for (ii = 0; ii < x; ii += z) + { + for (jj = 0; jj < y; jj += z) + { + if (array_2[ii][jj] != array[ii][jj] + array[ii][jj] + y + z) + return 3; + } + } + + + + for (ii = 0; ii < 10; ii++) { + for (jj = 0; jj< 15; jj++) { + array[ii][jj] = ii+jj; + array_2[ii][jj] = 0; + } + } + x = argc-3; + y = 20-atoi(argv[1]); + z = (20- atoi (argv[1]))/atoi(argv[1]); + /* (20-10)/10 evaluates to 1 all the time :-). */ + array_2[(argc-3):(20-atoi(argv[1])):(20-atoi(argv[1]))/atoi(argv[1])][(argc-3):(30-atoi(argv[2])): ((30-atoi(argv[2]))/atoi(argv[2]))] = array[(argc-3):20-atoi(argv[1]):(20-atoi(argv[1]))/atoi(argv[1])][(argc-3):(30-atoi(argv[2])): (30-atoi(argv[2]))/atoi(argv[2])] + array[(argc-3):20-atoi(argv[1]):(20-atoi(argv[1]))/atoi(argv[1])][(argc-3):(30-atoi(argv[2])): (30-atoi(argv[2]))/atoi(argv[2])] * array[(argc-3):20-atoi(argv[1]):(20-atoi(argv[1]))/atoi(argv[1])][(argc-3):(30-atoi(argv[2])): (30-atoi(argv[2]))/atoi(argv[2])]; + + for (ii = 0; ii < 10; ii++) + { + for (jj = 0; jj < 15; jj++) + { + if (array_2[ii][jj] != array[ii][jj] + array[ii][jj] * array[ii][jj]) + return 4; + } + } + return 0; +} diff --git a/gcc/testsuite/g++.dg/cilk-plus/AN/braced_list.cc b/gcc/testsuite/g++.dg/cilk-plus/AN/braced_list.cc new file mode 100755 index 0000000..b91de7a --- /dev/null +++ b/gcc/testsuite/g++.dg/cilk-plus/AN/braced_list.cc @@ -0,0 +1,13 @@ +/* { dg-do compile } */ +/* { dg-options "-fcilkplus -std=c++11 " } */ + +int main (void) +{ + int Array[100], Array2[100]; + + Array[{1,2}:2] = 5; /* { dg-error "braced list index is not allowed" } */ + Array[1:{1,2}:2] = 5; /* { dg-error "expected primary-expression before" } */ + Array[1:10:{1,2}] = 5; /* { dg-error "expected primary-expression before" } */ + + return 0; +} diff --git a/gcc/testsuite/g++.dg/cilk-plus/AN/builtin_fn_custom_tplt.cc b/gcc/testsuite/g++.dg/cilk-plus/AN/builtin_fn_custom_tplt.cc new file mode 100644 index 0000000..3d9e87b --- /dev/null +++ b/gcc/testsuite/g++.dg/cilk-plus/AN/builtin_fn_custom_tplt.cc @@ -0,0 +1,126 @@ +/* { dg-do run } */ +/* { dg-options "-fcilkplus " } */ + +#if HAVE_IO +#include +#endif + +#include + +template +T my_func (T x, T y) +{ + if (x > y) + return x; + else + return y; +} + +template +T main_func (T *array, T *array2, T identity_val, int size) +{ + T result; + + result = __sec_reduce (identity_val, array[0:size:1] * array2[0:size:1], + my_func); // my_func (identity_val, array[5] * array2[5]); + return result; +} +int main (void) +{ + int i_index = 0, f_index = 0, d_index = 0, l_index = 0; + int iarray[10], iarray2[10], i_result, i_max; + long larray[10], larray2[10], l_result, l_max; + float farray[10], farray2[10], f_result, f_max; + double darray[10], darray2[10], d_result, d_max; + for (int ii = 0; ii < 10; ii++) + { + if (ii%2 && ii) + { + darray[ii] = (double)(1.0000/(double)ii); + farray[ii] = (float)(1.00/(float)ii); + } + else + { + darray[ii] = (double) ii + 0.10; + farray[ii] = (float) (1.00/((float)(ii+1.000))); + } + darray2[ii] = (double) (1.00000/ (double)(ii+1)); + farray2[ii] = (float) (1.00/ (float)(ii+1)); + } + + for (int ii = 0; ii < 10; ii++) + { + iarray[ii] = ii; + larray[ii] = (long)ii; + } + + for (int ii = 0; ii < 10; ii++) + { + iarray2[ii] = (ii-5); + larray2[ii] = long (ii-5); + } +#if HAVE_IO + printf("Int: "); + for (int ii=0; ii < 10; ii++) + { + printf("%2d ", iarray[ii] * iarray2[ii]); + } + printf("\nfloat: "); + for (int ii=0; ii < 10; ii++) + { + printf("%4.3f ", farray[ii] * farray2[ii]); + } + + printf("\nlong: "); + for (int ii=0; ii < 10; ii++) + { + printf("%2d ", larray[ii] * larray2[ii]); + } + + printf("\ndouble: "); + for (int ii=0; ii < 10; ii++) + { + printf("%4.3f ", (float) (darray[ii] * darray2[ii])); + } + printf("\n"); +#endif + + i_result = main_func (iarray, iarray2, iarray[0] * iarray2[0], 10); + f_result = main_func(farray, farray2, 0.00, 10); + d_result = main_func(darray, darray2, 0.0000, 10); + l_result = main_func(larray, larray2, 0, 10); + +#if HAVE_IO + printf("int result = %2d\n", i_result); + printf ("long result = %2d\n", l_result); + printf("float result = %4.3f\n", f_result); + printf("double result = %4.3lf\n", d_result); +#endif + + i_max = iarray[0] * iarray2[0]; + f_max = farray[0] * farray2[0]; + d_max = darray[0] * darray2[0]; + l_max = larray[0] * larray2[0]; + for (int ii = 0; ii < 10; ii++) + { + if (i_max < iarray[ii] * iarray2[ii]) + i_max = iarray[ii] * iarray2[ii]; + if (f_max < farray[ii] * farray2[ii]) + f_max = farray[ii] * farray2[ii]; + if (d_max < darray[ii] * darray2[ii]) + d_max = darray[ii] * darray2[ii]; + if (l_max < larray[ii] * larray2[ii]) + l_max = larray[ii] * larray2[ii]; + } + + if (i_max != i_result) + return 1; + if (f_max != f_result) + return 2; + if (d_max != d_result) + return 3; + if (l_max != l_result) + return 4; + return 0; +} + diff --git a/gcc/testsuite/g++.dg/cilk-plus/AN/builtin_fn_mutating_tplt.cc b/gcc/testsuite/g++.dg/cilk-plus/AN/builtin_fn_mutating_tplt.cc new file mode 100644 index 0000000..db81912 --- /dev/null +++ b/gcc/testsuite/g++.dg/cilk-plus/AN/builtin_fn_mutating_tplt.cc @@ -0,0 +1,134 @@ +/* { dg-do run } */ +/* { dg-options "-fcilkplus" } */ + +#if HAVE_IO +#include +#include +#endif + +#include + +template +T my_func (T *x, T y) +{ + if (*x < y) + *x = y; + else + *x = *x; +} + +template T my_func (T *x, T y); +template +T main_func (T *array, T *array2, T identity_val, int size) +{ + T result = identity_val; + + __sec_reduce_mutating (&result, array[0:size] * array2[0:size:1], my_func); + +#if HAVE_IO + std::cout << "Result = " << result << std::endl; +#endif + return result; +} + +int main (void) +{ + int iarray[10], iarray2[10], i_result = 0, i_max; + long larray[10], larray2[10], l_result = 0, l_max; + float farray[10], farray2[10], f_result = 0, f_max; + double darray[10], darray2[10], d_result = 0, d_max; + for (int ii = 0; ii < 10; ii++) + { + if (ii%2 && ii) + { + darray[ii] = (double)(1.0000/(double)(ii)); + farray[ii] = (float)(1.00/(float)(ii)); + } + else + { + darray[ii] = (double) ii + 0.10; + farray[ii] = (float) (1.00/((float)(ii) + 0.10)); + } + darray2[ii] = (double) (1.00000/ (double)(ii+1)); + farray2[ii] = (float) (1.00/ (float)(ii+1)); + } + + for (int ii = 0; ii < 10; ii++) + { + iarray[ii] = ii; + larray[ii] = (long)ii; + } + + for (int ii = 0; ii < 10; ii++) + { + iarray2[ii] = (ii-5); + larray2[ii] = (long)ii-5; + } +#if HAVE_IO + printf("\nInt: "); + for (int ii=0; ii < 10; ii++) + { + printf("%2d ", iarray[ii] * iarray2[ii]); + } + printf("\nfloat: "); + for (int ii=0; ii < 10; ii++) + { + printf("%3.2f ", farray[ii] * farray2[ii]); + } + + printf("\nlong: "); + for (int ii=0; ii < 10; ii++) + { + printf("%2d ", larray[ii] * larray2[ii]); + } + + printf("\ndouble: "); + for (int ii=0; ii < 10; ii++) + { + printf("%4.3lf ", (float) (darray[ii] * darray2[ii])); + } + printf("\n"); +#endif + + i_result = main_func (iarray, iarray2, 0, 10); + l_result = main_func(larray, larray2, 0, 10); + f_result = main_func(farray, farray2, 0.00, 10); + d_result = main_func(darray, darray2, 0.0000, 10); + + i_max = iarray[0] * iarray2[0]; + d_max = darray[0] * darray2[0]; + f_max = farray[0] * farray2[0]; + l_max = larray[0] * larray2[0]; + for (int ii = 0; ii < 10; ii++) + { + if (iarray[ii] * iarray2[ii] > i_max) + i_max = iarray[ii] * iarray2[ii]; + if (darray[ii] * darray2[ii] > d_max) + d_max = darray[ii] * darray2[ii]; + if (farray[ii] * farray2[ii] > f_max) + f_max = farray[ii] * farray2[ii]; + if (larray[ii] * larray2[ii] > l_max) + l_max = larray[ii] * larray2[ii]; + } +#if HAVE_IO + printf("int result = %2d\n", i_max); + printf("long result = %2d\n", l_max); + printf("float result = %4.3f\n", f_max); + printf("double result = %4.3lf\n", (float)d_max); +#endif + + if (i_max != i_result) + return 1; + + if (f_max != f_result) + return 2; + + if (l_max != l_result) + return 3; + + if (d_max != d_result) + return 4; + + return 0; +} + diff --git a/gcc/testsuite/g++.dg/cilk-plus/AN/fp_triplet_values_tplt.c b/gcc/testsuite/g++.dg/cilk-plus/AN/fp_triplet_values_tplt.c new file mode 100644 index 0000000..1387558 --- /dev/null +++ b/gcc/testsuite/g++.dg/cilk-plus/AN/fp_triplet_values_tplt.c @@ -0,0 +1,36 @@ +/* { dg-do compile } */ +/* { dg-options "-fcilkplus" } */ + +float q; + +void func (int *x) +{ + *x = 5; +} +template int main2 (T x, T y, T z); + +int main (void) +{ + main2 (1.5, 2.3, 3.443); + main2 (1.34393, 2.38383, 4.38383); + return 0; +} +template +int main2 (T x, T y, T z) +{ + int array[10], array2[10]; + array2[:] = array[x:2]; /* { dg-error "start-index of array notation triplet is not an integer" } */ + array2[:] = array[1:y]; /* { dg-error "length of array notation triplet is not an integer" } */ + array2[1:2:z] = array[:]; /* { dg-error "stride of array notation triplet is not an integer" } */ + func (&array2[1:x:3]); /* { dg-error "length of array notation triplet is not an integer" } */ + array2[y:9]++; /* { dg-error "start-index of array notation triplet is not an integer" } */ + array2[1:x]++; /* { dg-error "length of array notation triplet is not an integer" } */ + array2[1:9:x]++; /* { dg-error "stride of array notation triplet is not an integer" } */ + + ++array2[1:q:3]; /* { dg-error "length of array notation triplet is not an integer" } */ + array2[:] = array[q:1:3]; /* { dg-error "start-index of array notation triplet is not an integer" } */ + array2[:] = array[1:q:3]; /* { dg-error "length of array notation triplet is not an integer" } */ + array2[:] = array[1:3:q]; /* { dg-error "stride of array notation triplet is not an integer" } */ + func (&array2[1:q:3]); /* { dg-error "length of array notation triplet is not an integer" } */ + return 0; +} diff --git a/gcc/testsuite/g++.dg/cilk-plus/AN/postincr_test.cc b/gcc/testsuite/g++.dg/cilk-plus/AN/postincr_test.cc new file mode 100644 index 0000000..b0952c7 --- /dev/null +++ b/gcc/testsuite/g++.dg/cilk-plus/AN/postincr_test.cc @@ -0,0 +1,107 @@ +/* { dg-do run } */ +/* { dg-options "-fcilkplus" } */ + +#define HAVE_IO 0 + +#if HAVE_IO +#include +#endif + +#include +template int main2(int argc); + +int main (void) +{ + return (main2(1) + main2 (1) + main2 (1)); +} + +#if HAVE_IO +template int print_array (T *array, int size); +template int print_array (T *array, int size) +{ + for (int ii = 0; ii < size; ii++) + printf("%d ", array[ii]); + printf("\n"); + return 0; +} +#endif + +template +int main2(int argc) +{ + T array[10], array_serial[10]; + + for (int ii = 0; ii < 10; ii++) { + array[ii] = 0; + array_serial[ii] = 0; + } + + array[:] = 19383; + for (int ii = 0; ii < 10; ii++) + array_serial[ii] = 19383; + + array[:]++; + + for (int ii = 0; ii < 10; ii++) + array_serial[ii]++; + +#if HAVE_IO + print_array(array, 10); + print_array(array_serial, 10); +#endif + + for (int ii = 0; ii < 10; ii++) + if (array_serial[ii] != array[ii]) + return 1; + + for (int ii = 0; ii < 10; ii++) + array[:]++; + + for (int ii = 0; ii < 10; ii++) + for (int jj = 0; jj < 10; jj++) + array_serial[jj]++; + +#if HAVE_IO + print_array(array, 10); + print_array(array_serial, 10); +#endif + + for (int ii = 0; ii < 10; ii++) + if (array_serial[ii] != array[ii]) + return 2; + + if (argc == 2) + array[0:10:1]++; + + if (argc == 2) + { + for (int ii = 0; ii < 10; ii++) + array_serial[ii]++; + } + +#if HAVE_IO + print_array(array, 10); + print_array(array_serial, 10); +#endif + + for (int ii = 0; ii < 10; ii++) + if (array_serial[ii] != array[ii]) + return 3; + + array[0:10/argc:argc]++; + + for (int ii = 0; ii < 10; ii += argc) + array_serial[ii]++; + + + for (int ii = 0; ii < 10; ii++) + if (array_serial[ii] != array[ii]) + return 4; + +#if HAVE_IO + print_array(array, 10); + print_array(array_serial, 10); +#endif + + return 0; +} diff --git a/gcc/testsuite/g++.dg/cilk-plus/AN/preincr_test.cc b/gcc/testsuite/g++.dg/cilk-plus/AN/preincr_test.cc new file mode 100644 index 0000000..f5552c7 --- /dev/null +++ b/gcc/testsuite/g++.dg/cilk-plus/AN/preincr_test.cc @@ -0,0 +1,106 @@ +/* { dg-do run } */ +/* { dg-options "-fcilkplus" } */ + + +#define HAVE_IO 0 + +#if HAVE_IO +#include +#endif + +#include +template int main2(int argc); + +int main (void) +{ + return (main2(1) + main2 (1) + main2 (1)); +} + +#if HAVE_IO +template int print_array (T *array, int size); +template int print_array (T *array, int size) +{ + for (int ii = 0; ii < size; ii++) + printf("%d ", array[ii]); + printf("\n"); + return 0; +} +#endif + +template +int main2(int argc) +{ + int array[10], array_serial[10]; + + for (int ii = 0; ii < 10; ii++) { + array[ii] = 0; + array_serial[ii] = 0; + } + + array[:] = 19383; + for (int ii = 0; ii < 10; ii++) + array_serial[ii] = 19383; + + ++array[:]; + + for (int ii = 0; ii < 10; ii++) + ++array_serial[ii]; + +#if HAVE_IO + print_array(array, 10); + print_array(array_serial, 10); +#endif + for (int ii = 0; ii < 10; ii++) + if (array_serial[ii] != array[ii]) + return 1; + + for (int ii = 0; ii < 10; ii++) + ++array[:]; + + for (int ii = 0; ii < 10; ii++) + for (int jj = 0; jj < 10; jj++) + ++array_serial[jj]; + +#if HAVE_IO + print_array(array, 10); + print_array(array_serial, 10); +#endif + for (int ii = 0; ii < 10; ii++) + if (array_serial[ii] != array[ii]) + return 2; + + if (argc == 2) + ++array[0:10:1]; + + if (argc == 2) + { + for (int ii = 0; ii < 10; ii++) + ++array_serial[ii]; + } + +#if HAVE_IO + print_array(array, 10); + print_array(array_serial, 10); +#endif + for (int ii = 0; ii < 10; ii++) + if (array_serial[ii] != array[ii]) + return 3; + + ++array[0:10/argc:argc]; + + for (int ii = 0; ii < 10; ii += argc) + { + ++array_serial[ii]; + } + +#if HAVE_IO + print_array(array, 10); + print_array(array_serial, 10); +#endif + + for (int ii = 0; ii < 10; ii++) + if (array_serial[ii] != array[ii]) + return 4; + + return 0; +} diff --git a/gcc/testsuite/g++.dg/cilk-plus/cilk-plus.exp b/gcc/testsuite/g++.dg/cilk-plus/cilk-plus.exp new file mode 100644 index 0000000..a153529 --- /dev/null +++ b/gcc/testsuite/g++.dg/cilk-plus/cilk-plus.exp @@ -0,0 +1,48 @@ +# Copyright (C) 2013 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GCC; see the file COPYING3. If not see +# . + +# Written by Balaji V. Iyer + + +load_lib g++-dg.exp + +dg-init +dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/AN/*.c]] " -fcilkplus" " " +dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/AN/*.c]] " -O0 -fcilkplus" " " +dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/AN/*.c]] " -O1 -fcilkplus" " " +dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/AN/*.c]] " -O2 -ftree-vectorize -fcilkplus" " " +dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/AN/*.c]] " -O3 -fcilkplus" " " +dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/AN/*.c]] " -g -fcilkplus" " " +dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/AN/*.c]] " -g -O0 -fcilkplus" " " +dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/AN/*.c]] " -g -O1 -fcilkplus" " " +dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/AN/*.c]] " -g -O2 -ftree-vectorize -fcilkplus" " " +dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/AN/*.c]] " -g -O3 -fcilkplus" " " +dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/AN/*.c]] " -O3 -ftree-vectorize -fcilkplus -g" " " +dg-finish + +dg-init +dg-runtest [lsort [glob -nocomplain $srcdir/g++.dg/cilk-plus/AN/*.cc]] " -fcilkplus" " " +dg-runtest [lsort [glob -nocomplain $srcdir/g++.dg/cilk-plus/AN/*.cc]] " -O0 -fcilkplus" " " +dg-runtest [lsort [glob -nocomplain $srcdir/g++.dg/cilk-plus/AN/*.cc]] " -O1 -fcilkplus" " " +dg-runtest [lsort [glob -nocomplain $srcdir/g++.dg/cilk-plus/AN/*.cc]] " -O2 -ftree-vectorize -fcilkplus" " " +dg-runtest [lsort [glob -nocomplain $srcdir/g++.dg/cilk-plus/AN/*.cc]] " -O3 -fcilkplus" " " +dg-runtest [lsort [glob -nocomplain $srcdir/g++.dg/cilk-plus/AN/*.cc]] " -g -fcilkplus" " " +dg-runtest [lsort [glob -nocomplain $srcdir/g++.dg/cilk-plus/AN/*.cc]] " -g -O0 -fcilkplus" " " +dg-runtest [lsort [glob -nocomplain $srcdir/g++.dg/cilk-plus/AN/*.cc]] " -g -O1 -fcilkplus" " " +dg-runtest [lsort [glob -nocomplain $srcdir/g++.dg/cilk-plus/AN/*.cc]] " -g -O2 -ftree-vectorize -fcilkplus" " " +dg-runtest [lsort [glob -nocomplain $srcdir/g++.dg/cilk-plus/AN/*.cc]] " -g -O3 -fcilkplus" " " +dg-runtest [lsort [glob -nocomplain $srcdir/g++.dg/cilk-plus/AN/*.cc]] " -O3 -ftree-vectorize -fcilkplus -g" " " +dg-finish diff --git a/gcc/testsuite/g++.dg/dg.exp b/gcc/testsuite/g++.dg/dg.exp old mode 100644 new mode 100755 index 7201359..710218e --- a/gcc/testsuite/g++.dg/dg.exp +++ b/gcc/testsuite/g++.dg/dg.exp @@ -33,6 +33,7 @@ dg-init set tests [lsort [find $srcdir/$subdir *.C]] set tests [prune $tests $srcdir/$subdir/bprob/*] set tests [prune $tests $srcdir/$subdir/charset/*] +set tests [prune $tests $srcdir/$subdir/cilk-plus/AN/*] set tests [prune $tests $srcdir/$subdir/compat/*] set tests [prune $tests $srcdir/$subdir/debug/*] set tests [prune $tests $srcdir/$subdir/dfp/*]