From patchwork Mon Dec 19 19:57:33 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Iyer, Balaji V" X-Patchwork-Id: 132304 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]) by ozlabs.org (Postfix) with SMTP id CB3D6B6FEB for ; Tue, 20 Dec 2011 06:57:58 +1100 (EST) Received: (qmail 17381 invoked by alias); 19 Dec 2011 19:57:57 -0000 Received: (qmail 17371 invoked by uid 22791); 19 Dec 2011 19:57:53 -0000 X-SWARE-Spam-Status: No, hits=-3.2 required=5.0 tests=AWL, BAYES_00, RP_MATCHES_RCVD, TW_TM X-Spam-Check-By: sourceware.org Received: from mga14.intel.com (HELO mga14.intel.com) (143.182.124.37) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Mon, 19 Dec 2011 19:57:36 +0000 Received: from azsmga001.ch.intel.com ([10.2.17.19]) by azsmga102.ch.intel.com with ESMTP; 19 Dec 2011 11:57:35 -0800 X-ExtLoop1: 1 Received: from azsmsx601.amr.corp.intel.com ([10.2.121.193]) by azsmga001.ch.intel.com with ESMTP; 19 Dec 2011 11:57:35 -0800 Received: from fmsmsx104.amr.corp.intel.com (10.19.9.35) by azsmsx601.amr.corp.intel.com (10.2.121.193) with Microsoft SMTP Server (TLS) id 8.2.255.0; Mon, 19 Dec 2011 12:57:35 -0700 Received: from fmsmsx102.amr.corp.intel.com ([169.254.2.8]) by FMSMSX104.amr.corp.intel.com ([169.254.4.24]) with mapi id 14.01.0355.002; Mon, 19 Dec 2011 11:57:34 -0800 From: "Iyer, Balaji V" To: "gcc-patches@gcc.gnu.org" Subject: [PATCH][Cilkplus] N-Dimension Polynomial Implementation Date: Mon, 19 Dec 2011 19:57:33 +0000 Message-ID: MIME-Version: 1.0 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 Hello Everyone, This patch is for the C-Compiler in Cilkplus GCC branch. It is an extension of the patch given in this submission: http://gcc.gnu.org/ml/gcc-patches/2011-12/msg01397.html. it implements a polynomial of N-dimension array notation. Thanking You, Yours Sincerely, Balaji V. Iyer. diff --git a/gcc/ChangeLog.cilk b/gcc/ChangeLog.cilk index bf848b1..2410953 100644 --- a/gcc/ChangeLog.cilk +++ b/gcc/ChangeLog.cilk @@ -1,3 +1,11 @@ +2011-12-22 Balaji V. Iyer + + * c-typeck.c (find_rank): Moved function to c-array-notations.c + (build_array_notation_expr): Likewise. Also added support for a + polynomial right-hand-size expression. + (replace_array_notations): New function. + (extract_array_notation_exprs): New function. + 2011-12-16 Balaji V. Iyer * c-typeck.c (find_rank): Modified to find rank of array notation diff --git a/gcc/Makefile.in b/gcc/Makefile.in index 34fa325..1721a42 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -1130,7 +1130,7 @@ C_COMMON_OBJS = c-family/c-common.o c-family/c-cppbuiltin.o c-family/c-dump.o \ c-family/c-format.o c-family/c-gimplify.o c-family/c-lex.o \ c-family/c-omp.o c-family/c-opts.o c-family/c-pch.o \ c-family/c-ppoutput.o c-family/c-pragma.o c-family/c-pretty-print.o \ - c-family/c-semantics.o c-family/c-ada-spec.o cilk-spawn.o + c-family/c-semantics.o c-family/c-ada-spec.o cilk-spawn.o c-array-notation.o # Language-specific object files for C and Objective C. C_AND_OBJC_OBJS = attribs.o c-errors.o c-decl.o c-typeck.o \ @@ -3447,6 +3447,10 @@ cilk-spawn.o: cilk-spawn.c $(GIMPLE_H) $(CONFIG_H) $(SYSTEM_H) $(TREE_H) \ pragma_simd.o: pragma_simd.c $(GIMPLE_H) $(CONFIG_H) $(SYSTEM_H) $(TREE_H) \ $(TREE_INLINE_H) +c-array-notation.o: c-array-notation.c c-lang.h $(CONFIG_H) $(SYSTEM_H) \ + coretypes.h $(TM_H) $(TREE_H) \ + $(C_TREE_H) $(TARGET_H) $(FLAGS_H) intl.h output.h $(EXPR_H) \ + langhooks.h tree-iterator.h $(BITMAP_H) $(GIMPLE_H) c-family/c-objc.h target-globals.o : target-globals.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \ $(TM_H) insn-config.h $(MACHMODE_H) $(GGC_H) toplev.h target-globals.h \ diff --git a/gcc/c-array-notation.c b/gcc/c-array-notation.c new file mode 100644 index 0000000..a435d22 --- /dev/null +++ b/gcc/c-array-notation.c @@ -0,0 +1,530 @@ +#include "config.h" +#include "system.h" +#include "coretypes.h" +#include "tm.h" +#include "tree.h" +#include "langhooks.h" +#include "c-tree.h" +#include "c-lang.h" +#include "flags.h" +#include "output.h" +#include "intl.h" +#include "target.h" +#include "tree-iterator.h" +#include "bitmap.h" +#include "gimple.h" +#include "c-family/c-objc.h" + +void replace_array_notations (tree *, tree *, tree *, int); +void find_rank (tree, int *); +void extract_array_notation_exprs (tree, tree **, int *); +tree fix_conditional_array_notations (tree); + +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 + { + for (ii = 0; ii < TREE_CODE_LENGTH (TREE_CODE (array)); ii++) + find_rank (TREE_OPERAND (array, ii), rank); + } + return; +} + +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 + { + for (ii = 0; ii < TREE_CODE_LENGTH (TREE_CODE (node)); ii++) + extract_array_notation_exprs (TREE_OPERAND (node, ii), array_list, + list_size); + } + return; +} + +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 + { + for (ii = 0; ii < TREE_CODE_LENGTH (TREE_CODE (*orig)); ii++) + { + replace_array_notations (&TREE_OPERAND (*orig, ii), list, + array_operand, array_size); + } + } + return; +} + +tree +build_array_notation_expr (location_t location, tree lhs, tree lhs_origtype, + enum tree_code modifycode, location_t rhs_loc, + tree rhs, tree rhs_origtype) +{ + 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_at (location, "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_at (location, "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 = push_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 + (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 + (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 + (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_modify_expr (location, array_expr_lhs, + lhs_origtype, modifycode, rhs_loc, + array_expr_rhs, rhs_origtype); + + 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[ii]) + cond_expr[ii] = build2 + (GT_EXPR, boolean_type_node, lhs_var[ii], lhs_length[ii]); + else + cond_expr[ii] = build2 + (LT_EXPR, boolean_type_node, lhs_var[ii], lhs_length[ii]); + } + } + + /* The following statements will do the following: + * : (in order from outermost to innermost) + * if (cond_expr) then go to body_label + * else go to exit_label + * : + * array expression + * + * (the increment, goto and exit_label goes from innermost to + * outermost). + * ii++ and jj++ + * go to if_stmt_label + * : + * + */ + + + for (ii = 0; ii < lhs_rank; ii++) + { + add_stmt (lhs_ind_init [ii]); + if (rhs_rank) + add_stmt (rhs_ind_init[ii]); + add_stmt (build1 (LABEL_EXPR, void_type_node, if_stmt_label[ii])); + add_stmt (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]))); + + add_stmt (body_label_expr[ii]); + } + + add_stmt (array_expr); + + for (ii = lhs_rank - 1; ii >= 0; ii--) + { + add_stmt (lhs_expr_incr[ii]); + if (rhs_rank && rhs_expr_incr[ii]) + add_stmt (rhs_expr_incr[ii]); + + add_stmt (build1 (GOTO_EXPR, void_type_node, if_stmt_label[ii])); + add_stmt (exit_label_expr[ii]); + } + + pop_stmt_list (loop); + + return loop; +} diff --git a/gcc/c-typeck.c b/gcc/c-typeck.c index c4ff22e..5dfecd9 100644 --- a/gcc/c-typeck.c +++ b/gcc/c-typeck.c @@ -5044,406 +5044,6 @@ build_modify_expr (location_t location, tree lhs, tree lhs_origtype, return result; } - -static int -find_rank (tree array) -{ - int rank = 0; - tree ii_tree = NULL_TREE, jj_tree = NULL_TREE; - int highest_rank = 0, jj = 0; - - if (TREE_CODE (array) != ARRAY_NOTATION_REF) - { - for (jj = 0; jj < TREE_CODE_LENGTH (TREE_CODE (array)); jj++) - { - rank = 0; - jj_tree = TREE_OPERAND (array, jj); - for (ii_tree = jj_tree; - ii_tree && TREE_CODE (ii_tree) == ARRAY_NOTATION_REF; - ii_tree = ARRAY_NOTATION_ARRAY (ii_tree)) - rank++; - - if (highest_rank != 0 && rank != 0 && highest_rank != rank) - error ("Rank Mismatch!"); - else if (highest_rank < rank) - highest_rank = rank; - } - } - else - { - for (ii_tree = array; - ii_tree && TREE_CODE (ii_tree) == ARRAY_NOTATION_REF; - ii_tree = ARRAY_NOTATION_ARRAY (ii_tree)) - rank++; - highest_rank = rank; - } - - return highest_rank; -} - -tree -build_array_notation_expr (location_t location, tree lhs, tree lhs_origtype, - enum tree_code modifycode, location_t rhs_loc, - tree rhs, tree rhs_origtype) -{ - 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; - int lhs_rank = 0, rhs_rank = 0, ii = 0; - tree ii_tree = NULL_TREE; - - lhs_rank = find_rank (lhs); - rhs_rank = find_rank (rhs); - - if (lhs_rank == 0 && rhs_rank != 0) - { - error_at (location, "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_at (location, "Rank-mismatch"); - return error_mark_node; - } - - lhs_vector = (bool *) xmalloc (sizeof (bool) * lhs_rank); - rhs_vector = (bool *) xmalloc (sizeof (bool) * rhs_rank); - - lhs_array = (tree *) xmalloc (sizeof (tree) * lhs_rank); - rhs_array = (tree *) xmalloc (sizeof (tree) * rhs_rank); - - lhs_value = (tree *) xmalloc (sizeof (tree) * lhs_rank); - rhs_value = (tree *) xmalloc (sizeof (tree) * rhs_rank); - - lhs_stride = (tree *) xmalloc (sizeof (tree) * lhs_rank); - rhs_stride = (tree *) xmalloc (sizeof (tree) * rhs_rank); - - lhs_length = (tree *) xmalloc (sizeof (tree) * lhs_rank); - rhs_length = (tree *) xmalloc (sizeof (tree) * rhs_rank); - - lhs_start = (tree *) xmalloc (sizeof (tree) * lhs_rank); - rhs_start = (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_rank); - - lhs_compare = (tree *) xmalloc (sizeof (tree) * lhs_rank); - rhs_compare = (tree *) xmalloc (sizeof (tree) * rhs_rank); - - 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) - { - ii = 0; - for (ii_tree = rhs; ii_tree && TREE_CODE (ii_tree) == ARRAY_NOTATION_REF; - ii_tree = ARRAY_NOTATION_ARRAY (ii_tree)) - { - rhs_array[ii] = ii_tree; - ii++; - } - } - - 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; - } - } - - if (TREE_CODE (rhs) == ARRAY_NOTATION_REF) - { - for (ii = 0; ii < rhs_rank; ii++) - { - if (TREE_CODE (rhs_array[ii]) == ARRAY_NOTATION_REF) - { - rhs_value[ii] = ARRAY_NOTATION_ARRAY (rhs_array[ii]); - rhs_start[ii] = ARRAY_NOTATION_START (rhs_array[ii]); - rhs_length[ii] = ARRAY_NOTATION_LENGTH (rhs_array[ii]); - rhs_stride[ii] = ARRAY_NOTATION_STRIDE (rhs_array[ii]); - rhs_vector[ii] = true; - /* If the stride value is variable (i.e. not constant) then - * assume that the length is positive - */ - if (!TREE_CONSTANT (rhs_length[ii])) - rhs_count_down[ii] = false; - else if (tree_int_cst_lt - (rhs_length[ii], - build_int_cst (TREE_TYPE (rhs_length[ii]), 0))) - rhs_count_down[ii] = true; - else - rhs_count_down[ii] = false; - } - else - rhs_vector[ii] = false; - } - } - - loop = push_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++) - { - if (rhs_vector[ii]) - { - rhs_var[ii] = build_decl (UNKNOWN_LOCATION, VAR_DECL, NULL_TREE, - TREE_TYPE (rhs_start[ii])); - 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_start[ii]), 0), - TREE_TYPE (rhs_start[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 - (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) - { - /* The last ARRAY NOTATION element's ARRAY component should be the - * array's base value - */ - array_expr_rhs = rhs_value[rhs_rank - 1]; - for (ii = rhs_rank - 1; ii >= 0; ii--) - { - /* Array[start_index + (induction_var * stride)] */ - array_expr_rhs = build_array_ref - (location, array_expr_rhs, - build2 (PLUS_EXPR, TREE_TYPE (rhs_var[ii]), rhs_start[ii], - build2 (MULT_EXPR, TREE_TYPE (rhs_var[ii]), rhs_var[ii], - rhs_stride[ii]))); - - if (rhs_count_down[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))); - else - 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))); - } - } - else - { - array_expr_rhs = rhs; - rhs_expr_incr[0] = NULL_TREE; - } - - array_expr = build_modify_expr (location, array_expr_lhs, - lhs_origtype, modifycode, rhs_loc, - array_expr_rhs, rhs_origtype); - - for (ii = 0; ii < lhs_rank; ii++) - { - if (rhs_rank && rhs_expr_incr[ii]) - { - if (lhs_count_down[ii]) - lhs_compare[ii] = build2 - (GT_EXPR, boolean_type_node, lhs_var[ii], lhs_length[ii]); - - else - lhs_compare[ii] = build2 - (LT_EXPR, boolean_type_node, lhs_var[ii], lhs_length[ii]); - - if (rhs_count_down[ii]) - rhs_compare[ii] = build2 - (GT_EXPR, boolean_type_node, rhs_var[ii], rhs_length[ii]); - else - rhs_compare[ii] = build2 - (LT_EXPR, boolean_type_node, rhs_var[ii], rhs_length[ii]); - - cond_expr[ii] = build2 (TRUTH_ANDIF_EXPR, void_type_node, - lhs_compare[ii], rhs_compare[ii]); - } - else - { - if (lhs_count_down[ii]) - cond_expr[ii] = build2 - (GT_EXPR, boolean_type_node, lhs_var[ii], lhs_length[ii]); - else - cond_expr[ii] = build2 - (LT_EXPR, boolean_type_node, lhs_var[ii], lhs_length[ii]); - } - } - - /* The following statements will do the following: - * : (in order from outermost to innermost) - * if (cond_expr) then go to body_label - * else go to exit_label - * : - * array expression - * - * (the increment, goto and exit_label goes from innermost to - * outermost). - * ii++ and jj++ - * go to if_stmt_label - * : - * - */ - - - for (ii = 0; ii < lhs_rank; ii++) - { - add_stmt (lhs_ind_init [ii]); - if (rhs_rank) - add_stmt (rhs_ind_init[ii]); - add_stmt (build1 (LABEL_EXPR, void_type_node, if_stmt_label[ii])); - add_stmt (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]))); - - add_stmt (body_label_expr[ii]); - } - - add_stmt (array_expr); - - for (ii = lhs_rank - 1; ii >= 0; ii--) - { - add_stmt (lhs_expr_incr[ii]); - if (rhs_rank && rhs_expr_incr[ii]) - add_stmt (rhs_expr_incr[ii]); - - add_stmt (build1 (GOTO_EXPR, void_type_node, if_stmt_label[ii])); - add_stmt (exit_label_expr[ii]); - } - - pop_stmt_list (loop); - - return loop; - -} - /* Return whether STRUCT_TYPE has an anonymous field with type TYPE. This is used to implement -fplan9-extensions. */