Hello Everyone, This patch is for the C++ Compiler in the Cilkplus branch. It will implement array notation for N-D triplets for modify expressions.
Thanking You, Yours Sincerely, Balaji V. Iyer.
diff --git a/gcc/cp/ChangeLog.cilk b/gcc/cp/ChangeLog.cilk index 7ac7dde..3ba0406 100644 --- a/gcc/cp/ChangeLog.cilk +++ b/gcc/cp/ChangeLog.cilk @@ -1,3 +1,19 @@ +2012-01-11 Balaji V. Iyer <balaji.v.i...@intel.com> + + * Make-lang.in: Added cp-array-notation.c file information. + * cp-array-notation.c (replace_array_notations): New function. + (find_rank): Likewise. + (extract_array_notation_exprs): Likewise. + (build_x_array_notation_exprs): Likewise. + * parser.c (cp_parser_array_notation): Likewise. + (cp_parser_nested_name_specifier_opt): Added a check to see if + cilkplus is enabled. + (cp_parser_postfix_open_square_expression): Added a check for CPP_COLON + to handle array notation. + (cp_parser_assignment_expression): Added a check for ARRAY_NOTATION_REF + and if so, then call build_x_array_notation_expr function. + * cp-tree.h: Added prototype for build_x_array_notation_expr. + 2011-11-11 Balaji V. Iyer <balaji.v.i...@intel.com> * cilk.c (for_local_cb): Changed a const tree cast to (tree *). diff --git a/gcc/cp/Make-lang.in b/gcc/cp/Make-lang.in index ee82235..ec6a347 100644 --- a/gcc/cp/Make-lang.in +++ b/gcc/cp/Make-lang.in @@ -87,7 +87,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 cp/cilk.o tree-mudflap.o $(CXX_C_OBJS) + cp/cp-gimplify.o cp/cilk.o cp/cp-array-notation.o tree-mudflap.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) @@ -272,6 +272,10 @@ CXX_PRETTY_PRINT_H = cp/cxx-pretty-print.h $(C_PRETTY_PRINT_H) cp/cilk.o: cp/cilk.c cilk.h cp/decl.h $(CXX_TREE_H) $(CONFIG_H) $(SYSTEM_H) \ $(TREE_DUMP_H) +cp/cp-array-notation.o: cp/cp-array-notation.c $(CXX_TREE_H) $(TM_H) \ + $(FLAGS_H) toplev.h $(DIAGNOSTIC_H) convert.h $(C_COMMON_H) $(TARGET_H) \ + output.h c-family/c-objc.h + cp/lex.o: cp/lex.c $(CXX_TREE_H) $(TM_H) $(FLAGS_H) \ $(C_PRAGMA_H) output.h input.h cp/operators.def $(TM_P_H) \ c-family/c-objc.h diff --git a/gcc/cp/cp-array-notation.c b/gcc/cp/cp-array-notation.c new file mode 100644 index 0000000..de1843a --- /dev/null +++ b/gcc/cp/cp-array-notation.c @@ -0,0 +1,625 @@ +/* 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) 2011, 2012 Free Software Foundation, Inc. + Contributed by Balaji V. Iyer <balaji.v.i...@intel.com>, + 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 + <http://www.gnu.org/licenses/>. */ + +#include "config.h" +#include "system.h" +#include "coretypes.h" +#include "tm.h" +#include "tree.h" +#include "cp-tree.h" +#include "c-family/c-common.h" +#include "c-family/c-objc.h" +#include "tree-inline.h" +#include "tree-mudflap.h" +#include "intl.h" +#include "toplev.h" +#include "flags.h" +#include "output.h" +#include "timevar.h" +#include "diagnostic.h" +#include "cgraph.h" +#include "tree-iterator.h" +#include "vec.h" +#include "target.h" +#include "gimple.h" +#include "bitmap.h" + + +void replace_array_notations (tree *, tree *, tree *, int); +void find_rank (tree array, int *rank); + +/* This function is to find the rank of an array notation expression. + * For example, an array notation of A[:][:] has a rank of 2. + */ +void +find_rank (tree array, int *rank) +{ + tree ii_tree; + int current_rank = 0, ii = 0; + + if (!array) + return; + else if (TREE_CODE (array) == ARRAY_NOTATION_REF) + { + for (ii_tree = array; + ii_tree && TREE_CODE (ii_tree) == ARRAY_NOTATION_REF; + ii_tree = ARRAY_NOTATION_ARRAY (ii_tree)) + current_rank++; + + if (*rank != 0 && *rank != current_rank) + error ("Rank Mismatch!"); + else if (*rank == 0) + *rank = current_rank; + } + else + { + if (TREE_CODE (array) == CALL_EXPR + || TREE_CODE (array) == AGGR_INIT_EXPR) + { + if (TREE_CODE (TREE_OPERAND (array, 0)) == INTEGER_CST) + { + int length = TREE_INT_CST_LOW (TREE_OPERAND (array, 0)); + for (ii = 0; ii < length; ii++) + find_rank (TREE_OPERAND (array, ii), rank); + } + else + gcc_unreachable (); + } + else + { + for (ii = 0; ii < TREE_CODE_LENGTH (TREE_CODE (array)); ii++) + find_rank (TREE_OPERAND (array, ii), rank); + } + } + return; +} + +/* this function will go through a tree and extract all the array notation + * expressions inside the subtrees + */ +void +extract_array_notation_exprs (tree node, tree **array_list, int *list_size) +{ + int ii = 0; + tree *new_array_list = NULL; + if (!node) + return; + else if (TREE_CODE (node) == ARRAY_NOTATION_REF) + { + ii = *list_size; + new_array_list = + (tree *) xrealloc (*array_list, (ii + 1) * sizeof (tree)); + gcc_assert (new_array_list); + new_array_list[ii] = node; + ii++; + *list_size = ii; + *array_list = new_array_list; + return; + } + else if (TREE_CODE (node) == STATEMENT_LIST) + { + tree_stmt_iterator ii_tsi; + for (ii_tsi = tsi_start (node); !tsi_end_p (ii_tsi); tsi_next (&ii_tsi)) + extract_array_notation_exprs (*tsi_stmt_ptr (ii_tsi), array_list, + list_size); + } + else if (TREE_CODE (node) == CALL_EXPR || TREE_CODE (node) == AGGR_INIT_EXPR) + { + if (TREE_CODE (TREE_OPERAND (node, 0)) == INTEGER_CST) + { + int length = TREE_INT_CST_LOW (TREE_OPERAND (node, 0)); + + for (ii = 0; ii < length; ii++) + extract_array_notation_exprs (TREE_OPERAND (node, ii), array_list, + list_size); + } + else + gcc_unreachable (); /* should not get here */ + + } + else + { + for (ii = 0; ii < TREE_CODE_LENGTH (TREE_CODE (node)); ii++) + extract_array_notation_exprs (TREE_OPERAND (node, ii), array_list, + list_size); + } + return; +} + +/* this function will replace a subtree that has array notation with the + * appropriate scalar equivalent + */ +void +replace_array_notations (tree *orig, tree *list, tree *array_operand, + int array_size) +{ + int ii = 0; + + if (array_size == 0 || *list == NULL || !*orig) + return; + + if (TREE_CODE (*orig) == ARRAY_NOTATION_REF) + { + for (ii = 0; ii < array_size; ii++) + { + if (*orig == list[ii]) + *orig = array_operand[ii]; + } + } + else if (TREE_CODE (*orig) == STATEMENT_LIST) + { + tree_stmt_iterator ii_tsi; + for (ii_tsi = tsi_start (*orig); !tsi_end_p (ii_tsi); tsi_next (&ii_tsi)) + replace_array_notations (tsi_stmt_ptr (ii_tsi), list, array_operand, + array_size); + } + else if (TREE_CODE (*orig) == CALL_EXPR + || TREE_CODE (*orig) == AGGR_INIT_EXPR) + { + if (TREE_CODE (TREE_OPERAND (*orig, 0)) == INTEGER_CST) + { + int length = TREE_INT_CST_LOW (TREE_OPERAND (*orig, 0)); + for (ii = 0; ii < length; ii++) + replace_array_notations (&TREE_OPERAND (*orig, ii), list, + array_operand, array_size); + } + else + gcc_unreachable (); /* should not get here! */ + } + else + { + for (ii = 0; ii < TREE_CODE_LENGTH (TREE_CODE (*orig)); ii++) + { + replace_array_notations (&TREE_OPERAND (*orig, ii), list, + array_operand, array_size); + } + } + return; +} + +/* this function is synonymous to the build_x_modify_expr. This function + * will build the equivalent array notation expression + */ +tree +build_x_array_notation_expr (tree lhs, enum tree_code modifycode, tree rhs, + tsubst_flags_t complain) +{ + bool *lhs_vector = NULL, **rhs_vector = NULL; + tree *lhs_array = NULL, **rhs_array = NULL; + tree array_expr_lhs = NULL_TREE, array_expr_rhs = NULL_TREE; + tree array_expr = NULL_TREE; + tree *lhs_value = NULL, **rhs_value = NULL; + tree *lhs_stride = NULL, *lhs_length = NULL, *lhs_start = NULL; + tree **rhs_stride = NULL, **rhs_length = NULL, **rhs_start = NULL; + tree loop = NULL_TREE, *lhs_var = NULL, *rhs_var = NULL; + tree *body_label = NULL, *body_label_expr = NULL; + tree *exit_label = NULL, *exit_label_expr = NULL, *cond_expr = NULL; + tree *if_stmt_label = NULL; + tree *lhs_expr_incr = NULL, *rhs_expr_incr = NULL; + tree *lhs_ind_init = NULL, *rhs_ind_init = NULL; + bool *lhs_count_down = NULL, **rhs_count_down = NULL; + tree *lhs_compare = NULL, *rhs_compare = NULL, *rhs_array_operand = NULL; + int lhs_rank = 0, rhs_rank = 0, ii = 0, jj = 0; + tree ii_tree = NULL_TREE; + tree *rhs_list = NULL; + int rhs_list_size = 0; + + find_rank (lhs, &lhs_rank); + find_rank (rhs, &rhs_rank); + + extract_array_notation_exprs (rhs, &rhs_list, &rhs_list_size); + + if (lhs_rank == 0 && rhs_rank != 0) + { + error ( "Left Hand-side rank cannot be scalar when " + "right-hand side is not"); + return error_mark_node; + } + if (lhs_rank != 0 && rhs_rank != 0 && lhs_rank != rhs_rank) + { + error ("Rank-mismatch"); + return error_mark_node; + } + + lhs_vector = (bool *) xmalloc (sizeof (bool) * lhs_rank); + rhs_vector = (bool **) xmalloc (sizeof (bool *) * rhs_list_size); + for (ii = 0; ii < rhs_list_size; ii++) + rhs_vector[ii] = (bool *) xmalloc (sizeof (bool) * rhs_rank); + + lhs_array = (tree *) xmalloc (sizeof (tree) * lhs_rank); + rhs_array = (tree **) xmalloc (sizeof (tree *) * rhs_list_size); + for (ii = 0; ii < rhs_list_size; ii++) + rhs_array[ii] = (tree *) xmalloc (sizeof (tree) * rhs_rank); + + lhs_value = (tree *) xmalloc (sizeof (tree) * lhs_rank); + + rhs_value = (tree **) xmalloc (sizeof (tree *) * rhs_list_size); + for (ii = 0; ii < rhs_list_size; ii++) + rhs_value[ii] = (tree *) xmalloc (sizeof (tree) * rhs_rank); + + lhs_stride = (tree *) xmalloc (sizeof (tree) * lhs_rank); + + rhs_stride = (tree **) xmalloc (sizeof (tree *) * rhs_list_size); + for (ii = 0; ii < rhs_list_size; ii++) + rhs_stride[ii] = (tree *) xmalloc (sizeof (tree) * rhs_rank); + + lhs_length = (tree *) xmalloc (sizeof (tree) * lhs_rank); + rhs_length = (tree **) xmalloc (sizeof (tree *) * rhs_list_size); + for (ii = 0; ii < rhs_list_size; ii++) + rhs_length[ii] = (tree *) xmalloc (sizeof (tree) * rhs_rank); + + + lhs_start = (tree *) xmalloc (sizeof (tree) * lhs_rank); + rhs_start = (tree **) xmalloc (sizeof (tree *) * rhs_list_size); + for (ii = 0; ii < rhs_list_size; ii++) + rhs_start[ii] = (tree *) xmalloc (sizeof (tree) * rhs_rank); + + lhs_var = (tree *) xmalloc (sizeof (tree) * lhs_rank); + rhs_var = (tree *) xmalloc (sizeof (tree) * rhs_rank); + + + /* The reason why we are just using lhs_rank for this is because we have the + * following scenarios: + * LHS_RANK == RHS_RANK + * LHS_RANK != RHS_RANK && RHS_RANK = 0 + * + * In both the scenarios, just checking the LHS_RANK is OK + */ + body_label = (tree *) xmalloc (sizeof (tree) * lhs_rank); + body_label_expr = (tree *) xmalloc (sizeof (tree) * lhs_rank); + exit_label = (tree *) xmalloc (sizeof (tree) * lhs_rank); + exit_label_expr = (tree *) xmalloc (sizeof (tree) * lhs_rank); + cond_expr = (tree *) xmalloc (sizeof (tree) * lhs_rank); + if_stmt_label = (tree *) xmalloc (sizeof (tree) * lhs_rank); + + lhs_expr_incr = (tree *) xmalloc (sizeof (tree) * lhs_rank); + rhs_expr_incr = (tree *) xmalloc (sizeof (tree) * rhs_rank); + + lhs_ind_init = (tree *) xmalloc (sizeof (tree) * lhs_rank); + rhs_ind_init = (tree *) xmalloc (sizeof (tree) * rhs_rank); + + lhs_count_down = (bool *) xmalloc (sizeof (bool) * lhs_rank); + rhs_count_down = (bool **) xmalloc (sizeof (bool *) * rhs_list_size); + for (ii = 0; ii < rhs_list_size; ii++) + rhs_count_down[ii] = (bool *) xmalloc (sizeof (bool) * rhs_rank); + + lhs_compare = (tree *) xmalloc (sizeof (tree) * lhs_rank); + rhs_compare = (tree *) xmalloc (sizeof (tree) * rhs_rank); + + rhs_array_operand = (tree *) xmalloc (sizeof (tree) * rhs_list_size); + + ii = 0; + for (ii_tree = lhs; ii_tree && TREE_CODE (ii_tree) == ARRAY_NOTATION_REF; + ii_tree = ARRAY_NOTATION_ARRAY (ii_tree)) + { + lhs_array[ii] = ii_tree; + ii++; + } + + if (rhs_rank) + { + for (ii = 0; ii < rhs_list_size; ii++) + { + jj = 0; + for (ii_tree = rhs_list[ii]; + ii_tree && TREE_CODE (ii_tree) == ARRAY_NOTATION_REF; + ii_tree = ARRAY_NOTATION_ARRAY (ii_tree)) + { + rhs_array[ii][jj] = ii_tree; + jj++; + } + } + } + + if (TREE_CODE (lhs) == ARRAY_NOTATION_REF) + { + for (ii = 0; ii < lhs_rank; ii++) + { + if (TREE_CODE (lhs_array[ii]) == ARRAY_NOTATION_REF) + { + lhs_value[ii] = ARRAY_NOTATION_ARRAY (lhs_array[ii]); + lhs_start[ii] = ARRAY_NOTATION_START (lhs_array[ii]); + lhs_length[ii] = ARRAY_NOTATION_LENGTH (lhs_array[ii]); + lhs_stride[ii] = ARRAY_NOTATION_STRIDE (lhs_array[ii]); + lhs_vector[ii] = true; + /* IF the stride value is variable (i.e. not constant) then + * assume that the length is positive + */ + if (!TREE_CONSTANT (lhs_length[ii])) + lhs_count_down[ii] = false; + else if (tree_int_cst_lt + (lhs_length[ii], + build_int_cst (TREE_TYPE (lhs_length[ii]), 0))) + lhs_count_down[ii] = true; + else + lhs_count_down[ii] = false; + } + else + lhs_vector[ii] = false; + } + } + + for (ii = 0; ii < rhs_list_size; ii++) + { + if (TREE_CODE (rhs_list[ii]) == ARRAY_NOTATION_REF) + { + for (jj = 0; jj < rhs_rank; jj++) + { + if (TREE_CODE (rhs_array[ii][jj]) == ARRAY_NOTATION_REF) + { + rhs_value[ii][jj] = ARRAY_NOTATION_ARRAY (rhs_array[ii][jj]); + rhs_start[ii][jj] = ARRAY_NOTATION_START (rhs_array[ii][jj]); + rhs_length[ii][jj] = ARRAY_NOTATION_LENGTH (rhs_array[ii][jj]); + rhs_stride[ii][jj] = ARRAY_NOTATION_STRIDE (rhs_array[ii][jj]); + rhs_vector[ii][jj] = true; + /* If the stride value is variable (i.e. not constant) then + * assume that the length is positive + */ + if (!TREE_CONSTANT (rhs_length[ii][jj])) + rhs_count_down[ii][jj] = false; + else if (tree_int_cst_lt + (rhs_length[ii][jj], + build_int_cst (TREE_TYPE (rhs_length[ii][jj]), 0))) + rhs_count_down[ii][jj] = true; + else + rhs_count_down[ii][jj] = false; + } + else + rhs_vector[ii][jj] = false; + } + } + } + + loop = alloc_stmt_list(); + + for (ii = 0; ii < lhs_rank; ii++) + { + if (lhs_vector[ii]) + { + lhs_var[ii] = build_decl (UNKNOWN_LOCATION, VAR_DECL, NULL_TREE, + TREE_TYPE (lhs_start[ii])); + lhs_ind_init[ii] = build_modify_expr + (UNKNOWN_LOCATION, lhs_var[ii], TREE_TYPE (lhs_var[ii]), + modifycode, + UNKNOWN_LOCATION, build_int_cst (TREE_TYPE (lhs_start[ii]), 0), + TREE_TYPE (lhs_start[ii])); + + } + } + + 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 (UNKNOWN_LOCATION, VAR_DECL, NULL_TREE, + integer_type_node); + rhs_ind_init[ii] = build_modify_expr + (UNKNOWN_LOCATION, rhs_var[ii], TREE_TYPE (rhs_var[ii]), + modifycode, + UNKNOWN_LOCATION, build_int_cst (TREE_TYPE (rhs_var[ii]), 0), + TREE_TYPE (rhs_var[ii])); + } + + + for (ii = 0; ii < lhs_rank ; ii++) + { + /* this will create the if statement label */ + if_stmt_label[ii] = build_decl (UNKNOWN_LOCATION, LABEL_DECL, NULL_TREE, + void_type_node); + DECL_CONTEXT (if_stmt_label[ii]) = current_function_decl; + DECL_ARTIFICIAL (if_stmt_label[ii]) = 0; + DECL_IGNORED_P (if_stmt_label[ii]) = 1; + + /* this label statment will point to the loop body */ + body_label[ii] = build_decl (UNKNOWN_LOCATION, LABEL_DECL, NULL_TREE, + void_type_node); + DECL_CONTEXT (body_label[ii]) = current_function_decl; + DECL_ARTIFICIAL (body_label[ii]) = 0; + DECL_IGNORED_P (body_label[ii]) = 1; + body_label_expr[ii] = build1 (LABEL_EXPR, void_type_node, body_label[ii]); + + /* this will create the exit label..i.e. where the while loop will branch + out of + */ + exit_label[ii] = build_decl (UNKNOWN_LOCATION, LABEL_DECL, NULL_TREE, + void_type_node); + DECL_CONTEXT (exit_label[ii]) = current_function_decl; + DECL_ARTIFICIAL (exit_label[ii]) = 0; + DECL_IGNORED_P (exit_label[ii]) = 1; + exit_label_expr[ii] = build1 (LABEL_EXPR, void_type_node, exit_label[ii]); + } + + if (lhs_rank) + { + /* The last ARRAY_NOTATION element's ARRAY component should be the array's + * base value + */ + array_expr_lhs = lhs_value[lhs_rank - 1]; + for (ii = lhs_rank - 1; ii >= 0; ii--) + { + /* Array[start_index + (induction_var * stride)] */ + array_expr_lhs = build_array_ref + (UNKNOWN_LOCATION, array_expr_lhs, + build2 (PLUS_EXPR, TREE_TYPE (lhs_var[ii]), lhs_start[ii], + build2 (MULT_EXPR, TREE_TYPE (lhs_var[ii]), lhs_var[ii], + lhs_stride[ii]))); + if (lhs_count_down[ii]) + lhs_expr_incr[ii] = + build2 (MODIFY_EXPR, void_type_node, lhs_var[ii], + build2 (PLUS_EXPR, TREE_TYPE (lhs_var[ii]), lhs_var[ii], + build_int_cst (TREE_TYPE (lhs_var[ii]), -1))); + else + lhs_expr_incr[ii] = + build2 (MODIFY_EXPR, void_type_node, lhs_var[ii], + build2 (PLUS_EXPR, TREE_TYPE (lhs_var[ii]), lhs_var[ii], + build_int_cst (TREE_TYPE (lhs_var[ii]), 1))); + } + } + + if (rhs_rank) + { + for (ii = 0; ii < rhs_list_size; ii++) + { + if (rhs_vector[ii][0]) + { + rhs_array_operand[ii] = rhs_value[ii][rhs_rank - 1]; + gcc_assert (rhs_array_operand[ii]); + for (jj = rhs_rank - 1; jj >= 0; jj--) + { + if (rhs_count_down[ii][jj]) + { + /* Array[start_index - (induction_var * stride)] */ + rhs_array_operand[ii] = build_array_ref + (UNKNOWN_LOCATION, rhs_array_operand[ii], + build2 (MINUS_EXPR, TREE_TYPE (rhs_var[jj]), + rhs_start[ii][jj], + build2 (MULT_EXPR, TREE_TYPE (rhs_var[jj]), + rhs_var[jj], + rhs_stride[ii][jj]))); + } + else + { + /* Array[start_index + (induction_var * stride)] */ + rhs_array_operand[ii] = build_array_ref + (UNKNOWN_LOCATION, rhs_array_operand[ii], + build2 (PLUS_EXPR, TREE_TYPE (rhs_var[jj]), + rhs_start[ii][jj], + build2 (MULT_EXPR, TREE_TYPE (rhs_var[jj]), + rhs_var[jj], + rhs_stride[ii][jj]))); + } + } + } + } + replace_array_notations (&rhs, rhs_list, rhs_array_operand, + rhs_list_size); + array_expr_rhs = rhs; + } + else + { + array_expr_rhs = rhs; + rhs_expr_incr[0] = NULL_TREE; + } + + for (ii = 0; ii < rhs_rank; ii++) + { + rhs_expr_incr[ii] = build2 + (MODIFY_EXPR, void_type_node, rhs_var[ii], + build2 (PLUS_EXPR, TREE_TYPE (rhs_var[ii]), rhs_var[ii], + build_int_cst (TREE_TYPE (rhs_var[ii]), 1))); + } + + + array_expr = build_x_modify_expr (array_expr_lhs, modifycode, array_expr_rhs, + complain); + + for (jj = 0; jj < lhs_rank; jj++) + { + if (rhs_rank && rhs_expr_incr[jj]) + { + if (lhs_count_down[jj]) + lhs_compare[jj] = build2 + (GT_EXPR, boolean_type_node, lhs_var[jj], lhs_length[jj]); + + else + lhs_compare[jj] = build2 + (LT_EXPR, boolean_type_node, lhs_var[jj], lhs_length[jj]); + + + /* What we are doing here is this: + * We always count up, so: + * if (length is negative ==> which means we count down) + * we multiply length by -1 and count up => ii < -LENGTH + * else + * we just count up, so we compare for ii < LENGTH + */ + if (rhs_count_down[0][jj]) + rhs_compare[jj] = build2 + (LT_EXPR, boolean_type_node, rhs_var[jj], + build2 (MULT_EXPR, TREE_TYPE (rhs_var[jj]), rhs_length[0][jj], + build_int_cst (TREE_TYPE (rhs_var[jj]), -1))); + else + rhs_compare[jj] = build2 (LT_EXPR, boolean_type_node, rhs_var[jj], + rhs_length[0][jj]); + + cond_expr[jj] = build2 (TRUTH_ANDIF_EXPR, void_type_node, + lhs_compare[jj], rhs_compare[jj]); + } + else + { + if (lhs_count_down[jj]) + cond_expr[jj] = build2 + (GT_EXPR, boolean_type_node, lhs_var[jj], lhs_length[jj]); + else + cond_expr[jj] = build2 + (LT_EXPR, boolean_type_node, lhs_var[jj], lhs_length[jj]); + } + } + + /* The following statements will do the following: + * <if_stmt_label>: (in order from outermost to innermost) + * if (cond_expr) then go to body_label + * else go to exit_label + * <body_label>: + * array expression + * + * (the increment, goto and exit_label goes from innermost to + * outermost). + * ii++ and jj++ + * go to if_stmt_label + * <exit_label>: + * <REST OF CODE> + */ + + + for (ii = 0; ii < lhs_rank; ii++) + { + append_to_statement_list (lhs_ind_init [ii], &loop); + if (rhs_rank) + append_to_statement_list (rhs_ind_init[ii], &loop); + append_to_statement_list (build1 (LABEL_EXPR, void_type_node, + if_stmt_label[ii]), &loop); + append_to_statement_list + (build3 (COND_EXPR, void_type_node, cond_expr[ii], + build1 (GOTO_EXPR, void_type_node, body_label[ii]), + build1 (GOTO_EXPR, void_type_node, exit_label[ii])), &loop); + + append_to_statement_list (body_label_expr[ii], &loop); + } + + append_to_statement_list (array_expr, &loop); + + for (ii = lhs_rank - 1; ii >= 0; ii--) + { + append_to_statement_list (lhs_expr_incr[ii], &loop); + if (rhs_rank && rhs_expr_incr[ii]) + append_to_statement_list (rhs_expr_incr[ii], &loop); + + append_to_statement_list + (build1 (GOTO_EXPR, void_type_node, if_stmt_label[ii]), &loop); + append_to_statement_list (exit_label_expr[ii], &loop); + } + + return loop; +} diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index ba259fb..d7cbefa 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -6022,7 +6022,10 @@ extern void cilk_address_modified_variables (tree); extern void mark_receiver_addressable (tree, tree); extern void gimplify_cilk_spawn (tree *, gimple_seq *, - gimple_seq *); + gimple_seq *); +/* In cp/cp-array-notations.c */ +extern tree build_x_array_notation_expr (tree, enum tree_code, tree, + tsubst_flags_t); /* -- end of C++ */ #endif /* ! GCC_CP_TREE_H */ diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index b02e935..9541b0e 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -234,6 +234,11 @@ static void cp_parser_initial_pragma static tree cp_literal_operator_id (const char *); + +static tree cp_parser_array_notation + (cp_parser *, tree, tree); + + /* Manifest constants. */ #define CP_LEXER_BUFFER_SIZE ((256 * 1024) / sizeof (cp_token)) #define CP_SAVED_TOKEN_STACK 5 @@ -4992,9 +4997,12 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser, && parser->colon_corrects_to_scope_p && cp_lexer_peek_nth_token (parser->lexer, 3)->type == CPP_NAME) { - error_at (token->location, - "found %<:%> in nested-name-specifier, expected %<::%>"); - token->type = CPP_SCOPE; + if (!flag_enable_cilk) /* this is OK in Array Notation */ + { + error_at (token->location, + "found %<:%> in nested-name-specifier, expected %<::%>"); + token->type = CPP_SCOPE; + } } if (token->type != CPP_SCOPE @@ -5964,7 +5972,6 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p, FOR_OFFSETOF is set if we're being called in that context, which changes how we deal with integer constant expressions. */ - static tree cp_parser_postfix_open_square_expression (cp_parser *parser, tree postfix_expression, @@ -5975,40 +5982,59 @@ 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 (cp_lexer_peek_token (parser->lexer)->type == CPP_COLON) + { + /* If we reach here, then we have something like this: + * ARRAY [:] + */ + if (flag_enable_cilk) + postfix_expression = cp_parser_array_notation (parser, NULL_TREE, + postfix_expression); + } else { - 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); - } + /* Here we have 3 options: + * 1. ARRAY [EXPR] -- Normal array call. + * 2. ARRAY [ EXPR : EXPR ] -- Array notation with default stride = 1. + * 3. ARRAY [ EXPR : EXPR : EXPR ] -- Array notation with userdefined + * stride. + */ + + /* 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 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 (postfix_expression, index); - - /* 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; + if (cp_lexer_peek_token (parser->lexer)->type == CPP_COLON) + { + if (flag_enable_cilk) + postfix_expression = cp_parser_array_notation (parser, index, + postfix_expression); + } + else + { + /* Look for the closing `]'. */ + cp_parser_require (parser, CPP_CLOSE_SQUARE, RT_CLOSE_SQUARE); + /* Build the ARRAY_REF. */ + postfix_expression = grok_array_decl (postfix_expression, index); + + /* 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; } @@ -7649,11 +7675,20 @@ cp_parser_assignment_expression (cp_parser* parser, bool cast_p, if (cp_parser_non_integral_constant_expression (parser, NIC_ASSIGNMENT)) return error_mark_node; - /* Build the assignment expression. */ - expr = build_x_modify_expr (expr, - assignment_operator, - rhs, - tf_warning_or_error); + + /* Check if expression is of type ARRAY_NOTATION_REF, if so then + * break up an array notation expression correctly + */ + if (TREE_CODE (expr) == ARRAY_NOTATION_REF + || TREE_CODE (rhs) == ARRAY_NOTATION_REF) + expr = build_x_array_notation_expr (expr, assignment_operator, + rhs, tf_warning_or_error); + else + /* Build the assignment expression. */ + expr = build_x_modify_expr (expr, + assignment_operator, + rhs, + tf_warning_or_error); } } } @@ -18373,6 +18408,8 @@ cp_parser_class_name (cp_parser *parser, names are ignored. */ if (cp_lexer_next_token_is (parser->lexer, CPP_SCOPE)) tag_type = typename_type; + else if (cp_lexer_next_token_is (parser->lexer, CPP_COLON)) + tag_type = none_type; /* Look up the name. */ decl = cp_parser_lookup_name (parser, identifier, tag_type, @@ -29042,4 +29079,99 @@ cp_parser_cilk_for_init_statement (cp_parser *parser, tree *init) return decl; } +static tree +cp_parser_array_notation (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; + + array_type = TREE_TYPE (array_value); + gcc_assert (array_type); + + type = TREE_TYPE (array_type); + token = cp_lexer_peek_token (parser->lexer); + + if (!token) + { + cp_parser_error (parser, "expected %<:%> or numeral"); + return NULL_TREE; + } + else if (token->type == CPP_COLON) + { + if (!init_index) + { + /* IF we are here, then we havea case like this A[:] */ + cp_lexer_consume_token (parser->lexer); + array_type_domain = TYPE_DOMAIN (array_type); + gcc_assert (array_type_domain); + + start_index = TYPE_MINVAL (array_type_domain); + start_index = fold_build1 (CONVERT_EXPR, integer_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); + + if (tree_int_cst_lt (build_int_cst (TREE_TYPE (length_index), 0), + length_index)) + stride = build_int_cst (TREE_TYPE (start_index), 1); + else + stride = build_int_cst (TREE_TYPE (start_index), -1); + } + 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); + + length_index = cp_parser_expression (parser, false, NULL); + + if (!length_index || length_index == error_mark_node) + { + cp_parser_skip_to_end_of_block_or_statement (parser); + return error_mark_node; + } + else if (cp_lexer_peek_token (parser->lexer)->type == CPP_COLON) + { + cp_lexer_consume_token (parser->lexer); + stride = cp_parser_expression (parser, false, NULL); + if (!stride || stride == error_mark_node) + { + cp_parser_skip_to_end_of_block_or_statement (parser); + return error_mark_node; + } + } + else + if (TREE_CONSTANT (start_index) && TREE_CONSTANT (length_index) + && tree_int_cst_lt (length_index, start_index)) + stride = build_int_cst (TREE_TYPE (start_index), -1); + else + stride = build_int_cst (TREE_TYPE (start_index), 1); + } + else + cp_parser_error (parser, "expected array-notation expression"); + } + else + cp_parser_error (parser, "expected array-notation expression"); + + cp_parser_require (parser, CPP_CLOSE_SQUARE, RT_CLOSE_SQUARE); + + value_tree = build5 (ARRAY_NOTATION_REF, NULL_TREE, NULL_TREE, NULL_TREE, + NULL_TREE, NULL_TREE, NULL_TREE); + ARRAY_NOTATION_ARRAY (value_tree) = array_value; + ARRAY_NOTATION_START (value_tree) = start_index; + ARRAY_NOTATION_LENGTH (value_tree) = length_index; + ARRAY_NOTATION_STRIDE (value_tree) = stride; + ARRAY_NOTATION_TYPE (value_tree) = type; + + TREE_TYPE (value_tree) = type; + + return value_tree; +} + #include "gt-cp-parser.h" diff --git a/gcc/testsuite/ChangeLog.cilk b/gcc/testsuite/ChangeLog.cilk index 33499cf..68c2e9d 100644 --- a/gcc/testsuite/ChangeLog.cilk +++ b/gcc/testsuite/ChangeLog.cilk @@ -1,3 +1,10 @@ +2011-01-11 Balaji V. Iyer <balaji.v.i...@intel.com> + + * g++.dg/cilk-plus/array_notation_tests/array_test1.cc: New. + * g++.dg/cilk-plus/array_notation_tests/array_test2.cc: New. + * g++.dg/cilk-plus/cilk-plus.exp: Added code to run array notation + tests. + 2011-12-23 Balaji V. Iyer <balaji.v.i...@intel.com> * gcc.dg/cilk-plus/array_notation_test/if_test.c: New. diff --git a/gcc/testsuite/g++.dg/cilk-plus/array_notation_tests/array_test1.cc b/gcc/testsuite/g++.dg/cilk-plus/array_notation_tests/array_test1.cc new file mode 100644 index 0000000..f776339 --- /dev/null +++ b/gcc/testsuite/g++.dg/cilk-plus/array_notation_tests/array_test1.cc @@ -0,0 +1,89 @@ +#if HAVE_IO +#include <iostream> +#endif + +#include <cstdlib> +int main(int argc, char **argv) +{ + int ii = 0, jj, kk, ll, array[10],array2[10], array_ND[10][10][10][10]; + int x = 0, y = 10, z = 1; + + if (argc != 3) + { +#if HAVE_IO + std::cout << "Usage: ./a.out 10 5" << std::endl; +#endif + return 0; + } + array[:] = 10; +#if HAVE_IO + std::cout << "Original " << std::endl; + for (ii = 0; ii < 10; ii++) + std::cout << "\tArray1[" << ii << "] = " << array[ii] << std::endl; +#endif + + /* This if loop will change all the 10's to 5's */ + array[:] = atoi (argv[2]); +#if HAVE_IO + std::cout << "Modified " << std::endl; + for (ii = 0; ii < 10; ii++) + std::cout << "\tArray1[" << ii << "] = " << array[ii] << std::endl; +#endif + array[:] = 10; +#if HAVE_IO + std::cout << "Original " << std::endl; + for (ii = 0; ii < 10; ii++) + std::cout << "\tArray1[" << ii << "] = " << array[ii] << std::endl; +#endif + /* This if loop will change all the 10's to 5's */ + array[atoi(argv[1])-10:atoi(argv[1]):atoi(argv[1])/10] = 5; +#if HAVE_IO + std::cout << "Modified " << std::endl; + for (ii = 0; ii < 10; ii++) + std::cout << "\tArray1[" << ii << "] = " << array[ii] << std::endl; +#endif + array[:] = 10; +#if HAVE_IO + std::cout << "Original " << std::endl; + for (ii = 0; ii < 10; ii++) + std::cout << "\tArray1[" << ii << "] = " << array[ii] << std::endl; +#endif + /* This if loop will change all the 10's to 5's */ + array[atoi(argv[1])-10:atoi(argv[1]):atoi(argv[1])/atoi(argv[2])] = + atoi (argv[1]) / atoi (argv[2]) + argc; +#if HAVE_IO + std::cout << "Modified " << std::endl; + for (ii = 0; ii < 10; ii++) + std::cout << "\tArray1[" << ii << "] = " << array[ii] << std::endl; +#endif + array[:] = 10; +#if HAVE_IO + std::cout << "Original " << std::endl; + for (ii = 0; ii < 10; ii++) + std::cout << "\tArray1[" << ii << "] = " << array[ii] << std::endl; +#endif + /* This if loop will change all the 10's to 5's */ + array[atoi(argv[1])-10:atoi(argv[1]):atoi(argv[1])/atoi(argv[2])] = + atoi (argv[1]) / atoi (argv[2]) + 3; +#if HAVE_IO + std::cout << "Modified " << std::endl; + for (ii = 0; ii < 10; ii++) + std::cout << "\tArray1[" << ii << "] = " << array[ii] << std::endl; +#endif + array[:] = 10; + array2[:] = 10; +#if HAVE_IO + std::cout << "Original " << std::endl; + for (ii = 0; ii < 10; ii++) + { + std::cout << "\tArray1[" << ii << "] = " << array[ii]; + std::cout << "\tArray2[" << ii << "] = " << array2[ii] << std::endl; + } +#endif + /* This if loop will change all the 10's to 5's */ + array[atoi(argv[1])-10:atoi(argv[1]):atoi(argv[1])/10] = + (25 * (array2[atoi(argv[1])-10:atoi(argv[1]):atoi(argv[1])/10] - + (atoi (argv[1]) / atoi (argv[2]) + argc)))/ atoi ("25"); + + return 0; +} diff --git a/gcc/testsuite/g++.dg/cilk-plus/array_notation_tests/array_test2.cc b/gcc/testsuite/g++.dg/cilk-plus/array_notation_tests/array_test2.cc new file mode 100644 index 0000000..a52915c --- /dev/null +++ b/gcc/testsuite/g++.dg/cilk-plus/array_notation_tests/array_test2.cc @@ -0,0 +1,73 @@ +#if TESTING +#include <iostream> +#endif + +#include <cstdlib> +#include <cassert> +int main(int argc, char **argv) +{ + int ii = 0, jj, kk, ll, array_ND[10][10][10][10], array_ND2[10][10][10][10]; + int x = 0, y = 10, z = 1; + + if (argc != 3) + { +#if HAVE_IO + std::cout << "Usage ./a.out 10 5" << std::endl; +#endif + return 0; + } + + array_ND[:][:][:][:] = 10; +#if HAVE_IO + std::cout << "Modified " << std::endl; + for (ii = 0; ii < 10; ii++) + for (jj = 0; jj < 10; jj++) + for (kk = 0; kk < 10; kk++) + for (ll = 0; ll < 10; ll++) + std::cout << "\tArray_ND[" << ii << "][" << jj << "][" << kk + << "][" << ll + << "] = " << array_ND[ii][jj][kk][ll] << std::endl; +#endif + array_ND[:][:][:][:] = 5; + array_ND2[:][:][:][:] = 10; + + /* This will replace all 10's to 5 */ + array_ND[0:10:1][atoi(argv[1])-10:atoi(argv[1]):atoi(argv[1])/10][:][:] = + (10 * (atoi (argv[1])/atoi(argv[2])) - array_ND2[0:10:1][atoi(argv[1])-10:atoi(argv[1]):atoi(argv[1])/10][:][:])/2; + +#if HAVE_IO + std::cout << "Modified " << std::endl; + for (ii = 0; ii < 10; ii++) + for (jj = 0; jj < 10; jj++) + for (kk = 0; kk < 10; kk++) + for (ll = 0; ll < 10; ll++) + { + std::cout << "\tArray_ND[" << ii << "][" << jj << "][" << kk + << "][" << ll + << "] = " << array_ND[ii][jj][kk][ll] << std::endl; + + assert (array_ND[ii][jj][kk][ll] == 5); + } +#endif + + array_ND[:][:][:][:] = 5; + array_ND2[:][:][:][:] = 10; + /* This will replace all 10's to 5 */ + array_ND[0:10:1][atoi(argv[1])-10:atoi(argv[1]):atoi(argv[1])/10][9:10:-1][9:-10:1] = + (10 * (atoi (argv[1])/atoi(argv[2])) - + array_ND2[0:10:1][atoi(argv[1])-10:atoi(argv[1]):atoi(argv[1])/10][:][:])/2; +#if HAVE_IO + std::cout << "Modified " << std::endl; + for (ii = 0; ii < 10; ii++) + for (jj = 0; jj < 10; jj++) + for (kk = 0; kk < 10; kk++) + for (ll = 0; ll < 10; ll++) + { + std::cout << "\tArray_ND[" << ii << "][" << jj << "][" << kk + << "][" << ll + << "] = " << array_ND[ii][jj][kk][ll] << std::endl; + assert (array_ND[ii][jj][kk][ll] == 5); + } +#endif + return 0; +} diff --git a/gcc/testsuite/g++.dg/cilk-plus/cilk_plus.exp b/gcc/testsuite/g++.dg/cilk-plus/cilk_plus.exp index 45a362a..1fa67ce 100644 --- a/gcc/testsuite/g++.dg/cilk-plus/cilk_plus.exp +++ b/gcc/testsuite/g++.dg/cilk-plus/cilk_plus.exp @@ -21,3 +21,8 @@ dg-init dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.cc]] " -w -lcilkrts -ldl -I $srcdir/../../libcilkrts/include " " " dg-finish + +dg-init +dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/array_notation_tests/*.cc]] " -O3 -ftree-vectorize" " " + +dg-finish