@@ -1,4 +1,11 @@
-2011-01-16 Balaji V. Iyer <balaji.v.iyer@intel.com>
+2012-01-20 Balaji V. Iyer <balaji.v.iyer@intel.com>
+
+ * Makefile.in: Added array-notation-common.c file for compilation.
+ * array-notation-common.c (mark_cold): New function.
+ (array_notation_init_builtins): Likewise.
+ * tree.h: Added a new enum list called "array_notation_reduce_type."
+
+2012-01-16 Balaji V. Iyer <balaji.v.iyer@intel.com>
* cilk.c (cilk_remove_annotated_functions): Added a int cast for
VEC_length in for-loop condition.
@@ -1452,6 +1452,7 @@ OBJS = \
xcoffout.o \
cilk.o \
cilk-low.o \
+ array-notation-common.o \
$(out_object_file) \
$(EXTRA_OBJS) \
$(host_hook_obj)
@@ -3437,6 +3438,8 @@ lower-subreg.o : lower-subreg.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
+array-notation-common.o: array-notation-common.c $(CONFIG_H) $(SYSTEM_H) \
+ $(TREE_H) $(RTL_H) $(OPTABS_H) $(GIMPLE_H) $(RECOG_H)
cilk.o: cilk.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(RTL_H) $(OPTABS_H) \
$(GIMPLE_H) $(RECOG_H) cilk.h
new file mode 100644
@@ -0,0 +1,101 @@
+/* This file is part of the Intel(R) Cilk(TM) Plus support
+ This file contains the builtin functions for Array
+ notations.
+ Copyright (C) 2012 Free Software Foundation, Inc.
+ Contributed by Balaji V. Iyer <balaji.v.iyer@intel.com>,
+ Intel Corporation
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "tree.h"
+#include "langhooks.h"
+#include "expr.h"
+#include "optabs.h" /* for sync_lock_release in detach */
+#include "recog.h"
+#include "cilk.h"
+#include "gimple.h"
+#include "tree-iterator.h"
+#include "c-family/c-common.h"
+#include "toplev.h" /* only correct declaration of warning() */
+#include "output.h"
+#include "dwarf2out.h"
+
+static void
+mark_cold (tree fndecl)
+{
+ DECL_ATTRIBUTES (fndecl) = tree_cons (get_identifier ("cold"), NULL_TREE,
+ DECL_ATTRIBUTES (fndecl));
+}
+
+void
+array_notation_init_builtins (void)
+{
+ tree func_type = NULL_TREE;
+ tree new_func = NULL_TREE;
+ func_type = build_function_type_list (integer_type_node, ptr_type_node,
+ NULL_TREE);
+ new_func = build_fn_decl ("__sec_reduce_add", func_type);
+ mark_cold (new_func);
+ new_func = lang_hooks.decls.pushdecl (new_func);
+
+ func_type = build_function_type_list (integer_type_node, ptr_type_node,
+ NULL_TREE);
+ new_func = build_fn_decl ("__sec_reduce_mul", func_type);
+ mark_cold (new_func);
+ new_func = lang_hooks.decls.pushdecl (new_func);
+
+ func_type = build_function_type_list (integer_type_node, ptr_type_node,
+ NULL_TREE);
+ new_func = build_fn_decl ("__sec_reduce_all_zeros", func_type);
+ mark_cold (new_func);
+ new_func = lang_hooks.decls.pushdecl (new_func);
+
+ func_type = build_function_type_list (integer_type_node, ptr_type_node,
+ NULL_TREE);
+ new_func = build_fn_decl ("__sec_reduce_any_zeros", func_type);
+ mark_cold (new_func);
+ new_func = lang_hooks.decls.pushdecl (new_func);
+
+ func_type = build_function_type_list (integer_type_node, ptr_type_node,
+ NULL_TREE);
+ new_func = build_fn_decl ("__sec_reduce_max", func_type);
+ mark_cold (new_func);
+ new_func = lang_hooks.decls.pushdecl (new_func);
+
+ func_type = build_function_type_list (integer_type_node, ptr_type_node,
+ NULL_TREE);
+ new_func = build_fn_decl ("__sec_reduce_min", func_type);
+ mark_cold (new_func);
+ new_func = lang_hooks.decls.pushdecl (new_func);
+
+ func_type = build_function_type_list (integer_type_node, ptr_type_node,
+ NULL_TREE);
+ new_func = build_fn_decl ("__sec_reduce_min_ind", func_type);
+ mark_cold (new_func);
+ new_func = lang_hooks.decls.pushdecl (new_func);
+
+ func_type = build_function_type_list (integer_type_node, ptr_type_node,
+ NULL_TREE);
+ new_func = build_fn_decl ("__sec_reduce_max_ind", func_type);
+ mark_cold (new_func);
+ new_func = lang_hooks.decls.pushdecl (new_func);
+ return;
+}
@@ -1,3 +1,8 @@
+2012-01-20 Balaji V. Iyer <balaji.v.iyer@intel.com>
+
+ * c-common.c (c_define_builtins): Added a call to
+ array_notation_init_builtins function.
+
2011-12-09 Balaji V. Iyer <balaji.v.iyer@intel.com>
* c-common.h: Added build_array_notation_expr prototype.
@@ -49,7 +49,7 @@ along with GCC; see the file COPYING3. If not see
#include "libfuncs.h"
#include "cilk.h"
-
+extern void array_notation_init_builtins (void);
enum expand_modifier {EXPAND_NORMAL = 0, EXPAND_STACK_PARM, EXPAND_SUM,
EXPAND_CONST_ADDRESS, EXPAND_INITIALIZER, EXPAND_WRITE,
EXPAND_MEMORY};
@@ -4660,7 +4660,10 @@ c_define_builtins (tree va_list_ref_type_node, tree va_list_arg_type_node)
/* this function will initialize all the builtin functions required by
* the cilkplus port */
if (flag_enable_cilk)
- cilk_init_builtins();
+ {
+ cilk_init_builtins ();
+ array_notation_init_builtins ();
+ }
targetm.init_builtins ();
@@ -1,3 +1,25 @@
+2012-01-20 Balaji V. Iyer <balaji.v.iyer@intel.com>
+
+ * call.c (convert_like_real): Type conversion is ignored if array
+ notation is present as a parameter.
+ * cp-array-notation.c (find_rank): Added a new parameter called
+ ignore_builtin_fn. Also handled a case for STATEMENT_LIST. Finally,
+ added a check to see if the builtin function should be ignored.
+ (extract_array_notation_exprs): Added a new parameter called
+ ignore_builtin_fn. Also added a check to see for ignore_builtin_fn.
+ (replace_array_notations): Likewise.
+ (build_x_array_notation_expr): Modified find_rank call to add a bool.
+ Also added a check if the funtion is a builtin array notation function.
+ Added a bool parameter to extract_array_notation_exprs, find_rank and
+ replace_array_notations.
+ (fix_builtin_array_notation_fn): New function.
+ (is_builtin_array_notation_fn): Likewise.
+ (build_x_reduce_expr): Likewise.
+ (contains_array_notation_expr): Likewise.
+ (fix_unary_array_notation_exprs): Changed the name of the parameter.
+ Also handled a case check for CALL_EXPR and if so, called
+ fix_builtin_array_notation_fn.
+
2012-01-17 Balaji V. Iyer <balaji.v.iyer@intel.com>
* cp-array-notation.c (max): New function.
@@ -43,6 +43,7 @@ along with GCC; see the file COPYING3. If not see
#include "timevar.h"
#include "cilk.h"
+extern bool contains_array_notation_expr (tree);
/* The various kinds of conversion. */
typedef enum conversion_kind {
@@ -5638,13 +5639,16 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
else if (t->kind == ck_identity)
break;
}
-
- permerror (input_location, "invalid conversion from %qT to %qT",
- TREE_TYPE (expr), totype);
- if (fn)
- permerror (DECL_SOURCE_LOCATION (fn),
- " initializing argument %P of %qD", argnum, fn);
-
+ if (flag_enable_cilk && contains_array_notation_expr (expr))
+ ;
+ else
+ {
+ permerror (input_location, "invalid conversion from %qT to %qT",
+ TREE_TYPE (expr), totype);
+ if (fn)
+ permerror (DECL_SOURCE_LOCATION (fn),
+ " initializing argument %P of %qD", argnum, fn);
+ }
return cp_convert (totype, expr);
}
@@ -45,20 +45,24 @@
#include "bitmap.h"
-void replace_array_notations (tree *, tree *, tree *, int);
-void find_rank (tree array, int *rank);
+void replace_array_notations (tree *, bool, tree *, tree *, int);
+void find_rank (tree, bool, int *);
static tree fix_conditional_array_notations_1 (tree stmt);
tree fix_unary_array_notation_exprs (tree stmt);
+static bool is_builtin_array_notation_fn (tree, an_reduce_type *);
+static tree build_x_reduce_expr (tree, enum tree_code, tree, tsubst_flags_t,
+ an_reduce_type);
+bool contains_array_notation_expr (tree);
/* This function is to find the rank of an array notation expression.
* For example, an array notation of A[:][:] has a rank of 2.
*/
void
-find_rank (tree array, int *rank)
+find_rank (tree array, bool ignore_builtin_fn, int *rank)
{
tree ii_tree;
int current_rank = 0, ii = 0;
-
+ an_reduce_type dummy_type = REDUCE_UNKNOWN;
if (!array)
return;
else if (TREE_CODE (array) == ARRAY_NOTATION_REF)
@@ -73,16 +77,31 @@ find_rank (tree array, int *rank)
else if (*rank == 0)
*rank = current_rank;
}
+ else if (TREE_CODE (array) == STATEMENT_LIST)
+ {
+ tree_stmt_iterator ii_tsi;
+ for (ii_tsi = tsi_start (array); !tsi_end_p (ii_tsi);
+ tsi_next (&ii_tsi))
+ find_rank (*tsi_stmt_ptr (ii_tsi), ignore_builtin_fn, rank);
+ }
else
{
if (TREE_CODE (array) == CALL_EXPR
|| TREE_CODE (array) == AGGR_INIT_EXPR)
{
+ tree func_name = CALL_EXPR_FN (array);
+ if (TREE_CODE (func_name) == ADDR_EXPR)
+ if (ignore_builtin_fn)
+ if (is_builtin_array_notation_fn (func_name, &dummy_type))
+ /* If it is a builtin function, then we know it returns a
+ * scalar
+ */
+ return;
if (TREE_CODE (TREE_OPERAND (array, 0)) == INTEGER_CST)
{
int length = TREE_INT_CST_LOW (TREE_OPERAND (array, 0));
for (ii = 0; ii < length; ii++)
- find_rank (TREE_OPERAND (array, ii), rank);
+ find_rank (TREE_OPERAND (array, ii), ignore_builtin_fn, rank);
}
else
gcc_unreachable ();
@@ -90,7 +109,7 @@ find_rank (tree array, int *rank)
else
{
for (ii = 0; ii < TREE_CODE_LENGTH (TREE_CODE (array)); ii++)
- find_rank (TREE_OPERAND (array, ii), rank);
+ find_rank (TREE_OPERAND (array, ii), ignore_builtin_fn, rank);
}
}
return;
@@ -100,10 +119,13 @@ find_rank (tree array, int *rank)
* expressions inside the subtrees
*/
void
-extract_array_notation_exprs (tree node, tree **array_list, int *list_size)
+extract_array_notation_exprs (tree node, bool ignore_builtin_fn,
+ tree **array_list, int *list_size)
{
int ii = 0;
tree *new_array_list = NULL;
+ an_reduce_type dummy_type = REDUCE_UNKNOWN;
+
if (!node)
return;
else if (TREE_CODE (node) == ARRAY_NOTATION_REF)
@@ -122,18 +144,36 @@ extract_array_notation_exprs (tree node, tree **array_list, int *list_size)
{
tree_stmt_iterator ii_tsi;
for (ii_tsi = tsi_start (node); !tsi_end_p (ii_tsi); tsi_next (&ii_tsi))
- extract_array_notation_exprs (*tsi_stmt_ptr (ii_tsi), array_list,
- list_size);
+ extract_array_notation_exprs (*tsi_stmt_ptr (ii_tsi), ignore_builtin_fn,
+ array_list, list_size);
}
else if (TREE_CODE (node) == CALL_EXPR || TREE_CODE (node) == AGGR_INIT_EXPR)
{
+ if (is_builtin_array_notation_fn (CALL_EXPR_FN (node), &dummy_type))
+ {
+ if (ignore_builtin_fn)
+ return;
+ else
+ {
+ ii = *list_size;
+ new_array_list = (tree *) xrealloc (*array_list, (ii + 1) *
+ sizeof (tree));
+ gcc_assert (new_array_list);
+ new_array_list[ii] = node;
+ ii++;
+ *list_size = ii;
+ *array_list = new_array_list;
+ return;
+ }
+ }
if (TREE_CODE (TREE_OPERAND (node, 0)) == INTEGER_CST)
{
int length = TREE_INT_CST_LOW (TREE_OPERAND (node, 0));
for (ii = 0; ii < length; ii++)
- extract_array_notation_exprs (TREE_OPERAND (node, ii), array_list,
- list_size);
+ extract_array_notation_exprs
+ (TREE_OPERAND (node, ii), ignore_builtin_fn, array_list,
+ list_size);
}
else
gcc_unreachable (); /* should not get here */
@@ -142,8 +182,8 @@ extract_array_notation_exprs (tree node, tree **array_list, int *list_size)
else
{
for (ii = 0; ii < TREE_CODE_LENGTH (TREE_CODE (node)); ii++)
- extract_array_notation_exprs (TREE_OPERAND (node, ii), array_list,
- list_size);
+ extract_array_notation_exprs (TREE_OPERAND (node, ii),
+ ignore_builtin_fn, array_list, list_size);
}
return;
}
@@ -152,10 +192,11 @@ extract_array_notation_exprs (tree node, tree **array_list, int *list_size)
* appropriate scalar equivalent
*/
void
-replace_array_notations (tree *orig, tree *list, tree *array_operand,
- int array_size)
+replace_array_notations (tree *orig, bool ignore_builtin_fn, tree *list,
+ tree *array_operand, int array_size)
{
int ii = 0;
+ an_reduce_type dummy_type = REDUCE_UNKNOWN;
if (array_size == 0 || *list == NULL || !*orig)
return;
@@ -172,18 +213,31 @@ replace_array_notations (tree *orig, tree *list, tree *array_operand,
{
tree_stmt_iterator ii_tsi;
for (ii_tsi = tsi_start (*orig); !tsi_end_p (ii_tsi); tsi_next (&ii_tsi))
- replace_array_notations (tsi_stmt_ptr (ii_tsi), list, array_operand,
- array_size);
+ replace_array_notations (tsi_stmt_ptr (ii_tsi), ignore_builtin_fn,
+ list, array_operand, array_size);
}
else if (TREE_CODE (*orig) == CALL_EXPR
|| TREE_CODE (*orig) == AGGR_INIT_EXPR)
{
+ if (is_builtin_array_notation_fn (CALL_EXPR_FN (*orig), &dummy_type))
+ {
+ if (!ignore_builtin_fn)
+ {
+ for (ii = 0; ii < array_size; ii++)
+ {
+ if (*orig == list[ii])
+ *orig = array_operand[ii];
+ }
+ }
+ return;
+ }
if (TREE_CODE (TREE_OPERAND (*orig, 0)) == INTEGER_CST)
{
int length = TREE_INT_CST_LOW (TREE_OPERAND (*orig, 0));
for (ii = 0; ii < length; ii++)
- replace_array_notations (&TREE_OPERAND (*orig, ii), list,
- array_operand, array_size);
+ replace_array_notations
+ (&TREE_OPERAND (*orig, ii), ignore_builtin_fn, list,
+ array_operand, array_size);
}
else
gcc_unreachable (); /* should not get here! */
@@ -192,8 +246,9 @@ replace_array_notations (tree *orig, tree *list, tree *array_operand,
{
for (ii = 0; ii < TREE_CODE_LENGTH (TREE_CODE (*orig)); ii++)
{
- replace_array_notations (&TREE_OPERAND (*orig, ii), list,
- array_operand, array_size);
+ replace_array_notations
+ (&TREE_OPERAND (*orig, ii), ignore_builtin_fn, list,
+ array_operand, array_size);
}
}
return;
@@ -235,17 +290,27 @@ build_x_array_notation_expr (tree lhs, enum tree_code modifycode, tree rhs,
tree ii_tree = NULL_TREE;
tree *rhs_list = NULL;
int rhs_list_size = 0;
+ an_reduce_type type = REDUCE_UNKNOWN;
- find_rank (lhs, &lhs_rank);
- find_rank (rhs, &rhs_rank);
+ find_rank (lhs, true, &lhs_rank);
+ find_rank (rhs, true, &rhs_rank);
/* If both are scalar, then no reason to do any of the components inside this
* function... a simple build_x_modify_expr would do.
*/
if (lhs_rank == 0 && rhs_rank == 0)
return NULL_TREE;
+
+ if (TREE_CODE (rhs) == CALL_EXPR)
+ {
+ if (is_builtin_array_notation_fn (CALL_EXPR_FN (rhs), &type))
+ {
+ loop = build_x_reduce_expr (lhs, modifycode, rhs, complain, type);
+ return loop;
+ }
+ }
- extract_array_notation_exprs (rhs, &rhs_list, &rhs_list_size);
+ extract_array_notation_exprs (rhs, true, &rhs_list, &rhs_list_size);
if (lhs_rank == 0 && rhs_rank != 0)
{
@@ -540,7 +605,7 @@ build_x_array_notation_expr (tree lhs, enum tree_code modifycode, tree rhs,
}
}
}
- replace_array_notations (&rhs, rhs_list, rhs_array_operand,
+ replace_array_notations (&rhs, true, rhs_list, rhs_array_operand,
rhs_list_size);
array_expr_rhs = rhs;
}
@@ -691,11 +756,11 @@ fix_conditional_array_notations_1 (tree stmt)
/* otherwise don't even touch the statement */
return stmt;
- find_rank (cond, &rank);
+ find_rank (cond, true, &rank);
if (rank == 0)
return stmt;
- extract_array_notation_exprs (cond, &array_list, &list_size);
+ extract_array_notation_exprs (cond, true, &array_list, &list_size);
if (*array_list == NULL_TREE || list_size == 0)
return stmt;
@@ -862,7 +927,7 @@ fix_conditional_array_notations_1 (tree stmt)
}
}
}
- replace_array_notations (&stmt, array_list, array_operand, list_size);
+ replace_array_notations (&stmt, true, array_list, array_operand, list_size);
for (ii = 0; ii < rank; ii++)
{
@@ -1154,8 +1219,422 @@ fix_array_notation_exprs (tree t)
return t;
}
+static tree
+fix_builtin_array_notation_fn (tree an_builtin_fn, tree *new_var)
+{
+ tree new_var_type = NULL_TREE, func_parm, new_expr, new_yes_expr, new_no_expr;
+ tree new_var_init;
+ an_reduce_type an_type = REDUCE_UNKNOWN;
+ tree *array_list = NULL;
+ int list_size = 0;
+ int rank = 0, ii = 0, jj = 0;
+ tree **array_ops, *array_var, *array_operand, jj_tree, loop;
+ tree **array_value, **array_stride, **array_length, **array_start;
+ tree *body_label, *body_label_expr, *exit_label, *exit_label_expr;
+ tree *compare_expr, *if_stmt_label, *expr_incr, *ind_init;
+ bool **count_down, **array_vector;
+
+ if (!is_builtin_array_notation_fn (CALL_EXPR_FN (an_builtin_fn), &an_type))
+ return NULL_TREE;
+
+ func_parm = CALL_EXPR_ARG (an_builtin_fn, 0);
+ while (TREE_CODE (func_parm) == CONVERT_EXPR
+ || TREE_CODE (func_parm) == NOP_EXPR)
+ func_parm = TREE_OPERAND (func_parm, 0);
+
+
+ find_rank (an_builtin_fn, false, &rank);
+ if (rank == 0)
+ return an_builtin_fn;
+ else if (rank > 1
+ && (an_type == REDUCE_MAX_INDEX || an_type == REDUCE_MIN_INDEX))
+ {
+ error ("__sec_reduce_min_ind or __sec_reduce_max_ind cannot have arrays"
+ " with dimension greater than 1.");
+ fnotice (stderr, "confused by earlier errors, bailing out\n");
+ exit (ICE_EXIT_CODE);
+ }
+
+ extract_array_notation_exprs (func_parm, true, &array_list, &list_size);
+
+ switch (an_type)
+ {
+ case REDUCE_ADD:
+ case REDUCE_MUL:
+ case REDUCE_MAX:
+ case REDUCE_MIN:
+ new_var_type = ARRAY_NOTATION_TYPE (array_list[0]);
+ break;
+ case REDUCE_ALL_ZEROS:
+ case REDUCE_ANY_ZEROS:
+ new_var_type = integer_type_node;
+ break;
+ case REDUCE_MAX_INDEX:
+ case REDUCE_MIN_INDEX:
+ new_var_type = integer_type_node;
+ break;
+ default:
+ gcc_unreachable ();
+ }
+
+
+ array_ops = (tree **) xmalloc (sizeof (tree *) * list_size);
+ for (ii = 0; ii < list_size; ii++)
+ array_ops[ii] = (tree *) xmalloc (sizeof (tree) * rank);
+
+ array_vector = (bool **) xmalloc (sizeof (bool *) * list_size);
+ for (ii = 0; ii < list_size; ii++)
+ array_vector[ii] = (bool *) xmalloc (sizeof (bool) * rank);
+
+ array_value = (tree **) xmalloc (sizeof (tree *) * list_size);
+ array_stride = (tree **) xmalloc (sizeof (tree *) * list_size);
+ array_length = (tree **) xmalloc (sizeof (tree *) * list_size);
+ array_start = (tree **) xmalloc (sizeof (tree *) * list_size);
+
+ for (ii = 0; ii < list_size; ii++)
+ {
+ array_value[ii] = (tree *) xmalloc (sizeof (tree) * rank);
+ array_stride[ii] = (tree *) xmalloc (sizeof (tree) * rank);
+ array_length[ii] = (tree *) xmalloc (sizeof (tree) * rank);
+ array_start[ii] = (tree *) xmalloc (sizeof (tree) * rank);
+ }
+
+ body_label = (tree *) xmalloc(sizeof (tree) * rank);
+ body_label_expr = (tree *) xmalloc (sizeof (tree) * rank);
+ exit_label = (tree *) xmalloc (sizeof (tree) * rank);
+ exit_label_expr = (tree *) xmalloc (sizeof (tree) * rank);
+ compare_expr = (tree *) xmalloc (sizeof (tree) * rank);
+ if_stmt_label = (tree *) xmalloc (sizeof (tree) * rank);
+
+ expr_incr = (tree *) xmalloc (sizeof (tree) * rank);
+ ind_init = (tree *) xmalloc (sizeof (tree) * rank);
+
+ count_down = (bool **) xmalloc (sizeof (bool *) * list_size);
+ for (ii = 0; ii < list_size; ii++)
+ count_down[ii] = (bool *) xmalloc (sizeof (bool) * rank);
+
+ array_operand = (tree *) xmalloc (sizeof (tree) * list_size);
+
+ array_var = (tree *) xmalloc (sizeof (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++)
+ {
+ if (TREE_CODE (array_list[ii]) == 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] =
+ ARRAY_NOTATION_LENGTH (array_ops[ii][jj]);
+ array_stride[ii][jj] =
+ 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;
+ }
+ }
+ }
+
+ loop = alloc_stmt_list ();
+
+
+ for (ii = 0; ii < rank; ii++)
+ {
+ array_var[ii] = build_decl (UNKNOWN_LOCATION, VAR_DECL, NULL_TREE,
+ integer_type_node);
+ ind_init[ii] =
+ build_modify_expr (UNKNOWN_LOCATION, array_var[ii],
+ TREE_TYPE (array_var[ii]), NOP_EXPR,
+ UNKNOWN_LOCATION,
+ build_int_cst (TREE_TYPE (array_var[ii]), 0),
+ TREE_TYPE (array_var[ii]));
+ }
+
+ for (ii = 0; ii < rank ; ii++)
+ {
+ /* this will create the if statement label */
+ if_stmt_label[ii] = build_decl (UNKNOWN_LOCATION, LABEL_DECL, NULL_TREE,
+ void_type_node);
+ DECL_CONTEXT (if_stmt_label[ii]) = current_function_decl;
+ DECL_ARTIFICIAL (if_stmt_label[ii]) = 0;
+ DECL_IGNORED_P (if_stmt_label[ii]) = 1;
+
+ /* this label statment will point to the loop body */
+ body_label[ii] = build_decl (UNKNOWN_LOCATION, LABEL_DECL, NULL_TREE,
+ void_type_node);
+ DECL_CONTEXT (body_label[ii]) = current_function_decl;
+ DECL_ARTIFICIAL (body_label[ii]) = 0;
+ DECL_IGNORED_P (body_label[ii]) = 1;
+ body_label_expr[ii] = build1 (LABEL_EXPR, void_type_node, body_label[ii]);
+
+ /* this will create the exit label..i.e. where the while loop will branch
+ out of
+ */
+ exit_label[ii] = build_decl (UNKNOWN_LOCATION, LABEL_DECL, NULL_TREE,
+ void_type_node);
+ DECL_CONTEXT (exit_label[ii]) = current_function_decl;
+ DECL_ARTIFICIAL (exit_label[ii]) = 0;
+ DECL_IGNORED_P (exit_label[ii]) = 1;
+ exit_label_expr[ii] = build1 (LABEL_EXPR, void_type_node, exit_label[ii]);
+ }
+
+ for (ii = 0; ii < list_size; ii++)
+ {
+ if (array_vector[ii][0])
+ {
+ array_operand[ii] = array_value[ii][rank - 1];
+ gcc_assert (array_operand[ii]);
+
+ for (jj = rank - 1; jj >= 0; jj--)
+ {
+ if (count_down[ii][jj])
+ {
+ /* Array[start_index - (induction_var * stride)] */
+ array_operand[ii] = build_array_ref
+ (UNKNOWN_LOCATION, array_operand[ii],
+ build2 (MINUS_EXPR, TREE_TYPE (array_var[jj]),
+ array_start[ii][jj],
+ build2 (MULT_EXPR, TREE_TYPE (array_var[jj]),
+ array_var[jj], array_stride[ii][jj])));
+ }
+ else
+ {
+ /* Array[start_index + (induction_var * stride)] */
+ array_operand[ii] = build_array_ref
+ (UNKNOWN_LOCATION, array_operand[ii],
+ build2 (PLUS_EXPR, TREE_TYPE (array_var[jj]),
+ array_start[ii][jj],
+ build2 (MULT_EXPR, TREE_TYPE (array_var[jj]),
+ array_var[jj], array_stride[ii][jj])));
+ }
+ }
+ }
+ }
+ replace_array_notations (&func_parm, true, array_list, array_operand,
+ list_size);
+
+ 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]);
+ }
+ }
+
+ *new_var = build_decl (UNKNOWN_LOCATION, VAR_DECL, NULL_TREE, new_var_type);
+ gcc_assert (*new_var);
+
+ switch (an_type)
+ {
+ case REDUCE_ADD:
+ new_var_init = build_x_modify_expr
+ (*new_var, NOP_EXPR, build_int_cst (new_var_type, 0), 1);
+ new_expr = build_x_modify_expr (*new_var, PLUS_EXPR, func_parm, 1);
+ break;
+ case REDUCE_MUL:
+ new_var_init = build_x_modify_expr
+ (*new_var, NOP_EXPR, build_int_cst (new_var_type, 1), 1);
+ new_expr = build_x_modify_expr (*new_var, MULT_EXPR, func_parm, 1);
+ break;
+ case REDUCE_ALL_ZEROS:
+ new_var_init = build_x_modify_expr
+ (*new_var, NOP_EXPR, build_int_cst (new_var_type, 1), 1);
+ /* Initially you assume everything is zero, now if we find a case where
+ * it is NOT true, then we set the result to false. Otherwise
+ * we just keep the previous value
+ */
+ new_yes_expr = build_x_modify_expr
+ (*new_var, NOP_EXPR, build_int_cst (TREE_TYPE (*new_var), 0), 1);
+ new_no_expr = build_x_modify_expr (*new_var, NOP_EXPR, *new_var, 1);
+ new_expr = build_x_conditional_expr (func_parm, new_yes_expr,
+ new_no_expr, 1);
+ break;
+ case REDUCE_ANY_ZEROS:
+ new_var_init = build_x_modify_expr
+ (*new_var, NOP_EXPR, build_int_cst (new_var_type, 0), 1);
+ /* Initially we assume there are NO zeros in the list. When we find
+ * a non-zero, we keep the previous value. If we find a zero, we
+ * set the value to true
+ */
+ new_no_expr = build_x_modify_expr
+ (*new_var, NOP_EXPR, build_int_cst (TREE_TYPE (*new_var), 1), 1);
+ new_yes_expr = build_x_modify_expr (*new_var, NOP_EXPR, *new_var, 1);
+ new_expr = build_x_conditional_expr (func_parm, new_yes_expr,
+ new_no_expr, 1);
+ break;
+ case REDUCE_MAX:
+ if (INTEGRAL_TYPE_P (new_var_type))
+ new_var_init = build_x_modify_expr
+ (*new_var, NOP_EXPR, TYPE_MIN_VALUE (new_var_type), 1);
+ else /* Otherwise, we pick the first item in the array */
+ new_var_init = build_x_modify_expr
+ (*new_var, NOP_EXPR,
+ build_array_ref (UNKNOWN_LOCATION,
+ TREE_OPERAND (array_operand[0], 0),
+ build_int_cst (integer_type_node, 0)), 1);
+ new_no_expr = build_x_modify_expr (*new_var, NOP_EXPR, *new_var, 1);
+ new_yes_expr = build_x_modify_expr (*new_var, NOP_EXPR, func_parm, 1);
+ new_expr = build_x_conditional_expr
+ (build2 (LT_EXPR, TREE_TYPE (*new_var), *new_var, func_parm),
+ new_yes_expr, new_no_expr, 1);
+ break;
+ case REDUCE_MIN:
+ if (INTEGRAL_TYPE_P (new_var_type))
+ new_var_init = build_x_modify_expr
+ (*new_var, NOP_EXPR, TYPE_MAX_VALUE (new_var_type), 1);
+ else /* Otherwise, we the first item in the array */
+ new_var_init = build_x_modify_expr
+ (*new_var, NOP_EXPR,
+ build_array_ref (UNKNOWN_LOCATION,
+ TREE_OPERAND (array_operand[0], 0),
+ build_int_cst (integer_type_node, 0)), 1);
+ new_no_expr = build_x_modify_expr (*new_var, NOP_EXPR, *new_var, 1);
+ new_yes_expr = build_x_modify_expr (*new_var, NOP_EXPR, func_parm, 1);
+ new_expr = build_x_conditional_expr
+ (build2 (GT_EXPR, TREE_TYPE (*new_var), *new_var, func_parm),
+ new_yes_expr, new_no_expr, 1);
+ break;
+ case REDUCE_MAX_INDEX:
+ new_var_init = build_x_modify_expr
+ (*new_var, NOP_EXPR, build_int_cst (new_var_type, 0), 1);
+ new_no_expr = build_x_modify_expr (*new_var, NOP_EXPR, *new_var, 1);
+ if (list_size > 1) /* this means there is more than 1 */
+ new_yes_expr = build_x_modify_expr (*new_var, NOP_EXPR, array_var[0],
+ 1);
+ else
+ new_yes_expr = build_x_modify_expr
+ (*new_var, NOP_EXPR, TREE_OPERAND (array_operand[0], 1), 1);
+
+ new_expr = build_x_conditional_expr
+ (build2 (LT_EXPR, TREE_TYPE (*new_var), *new_var, func_parm),
+ new_yes_expr, new_no_expr, 1);
+ break;
+ case REDUCE_MIN_INDEX:
+ new_var_init = build_x_modify_expr
+ (*new_var, NOP_EXPR, build_int_cst (new_var_type, 0), 1);
+ new_no_expr = build_x_modify_expr (*new_var, NOP_EXPR, *new_var, 1);
+ if (list_size > 1)
+ new_yes_expr = build_x_modify_expr (*new_var, NOP_EXPR, array_var[0],
+ 1);
+ else
+ new_yes_expr = build_x_modify_expr
+ (*new_var, NOP_EXPR, TREE_OPERAND (array_operand[0], 1), 1);
+
+ new_expr = build_x_conditional_expr
+ (build2 (GT_EXPR, TREE_TYPE (*new_var), *new_var, func_parm),
+ new_yes_expr, new_no_expr, 1);
+ break;
+ default:
+ gcc_unreachable ();
+ break;
+ }
+
+ append_to_statement_list (new_var_init, &loop);
+
+ for (ii = 0; ii < rank; ii++)
+ {
+ append_to_statement_list (ind_init [ii], &loop);
+
+ append_to_statement_list
+ (build1 (LABEL_EXPR, void_type_node, if_stmt_label[ii]), &loop);
+ append_to_statement_list
+ (build3 (COND_EXPR, void_type_node, compare_expr[ii],
+ build1 (GOTO_EXPR, void_type_node, body_label[ii]),
+ build1 (GOTO_EXPR, void_type_node, exit_label[ii])), &loop);
+ append_to_statement_list (body_label_expr[ii], &loop);
+ }
+
+ append_to_statement_list (new_expr, &loop);
+
+ for (ii = rank - 1; ii >= 0; ii--)
+ {
+ append_to_statement_list (expr_incr[ii], &loop);
+ append_to_statement_list
+ (build1 (GOTO_EXPR, void_type_node, if_stmt_label[ii]), &loop);
+ append_to_statement_list (exit_label_expr[ii], &loop);
+ }
+
+ free (body_label);
+ free (body_label_expr);
+ free (exit_label);
+ free (exit_label_expr);
+ free (compare_expr);
+ free (if_stmt_label);
+ free (expr_incr);
+ free (ind_init);
+ free (array_operand);
+ free (array_var);
+
+ for (ii = 0; ii < list_size; ii++)
+ {
+ free (count_down[ii]);
+ free (array_value[ii]);
+ free (array_stride[ii]);
+ free (array_length[ii]);
+ free (array_start[ii]);
+ free (array_ops[ii]);
+ free (array_vector[ii]);
+ }
+
+ free (count_down);
+ free (array_value);
+ free (array_stride);
+ free (array_length);
+ free (array_start);
+ free (array_ops);
+ free (array_vector);
+
+
+ return loop;
+}
+
+
tree
-fix_unary_array_notation_exprs (tree stmt)
+fix_unary_array_notation_exprs (tree orig_stmt)
{
tree *array_list = NULL;
@@ -1166,11 +1645,35 @@ fix_unary_array_notation_exprs (tree stmt)
tree *body_label, *body_label_expr, *exit_label, *exit_label_expr;
tree *compare_expr, *if_stmt_label, *expr_incr, *ind_init;
bool **count_down, **array_vector;
- find_rank (stmt, &rank);
+ tree builtin_loop, stmt = NULL_TREE, new_var = NULL_TREE;
+
+ find_rank (orig_stmt, false, &rank);
if (rank == 0)
- return stmt;
+ return orig_stmt;
- extract_array_notation_exprs (stmt, &array_list, &list_size);
+ extract_array_notation_exprs (orig_stmt, false, &array_list, &list_size);
+
+ stmt = alloc_stmt_list ();
+ for (ii = 0; ii < list_size; ii++)
+ {
+ if (TREE_CODE (array_list[ii]) == CALL_EXPR
+ || TREE_CODE (array_list[ii]) == AGGR_INIT_EXPR)
+ {
+ builtin_loop =
+ fix_builtin_array_notation_fn (array_list[ii], &new_var);
+ append_to_statement_list (builtin_loop, &stmt);
+ replace_array_notations (&orig_stmt, false, &array_list[ii],
+ &new_var, 1);
+ }
+ }
+ append_to_statement_list (orig_stmt, &stmt);
+ rank = 0;
+ list_size = 0;
+ array_list = NULL;
+ extract_array_notation_exprs (stmt, true, &array_list, &list_size);
+ find_rank (stmt, true, &rank);
+ if (rank == 0)
+ return stmt;
if (*array_list == NULL_TREE || list_size == 0)
return stmt;
@@ -1334,7 +1837,7 @@ fix_unary_array_notation_exprs (tree stmt)
}
}
}
- replace_array_notations (&stmt, array_list, array_operand, list_size);
+ replace_array_notations (&stmt, true, array_list, array_operand, list_size);
for (ii = 0; ii < rank; ii++)
{
@@ -1416,3 +1919,97 @@ fix_unary_array_notation_exprs (tree stmt)
stmt = loop;
return stmt;
}
+
+static bool
+is_builtin_array_notation_fn (tree func_name, an_reduce_type *type)
+{
+ const char *function_name;
+
+ if (!func_name)
+ return false;
+
+ if (TREE_CODE (func_name) == IDENTIFIER_NODE)
+ function_name = IDENTIFIER_POINTER (DECL_NAME (func_name));
+ else if (TREE_CODE (func_name) == ADDR_EXPR)
+ {
+ func_name = TREE_OPERAND (func_name, 0);
+ if (TREE_CODE (func_name) == FUNCTION_DECL)
+ function_name = IDENTIFIER_POINTER (DECL_NAME (func_name));
+ }
+
+ if (!function_name)
+ return false;
+
+ if (!strcmp (function_name, "__sec_reduce_add"))
+ {
+ *type = REDUCE_ADD;
+ return true;
+ }
+ else if (!strcmp (function_name, "__sec_reduce_mul"))
+ {
+ *type = REDUCE_MUL;
+ return true;
+ }
+ else if (!strcmp (function_name, "__sec_reduce_all_zeros"))
+ {
+ *type = REDUCE_ALL_ZEROS;
+ return true;
+ }
+ else if (!strcmp (function_name, "__sec_reduce_any_zeros"))
+ {
+ *type = REDUCE_ANY_ZEROS;
+ return true;
+ }
+ else if (!strcmp (function_name, "__sec_reduce_max"))
+ {
+ *type = REDUCE_MAX;
+ return true;
+ }
+ else if (!strcmp (function_name, "__sec_reduce_min"))
+ {
+ *type = REDUCE_MIN;
+ return true;
+ }
+ else if (!strcmp (function_name, "__sec_reduce_min_ind"))
+ {
+ *type = REDUCE_MIN_INDEX;
+ return true;
+ }
+ else if (!strcmp (function_name, "__sec_reduce_max_ind"))
+ {
+ *type = REDUCE_MAX_INDEX;
+ return true;
+ }
+ else
+ {
+ *type = REDUCE_UNKNOWN;
+ return false;
+ }
+ return false;
+}
+
+
+static tree
+build_x_reduce_expr (tree lhs, enum tree_code modifycode, tree rhs,
+ tsubst_flags_t complain, an_reduce_type type)
+{
+ if (!type)
+ {
+ return build_x_modify_expr (lhs, modifycode, rhs, complain);
+ }
+ return NULL_TREE;
+}
+
+bool
+contains_array_notation_expr (tree expr)
+{
+ tree *array_list = NULL;
+ int list_size = 0;
+
+ extract_array_notation_exprs (expr, false, &array_list, &list_size);
+ if (*array_list == NULL || list_size == 0)
+ return false;
+ else
+ return true;
+}
+
@@ -41,7 +41,7 @@ along with GCC; see the file COPYING3. If not see
#include "tree-pretty-print.h"
#include "parser.h"
-extern void extract_array_notation_exprs (tree, tree **, int *);
+extern void extract_array_notation_exprs (tree, bool, tree **, int *);
extern tree fix_unary_array_notation_exprs (tree);
struct pragma_simd_values local_simd_values;
@@ -1,3 +1,7 @@
+2012-01-21 Balaji V. Iyer <balaji.v.iyer@intel.com>
+
+ * g++.dg/cilk-plus/array_notation_tests/builtin_funcs.cc: New.
+
2012-01-17 Balaji V. Iyer <balaji.v.iyer@intel.com>
* g++.dg/cilk-plus/array_notation_tests/predecr_test.cc: New.
new file mode 100644
@@ -0,0 +1,92 @@
+#if HAVE_IO
+#include <iostream>
+#endif
+#include <cstdlib>
+
+extern int funct(int x);
+extern int funct2(int x, int y);
+extern void func_ptr (int *x);
+
+/* char __sec_reduce_add (int *); */
+int main(int argc, char **argv)
+{
+ int array[10], array2[10], x = 0, y;
+ int x_correct, y_correct;
+
+ for (int ii = 0; ii < 10; ii++)
+ {
+ array[ii] = 1+ii;
+ array2[ii]= 2;
+ }
+
+ x = __sec_reduce_max (array[:] + array2[:]);
+ y = __sec_reduce_max_ind (array[:] + array2[:]);
+#if HAVE_IO
+ std::cout << "Max = " << x << " Max Index = " << y << std::endl;
+#endif
+
+ x = __sec_reduce_max (array[0:5:1] + array2[5:5:1]);
+ y = __sec_reduce_max_ind (array[0:5] + array2[5:5:1]);
+#if HAVE_IO
+ std::cout << "Max = " << x << " Max Index = " << y << std::endl;
+#endif
+
+ x = __sec_reduce_min (array[:] + array2[:]);
+ y = __sec_reduce_min_ind (array[:] + array2[:]);
+#if HAVE_IO
+ std::cout << "Min = " << x << " Min Index = " << y << std::endl;
+#endif
+
+ x = __sec_reduce_min (array[0:5:1] + array2[5:5:1]);
+ y = __sec_reduce_min_ind (array[0:5] + array2[5:5:1]);
+#if HAVE_IO
+ std::cout << "Min = " << x << " Min Index = " << y << std::endl;
+#endif
+
+ x = __sec_reduce_add (array[:] + array2[:]);
+ y = __sec_reduce_mul (array[:] + array2[:]);
+
+ x_correct = 0;
+ y_correct = 1;
+ for (int ii = 0; ii < 10; ii++)
+ {
+ x_correct += (array[ii] + array2[ii]);
+ y_correct *= (array[ii] + array2[ii]);
+ }
+#if HAVE_IO
+ std::cout << "Add = " << x
+ << " Multiply = " << y << std::endl;
+ std::cout << "Add(Correct) = " << x_correct
+ << " Multiply (Correct) = " << y_correct << std::endl;
+#endif
+
+ x = __sec_reduce_add (array[0:5:1] + array2[5:5:1]);
+ y = __sec_reduce_mul (array[0:5] + array2[5:5:1]);
+
+ x_correct = 0;
+ y_correct = 1;
+ for (int ii = 0; ii < 5; ii++)
+ {
+ x_correct += (array[ii] + array2[5+ii]);
+ y_correct *= (array[ii] + array2[5+ii]);
+ }
+#if HAVE_IO
+ std::cout << "Add = " << x
+ << " Multiply = " << y << std::endl;
+ std::cout << "Add(Correct) = " << x_correct
+ << " Multiply (Correct) = " << y_correct << std::endl;
+#endif
+
+ array[:] = argc - atoi ("1");
+
+ for (int ii = 0; ii < 10; ii++)
+ array2[ii] = argc - ii;
+
+ x = __sec_reduce_all_zeros (array[0:5:1]);
+ y = __sec_reduce_any_zeros (array2[:]);
+#if HAVE_IO
+ std::cout << "All Zeros = " << x << " Any Zeros = " << y << std::endl;
+#endif
+
+ return 0;
+}
@@ -73,8 +73,6 @@ struct reduction_values
int not_reduced;
struct reduction_values *ptr_next;
};
-
-
/* bviyer: Since we can have multiple pragma simd, this will hold the values of
* each of the pragma simd and then as soon as it finds a for loop
@@ -105,11 +103,19 @@ struct pragma_simd_values
struct pragma_simd_values *ptr_next;
};
-
-
-
extern struct pragma_simd_values *psv_head;
+typedef enum array_notation_reduce_type {
+ REDUCE_UNKNOWN = 0,
+ REDUCE_ADD,
+ REDUCE_MUL,
+ REDUCE_ALL_ZEROS,
+ REDUCE_ANY_ZEROS,
+ REDUCE_MAX,
+ REDUCE_MIN,
+ REDUCE_MAX_INDEX,
+ REDUCE_MIN_INDEX
+} an_reduce_type;
#undef DEFTREECODE