Hello Everyone, This patch is for the C Compiler in Cilkplus branch. It is an extension of the following patch: http://gcc.gnu.org/ml/gcc-patches/2011-12/msg00691.html. This patch will implement an N-dimension array notation for assignment expressions.
Thanking You, Yours sincerely, Balaji V. Iyer.
diff --git a/gcc/ChangeLog.cilk b/gcc/ChangeLog.cilk index 6d2b694..bf848b1 100644 --- a/gcc/ChangeLog.cilk +++ b/gcc/ChangeLog.cilk @@ -1,3 +1,10 @@ +2011-12-16 Balaji V. Iyer <balaji.v.i...@intel.com> + + * c-typeck.c (find_rank): Modified to find rank of array notation + inside expressions such as PLUS_EXPR. + (build_array_notation_expr): Added support for N-Diamension array + notation. + 2011-12-09 Balaji V. Iyer <balaji.v.i...@intel.com> * c-typeck.c (build_array_notation_expr): New function. diff --git a/gcc/c-typeck.c b/gcc/c-typeck.c index d9cf8e4..c4ff22e 100644 --- a/gcc/c-typeck.c +++ b/gcc/c-typeck.c @@ -5044,231 +5044,399 @@ 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 = false, rhs_vector = false; - tree array_expr_lhs = NULL_TREE, array_expr_rhs = NULL_TREE, array_expr; - tree lhs_value = NULL_TREE, rhs_value = NULL_TREE; - tree lhs_stride = NULL_TREE, lhs_length = NULL_TREE, lhs_start = NULL_TREE; - tree rhs_stride = NULL_TREE, rhs_length = NULL_TREE, rhs_start = NULL_TREE; - tree loop, lhs_var = NULL_TREE, rhs_var = NULL_TREE; - tree body_label, body_label_expr; - tree exit_label, exit_label_expr, cond_expr, if_stmt_label; - tree temp = NULL_TREE; - tree lhs_expr_incr = NULL_TREE, rhs_expr_incr = NULL_TREE; - bool lhs_count_down = false, rhs_count_down = false; + 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; - if (TREE_CODE(lhs) == ARRAY_NOTATION_REF) - { - lhs_value = ARRAY_NOTATION_ARRAY (lhs); - lhs_start = ARRAY_NOTATION_START (lhs); - lhs_length = ARRAY_NOTATION_LENGTH (lhs); - lhs_stride = ARRAY_NOTATION_STRIDE (lhs); - lhs_vector = true; - /* if the stride value is variable (i.e. not constant) then assume the - programmer knows what he is doing and keep on going */ - if (!TREE_CONSTANT (lhs_length)) - lhs_count_down = false; /* assume we count up */ - else if (tree_int_cst_lt (lhs_length, - build_int_cst (TREE_TYPE (lhs_length), 0))) - lhs_count_down = true; + 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; } - else + if (lhs_rank != 0 && rhs_rank != 0 && lhs_rank != rhs_rank) { - if (TREE_CODE(rhs) == ARRAY_NOTATION_REF) - error ("Assignment of vector to a scalar is prohibited"); - else - lhs_vector = false; + 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) { - rhs_value = ARRAY_NOTATION_ARRAY (rhs); - rhs_start = ARRAY_NOTATION_START (rhs); - rhs_length = ARRAY_NOTATION_LENGTH (rhs); - rhs_stride = ARRAY_NOTATION_STRIDE (rhs); - rhs_vector = true; - - /* if the stride value is variable (i.e. not constant) then assume the - programmer knows what he is doing and keep on going */ - if (!TREE_CONSTANT (rhs_length)) - rhs_count_down = false; /* assume wwe count up */ - else if (tree_int_cst_lt (rhs_length, - build_int_cst (TREE_TYPE (rhs_length), 0))) - rhs_count_down = true; + 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; + } } - else - rhs_vector = false; loop = push_stmt_list(); - if (lhs_vector) + for (ii = 0; ii < lhs_rank; ii++) { - lhs_var = build_decl (UNKNOWN_LOCATION, VAR_DECL, NULL_TREE, - TREE_TYPE (lhs_start)); - temp = build_modify_expr - (UNKNOWN_LOCATION, lhs_var, TREE_TYPE (lhs_var), modifycode, - UNKNOWN_LOCATION, build_int_cst (TREE_TYPE (lhs_start), 0), - TREE_TYPE (lhs_start)); - add_stmt (temp); + 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])); + + } } - if (rhs_vector) + for (ii = 0; ii < rhs_rank; ii++) { - rhs_var = build_decl (UNKNOWN_LOCATION, VAR_DECL, NULL_TREE, - TREE_TYPE (rhs_start)); - add_stmt (build_modify_expr (UNKNOWN_LOCATION, rhs_var, - TREE_TYPE (rhs_var), modifycode, - UNKNOWN_LOCATION, - build_int_cst (TREE_TYPE(rhs_start), 0), - TREE_TYPE (rhs_start))); + 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])); + + } } - - /* this will create the if statement label */ - if_stmt_label = build_decl (UNKNOWN_LOCATION, LABEL_DECL, NULL_TREE, - void_type_node); - DECL_CONTEXT (if_stmt_label) = current_function_decl; - DECL_ARTIFICIAL (if_stmt_label) = 0; - DECL_IGNORED_P (if_stmt_label) = 1; + 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 = build_decl (UNKNOWN_LOCATION, LABEL_DECL, NULL_TREE, - void_type_node); - DECL_CONTEXT (body_label) = current_function_decl; - DECL_ARTIFICIAL (body_label) = 0; - DECL_IGNORED_P (body_label) = 1; - body_label_expr = build1 (LABEL_EXPR, void_type_node, body_label); - - /* this will create the exit label..i.e. where the while loop will branch - out of - */ - exit_label = build_decl (UNKNOWN_LOCATION, LABEL_DECL, NULL_TREE, - void_type_node); - DECL_CONTEXT (exit_label) = current_function_decl; - DECL_ARTIFICIAL (exit_label) = 0; - DECL_IGNORED_P (exit_label) = 1; - exit_label_expr = build1 (LABEL_EXPR, void_type_node, exit_label); - - if (lhs_vector) - { - /* Array[start_index + (induction_var * stride)] */ - array_expr_lhs = build_array_ref - (location, lhs_value, build2 (PLUS_EXPR, TREE_TYPE (lhs_var), lhs_start, - build2 (MULT_EXPR, TREE_TYPE (lhs_var), - lhs_var, lhs_stride))); - if (lhs_count_down) - lhs_expr_incr = build2 (MODIFY_EXPR, void_type_node, lhs_var, - build2 (PLUS_EXPR, TREE_TYPE (lhs_var), lhs_var, - build_int_cst (TREE_TYPE (lhs_var), - -1))); - else - lhs_expr_incr = build2 (MODIFY_EXPR, void_type_node, lhs_var, - build2 (PLUS_EXPR, TREE_TYPE (lhs_var), lhs_var, - build_int_cst (TREE_TYPE (lhs_var), - 1))); - } - if (rhs_vector) + /* 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) { - - array_expr_rhs = build_array_ref - (location, rhs_value, build2 (PLUS_EXPR, TREE_TYPE (rhs_var), rhs_start, - build2 (MULT_EXPR, TREE_TYPE (rhs_var), - rhs_var, rhs_stride))); - if (rhs_count_down) - rhs_expr_incr = build2 (MODIFY_EXPR, void_type_node, rhs_var, - build2 (PLUS_EXPR, TREE_TYPE (rhs_var), rhs_var, - build_int_cst (TREE_TYPE (rhs_var), - -1))); - else - rhs_expr_incr = build2 (MODIFY_EXPR, void_type_node, rhs_var, - build2 (PLUS_EXPR, TREE_TYPE (rhs_var), rhs_var, - build_int_cst (TREE_TYPE (rhs_var), - 1))); + /* 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 = NULL_TREE; + 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); - if (rhs_expr_incr) + for (ii = 0; ii < lhs_rank; ii++) { - tree lhs_compare, rhs_compare; - if (lhs_count_down) - lhs_compare = build2 (GE_EXPR, boolean_type_node, lhs_var, - build2 (PLUS_EXPR, TREE_TYPE (lhs_length), - lhs_length, - build_int_cst (TREE_TYPE (lhs_length), - 1))); - else - lhs_compare = build2 (LE_EXPR, boolean_type_node, lhs_var, - build2 (MINUS_EXPR, TREE_TYPE (lhs_length), - lhs_length, - build_int_cst (TREE_TYPE (lhs_length), - 1))); - - if (rhs_count_down) - rhs_compare = build2 (GE_EXPR, boolean_type_node, rhs_var, - build2 (PLUS_EXPR, TREE_TYPE (rhs_length), - rhs_length, - build_int_cst (TREE_TYPE (rhs_length), - 1))); - else - rhs_compare = build2 (LE_EXPR, boolean_type_node, rhs_var, - build2 (MINUS_EXPR, TREE_TYPE (rhs_length), - rhs_length, - build_int_cst (TREE_TYPE (rhs_length), - 1))); + 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 = build2 (TRUTH_ANDIF_EXPR, void_type_node, lhs_compare, - rhs_compare); - } - else - { - if (lhs_count_down) - cond_expr = build2 (GE_EXPR, boolean_type_node, lhs_var, - build2 (PLUS_EXPR, TREE_TYPE (lhs_length), - lhs_length, - build_int_cst (TREE_TYPE (lhs_length), 1))); + cond_expr[ii] = build2 (TRUTH_ANDIF_EXPR, void_type_node, + lhs_compare[ii], rhs_compare[ii]); + } else - cond_expr = build2 (LE_EXPR, boolean_type_node, lhs_var, - fold_build2 (PLUS_EXPR, TREE_TYPE (lhs_length), - lhs_length, - build_int_cst (TREE_TYPE (lhs_length), -1))); + { + 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: - * <if_stmt_label>: + * <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> */ + - add_stmt (build1 (LABEL_EXPR, void_type_node, if_stmt_label)); - add_stmt (build3 (COND_EXPR, void_type_node, cond_expr, - build1 (GOTO_EXPR, void_type_node, body_label), - build1 (GOTO_EXPR, void_type_node, exit_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); + add_stmt (body_label_expr[ii]); + } + add_stmt (array_expr); - add_stmt (lhs_expr_incr); - if (rhs_expr_incr) - add_stmt (rhs_expr_incr); + + 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)); - add_stmt (exit_label_expr); + add_stmt (build1 (GOTO_EXPR, void_type_node, if_stmt_label[ii])); + add_stmt (exit_label_expr[ii]); + } pop_stmt_list (loop);