Commit 713b46fa by Balaji V. Iyer Committed by Balaji V. Iyer

Replaced Dynamic arrays with vec trees in Array Notation for C.

gcc/c-family/ChangeLog
2013-06-21  Balaji V. Iyer  <balaji.v.iyer@intel.com>

        * array-notation-common.c (length_mismatch_in_expr): Changed the
        parameter type's from a dynamic array to a vec_tree.  Also removed
        the size parameters.
        * c-common.h (length_mismatch_in_expr_p): Fixed prototype's as per
        the change above.

gcc/cp/ChangeLog
2013-06-21  Balaji V. Iyer  <balaji.v.iyer@intel.com>

        * cp-array-notation.c (cp_length_mismatch_in_expr_p): Remove.
        (expand_an_in_modify_expr): Changed a function call from the above
        removed function to length_mismatch_in_expr_p.

gcc/c/ChangeLog
2013-06-21  Balaji V. Iyer  <balaji.v.iyer@intel.com>

        * c-array-notation.c (make_triplet_val_inv): New function.
        (create_cmp_incr): Likewise.
        (create_array_refs): Likewise.
        (fix_builtin_array_notation_fn): Replaced all mallocs with tree vec.
        Also modularized common parts between functions and called the function.
        (build_array_notation_expr): Likewise.
        (fix_conditional_array_notations_1): Likewise.
        (fix_array_notation_expr): Likewise.
        (fix_array_notation_call_expr): Likewise.

From-SVN: r200405
parent 818cac82
...@@ -4,6 +4,14 @@ ...@@ -4,6 +4,14 @@
* c-cppbuiltin.c (c_cpp_builtins): Likewise. * c-cppbuiltin.c (c_cpp_builtins): Likewise.
* c-opts.c (c_common_post_options): Likewise. * c-opts.c (c_common_post_options): Likewise.
2013-06-21 Balaji V. Iyer <balaji.v.iyer@intel.com>
* array-notation-common.c (length_mismatch_in_expr): Changed the
parameter type's from a dynamic array to a vec_tree. Also removed
the size parameters.
* c-common.h (length_mismatch_in_expr_p): Fixed prototype's as per
the change above.
2013-06-21 Balaji V. Iyer <balaji.v.iyer@intel.com> 2013-06-21 Balaji V. Iyer <balaji.v.iyer@intel.com>
* c-common.h (struct cilkplus_an_parts): New structure. * c-common.h (struct cilkplus_an_parts): New structure.
......
...@@ -75,35 +75,37 @@ extract_sec_implicit_index_arg (location_t location, tree fn) ...@@ -75,35 +75,37 @@ extract_sec_implicit_index_arg (location_t location, tree fn)
return return_int; return return_int;
} }
/* Returns true if there is length mismatch among expressions /* Returns true if there is a length mismatch among exprssions that are at the
on the same dimension and on the same side of the equal sign. The same dimension and one the same side of the equal sign. The Array notation
expressions (or ARRAY_NOTATION lengths) are passed in through 2-D array lengths (LIST->LENGTH) is passed in as a 2D vector of trees. */
**LIST where X and Y indicate first and second dimension sizes of LIST,
respectively. */
bool bool
length_mismatch_in_expr_p (location_t loc, tree **list, size_t x, size_t y) length_mismatch_in_expr_p (location_t loc, vec<vec<an_parts> >list)
{ {
size_t ii, jj; size_t ii, jj;
tree start = NULL_TREE; tree length = NULL_TREE;
HOST_WIDE_INT l_start, l_node; HOST_WIDE_INT l_length, l_node;
size_t x = list.length ();
size_t y = list[0].length ();
for (jj = 0; jj < y; jj++) for (jj = 0; jj < y; jj++)
{ {
start = NULL_TREE; length = NULL_TREE;
for (ii = 0; ii < x; ii++) for (ii = 0; ii < x; ii++)
{ {
if (!start) if (!length)
start = list[ii][jj]; length = list[ii][jj].length;
else if (TREE_CODE (start) == INTEGER_CST) else if (TREE_CODE (length) == INTEGER_CST)
{ {
/* If start is a INTEGER, and list[ii][jj] is an integer then /* If length is a INTEGER, and list[ii][jj] is an integer then
check if they are equal. If they are not equal then return check if they are equal. If they are not equal then return
true. */ true. */
if (TREE_CODE (list[ii][jj]) == INTEGER_CST) if (TREE_CODE (list[ii][jj].length) == INTEGER_CST)
{ {
l_node = int_cst_value (list[ii][jj]); l_node = int_cst_value (list[ii][jj].length);
l_start = int_cst_value (start); l_length = int_cst_value (length);
if (absu_hwi (l_start) != absu_hwi (l_node)) if (absu_hwi (l_length) != absu_hwi (l_node))
{ {
error_at (loc, "length mismatch in expression"); error_at (loc, "length mismatch in expression");
return true; return true;
...@@ -111,9 +113,9 @@ length_mismatch_in_expr_p (location_t loc, tree **list, size_t x, size_t y) ...@@ -111,9 +113,9 @@ length_mismatch_in_expr_p (location_t loc, tree **list, size_t x, size_t y)
} }
} }
else else
/* We set the start node as the current node just in case it turns /* We set the length node as the current node just in case it turns
out to be an integer. */ out to be an integer. */
start = list[ii][jj]; length = list[ii][jj].length;
} }
} }
return false; return false;
......
...@@ -1193,7 +1193,7 @@ extern bool contains_array_notation_expr (tree); ...@@ -1193,7 +1193,7 @@ extern bool contains_array_notation_expr (tree);
extern tree expand_array_notation_exprs (tree); extern tree expand_array_notation_exprs (tree);
extern tree fix_conditional_array_notations (tree); extern tree fix_conditional_array_notations (tree);
extern tree find_correct_array_notation_type (tree); extern tree find_correct_array_notation_type (tree);
extern bool length_mismatch_in_expr_p (location_t, tree **, size_t, size_t); extern bool length_mismatch_in_expr_p (location_t, vec<vec<an_parts> >);
extern enum built_in_function is_cilkplus_reduce_builtin (tree); extern enum built_in_function is_cilkplus_reduce_builtin (tree);
extern bool find_rank (location_t, tree, tree, bool, size_t *); extern bool find_rank (location_t, tree, tree, bool, size_t *);
extern void extract_array_notation_exprs (tree, bool, vec<tree, va_gc> **); extern void extract_array_notation_exprs (tree, bool, vec<tree, va_gc> **);
......
2013-06-21 Balaji V. Iyer <balaji.v.iyer@intel.com>
* c-array-notation.c (make_triplet_val_inv): New function.
(create_cmp_incr): Likewise.
(create_array_refs): Likewise.
(fix_builtin_array_notation_fn): Replaced all mallocs with tree vec.
Also modularized common parts between functions and called the function.
(build_array_notation_expr): Likewise.
(fix_conditional_array_notations_1): Likewise.
(fix_array_notation_expr): Likewise.
(fix_array_notation_call_expr): Likewise.
2013-06-18 Marek Polacek <polacek@redhat.com> 2013-06-18 Marek Polacek <polacek@redhat.com>
PR c/57630 PR c/57630
......
...@@ -74,6 +74,83 @@ ...@@ -74,6 +74,83 @@
#include "opts.h" #include "opts.h"
#include "c-family/c-common.h" #include "c-family/c-common.h"
/* If *VALUE is not of type INTEGER_CST, PARM_DECL or VAR_DECL, then map it
to a variable and then set *VALUE to the new variable. */
static inline void
make_triplet_val_inv (location_t loc, tree *value)
{
tree var, new_exp;
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);
new_exp = build_modify_expr (loc, var, TREE_TYPE (var), NOP_EXPR, loc,
*value, TREE_TYPE (*value));
add_stmt (new_exp);
*value = var;
}
}
/* 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_incr (location_t loc, vec<an_loop_parts> *node, size_t rank,
vec<vec<an_parts> > an_info)
{
for (size_t ii = 0; ii < rank; ii++)
{
tree var = (*node)[ii].var;
tree length = an_info[0][ii].length;
(*node)[ii].incr = build_unary_op (loc, POSTINCREMENT_EXPR, var, 0);
(*node)[ii].cmp = build2 (LT_EXPR, boolean_type_node, var, length);
}
}
/* 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<tree, va_gc> *
create_array_refs (location_t loc, vec<vec<an_parts> > an_info,
vec<an_loop_parts> an_loop_info, size_t size, size_t rank)
{
tree ind_mult, ind_incr;
vec<tree, va_gc> *array_operand = NULL;
for (size_t ii = 0; ii < size; ii++)
if (an_info[ii][0].is_vector)
{
tree array_opr = an_info[ii][rank - 1].value;
for (int s_jj = rank - 1; s_jj >= 0; s_jj--)
{
tree var = an_loop_info[s_jj].var;
tree stride = an_info[ii][s_jj].stride;
tree start = an_info[ii][s_jj].start;
ind_mult = build2 (MULT_EXPR, TREE_TYPE (var), var, stride);
ind_incr = build2 (PLUS_EXPR, TREE_TYPE (var), start, ind_mult);
array_opr = build_array_ref (loc, array_opr, ind_incr);
}
vec_safe_push (array_operand, array_opr);
}
else
/* This is just a dummy node to make sure both the list sizes for both
array list and array operand list are the same. */
vec_safe_push (array_operand, integer_one_node);
return array_operand;
}
/* Replaces all the scalar expressions in *NODE. Returns a STATEMENT_LIST that /* Replaces all the scalar expressions in *NODE. Returns a STATEMENT_LIST that
holds the NODE along with variables that holds the results of the invariant holds the NODE along with variables that holds the results of the invariant
expressions. */ expressions. */
...@@ -124,16 +201,13 @@ fix_builtin_array_notation_fn (tree an_builtin_fn, tree *new_var) ...@@ -124,16 +201,13 @@ fix_builtin_array_notation_fn (tree an_builtin_fn, tree *new_var)
tree new_yes_list, new_cond_expr, new_var_init = NULL_TREE; tree new_yes_list, new_cond_expr, new_var_init = NULL_TREE;
tree new_exp_init = NULL_TREE; tree new_exp_init = NULL_TREE;
vec<tree, va_gc> *array_list = NULL, *array_operand = NULL; vec<tree, va_gc> *array_list = NULL, *array_operand = NULL;
size_t list_size = 0, rank = 0, ii = 0, jj = 0; size_t list_size = 0, rank = 0, ii = 0;
int s_jj = 0; tree loop_init, array_op0;
tree **array_ops, *array_var, jj_tree, loop_init, array_op0;
tree **array_value, **array_stride, **array_length, **array_start;
tree *compare_expr, *expr_incr, *ind_init;
tree identity_value = NULL_TREE, call_fn = NULL_TREE, new_call_expr, body; tree identity_value = NULL_TREE, call_fn = NULL_TREE, new_call_expr, body;
bool **count_down, **array_vector;
location_t location = UNKNOWN_LOCATION; location_t location = UNKNOWN_LOCATION;
tree loop_with_init = alloc_stmt_list (); tree loop_with_init = alloc_stmt_list ();
vec<vec<an_parts> > an_info = vNULL;
vec<an_loop_parts> an_loop_info = vNULL;
enum built_in_function an_type = enum built_in_function an_type =
is_cilkplus_reduce_builtin (CALL_EXPR_FN (an_builtin_fn)); is_cilkplus_reduce_builtin (CALL_EXPR_FN (an_builtin_fn));
if (an_type == BUILT_IN_NONE) if (an_type == BUILT_IN_NONE)
...@@ -201,157 +275,27 @@ fix_builtin_array_notation_fn (tree an_builtin_fn, tree *new_var) ...@@ -201,157 +275,27 @@ fix_builtin_array_notation_fn (tree an_builtin_fn, tree *new_var)
default: default:
gcc_unreachable (); gcc_unreachable ();
} }
array_ops = XNEWVEC (tree *, list_size);
for (ii = 0; ii < list_size; ii++)
array_ops[ii] = XNEWVEC (tree, rank);
array_vector = XNEWVEC (bool *, list_size);
for (ii = 0; ii < list_size; ii++)
array_vector[ii] = XNEWVEC (bool, rank);
array_value = XNEWVEC (tree *, list_size);
array_stride = XNEWVEC (tree *, list_size);
array_length = XNEWVEC (tree *, list_size);
array_start = XNEWVEC (tree *, list_size);
for (ii = 0; ii < list_size; ii++)
{
array_value[ii] = XNEWVEC (tree, rank);
array_stride[ii] = XNEWVEC (tree, rank);
array_length[ii] = XNEWVEC (tree, rank);
array_start[ii] = XNEWVEC (tree, rank);
}
compare_expr = XNEWVEC (tree, rank);
expr_incr = XNEWVEC (tree, rank);
ind_init = XNEWVEC (tree, rank);
count_down = XNEWVEC (bool *, list_size);
for (ii = 0; ii < list_size; ii++)
count_down[ii] = XNEWVEC (bool, rank);
array_var = XNEWVEC (tree, rank);
for (ii = 0; ii < list_size; ii++)
{
jj = 0;
for (jj_tree = (*array_list)[ii];
jj_tree && TREE_CODE (jj_tree) == ARRAY_NOTATION_REF;
jj_tree = ARRAY_NOTATION_ARRAY (jj_tree))
{
array_ops[ii][jj] = jj_tree;
jj++;
}
}
for (ii = 0; ii < list_size; ii++)
{
tree array_node = (*array_list)[ii];
if (TREE_CODE (array_node) == ARRAY_NOTATION_REF)
{
for (jj = 0; jj < rank; jj++)
{
if (TREE_CODE (array_ops[ii][jj]) == ARRAY_NOTATION_REF)
{
array_value[ii][jj] =
ARRAY_NOTATION_ARRAY (array_ops[ii][jj]);
array_start[ii][jj] =
ARRAY_NOTATION_START (array_ops[ii][jj]);
array_length[ii][jj] =
fold_build1 (CONVERT_EXPR, integer_type_node,
ARRAY_NOTATION_LENGTH (array_ops[ii][jj]));
array_stride[ii][jj] =
fold_build1 (CONVERT_EXPR, integer_type_node,
ARRAY_NOTATION_STRIDE (array_ops[ii][jj]));
array_vector[ii][jj] = true;
if (!TREE_CONSTANT (array_length[ii][jj]))
count_down[ii][jj] = false;
else if (tree_int_cst_lt
(array_length[ii][jj],
build_int_cst (TREE_TYPE (array_length[ii][jj]),
0)))
count_down[ii][jj] = true;
else
count_down[ii][jj] = false;
}
else
array_vector[ii][jj] = false;
}
}
}
an_loop_info.safe_grow_cleared (rank);
cilkplus_extract_an_triplets (array_list, list_size, rank, &an_info);
loop_init = alloc_stmt_list (); loop_init = alloc_stmt_list ();
for (ii = 0; ii < rank; ii++) for (ii = 0; ii < rank; ii++)
{ {
array_var[ii] = build_decl (location, VAR_DECL, NULL_TREE, an_loop_info[ii].var = build_decl (location, VAR_DECL, NULL_TREE,
integer_type_node); integer_type_node);
ind_init[ii] = an_loop_info[ii].ind_init =
build_modify_expr (location, array_var[ii], build_modify_expr (location, an_loop_info[ii].var,
TREE_TYPE (array_var[ii]), NOP_EXPR, TREE_TYPE (an_loop_info[ii].var), NOP_EXPR,
location, location,
build_int_cst (TREE_TYPE (array_var[ii]), 0), build_int_cst (TREE_TYPE (an_loop_info[ii].var), 0),
TREE_TYPE (array_var[ii])); TREE_TYPE (an_loop_info[ii].var));
}
for (ii = 0; ii < list_size; ii++)
{
if (array_vector[ii][0])
{
tree array_opr_node = array_value[ii][rank - 1];
for (s_jj = rank - 1; s_jj >= 0; s_jj--)
{
if (count_down[ii][s_jj])
{
/* Array[start_index - (induction_var * stride)] */
array_opr_node = build_array_ref
(location, array_opr_node,
build2 (MINUS_EXPR, TREE_TYPE (array_var[s_jj]),
array_start[ii][s_jj],
build2 (MULT_EXPR, TREE_TYPE (array_var[s_jj]),
array_var[s_jj], array_stride[ii][s_jj])));
}
else
{
/* Array[start_index + (induction_var * stride)] */
array_opr_node = build_array_ref
(location, array_opr_node,
build2 (PLUS_EXPR, TREE_TYPE (array_var[s_jj]),
array_start[ii][s_jj],
build2 (MULT_EXPR, TREE_TYPE (array_var[s_jj]),
array_var[s_jj], array_stride[ii][s_jj])));
}
}
vec_safe_push (array_operand, array_opr_node);
}
else
/* This is just a dummy node to make sure the list sizes for both
array list and array operand list are the same. */
vec_safe_push (array_operand, integer_one_node);
} }
array_operand = create_array_refs (location, an_info, an_loop_info,
list_size, rank);
replace_array_notations (&func_parm, true, array_list, array_operand); replace_array_notations (&func_parm, true, array_list, array_operand);
for (ii = 0; ii < rank; ii++)
expr_incr[ii] =
build2 (MODIFY_EXPR, void_type_node, array_var[ii],
build2 (PLUS_EXPR, TREE_TYPE (array_var[ii]), array_var[ii],
build_int_cst (TREE_TYPE (array_var[ii]), 1)));
for (jj = 0; jj < rank; jj++)
{
if (rank && expr_incr[jj])
{
if (count_down[0][jj])
compare_expr[jj] =
build2 (LT_EXPR, boolean_type_node, array_var[jj],
build2 (MULT_EXPR, TREE_TYPE (array_var[jj]),
array_length[0][jj],
build_int_cst (TREE_TYPE (array_var[jj]), -1)));
else
compare_expr[jj] = build2 (LT_EXPR, boolean_type_node,
array_var[jj], array_length[0][jj]);
}
}
create_cmp_incr (location, &an_loop_info, rank, an_info);
if (an_type != BUILT_IN_CILKPLUS_SEC_REDUCE_MUTATING) if (an_type != BUILT_IN_CILKPLUS_SEC_REDUCE_MUTATING)
{ {
*new_var = build_decl (location, VAR_DECL, NULL_TREE, new_var_type); *new_var = build_decl (location, VAR_DECL, NULL_TREE, new_var_type);
...@@ -519,7 +463,7 @@ fix_builtin_array_notation_fn (tree an_builtin_fn, tree *new_var) ...@@ -519,7 +463,7 @@ fix_builtin_array_notation_fn (tree an_builtin_fn, tree *new_var)
{ {
new_yes_ind = build_modify_expr new_yes_ind = build_modify_expr
(location, *new_var, TREE_TYPE (*new_var), NOP_EXPR, (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
location, array_var[0], TREE_TYPE (array_var[0])); location, an_loop_info[0].var, TREE_TYPE (an_loop_info[0].var));
new_yes_expr = build_modify_expr new_yes_expr = build_modify_expr
(location, array_ind_value, TREE_TYPE (array_ind_value), (location, array_ind_value, TREE_TYPE (array_ind_value),
NOP_EXPR, NOP_EXPR,
...@@ -569,7 +513,7 @@ fix_builtin_array_notation_fn (tree an_builtin_fn, tree *new_var) ...@@ -569,7 +513,7 @@ fix_builtin_array_notation_fn (tree an_builtin_fn, tree *new_var)
{ {
new_yes_ind = build_modify_expr new_yes_ind = build_modify_expr
(location, *new_var, TREE_TYPE (*new_var), NOP_EXPR, (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
location, array_var[0], TREE_TYPE (array_var[0])); location, an_loop_info[0].var, TREE_TYPE (an_loop_info[0].var));
new_yes_expr = build_modify_expr new_yes_expr = build_modify_expr
(location, array_ind_value, TREE_TYPE (array_ind_value), (location, array_ind_value, TREE_TYPE (array_ind_value),
NOP_EXPR, NOP_EXPR,
...@@ -619,7 +563,7 @@ fix_builtin_array_notation_fn (tree an_builtin_fn, tree *new_var) ...@@ -619,7 +563,7 @@ fix_builtin_array_notation_fn (tree an_builtin_fn, tree *new_var)
} }
for (ii = 0; ii < rank; ii++) for (ii = 0; ii < rank; ii++)
append_to_statement_list (ind_init [ii], &loop_init); append_to_statement_list (an_loop_info[ii].ind_init, &loop_init);
if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND
|| an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MIN_IND) || an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MIN_IND)
...@@ -632,33 +576,14 @@ fix_builtin_array_notation_fn (tree an_builtin_fn, tree *new_var) ...@@ -632,33 +576,14 @@ fix_builtin_array_notation_fn (tree an_builtin_fn, tree *new_var)
for (ii = 0; ii < rank; ii++) for (ii = 0; ii < rank; ii++)
{ {
tree new_loop = push_stmt_list (); tree new_loop = push_stmt_list ();
c_finish_loop (location, compare_expr[ii], expr_incr[ii], body, NULL_TREE, c_finish_loop (location, an_loop_info[ii].cmp, an_loop_info[ii].incr,
NULL_TREE, true); body, NULL_TREE, NULL_TREE, true);
body = pop_stmt_list (new_loop); body = pop_stmt_list (new_loop);
} }
append_to_statement_list_force (body, &loop_with_init); append_to_statement_list_force (body, &loop_with_init);
XDELETEVEC (compare_expr); an_info.release ();
XDELETEVEC (expr_incr); an_loop_info.release ();
XDELETEVEC (ind_init);
XDELETEVEC (array_var);
for (ii = 0; ii < list_size; ii++)
{
XDELETEVEC (count_down[ii]);
XDELETEVEC (array_value[ii]);
XDELETEVEC (array_stride[ii]);
XDELETEVEC (array_length[ii]);
XDELETEVEC (array_start[ii]);
XDELETEVEC (array_ops[ii]);
XDELETEVEC (array_vector[ii]);
}
XDELETEVEC (count_down);
XDELETEVEC (array_value);
XDELETEVEC (array_stride);
XDELETEVEC (array_length);
XDELETEVEC (array_start);
XDELETEVEC (array_ops);
XDELETEVEC (array_vector);
return loop_with_init; return loop_with_init;
} }
...@@ -674,31 +599,22 @@ build_array_notation_expr (location_t location, tree lhs, tree lhs_origtype, ...@@ -674,31 +599,22 @@ build_array_notation_expr (location_t location, tree lhs, tree lhs_origtype,
enum tree_code modifycode, location_t rhs_loc, enum tree_code modifycode, location_t rhs_loc,
tree rhs, tree rhs_origtype) tree rhs, tree rhs_origtype)
{ {
bool **lhs_vector = NULL, **rhs_vector = NULL, found_builtin_fn = false; bool found_builtin_fn = false;
tree **lhs_array = NULL, **rhs_array = NULL;
tree array_expr_lhs = NULL_TREE, array_expr_rhs = NULL_TREE; tree array_expr_lhs = NULL_TREE, array_expr_rhs = NULL_TREE;
tree array_expr = NULL_TREE; tree array_expr = NULL_TREE;
tree **lhs_value = NULL, **rhs_value = NULL; tree an_init = NULL_TREE;
tree **lhs_stride = NULL, **lhs_length = NULL, **lhs_start = NULL; vec<tree> cond_expr = vNULL;
tree **rhs_stride = NULL, **rhs_length = NULL, **rhs_start = NULL;
tree an_init = NULL_TREE, *lhs_var = NULL, *rhs_var = NULL;
tree *cond_expr = NULL;
tree body, loop_with_init = alloc_stmt_list(); tree body, loop_with_init = alloc_stmt_list();
tree scalar_mods = NULL_TREE; tree scalar_mods = NULL_TREE;
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;
vec<tree, va_gc> *rhs_array_operand = NULL, *lhs_array_operand = NULL; vec<tree, va_gc> *rhs_array_operand = NULL, *lhs_array_operand = NULL;
size_t lhs_rank = 0, rhs_rank = 0; size_t lhs_rank = 0, rhs_rank = 0;
size_t ii = 0, jj = 0; size_t ii = 0;
int s_jj = 0;
tree ii_tree = NULL_TREE, new_modify_expr;
vec<tree, va_gc> *lhs_list = NULL, *rhs_list = NULL; vec<tree, va_gc> *lhs_list = NULL, *rhs_list = NULL;
tree new_var = NULL_TREE, builtin_loop = NULL_TREE; tree new_modify_expr, new_var = NULL_TREE, builtin_loop = NULL_TREE;
tree begin_var, lngth_var, strde_var; size_t rhs_list_size = 0, lhs_list_size = 0;
size_t rhs_list_size = 0, lhs_list_size = 0; vec<vec<an_parts> > lhs_an_info = vNULL, rhs_an_info = vNULL;
vec<an_loop_parts> lhs_an_loop_info = vNULL, rhs_an_loop_info = vNULL;
/* If either of this is true, an error message must have been send out /* If either of this is true, an error message must have been send out
already. Not necessary to send out multiple error messages. */ already. Not necessary to send out multiple error messages. */
if (lhs == error_mark_node || rhs == error_mark_node) if (lhs == error_mark_node || rhs == error_mark_node)
...@@ -810,296 +726,49 @@ build_array_notation_expr (location_t location, tree lhs, tree lhs_origtype, ...@@ -810,296 +726,49 @@ build_array_notation_expr (location_t location, tree lhs, tree lhs_origtype,
/* Here we assign the array notation components to variable so that we can /* Here we assign the array notation components to variable so that we can
satisfy the exec once rule. */ satisfy the exec once rule. */
for (ii = 0; ii < lhs_list_size; ii++) for (ii = 0; ii < lhs_list_size; ii++)
{ {
tree array_node = (*lhs_list)[ii]; tree array_node = (*lhs_list)[ii];
tree array_begin = ARRAY_NOTATION_START (array_node); make_triplet_val_inv (location, &ARRAY_NOTATION_START (array_node));
tree array_lngth = ARRAY_NOTATION_LENGTH (array_node); make_triplet_val_inv (location, &ARRAY_NOTATION_LENGTH (array_node));
tree array_strde = ARRAY_NOTATION_STRIDE (array_node); make_triplet_val_inv (location, &ARRAY_NOTATION_STRIDE (array_node));
if (TREE_CODE (array_begin) != INTEGER_CST)
{
begin_var = build_decl (location, VAR_DECL, NULL_TREE,
integer_type_node);
add_stmt (build_modify_expr (location, begin_var,
TREE_TYPE (begin_var),
NOP_EXPR, location, array_begin,
TREE_TYPE (array_begin)));
ARRAY_NOTATION_START (array_node) = begin_var;
}
if (TREE_CODE (array_lngth) != INTEGER_CST)
{
lngth_var = build_decl (location, VAR_DECL, NULL_TREE,
integer_type_node);
add_stmt (build_modify_expr (location, lngth_var,
TREE_TYPE (lngth_var),
NOP_EXPR, location, array_lngth,
TREE_TYPE (array_lngth)));
ARRAY_NOTATION_LENGTH (array_node) = lngth_var;
}
if (TREE_CODE (array_strde) != INTEGER_CST)
{
strde_var = build_decl (location, VAR_DECL, NULL_TREE,
integer_type_node);
add_stmt (build_modify_expr (location, strde_var,
TREE_TYPE (strde_var),
NOP_EXPR, location, array_strde,
TREE_TYPE (array_strde)));
ARRAY_NOTATION_STRIDE (array_node) = strde_var;
}
}
for (ii = 0; ii < rhs_list_size; ii++)
{
tree array_node = (*rhs_list)[ii];
if (array_node && TREE_CODE (array_node) == ARRAY_NOTATION_REF)
{
tree array_begin = ARRAY_NOTATION_START (array_node);
tree array_lngth = ARRAY_NOTATION_LENGTH (array_node);
tree array_strde = ARRAY_NOTATION_STRIDE (array_node);
if (TREE_CODE (array_begin) != INTEGER_CST)
{
begin_var = build_decl (location, VAR_DECL, NULL_TREE,
integer_type_node);
add_stmt (build_modify_expr (location, begin_var,
TREE_TYPE (begin_var),
NOP_EXPR, location, array_begin,
TREE_TYPE (array_begin)));
ARRAY_NOTATION_START (array_node) = begin_var;
}
if (TREE_CODE (array_lngth) != INTEGER_CST)
{
lngth_var = build_decl (location, VAR_DECL, NULL_TREE,
integer_type_node);
add_stmt (build_modify_expr (location, lngth_var,
TREE_TYPE (lngth_var),
NOP_EXPR, location, array_lngth,
TREE_TYPE (array_lngth)));
ARRAY_NOTATION_LENGTH (array_node) = lngth_var;
}
if (TREE_CODE (array_strde) != INTEGER_CST)
{
strde_var = build_decl (location, VAR_DECL, NULL_TREE,
integer_type_node);
add_stmt (build_modify_expr (location, strde_var,
TREE_TYPE (strde_var),
NOP_EXPR, location, array_strde,
TREE_TYPE (array_strde)));
ARRAY_NOTATION_STRIDE (array_node) = strde_var;
}
}
} }
lhs_vector = XNEWVEC (bool *, lhs_list_size);
for (ii = 0; ii < lhs_list_size; ii++)
lhs_vector[ii] = XNEWVEC (bool, lhs_rank);
rhs_vector = XNEWVEC (bool *, rhs_list_size);
for (ii = 0; ii < rhs_list_size; ii++)
rhs_vector[ii] = XNEWVEC (bool, rhs_rank);
lhs_array = XNEWVEC (tree *, lhs_list_size);
for (ii = 0; ii < lhs_list_size; ii++)
lhs_array[ii] = XNEWVEC (tree, lhs_rank);
rhs_array = XNEWVEC (tree *, rhs_list_size);
for (ii = 0; ii < rhs_list_size; ii++)
rhs_array[ii] = XNEWVEC (tree, rhs_rank);
lhs_value = XNEWVEC (tree *, lhs_list_size);
for (ii = 0; ii < lhs_list_size; ii++)
lhs_value[ii] = XNEWVEC (tree, lhs_rank);
rhs_value = XNEWVEC (tree *, rhs_list_size);
for (ii = 0; ii < rhs_list_size; ii++)
rhs_value[ii] = XNEWVEC (tree, rhs_rank);
lhs_stride = XNEWVEC (tree *, lhs_list_size);
for (ii = 0; ii < lhs_list_size; ii++)
lhs_stride[ii] = XNEWVEC (tree, lhs_rank);
rhs_stride = XNEWVEC (tree *, rhs_list_size);
for (ii = 0; ii < rhs_list_size; ii++) for (ii = 0; ii < rhs_list_size; ii++)
rhs_stride[ii] = XNEWVEC (tree, rhs_rank); if ((*rhs_list)[ii] && TREE_CODE ((*rhs_list)[ii]) == ARRAY_NOTATION_REF)
{
lhs_length = XNEWVEC (tree *, lhs_list_size); tree array_node = (*rhs_list)[ii];
for (ii = 0; ii < lhs_list_size; ii++) make_triplet_val_inv (location, &ARRAY_NOTATION_START (array_node));
lhs_length[ii] = XNEWVEC (tree, lhs_rank); make_triplet_val_inv (location, &ARRAY_NOTATION_LENGTH (array_node));
make_triplet_val_inv (location, &ARRAY_NOTATION_STRIDE (array_node));
rhs_length = XNEWVEC (tree *, rhs_list_size); }
for (ii = 0; ii < rhs_list_size; ii++)
rhs_length[ii] = XNEWVEC (tree, rhs_rank);
lhs_start = XNEWVEC (tree *, lhs_list_size);
for (ii = 0; ii < lhs_list_size; ii++)
lhs_start[ii] = XNEWVEC (tree, lhs_rank);
rhs_start = XNEWVEC (tree *, rhs_list_size);
for (ii = 0; ii < rhs_list_size; ii++)
rhs_start[ii] = XNEWVEC (tree, rhs_rank);
lhs_var = XNEWVEC (tree, lhs_rank);
rhs_var = XNEWVEC (tree, rhs_rank);
cond_expr = XNEWVEC (tree, MAX (lhs_rank, rhs_rank));
lhs_expr_incr = XNEWVEC (tree, lhs_rank);
rhs_expr_incr =XNEWVEC (tree, rhs_rank);
lhs_ind_init = XNEWVEC (tree, lhs_rank);
rhs_ind_init = XNEWVEC (tree, rhs_rank);
lhs_count_down = XNEWVEC (bool *, lhs_list_size);
for (ii = 0; ii < lhs_list_size; ii++)
lhs_count_down[ii] = XNEWVEC (bool, lhs_rank);
rhs_count_down = XNEWVEC (bool *, rhs_list_size); cond_expr.safe_grow_cleared (MAX (lhs_rank, rhs_rank));
for (ii = 0; ii < rhs_list_size; ii++)
rhs_count_down[ii] = XNEWVEC (bool, rhs_rank);
lhs_compare = XNEWVEC (tree, lhs_rank); lhs_an_loop_info.safe_grow_cleared (lhs_rank);
rhs_compare = XNEWVEC (tree, rhs_rank);
if (lhs_rank)
{
for (ii = 0; ii < lhs_list_size; ii++)
{
jj = 0;
ii_tree = (*lhs_list)[ii];
while (ii_tree)
{
if (TREE_CODE (ii_tree) == ARRAY_NOTATION_REF)
{
lhs_array[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) == PARM_DECL)
break;
}
}
}
else
lhs_array[0][0] = NULL_TREE;
if (rhs_rank) if (rhs_rank)
{ rhs_an_loop_info.safe_grow_cleared (rhs_rank);
for (ii = 0; ii < rhs_list_size; ii++)
{
jj = 0;
ii_tree = (*rhs_list)[ii];
while (ii_tree)
{
if (TREE_CODE (ii_tree) == ARRAY_NOTATION_REF)
{
rhs_array[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) == PARM_DECL
|| TREE_CODE (ii_tree) == CALL_EXPR)
break;
}
}
}
for (ii = 0; ii < lhs_list_size; ii++) cilkplus_extract_an_triplets (lhs_list, lhs_list_size, lhs_rank,
{ &lhs_an_info);
tree lhs_node = (*lhs_list)[ii]; if (rhs_rank)
if (TREE_CODE (lhs_node) == ARRAY_NOTATION_REF)
{
for (jj = 0; jj < lhs_rank; jj++)
{
if (TREE_CODE (lhs_array[ii][jj]) == ARRAY_NOTATION_REF)
{
lhs_value[ii][jj] = ARRAY_NOTATION_ARRAY (lhs_array[ii][jj]);
lhs_start[ii][jj] = ARRAY_NOTATION_START (lhs_array[ii][jj]);
lhs_length[ii][jj] =
fold_build1 (CONVERT_EXPR, integer_type_node,
ARRAY_NOTATION_LENGTH (lhs_array[ii][jj]));
lhs_stride[ii][jj] =
fold_build1 (CONVERT_EXPR, integer_type_node,
ARRAY_NOTATION_STRIDE (lhs_array[ii][jj]));
lhs_vector[ii][jj] = true;
/* IF the stride value is variable (i.e. not constant) then
assume that the length is positive. */
if (!TREE_CONSTANT (lhs_length[ii][jj]))
lhs_count_down[ii][jj] = false;
else if (tree_int_cst_lt
(lhs_length[ii][jj],
build_zero_cst (TREE_TYPE (lhs_length[ii][jj]))))
lhs_count_down[ii][jj] = true;
else
lhs_count_down[ii][jj] = false;
}
else
lhs_vector[ii][jj] = false;
}
}
}
for (ii = 0; ii < rhs_list_size; ii++)
{ {
if (TREE_CODE ((*rhs_list)[ii]) == ARRAY_NOTATION_REF) rhs_an_loop_info.safe_grow_cleared (rhs_rank);
{ cilkplus_extract_an_triplets (rhs_list, rhs_list_size, rhs_rank,
for (jj = 0; jj < rhs_rank; jj++) &rhs_an_info);
{
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] =
fold_build1 (CONVERT_EXPR, integer_type_node,
ARRAY_NOTATION_LENGTH (rhs_array[ii][jj]));
rhs_stride[ii][jj] =
fold_build1 (CONVERT_EXPR, integer_type_node,
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;
}
}
else
for (jj = 0; jj < rhs_rank; jj++)
{
rhs_vector[ii][jj] = false;
rhs_length[ii][jj] = NULL_TREE;
}
} }
if (length_mismatch_in_expr_p (EXPR_LOCATION (lhs), lhs_an_info)
if (length_mismatch_in_expr_p (EXPR_LOCATION (lhs), lhs_length, || (rhs_rank
lhs_list_size, lhs_rank) && length_mismatch_in_expr_p (EXPR_LOCATION (rhs), rhs_an_info)))
|| length_mismatch_in_expr_p (EXPR_LOCATION (rhs), rhs_length,
rhs_list_size, rhs_rank))
{ {
pop_stmt_list (an_init); pop_stmt_list (an_init);
return error_mark_node; return error_mark_node;
} }
if (lhs_list_size > 0 && rhs_list_size > 0 && lhs_rank > 0 && rhs_rank > 0 if (lhs_list_size > 0 && rhs_list_size > 0 && lhs_rank > 0 && rhs_rank > 0
&& TREE_CODE (lhs_length[0][0]) == INTEGER_CST && TREE_CODE (lhs_an_info[0][0].length) == INTEGER_CST
&& rhs_length[0][0] && rhs_an_info[0][0].length
&& TREE_CODE (rhs_length[0][0]) == INTEGER_CST) && TREE_CODE (rhs_an_info[0][0].length) == INTEGER_CST)
{ {
HOST_WIDE_INT l_length = int_cst_value (lhs_length[0][0]); HOST_WIDE_INT l_length = int_cst_value (lhs_an_info[0][0].length);
HOST_WIDE_INT r_length = int_cst_value (rhs_length[0][0]); HOST_WIDE_INT r_length = int_cst_value (rhs_an_info[0][0].length);
/* Length can be negative or positive. As long as the magnitude is OK, /* Length can be negative or positive. As long as the magnitude is OK,
then the array notation is valid. */ then the array notation is valid. */
if (absu_hwi (l_length) != absu_hwi (r_length)) if (absu_hwi (l_length) != absu_hwi (r_length))
...@@ -1110,256 +779,77 @@ build_array_notation_expr (location_t location, tree lhs, tree lhs_origtype, ...@@ -1110,256 +779,77 @@ build_array_notation_expr (location_t location, tree lhs, tree lhs_origtype,
} }
} }
for (ii = 0; ii < lhs_rank; ii++) for (ii = 0; ii < lhs_rank; ii++)
{ if (lhs_an_info[0][ii].is_vector)
if (lhs_vector[0][ii]) {
{ lhs_an_loop_info[ii].var = build_decl (location, VAR_DECL, NULL_TREE,
lhs_var[ii] = build_decl (location, VAR_DECL, NULL_TREE, integer_type_node);
integer_type_node); lhs_an_loop_info[ii].ind_init = build_modify_expr
lhs_ind_init[ii] = build_modify_expr (location, lhs_an_loop_info[ii].var,
(location, lhs_var[ii], TREE_TYPE (lhs_var[ii]), TREE_TYPE (lhs_an_loop_info[ii].var), NOP_EXPR,
NOP_EXPR, location, build_zero_cst (TREE_TYPE (lhs_an_loop_info[ii].var)),
location, build_zero_cst (TREE_TYPE (lhs_var[ii])), TREE_TYPE (lhs_an_loop_info[ii].var));
TREE_TYPE (lhs_var[ii])); }
}
}
for (ii = 0; ii < rhs_rank; ii++) for (ii = 0; ii < rhs_rank; ii++)
{ {
/* When we have a polynomial, we assume that the indices are of type /* When we have a polynomial, we assume that the indices are of type
integer. */ integer. */
rhs_var[ii] = build_decl (location, VAR_DECL, NULL_TREE, rhs_an_loop_info[ii].var = build_decl (location, VAR_DECL, NULL_TREE,
integer_type_node); integer_type_node);
rhs_ind_init[ii] = build_modify_expr rhs_an_loop_info[ii].ind_init = build_modify_expr
(location, rhs_var[ii], TREE_TYPE (rhs_var[ii]), (location, rhs_an_loop_info[ii].var,
NOP_EXPR, TREE_TYPE (rhs_an_loop_info[ii].var), NOP_EXPR,
location, build_int_cst (TREE_TYPE (rhs_var[ii]), 0), location, build_int_cst (TREE_TYPE (rhs_an_loop_info[ii].var), 0),
TREE_TYPE (rhs_var[ii])); TREE_TYPE (rhs_an_loop_info[ii].var));
} }
if (lhs_rank) if (lhs_rank)
{ {
for (ii = 0; ii < lhs_list_size; ii++) lhs_array_operand = create_array_refs
{ (location, lhs_an_info, lhs_an_loop_info, lhs_list_size, lhs_rank);
if (lhs_vector[ii][0])
{
/* The last ARRAY_NOTATION element's ARRAY component should be
the array's base value. */
tree lhs_array_opr = lhs_value[ii][lhs_rank - 1];
for (s_jj = lhs_rank - 1; s_jj >= 0; s_jj--)
{
if (lhs_count_down[ii][s_jj])
/* Array[start_index + (induction_var * stride)]. */
lhs_array_opr = build_array_ref
(location, lhs_array_opr,
build2 (MINUS_EXPR, TREE_TYPE (lhs_var[s_jj]),
lhs_start[ii][s_jj],
build2 (MULT_EXPR, TREE_TYPE (lhs_var[s_jj]),
lhs_var[s_jj],
lhs_stride[ii][s_jj])));
else
lhs_array_opr = build_array_ref
(location, lhs_array_opr,
build2 (PLUS_EXPR, TREE_TYPE (lhs_var[s_jj]),
lhs_start[ii][s_jj],
build2 (MULT_EXPR, TREE_TYPE (lhs_var[s_jj]),
lhs_var[s_jj],
lhs_stride[ii][s_jj])));
}
vec_safe_push (lhs_array_operand, lhs_array_opr);
}
else
vec_safe_push (lhs_array_operand, integer_one_node);
}
replace_array_notations (&lhs, true, lhs_list, lhs_array_operand); replace_array_notations (&lhs, true, lhs_list, lhs_array_operand);
array_expr_lhs = lhs; array_expr_lhs = lhs;
} }
if (rhs_array_operand)
vec_safe_truncate (rhs_array_operand, 0);
if (rhs_rank) if (rhs_rank)
{ {
for (ii = 0; ii < rhs_list_size; ii++) rhs_array_operand = create_array_refs
{ (location, rhs_an_info, rhs_an_loop_info, rhs_list_size, rhs_rank);
if (rhs_vector[ii][0]) replace_array_notations (&rhs, true, rhs_list, rhs_array_operand);
{ vec_safe_truncate (rhs_array_operand, 0);
tree rhs_array_opr = rhs_value[ii][rhs_rank - 1]; rhs_array_operand = fix_sec_implicit_args (location, rhs_list,
for (s_jj = rhs_rank - 1; s_jj >= 0; s_jj--) rhs_an_loop_info, rhs_rank,
{ rhs);
if (rhs_count_down[ii][s_jj]) if (!rhs_array_operand)
/* Array[start_index - (induction_var * stride)] */ return error_mark_node;
rhs_array_opr = build_array_ref
(location, rhs_array_opr,
build2 (MINUS_EXPR, TREE_TYPE (rhs_var[s_jj]),
rhs_start[ii][s_jj],
build2 (MULT_EXPR, TREE_TYPE (rhs_var[s_jj]),
rhs_var[s_jj],
rhs_stride[ii][s_jj])));
else
/* Array[start_index + (induction_var * stride)] */
rhs_array_opr = build_array_ref
(location, rhs_array_opr,
build2 (PLUS_EXPR, TREE_TYPE (rhs_var[s_jj]),
rhs_start[ii][s_jj],
build2 (MULT_EXPR, TREE_TYPE (rhs_var[s_jj]),
rhs_var[s_jj],
rhs_stride[ii][s_jj])));
}
vec_safe_push (rhs_array_operand, rhs_array_opr);
}
else
/* This is just a dummy node to make sure the list sizes for both
array list and array operand list are the same. */
vec_safe_push (rhs_array_operand, integer_one_node);
}
for (ii = 0; ii < rhs_list_size; ii++)
{
tree rhs_node = (*rhs_list)[ii];
if (TREE_CODE (rhs_node) == CALL_EXPR)
{
int idx_value = 0;
tree func_name = CALL_EXPR_FN (rhs_node);
if (TREE_CODE (func_name) == ADDR_EXPR)
if (is_sec_implicit_index_fn (func_name))
{
idx_value =
extract_sec_implicit_index_arg (location, rhs_node);
if (idx_value == -1) /* This means we have an error. */
return error_mark_node;
else if (idx_value < (int) lhs_rank && idx_value >= 0)
vec_safe_push (rhs_array_operand, lhs_var[idx_value]);
else
{
size_t ee = 0;
tree lhs_base = (*lhs_list)[ii];
for (ee = 0; ee < lhs_rank; ee++)
lhs_base = ARRAY_NOTATION_ARRAY (lhs_base);
error_at (location, "__sec_implicit_index argument %d "
"must be less than rank of %qD", idx_value,
lhs_base);
return error_mark_node;
}
}
}
}
replace_array_notations (&rhs, true, rhs_list, rhs_array_operand); replace_array_notations (&rhs, true, rhs_list, rhs_array_operand);
array_expr_rhs = rhs;
} }
else else if (rhs_list_size > 0)
{ {
for (ii = 0; ii < rhs_list_size; ii++) rhs_array_operand = fix_sec_implicit_args (location, rhs_list,
{ lhs_an_loop_info, lhs_rank,
tree rhs_node = (*rhs_list)[ii]; lhs);
if (TREE_CODE (rhs_node) == CALL_EXPR) if (!rhs_array_operand)
{ return error_mark_node;
int idx_value = 0;
tree func_name = CALL_EXPR_FN (rhs_node);
if (TREE_CODE (func_name) == ADDR_EXPR)
if (is_sec_implicit_index_fn (func_name))
{
idx_value =
extract_sec_implicit_index_arg (location, rhs_node);
if (idx_value == -1) /* This means we have an error. */
return error_mark_node;
else if (idx_value < (int) lhs_rank && idx_value >= 0)
vec_safe_push (rhs_array_operand, lhs_var[idx_value]);
else
{
size_t ee = 0;
tree lhs_base = (*lhs_list)[ii];
for (ee = 0; ee < lhs_rank; ee++)
lhs_base = ARRAY_NOTATION_ARRAY (lhs_base);
error_at (location, "__sec_implicit_index argument %d "
"must be less than rank of %qD", idx_value,
lhs_base);
return error_mark_node;
}
}
}
}
replace_array_notations (&rhs, true, rhs_list, rhs_array_operand); replace_array_notations (&rhs, true, rhs_list, rhs_array_operand);
array_expr_rhs = rhs;
rhs_expr_incr[0] = NULL_TREE;
} }
array_expr_lhs = lhs;
for (ii = 0; ii < rhs_rank; ii++) array_expr_rhs = rhs;
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_one_cst (TREE_TYPE (rhs_var[ii]))));
for (ii = 0; ii < lhs_rank; 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_one_cst (TREE_TYPE (lhs_var[ii]))));
/* If array_expr_lhs is NULL, then we have function that returns void or
its return value is ignored. */
if (!array_expr_lhs)
array_expr_lhs = lhs;
array_expr = build_modify_expr (location, array_expr_lhs, lhs_origtype, array_expr = build_modify_expr (location, array_expr_lhs, lhs_origtype,
modifycode, rhs_loc, array_expr_rhs, modifycode, rhs_loc, array_expr_rhs,
rhs_origtype); rhs_origtype);
create_cmp_incr (location, &lhs_an_loop_info, lhs_rank, lhs_an_info);
for (jj = 0; jj < MAX (lhs_rank, rhs_rank); jj++) if (rhs_rank)
{ create_cmp_incr (location, &rhs_an_loop_info, rhs_rank, rhs_an_info);
if (rhs_rank && rhs_expr_incr[jj])
{ for (ii = 0; ii < MAX (lhs_rank, rhs_rank); ii++)
size_t iii = 0; if (ii < lhs_rank && ii < rhs_rank)
if (lhs_rank == 0) cond_expr[ii] = build2 (TRUTH_ANDIF_EXPR, boolean_type_node,
lhs_compare[jj] = integer_one_node; lhs_an_loop_info[ii].cmp,
else if (lhs_count_down[0][jj]) rhs_an_loop_info[ii].cmp);
lhs_compare[jj] = build2 else if (ii < lhs_rank && ii >= rhs_rank)
(GT_EXPR, boolean_type_node, lhs_var[jj], lhs_length[0][jj]); cond_expr[ii] = lhs_an_loop_info[ii].cmp;
else else
lhs_compare[jj] = build2 gcc_unreachable ();
(LT_EXPR, boolean_type_node, lhs_var[jj], lhs_length[0][jj]);
/* The reason why we have this here is for the following case:
Array[:][:] = function_call(something) + Array2[:][:];
So, we will skip the first operand of RHS and then go to the
2nd to find whether we should count up or down. */
for (iii = 0; iii < rhs_list_size; iii++)
if (rhs_vector[iii][jj])
break;
/* 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[iii][jj])
/* We use iii for rhs_length because that is the correct countdown
we have to use. */
rhs_compare[jj] = build2
(LT_EXPR, boolean_type_node, rhs_var[jj],
build2 (MULT_EXPR, TREE_TYPE (rhs_var[jj]),
rhs_length[iii][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[iii][jj]);
if (lhs_compare[ii] != integer_one_node)
cond_expr[jj] = build2 (TRUTH_ANDIF_EXPR, void_type_node,
lhs_compare[jj], rhs_compare[jj]);
else
cond_expr[jj] = rhs_compare[jj];
}
else
{
if (lhs_count_down[0][jj])
cond_expr[jj] = build2
(GT_EXPR, boolean_type_node, lhs_var[jj], lhs_length[0][jj]);
else
cond_expr[jj] = build2
(LT_EXPR, boolean_type_node, lhs_var[jj], lhs_length[0][jj]);
}
}
an_init = pop_stmt_list (an_init); an_init = pop_stmt_list (an_init);
append_to_statement_list_force (an_init, &loop_with_init); append_to_statement_list_force (an_init, &loop_with_init);
...@@ -1369,18 +859,27 @@ build_array_notation_expr (location_t location, tree lhs, tree lhs_origtype, ...@@ -1369,18 +859,27 @@ build_array_notation_expr (location_t location, tree lhs, tree lhs_origtype,
tree incr_list = alloc_stmt_list (); tree incr_list = alloc_stmt_list ();
tree new_loop = push_stmt_list (); tree new_loop = push_stmt_list ();
if (lhs_rank) if (lhs_rank)
add_stmt (lhs_ind_init[ii]); add_stmt (lhs_an_loop_info[ii].ind_init);
if (rhs_rank) if (rhs_rank)
add_stmt (rhs_ind_init[ii]); add_stmt (rhs_an_loop_info[ii].ind_init);
if (lhs_rank) if (lhs_rank)
append_to_statement_list_force (lhs_expr_incr[ii], &incr_list); append_to_statement_list_force (lhs_an_loop_info[ii].incr, &incr_list);
if (rhs_rank && rhs_expr_incr[ii]) if (rhs_rank && rhs_an_loop_info[ii].incr)
append_to_statement_list_force (rhs_expr_incr[ii], &incr_list); append_to_statement_list_force (rhs_an_loop_info[ii].incr, &incr_list);
c_finish_loop (location, cond_expr[ii], incr_list, body, NULL_TREE, c_finish_loop (location, cond_expr[ii], incr_list, body, NULL_TREE,
NULL_TREE, true); NULL_TREE, true);
body = pop_stmt_list (new_loop); body = pop_stmt_list (new_loop);
} }
append_to_statement_list_force (body, &loop_with_init); append_to_statement_list_force (body, &loop_with_init);
lhs_an_info.release ();
lhs_an_loop_info.release ();
if (rhs_rank)
{
rhs_an_info.release ();
rhs_an_loop_info.release ();
}
cond_expr.release ();
return loop_with_init; return loop_with_init;
} }
...@@ -1396,15 +895,13 @@ fix_conditional_array_notations_1 (tree stmt) ...@@ -1396,15 +895,13 @@ fix_conditional_array_notations_1 (tree stmt)
vec<tree, va_gc> *array_list = NULL, *array_operand = NULL; vec<tree, va_gc> *array_list = NULL, *array_operand = NULL;
size_t list_size = 0; size_t list_size = 0;
tree cond = NULL_TREE, builtin_loop = NULL_TREE, new_var = NULL_TREE; tree cond = NULL_TREE, builtin_loop = NULL_TREE, new_var = NULL_TREE;
size_t rank = 0, ii = 0, jj = 0; size_t rank = 0, ii = 0;
int s_jj = 0; tree loop_init;
tree **array_ops, *array_var, jj_tree, loop_init;
tree **array_value, **array_stride, **array_length, **array_start;
tree *compare_expr, *expr_incr, *ind_init;
bool **count_down, **array_vector;
tree begin_var, lngth_var, strde_var;
location_t location = EXPR_LOCATION (stmt); location_t location = EXPR_LOCATION (stmt);
tree body = NULL_TREE, loop_with_init = alloc_stmt_list (); tree body = NULL_TREE, loop_with_init = alloc_stmt_list ();
vec<vec<an_parts> > an_info = vNULL;
vec<an_loop_parts> an_loop_info = vNULL;
if (TREE_CODE (stmt) == COND_EXPR) if (TREE_CODE (stmt) == COND_EXPR)
cond = COND_EXPR_COND (stmt); cond = COND_EXPR_COND (stmt);
else if (TREE_CODE (stmt) == SWITCH_EXPR) else if (TREE_CODE (stmt) == SWITCH_EXPR)
...@@ -1440,7 +937,6 @@ fix_conditional_array_notations_1 (tree stmt) ...@@ -1440,7 +937,6 @@ fix_conditional_array_notations_1 (tree stmt)
} }
} }
} }
if (!find_rank (location, stmt, stmt, true, &rank)) if (!find_rank (location, stmt, stmt, true, &rank))
{ {
pop_stmt_list (loop_init); pop_stmt_list (loop_init);
...@@ -1458,194 +954,34 @@ fix_conditional_array_notations_1 (tree stmt) ...@@ -1458,194 +954,34 @@ fix_conditional_array_notations_1 (tree stmt)
return stmt; return stmt;
list_size = vec_safe_length (array_list); list_size = vec_safe_length (array_list);
an_loop_info.safe_grow_cleared (rank);
array_ops = XNEWVEC (tree *, list_size);
for (ii = 0; ii < list_size; ii++)
array_ops[ii] = XNEWVEC (tree, rank);
array_vector = XNEWVEC (bool *, list_size);
for (ii = 0; ii < list_size; ii++)
array_vector[ii] = XNEWVEC (bool, rank);
array_value = XNEWVEC (tree *, list_size);
array_stride = XNEWVEC (tree *, list_size);
array_length = XNEWVEC (tree *, list_size);
array_start = XNEWVEC (tree *, list_size);
for (ii = 0; ii < list_size; ii++)
{
array_value[ii] = XNEWVEC (tree, rank);
array_stride[ii] = XNEWVEC (tree, rank);
array_length[ii] = XNEWVEC (tree, rank);
array_start[ii] = XNEWVEC (tree, rank);
}
compare_expr = XNEWVEC (tree, rank);
expr_incr = XNEWVEC (tree, rank);
ind_init = XNEWVEC (tree, rank);
count_down = XNEWVEC (bool *, list_size);
for (ii = 0; ii < list_size; ii++)
count_down[ii] = XNEWVEC (bool, rank);
array_var = XNEWVEC (tree, rank);
for (ii = 0; ii < list_size; ii++)
{
tree array_node = (*array_list)[ii];
if (array_node && TREE_CODE (array_node) == ARRAY_NOTATION_REF)
{
tree array_begin = ARRAY_NOTATION_START (array_node);
tree array_lngth = ARRAY_NOTATION_LENGTH (array_node);
tree array_strde = ARRAY_NOTATION_STRIDE (array_node);
if (TREE_CODE (array_begin) != INTEGER_CST)
{
begin_var = build_decl (location, VAR_DECL, NULL_TREE,
integer_type_node);
add_stmt (build_modify_expr (location, begin_var,
TREE_TYPE (begin_var),
NOP_EXPR, location, array_begin,
TREE_TYPE (array_begin)));
ARRAY_NOTATION_START (array_node) = begin_var;
}
if (TREE_CODE (array_lngth) != INTEGER_CST)
{
lngth_var = build_decl (location, VAR_DECL, NULL_TREE,
integer_type_node);
add_stmt (build_modify_expr (location, lngth_var,
TREE_TYPE (lngth_var),
NOP_EXPR, location, array_lngth,
TREE_TYPE (array_lngth)));
ARRAY_NOTATION_LENGTH (array_node) = lngth_var;
}
if (TREE_CODE (array_strde) != INTEGER_CST)
{
strde_var = build_decl (location, VAR_DECL, NULL_TREE,
integer_type_node);
add_stmt (build_modify_expr (location, strde_var,
TREE_TYPE (strde_var),
NOP_EXPR, location, array_strde,
TREE_TYPE (array_strde)));
ARRAY_NOTATION_STRIDE (array_node) = strde_var;
}
}
}
for (ii = 0; ii < list_size; ii++)
{
tree array_node = (*array_list)[ii];
jj = 0;
for (jj_tree = array_node;
jj_tree && TREE_CODE (jj_tree) == ARRAY_NOTATION_REF;
jj_tree = ARRAY_NOTATION_ARRAY (jj_tree))
{
array_ops[ii][jj] = jj_tree;
jj++;
}
}
for (ii = 0; ii < list_size; ii++) for (ii = 0; ii < list_size; ii++)
{ if ((*array_list)[ii]
tree array_node = (*array_list)[ii]; && TREE_CODE ((*array_list)[ii]) == ARRAY_NOTATION_REF)
if (TREE_CODE (array_node) == ARRAY_NOTATION_REF) {
{ tree array_node = (*array_list)[ii];
for (jj = 0; jj < rank; jj++) make_triplet_val_inv (location, &ARRAY_NOTATION_START (array_node));
{ make_triplet_val_inv (location, &ARRAY_NOTATION_LENGTH (array_node));
if (TREE_CODE (array_ops[ii][jj]) == ARRAY_NOTATION_REF) make_triplet_val_inv (location, &ARRAY_NOTATION_STRIDE (array_node));
{ }
array_value[ii][jj] = cilkplus_extract_an_triplets (array_list, list_size, rank, &an_info);
ARRAY_NOTATION_ARRAY (array_ops[ii][jj]);
array_start[ii][jj] =
ARRAY_NOTATION_START (array_ops[ii][jj]);
array_length[ii][jj] =
fold_build1 (CONVERT_EXPR, integer_type_node,
ARRAY_NOTATION_LENGTH (array_ops[ii][jj]));
array_stride[ii][jj] =
fold_build1 (CONVERT_EXPR, integer_type_node,
ARRAY_NOTATION_STRIDE (array_ops[ii][jj]));
array_vector[ii][jj] = true;
if (!TREE_CONSTANT (array_length[ii][jj]))
count_down[ii][jj] = false;
else if (tree_int_cst_lt
(array_length[ii][jj],
build_int_cst (TREE_TYPE (array_length[ii][jj]),
0)))
count_down[ii][jj] = true;
else
count_down[ii][jj] = false;
}
else
array_vector[ii][jj] = false;
}
}
}
for (ii = 0; ii < rank; ii++) for (ii = 0; ii < rank; ii++)
{ {
array_var[ii] = build_decl (location, VAR_DECL, NULL_TREE, an_loop_info[ii].var = build_decl (location, VAR_DECL, NULL_TREE,
integer_type_node); integer_type_node);
ind_init[ii] = an_loop_info[ii].ind_init =
build_modify_expr (location, array_var[ii], build_modify_expr (location, an_loop_info[ii].var,
TREE_TYPE (array_var[ii]), NOP_EXPR, TREE_TYPE (an_loop_info[ii].var), NOP_EXPR,
location, location,
build_int_cst (TREE_TYPE (array_var[ii]), 0), build_int_cst (TREE_TYPE (an_loop_info[ii].var), 0),
TREE_TYPE (array_var[ii])); TREE_TYPE (an_loop_info[ii].var));
}
for (ii = 0; ii < list_size; ii++)
{
if (array_vector[ii][0])
{
tree array_opr = array_value[ii][rank - 1];
for (s_jj = rank - 1; s_jj >= 0; s_jj--)
{
if (count_down[ii][s_jj])
/* Array[start_index - (induction_var * stride)] */
array_opr = build_array_ref
(location, array_opr,
build2 (MINUS_EXPR, TREE_TYPE (array_var[s_jj]),
array_start[ii][s_jj],
build2 (MULT_EXPR, TREE_TYPE (array_var[s_jj]),
array_var[s_jj], array_stride[ii][s_jj])));
else
/* Array[start_index + (induction_var * stride)] */
array_opr = build_array_ref
(location, array_opr,
build2 (PLUS_EXPR, TREE_TYPE (array_var[s_jj]),
array_start[ii][s_jj],
build2 (MULT_EXPR, TREE_TYPE (array_var[s_jj]),
array_var[s_jj], array_stride[ii][s_jj])));
}
vec_safe_push (array_operand, array_opr);
}
else
/* This is just a dummy node to make sure the list sizes for both
array list and array operand list are the same. */
vec_safe_push (array_operand, integer_one_node);
} }
array_operand = create_array_refs (location, an_info, an_loop_info,
list_size, rank);
replace_array_notations (&stmt, true, array_list, array_operand); replace_array_notations (&stmt, true, array_list, array_operand);
for (ii = 0; ii < rank; ii++) create_cmp_incr (location, &an_loop_info, rank, an_info);
expr_incr[ii] = build2 (MODIFY_EXPR, void_type_node, array_var[ii],
build2 (PLUS_EXPR, TREE_TYPE (array_var[ii]),
array_var[ii],
build_int_cst (TREE_TYPE (array_var[ii]),
1)));
for (jj = 0; jj < rank; jj++)
{
if (rank && expr_incr[jj])
{
if (count_down[0][jj])
compare_expr[jj] =
build2 (LT_EXPR, boolean_type_node, array_var[jj],
build2 (MULT_EXPR, TREE_TYPE (array_var[jj]),
array_length[0][jj],
build_int_cst (TREE_TYPE (array_var[jj]), -1)));
else
compare_expr[jj] = build2 (LT_EXPR, boolean_type_node,
array_var[jj], array_length[0][jj]);
}
}
loop_init = pop_stmt_list (loop_init); loop_init = pop_stmt_list (loop_init);
body = stmt; body = stmt;
append_to_statement_list_force (loop_init, &loop_with_init); append_to_statement_list_force (loop_init, &loop_with_init);
...@@ -1653,33 +989,15 @@ fix_conditional_array_notations_1 (tree stmt) ...@@ -1653,33 +989,15 @@ fix_conditional_array_notations_1 (tree stmt)
for (ii = 0; ii < rank; ii++) for (ii = 0; ii < rank; ii++)
{ {
tree new_loop = push_stmt_list (); tree new_loop = push_stmt_list ();
add_stmt (ind_init[ii]); add_stmt (an_loop_info[ii].ind_init);
c_finish_loop (location, compare_expr[ii], expr_incr[ii], body, NULL_TREE, c_finish_loop (location, an_loop_info[ii].cmp, an_loop_info[ii].incr,
NULL_TREE, true); body, NULL_TREE, NULL_TREE, true);
body = pop_stmt_list (new_loop); body = pop_stmt_list (new_loop);
} }
append_to_statement_list_force (body, &loop_with_init); append_to_statement_list_force (body, &loop_with_init);
XDELETEVEC (expr_incr);
XDELETEVEC (ind_init);
for (ii = 0; ii < list_size; ii++)
{
XDELETEVEC (count_down[ii]);
XDELETEVEC (array_value[ii]);
XDELETEVEC (array_stride[ii]);
XDELETEVEC (array_length[ii]);
XDELETEVEC (array_start[ii]);
XDELETEVEC (array_ops[ii]);
XDELETEVEC (array_vector[ii]);
}
XDELETEVEC (count_down); an_loop_info.release ();
XDELETEVEC (array_value); an_info.release ();
XDELETEVEC (array_stride);
XDELETEVEC (array_length);
XDELETEVEC (array_start);
XDELETEVEC (array_ops);
XDELETEVEC (array_vector);
return loop_with_init; return loop_with_init;
} }
...@@ -1716,13 +1034,11 @@ fix_array_notation_expr (location_t location, enum tree_code code, ...@@ -1716,13 +1034,11 @@ fix_array_notation_expr (location_t location, enum tree_code code,
{ {
vec<tree, va_gc> *array_list = NULL, *array_operand = NULL; vec<tree, va_gc> *array_list = NULL, *array_operand = NULL;
size_t list_size = 0, rank = 0, ii = 0, jj = 0; size_t list_size = 0, rank = 0, ii = 0;
int s_jj = 0; tree loop_init;
tree **array_ops, *array_var, jj_tree, loop_init;
tree **array_value, **array_stride, **array_length, **array_start;
tree *compare_expr, *expr_incr, *ind_init;
tree body, loop_with_init = alloc_stmt_list (); tree body, loop_with_init = alloc_stmt_list ();
bool **count_down, **array_vector; vec<vec<an_parts> > an_info = vNULL;
vec<an_loop_parts> an_loop_info = vNULL;
if (!find_rank (location, arg.value, arg.value, false, &rank)) if (!find_rank (location, arg.value, arg.value, false, &rank))
{ {
...@@ -1742,165 +1058,33 @@ fix_array_notation_expr (location_t location, enum tree_code code, ...@@ -1742,165 +1058,33 @@ fix_array_notation_expr (location_t location, enum tree_code code,
return arg; return arg;
list_size = vec_safe_length (array_list); list_size = vec_safe_length (array_list);
array_ops = XNEWVEC (tree *, list_size);
for (ii = 0; ii < list_size; ii++)
array_ops[ii] = XNEWVEC (tree, rank);
array_vector = XNEWVEC (bool *, list_size);
for (ii = 0; ii < list_size; ii++)
array_vector[ii] = XNEWVEC (bool, rank);
array_value = XNEWVEC (tree *, list_size);
array_stride = XNEWVEC (tree *, list_size);
array_length = XNEWVEC (tree *, list_size);
array_start = XNEWVEC (tree *, list_size);
for (ii = 0; ii < list_size; ii++)
{
array_value[ii] = XNEWVEC (tree, rank);
array_stride[ii] = XNEWVEC (tree, rank);
array_length[ii] = XNEWVEC (tree, rank);
array_start[ii] = XNEWVEC (tree, rank);
}
compare_expr = XNEWVEC (tree, rank); an_loop_info.safe_grow_cleared (rank);
expr_incr = XNEWVEC (tree, rank); cilkplus_extract_an_triplets (array_list, list_size, rank, &an_info);
ind_init = XNEWVEC (tree, rank);
count_down = XNEWVEC (bool *, list_size);
for (ii = 0; ii < list_size; ii++)
count_down[ii] = XNEWVEC (bool, rank);
array_var = XNEWVEC (tree, rank);
for (ii = 0; ii < list_size; ii++)
{
jj = 0;
for (jj_tree = (*array_list)[ii];
jj_tree && TREE_CODE (jj_tree) == ARRAY_NOTATION_REF;
jj_tree = ARRAY_NOTATION_ARRAY (jj_tree))
{
array_ops[ii][jj] = jj_tree;
jj++;
}
}
loop_init = push_stmt_list (); loop_init = push_stmt_list ();
for (ii = 0; ii < list_size; ii++)
{
tree array_node = (*array_list)[ii];
if (TREE_CODE (array_node) == ARRAY_NOTATION_REF)
{
for (jj = 0; jj < rank; jj++)
{
if (TREE_CODE (array_ops[ii][jj]) == ARRAY_NOTATION_REF)
{
array_value[ii][jj] =
ARRAY_NOTATION_ARRAY (array_ops[ii][jj]);
array_start[ii][jj] =
ARRAY_NOTATION_START (array_ops[ii][jj]);
array_length[ii][jj] =
fold_build1 (CONVERT_EXPR, integer_type_node,
ARRAY_NOTATION_LENGTH (array_ops[ii][jj]));
array_stride[ii][jj] =
fold_build1 (CONVERT_EXPR, integer_type_node,
ARRAY_NOTATION_STRIDE (array_ops[ii][jj]));
array_vector[ii][jj] = true;
if (!TREE_CONSTANT (array_length[ii][jj]))
count_down[ii][jj] = false;
else if (tree_int_cst_lt
(array_length[ii][jj],
build_int_cst (TREE_TYPE (array_length[ii][jj]),
0)))
count_down[ii][jj] = true;
else
count_down[ii][jj] = false;
}
else
array_vector[ii][jj] = false;
}
}
}
for (ii = 0; ii < rank; ii++) for (ii = 0; ii < rank; ii++)
{ {
array_var[ii] = build_decl (location, VAR_DECL, NULL_TREE, an_loop_info[ii].var = build_decl (location, VAR_DECL, NULL_TREE,
integer_type_node); integer_type_node);
ind_init[ii] = an_loop_info[ii].ind_init =
build_modify_expr (location, array_var[ii], build_modify_expr (location, an_loop_info[ii].var,
TREE_TYPE (array_var[ii]), NOP_EXPR, TREE_TYPE (an_loop_info[ii].var), NOP_EXPR,
location, location,
build_int_cst (TREE_TYPE (array_var[ii]), 0), build_int_cst (TREE_TYPE (an_loop_info[ii].var), 0),
TREE_TYPE (array_var[ii])); TREE_TYPE (an_loop_info[ii].var));;
} }
for (ii = 0; ii < list_size; ii++) array_operand = create_array_refs (location, an_info, an_loop_info,
{ list_size, rank);
if (array_vector[ii][0])
{
tree array_opr = array_value[ii][rank - 1];
for (s_jj = rank - 1; s_jj >= 0; s_jj--)
{
if (count_down[ii][s_jj])
/* Array[start_index - (induction_var * stride)] */
array_opr = build_array_ref
(location, array_opr,
build2 (MINUS_EXPR, TREE_TYPE (array_var[s_jj]),
array_start[ii][s_jj],
build2 (MULT_EXPR, TREE_TYPE (array_var[s_jj]),
array_var[s_jj], array_stride[ii][s_jj])));
else
/* Array[start_index + (induction_var * stride)] */
array_opr = build_array_ref
(location, array_opr,
build2 (PLUS_EXPR, TREE_TYPE (array_var[s_jj]),
array_start[ii][s_jj],
build2 (MULT_EXPR, TREE_TYPE (array_var[s_jj]),
array_var[s_jj], array_stride[ii][s_jj])));
}
vec_safe_push (array_operand, array_opr);
}
else
/* This is just a dummy node to make sure the list sizes for both
array list and array operand list are the same. */
vec_safe_push (array_operand, integer_one_node);
}
replace_array_notations (&arg.value, true, array_list, array_operand); replace_array_notations (&arg.value, true, array_list, array_operand);
create_cmp_incr (location, &an_loop_info, rank, an_info);
for (ii = 0; ii < rank; ii++) arg = default_function_array_read_conversion (location, arg);
expr_incr[ii] =
build2 (MODIFY_EXPR, void_type_node, array_var[ii],
build2 (PLUS_EXPR, TREE_TYPE (array_var[ii]), array_var[ii],
build_int_cst (TREE_TYPE (array_var[ii]), 1)));
for (jj = 0; jj < rank; jj++)
{
if (rank && expr_incr[jj])
{
if (count_down[0][jj])
compare_expr[jj] =
build2 (LT_EXPR, boolean_type_node, array_var[jj],
build2 (MULT_EXPR, TREE_TYPE (array_var[jj]),
array_length[0][jj],
build_int_cst (TREE_TYPE (array_var[jj]), -1)));
else
compare_expr[jj] = build2 (LT_EXPR, boolean_type_node,
array_var[jj], array_length[0][jj]);
}
}
if (code == POSTINCREMENT_EXPR || code == POSTDECREMENT_EXPR) if (code == POSTINCREMENT_EXPR || code == POSTDECREMENT_EXPR)
{ arg.value = build_unary_op (location, code, arg.value, 0);
arg = default_function_array_read_conversion (location, arg);
arg.value = build_unary_op (location, code, arg.value, 0);
}
else if (code == PREINCREMENT_EXPR || code == PREDECREMENT_EXPR) else if (code == PREINCREMENT_EXPR || code == PREDECREMENT_EXPR)
{ arg = parser_build_unary_op (location, code, arg);
arg = default_function_array_read_conversion (location, arg);
arg = parser_build_unary_op (location, code, arg);
}
loop_init = pop_stmt_list (loop_init); loop_init = pop_stmt_list (loop_init);
append_to_statement_list_force (loop_init, &loop_with_init); append_to_statement_list_force (loop_init, &loop_with_init);
...@@ -1909,36 +1093,16 @@ fix_array_notation_expr (location_t location, enum tree_code code, ...@@ -1909,36 +1093,16 @@ fix_array_notation_expr (location_t location, enum tree_code code,
for (ii = 0; ii < rank; ii++) for (ii = 0; ii < rank; ii++)
{ {
tree new_loop = push_stmt_list (); tree new_loop = push_stmt_list ();
add_stmt (ind_init[ii]); add_stmt (an_loop_info[ii].ind_init);
c_finish_loop (location, compare_expr[ii], expr_incr[ii], body, NULL_TREE, c_finish_loop (location, an_loop_info[ii].cmp,
an_loop_info[ii].incr, body, NULL_TREE,
NULL_TREE, true); NULL_TREE, true);
body = pop_stmt_list (new_loop); body = pop_stmt_list (new_loop);
} }
append_to_statement_list_force (body, &loop_with_init); append_to_statement_list_force (body, &loop_with_init);
XDELETEVEC (expr_incr);
XDELETEVEC (ind_init);
XDELETEVEC (array_var);
for (ii = 0; ii < list_size; ii++)
{
XDELETEVEC (count_down[ii]);
XDELETEVEC (array_value[ii]);
XDELETEVEC (array_stride[ii]);
XDELETEVEC (array_length[ii]);
XDELETEVEC (array_start[ii]);
XDELETEVEC (array_ops[ii]);
XDELETEVEC (array_vector[ii]);
}
XDELETEVEC (count_down);
XDELETEVEC (array_value);
XDELETEVEC (array_stride);
XDELETEVEC (array_length);
XDELETEVEC (array_start);
XDELETEVEC (array_ops);
XDELETEVEC (array_vector);
arg.value = loop_with_init; arg.value = loop_with_init;
an_info.release ();
an_loop_info.release ();
return arg; return arg;
} }
...@@ -1950,15 +1114,12 @@ fix_array_notation_call_expr (tree arg) ...@@ -1950,15 +1114,12 @@ fix_array_notation_call_expr (tree arg)
{ {
vec<tree, va_gc> *array_list = NULL, *array_operand = NULL; vec<tree, va_gc> *array_list = NULL, *array_operand = NULL;
tree new_var = NULL_TREE; tree new_var = NULL_TREE;
size_t list_size = 0, rank = 0, ii = 0, jj = 0; size_t list_size = 0, rank = 0, ii = 0;
int s_jj = 0; tree loop_init;
tree **array_ops, *array_var, jj_tree, loop_init;
tree **array_value, **array_stride, **array_length, **array_start;
tree body, loop_with_init = alloc_stmt_list (); tree body, loop_with_init = alloc_stmt_list ();
tree *compare_expr, *expr_incr, *ind_init;
bool **count_down, **array_vector;
tree begin_var, lngth_var, strde_var;
location_t location = UNKNOWN_LOCATION; location_t location = UNKNOWN_LOCATION;
vec<vec<an_parts> > an_info = vNULL;
vec<an_loop_parts> an_loop_info = vNULL;
if (TREE_CODE (arg) == CALL_EXPR if (TREE_CODE (arg) == CALL_EXPR
&& is_cilkplus_reduce_builtin (CALL_EXPR_FN (arg))) && is_cilkplus_reduce_builtin (CALL_EXPR_FN (arg)))
...@@ -1967,8 +1128,7 @@ fix_array_notation_call_expr (tree arg) ...@@ -1967,8 +1128,7 @@ fix_array_notation_call_expr (tree arg)
/* We are ignoring the new var because either the user does not want to /* We are ignoring the new var because either the user does not want to
capture it OR he is using sec_reduce_mutating function. */ capture it OR he is using sec_reduce_mutating function. */
return loop_init; return loop_init;
} }
if (!find_rank (location, arg, arg, false, &rank)) if (!find_rank (location, arg, arg, false, &rank))
return error_mark_node; return error_mark_node;
...@@ -1981,237 +1141,53 @@ fix_array_notation_call_expr (tree arg) ...@@ -1981,237 +1141,53 @@ fix_array_notation_call_expr (tree arg)
list_size = vec_safe_length (array_list); list_size = vec_safe_length (array_list);
location = EXPR_LOCATION (arg); location = EXPR_LOCATION (arg);
an_loop_info.safe_grow_cleared (rank);
array_ops = XNEWVEC (tree *, list_size);
for (ii = 0; ii < list_size; ii++)
array_ops[ii] = XNEWVEC (tree, rank);
array_vector = XNEWVEC (bool *, list_size);
for (ii = 0; ii < list_size; ii++)
array_vector[ii] = (bool *) XNEWVEC (bool, rank);
array_value = XNEWVEC (tree *, list_size);
array_stride = XNEWVEC (tree *, list_size);
array_length = XNEWVEC (tree *, list_size);
array_start = XNEWVEC (tree *, list_size);
for (ii = 0; ii < list_size; ii++)
{
array_value[ii] = XNEWVEC (tree, rank);
array_stride[ii] = XNEWVEC (tree, rank);
array_length[ii] = XNEWVEC (tree, rank);
array_start[ii] = XNEWVEC (tree, rank);
}
compare_expr = XNEWVEC (tree, rank);
expr_incr = XNEWVEC (tree, rank);
ind_init = XNEWVEC (tree, rank);
count_down = XNEWVEC (bool *, list_size);
for (ii = 0; ii < list_size; ii++)
count_down[ii] = XNEWVEC (bool, rank);
array_var = XNEWVEC (tree, rank);
loop_init = push_stmt_list (); loop_init = push_stmt_list ();
for (ii = 0; ii < list_size; ii++) for (ii = 0; ii < list_size; ii++)
{ if ((*array_list)[ii]
tree array_node = (*array_list)[ii]; && TREE_CODE ((*array_list)[ii]) == ARRAY_NOTATION_REF)
if (array_node && TREE_CODE (array_node) == ARRAY_NOTATION_REF)
{
tree array_begin = ARRAY_NOTATION_START (array_node);
tree array_lngth = ARRAY_NOTATION_LENGTH (array_node);
tree array_strde = ARRAY_NOTATION_STRIDE (array_node);
if (TREE_CODE (array_begin) != INTEGER_CST)
{
begin_var = build_decl (location, VAR_DECL, NULL_TREE,
integer_type_node);
add_stmt (build_modify_expr (location, begin_var,
TREE_TYPE (begin_var),
NOP_EXPR, location, array_begin,
TREE_TYPE (array_begin)));
ARRAY_NOTATION_START (array_node) = begin_var;
}
if (TREE_CODE (array_lngth) != INTEGER_CST)
{
lngth_var = build_decl (location, VAR_DECL, NULL_TREE,
integer_type_node);
add_stmt (build_modify_expr (location, lngth_var,
TREE_TYPE (lngth_var),
NOP_EXPR, location, array_lngth,
TREE_TYPE (array_lngth)));
ARRAY_NOTATION_LENGTH (array_node) = lngth_var;
}
if (TREE_CODE (array_strde) != INTEGER_CST)
{
strde_var = build_decl (location, VAR_DECL, NULL_TREE,
integer_type_node);
add_stmt (build_modify_expr (location, strde_var,
TREE_TYPE (strde_var),
NOP_EXPR, location, array_strde,
TREE_TYPE (array_strde)));
ARRAY_NOTATION_STRIDE (array_node) = strde_var;
}
}
}
for (ii = 0; ii < list_size; ii++)
{
jj = 0;
for (jj_tree = (*array_list)[ii];
jj_tree && TREE_CODE (jj_tree) == ARRAY_NOTATION_REF;
jj_tree = ARRAY_NOTATION_ARRAY (jj_tree))
{ {
array_ops[ii][jj] = jj_tree; tree array_node = (*array_list)[ii];
jj++; make_triplet_val_inv (location, &ARRAY_NOTATION_START (array_node));
make_triplet_val_inv (location, &ARRAY_NOTATION_LENGTH (array_node));
make_triplet_val_inv (location, &ARRAY_NOTATION_STRIDE (array_node));
} }
} cilkplus_extract_an_triplets (array_list, list_size, rank, &an_info);
if (length_mismatch_in_expr_p (location, an_info))
for (ii = 0; ii < list_size; ii++)
{
tree array_node = (*array_list)[ii];
if (TREE_CODE (array_node) == ARRAY_NOTATION_REF)
{
for (jj = 0; jj < rank; jj++)
{
if (TREE_CODE (array_ops[ii][jj]) == ARRAY_NOTATION_REF)
{
array_value[ii][jj] =
ARRAY_NOTATION_ARRAY (array_ops[ii][jj]);
array_start[ii][jj] =
ARRAY_NOTATION_START (array_ops[ii][jj]);
array_length[ii][jj] =
fold_build1 (CONVERT_EXPR, integer_type_node,
ARRAY_NOTATION_LENGTH (array_ops[ii][jj]));
array_stride[ii][jj] =
fold_build1 (CONVERT_EXPR, integer_type_node,
ARRAY_NOTATION_STRIDE (array_ops[ii][jj]));
array_vector[ii][jj] = true;
if (!TREE_CONSTANT (array_length[ii][jj]))
count_down[ii][jj] = false;
else if (tree_int_cst_lt
(array_length[ii][jj],
build_int_cst (TREE_TYPE (array_length[ii][jj]),
0)))
count_down[ii][jj] = true;
else
count_down[ii][jj] = false;
}
else
array_vector[ii][jj] = false;
}
}
}
if (length_mismatch_in_expr_p (location, array_length, list_size, rank))
{ {
pop_stmt_list (loop_init); pop_stmt_list (loop_init);
return error_mark_node; return error_mark_node;
} }
for (ii = 0; ii < rank; ii++) for (ii = 0; ii < rank; ii++)
{ {
array_var[ii] = build_decl (location, VAR_DECL, NULL_TREE, an_loop_info[ii].var = build_decl (location, VAR_DECL, NULL_TREE,
integer_type_node); integer_type_node);
ind_init[ii] = an_loop_info[ii].ind_init =
build_modify_expr (location, array_var[ii], build_modify_expr (location, an_loop_info[ii].var,
TREE_TYPE (array_var[ii]), NOP_EXPR, TREE_TYPE (an_loop_info[ii].var), NOP_EXPR, location,
location, build_int_cst (TREE_TYPE (an_loop_info[ii].var), 0),
build_int_cst (TREE_TYPE (array_var[ii]), 0), TREE_TYPE (an_loop_info[ii].var));
TREE_TYPE (array_var[ii]));
} }
for (ii = 0; ii < list_size; ii++) array_operand = create_array_refs (location, an_info, an_loop_info,
{ list_size, rank);
if (array_vector[ii][0])
{
tree array_opr_node = array_value[ii][rank - 1];
for (s_jj = rank - 1; s_jj >= 0; s_jj--)
{
if (count_down[ii][s_jj])
/* Array[start_index - (induction_var * stride)] */
array_opr_node = build_array_ref
(location, array_opr_node,
build2 (MINUS_EXPR, TREE_TYPE (array_var[s_jj]),
array_start[ii][s_jj],
build2 (MULT_EXPR, TREE_TYPE (array_var[s_jj]),
array_var[s_jj], array_stride[ii][s_jj])));
else
/* Array[start_index + (induction_var * stride)] */
array_opr_node = build_array_ref
(location, array_opr_node,
build2 (PLUS_EXPR, TREE_TYPE (array_var[s_jj]),
array_start[ii][s_jj],
build2 (MULT_EXPR, TREE_TYPE (array_var[s_jj]),
array_var[s_jj], array_stride[ii][s_jj])));
}
vec_safe_push (array_operand, array_opr_node);
}
else
/* This is just a dummy node to make sure the list sizes for both
array list and array operand list are the same. */
vec_safe_push (array_operand, integer_one_node);
}
replace_array_notations (&arg, true, array_list, array_operand); replace_array_notations (&arg, true, array_list, array_operand);
for (ii = 0; ii < rank; ii++) create_cmp_incr (location, &an_loop_info, rank, an_info);
expr_incr[ii] =
build2 (MODIFY_EXPR, void_type_node, array_var[ii],
build2 (PLUS_EXPR, TREE_TYPE (array_var[ii]), array_var[ii],
build_int_cst (TREE_TYPE (array_var[ii]), 1)));
for (jj = 0; jj < rank; jj++)
{
if (rank && expr_incr[jj])
{
if (count_down[0][jj])
compare_expr[jj] =
build2 (LT_EXPR, boolean_type_node, array_var[jj],
build2 (MULT_EXPR, TREE_TYPE (array_var[jj]),
array_length[0][jj],
build_int_cst (TREE_TYPE (array_var[jj]), -1)));
else
compare_expr[jj] = build2 (LT_EXPR, boolean_type_node,
array_var[jj], array_length[0][jj]);
}
}
loop_init = pop_stmt_list (loop_init); loop_init = pop_stmt_list (loop_init);
append_to_statement_list_force (loop_init, &loop_with_init); append_to_statement_list_force (loop_init, &loop_with_init);
body = arg; body = arg;
for (ii = 0; ii < rank; ii++) for (ii = 0; ii < rank; ii++)
{ {
tree new_loop = push_stmt_list (); tree new_loop = push_stmt_list ();
add_stmt (ind_init[ii]); add_stmt (an_loop_info[ii].ind_init);
c_finish_loop (location, compare_expr[ii], expr_incr[ii], body, NULL_TREE, c_finish_loop (location, an_loop_info[ii].cmp, an_loop_info[ii].incr,
NULL_TREE, true); body, NULL_TREE, NULL_TREE, true);
body = pop_stmt_list (new_loop); body = pop_stmt_list (new_loop);
} }
append_to_statement_list_force (body, &loop_with_init); append_to_statement_list_force (body, &loop_with_init);
XDELETEVEC (compare_expr); an_loop_info.release ();
XDELETEVEC (expr_incr); an_info.release ();
XDELETEVEC (ind_init);
XDELETEVEC (array_var);
for (ii = 0; ii < list_size; ii++)
{
XDELETEVEC (count_down[ii]);
XDELETEVEC (array_value[ii]);
XDELETEVEC (array_stride[ii]);
XDELETEVEC (array_length[ii]);
XDELETEVEC (array_start[ii]);
XDELETEVEC (array_ops[ii]);
XDELETEVEC (array_vector[ii]);
}
XDELETEVEC (count_down);
XDELETEVEC (array_value);
XDELETEVEC (array_stride);
XDELETEVEC (array_length);
XDELETEVEC (array_start);
XDELETEVEC (array_ops);
XDELETEVEC (array_vector);
return loop_with_init; return loop_with_init;
} }
...@@ -2390,4 +1366,3 @@ build_array_notation_ref (location_t loc, tree array, tree start_index, ...@@ -2390,4 +1366,3 @@ build_array_notation_ref (location_t loc, tree array, tree start_index,
return array_ntn_tree; return array_ntn_tree;
} }
...@@ -42,6 +42,12 @@ ...@@ -42,6 +42,12 @@
2013-06-21 Balaji V. Iyer <balaji.v.iyer@intel.com> 2013-06-21 Balaji V. Iyer <balaji.v.iyer@intel.com>
* cp-array-notation.c (cp_length_mismatch_in_expr_p): Remove.
(expand_an_in_modify_expr): Changed a function call from the above
removed function to length_mismatch_in_expr_p.
2013-06-21 Balaji V. Iyer <balaji.v.iyer@intel.com>
* call.c (convert_like_real): Added a check if array notation is present * call.c (convert_like_real): Added a check if array notation is present
in expression. If so, then no conversion of arguments is necessary. in expression. If so, then no conversion of arguments is necessary.
(build_over_call): Likewise. (build_over_call): Likewise.
......
...@@ -78,52 +78,6 @@ create_an_loop (tree init, tree cond, tree incr, tree body) ...@@ -78,52 +78,6 @@ create_an_loop (tree init, tree cond, tree incr, tree body)
finish_for_stmt (for_stmt); 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->LENGTH) is passed in as a 2D vector of trees. */
static bool
cp_length_mismatch_in_expr_p (location_t loc, vec<vec<an_parts> >list)
{
size_t ii, jj;
tree length = NULL_TREE;
HOST_WIDE_INT l_length, l_node;
size_t x = list.length ();
size_t y = list[0].length ();
for (jj = 0; jj < y; jj++)
{
length = NULL_TREE;
for (ii = 0; ii < x; ii++)
{
if (!length)
length = list[ii][jj].length;
else if (TREE_CODE (length) == INTEGER_CST)
{
/* If length 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].length) == INTEGER_CST)
{
l_node = int_cst_value (list[ii][jj].length);
l_length = int_cst_value (length);
if (absu_hwi (l_length) != absu_hwi (l_node))
{
error_at (loc, "length mismatch in expression");
return true;
}
}
}
else
/* We set the length node as the current node just in case it turns
out to be an integer. */
length = list[ii][jj].length;
}
}
return false;
}
/* If *VALUE is not a constant integer, then this function replaces it with /* If *VALUE is not a constant integer, then this function replaces it with
a variable to make it loop invariant for array notations. */ a variable to make it loop invariant for array notations. */
...@@ -744,9 +698,9 @@ expand_an_in_modify_expr (location_t location, tree lhs, ...@@ -744,9 +698,9 @@ expand_an_in_modify_expr (location_t location, tree lhs,
if (rhs_list) if (rhs_list)
cilkplus_extract_an_triplets (rhs_list, rhs_list_size, rhs_rank, cilkplus_extract_an_triplets (rhs_list, rhs_list_size, rhs_rank,
&rhs_an_info); &rhs_an_info);
if (cp_length_mismatch_in_expr_p (EXPR_LOCATION (lhs), lhs_an_info) if (length_mismatch_in_expr_p (EXPR_LOCATION (lhs), lhs_an_info)
|| (rhs_list && cp_length_mismatch_in_expr_p (EXPR_LOCATION (rhs), || (rhs_list && length_mismatch_in_expr_p (EXPR_LOCATION (rhs),
rhs_an_info))) rhs_an_info)))
{ {
pop_stmt_list (an_init); pop_stmt_list (an_init);
return error_mark_node; return error_mark_node;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment