@@ -1,3 +1,17 @@
+2012-05-07 Balaji V. Iyer <balaji.v.iyer@intel.com>
+
+ * c-parser.c (c_parser_declaration_or_fndef): Saved function arguments
+ for an elemental function.
+ * elem-function.c (find_elem_fn_parm_type_1): Added step-size parameter.
+ (find_elem_fn_parm_type): Likewise.
+ * tree-vect-stmts.c (vect_get_vec_def_for_operand): Added step-size
+ support for linear clause. Also called elem_fn_linear_init_vector for
+ linear clause.
+ (vectorizable_call): When linear clause is set, set the vector type to
+ constant_def.
+ (elem_fn_linear_init_vector): New function.
+ * tree.c (build_elem_fn_linear_vector_from_val): Likewise.
+
2012-04-24 Balaji V. Iyer <balaji.v.iyer@intel.com>
* elem-function.c (find_elem_fn_param_type_1): New function.
@@ -1640,7 +1640,7 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
specs->attrs = NULL_TREE;
while (true)
{
- struct c_declarator *declarator;
+ struct c_declarator *declarator = NULL;
bool dummy = false;
timevar_id_t tv;
tree fnbody;
@@ -1705,6 +1705,11 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
tree d = start_decl (declarator, specs, false,
chainon (postfix_attrs,
all_prefix_attrs));
+ if (d && TREE_CODE (d) == FUNCTION_DECL
+ && declarator->kind == cdk_function
+ && lookup_attribute ("vector", all_prefix_attrs)
+ && declarator && declarator->u.arg_info)
+ DECL_ARGUMENTS (d) = declarator->u.arg_info->parms;
if (d)
finish_decl (d, UNKNOWN_LOCATION, NULL_TREE,
NULL_TREE, asm_name);
@@ -85,7 +85,7 @@ static tree create_processor_attribute (elem_fn_info *, tree *);
/* this is an helper function for find_elem_fn_param_type */
static enum elem_fn_parm_type
-find_elem_fn_parm_type_1 (tree fndecl, int parm_no)
+find_elem_fn_parm_type_1 (tree fndecl, int parm_no, tree *step_size)
{
int ii = 0;
elem_fn_info *elem_fn_values;
@@ -96,7 +96,12 @@ find_elem_fn_parm_type_1 (tree fndecl, int parm_no)
for (ii = 0; ii < elem_fn_values->no_lvars; ii++)
if (elem_fn_values->linear_location[ii] == parm_no)
- return TYPE_LINEAR;
+ {
+ if (step_size != NULL)
+ *step_size = build_int_cst (integer_type_node,
+ elem_fn_values->linear_steps[ii]);
+ return TYPE_LINEAR;
+ }
for (ii = 0; ii < elem_fn_values->no_uvars; ii++)
if (elem_fn_values->uniform_location[ii] == parm_no)
@@ -109,7 +114,7 @@ find_elem_fn_parm_type_1 (tree fndecl, int parm_no)
/* this function will return the type of a parameter in elemental function.
The choices are UNIFORM or LINEAR. */
enum elem_fn_parm_type
-find_elem_fn_parm_type (gimple stmt, tree op)
+find_elem_fn_parm_type (gimple stmt, tree op, tree *step_size)
{
tree fndecl, parm = NULL_TREE;
int ii, nargs;
@@ -128,7 +133,7 @@ find_elem_fn_parm_type (gimple stmt, tree op)
parm = gimple_call_arg (stmt, ii);
if (op == parm)
{
- return_type = find_elem_fn_parm_type_1 (fndecl, 1);
+ return_type = find_elem_fn_parm_type_1 (fndecl, ii, step_size);
return return_type;
}
}
@@ -42,6 +42,7 @@ along with GCC; see the file COPYING3. If not see
#include "langhooks.h"
#include "cilk.h"
+extern enum elem_fn_parm_type find_elem_fn_parm_type (gimple, tree, tree *);
/* Return a variable of type ELEM_TYPE[NELEMS]. */
static tree
@@ -1259,8 +1260,8 @@ vect_get_vec_def_for_operand (tree op, gimple stmt, tree *scalar_def)
enum vect_def_type dt;
bool is_simple_use;
tree vector_type;
-
- extern enum elem_fn_parm_type find_elem_fn_parm_type (gimple, tree);
+ enum elem_fn_parm_type parm_type;
+ tree step_size = NULL_TREE;
if (vect_print_dump_info (REPORT_DETAILS))
{
@@ -1289,14 +1290,12 @@ vect_get_vec_def_for_operand (tree op, gimple stmt, tree *scalar_def)
&& gimple_code (stmt) == GIMPLE_CALL
&& is_elem_fn (gimple_call_fndecl (stmt)))
{
- enum elem_fn_parm_type parm_type = find_elem_fn_parm_type (stmt, op);
- if (parm_type == TYPE_UNIFORM)
+ parm_type = find_elem_fn_parm_type (stmt, op, &step_size);
+ if (parm_type == TYPE_UNIFORM || parm_type == TYPE_LINEAR)
dt = vect_constant_def;
- else if (parm_type == TYPE_LINEAR)
- {
- ;
- }
}
+ else
+ parm_type = TYPE_NONE;
switch (dt)
{
@@ -1313,8 +1312,13 @@ vect_get_vec_def_for_operand (tree op, gimple stmt, tree *scalar_def)
/* Create 'vect_cst_ = {cst,cst,...,cst}' */
if (vect_print_dump_info (REPORT_DETAILS))
fprintf (vect_dump, "Create vector_cst. nunits = %d", nunits);
-
- return vect_init_vector (stmt, op, vector_type, NULL);
+ if (!flag_enable_cilk
+ || (parm_type == TYPE_NONE || parm_type == TYPE_UNIFORM))
+ return vect_init_vector (stmt, op, vector_type, NULL);
+ else if (flag_enable_cilk && parm_type == TYPE_LINEAR)
+ return elem_fn_linear_init_vector (stmt, op, vector_type,
+ step_size, NULL);
+
}
/* Case 2: operand is defined outside the loop - loop invariant. */
@@ -1640,6 +1644,7 @@ vectorizable_call (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt,
enum { NARROW, NONE, WIDEN } modifier;
size_t i, nargs;
tree lhs;
+ tree step_size = NULL_TREE;
if (!STMT_VINFO_RELEVANT_P (stmt_info) && !bb_vinfo)
return false;
@@ -1841,6 +1846,16 @@ vectorizable_call (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt,
else
{
vec_oprnd0 = gimple_call_arg (new_stmt, i);
+ if (flag_enable_cilk
+ && gimple_code (new_stmt) == GIMPLE_CALL
+ && is_elem_fn (gimple_call_fndecl (new_stmt)))
+ {
+ enum elem_fn_parm_type parm_type =
+ find_elem_fn_parm_type (stmt, op, &step_size);
+ if (parm_type == TYPE_UNIFORM
+ || parm_type == TYPE_LINEAR)
+ dt[i] = vect_constant_def;
+ }
vec_oprnd0
= vect_get_vec_def_for_stmt_copy (dt[i], vec_oprnd0);
}
@@ -6549,3 +6564,55 @@ supportable_narrowing_operation (enum tree_code code,
VEC_free (tree, heap, *interm_types);
return false;
}
+
+/* Function vect_init_vector.
+
+ Insert a new stmt (INIT_STMT) that initializes a new variable of type
+ TYPE with the value VAL. If TYPE is a vector type and VAL does not have
+ vector type a vector with all elements equal to VAL is created first.
+ Place the initialization at BSI if it is not NULL. Otherwise, place the
+ initialization at the loop preheader.
+ Return the DEF of INIT_STMT.
+ It will be used in the vectorization of STMT. */
+
+tree
+elem_fn_linear_init_vector (gimple stmt, tree val, tree type, tree step_size,
+ gimple_stmt_iterator *gsi)
+{
+ tree new_var;
+ gimple init_stmt;
+ tree vec_oprnd;
+ tree new_temp;
+
+ if (TREE_CODE (type) == VECTOR_TYPE
+ && TREE_CODE (TREE_TYPE (val)) != VECTOR_TYPE)
+ {
+ if (!types_compatible_p (TREE_TYPE (type), TREE_TYPE (val)))
+ {
+ if (CONSTANT_CLASS_P (val))
+ val = fold_unary (VIEW_CONVERT_EXPR, TREE_TYPE (type), val);
+ else
+ {
+ new_var = create_tmp_reg (TREE_TYPE (type), NULL);
+ add_referenced_var (new_var);
+ init_stmt = gimple_build_assign_with_ops (NOP_EXPR,
+ new_var, val,
+ NULL_TREE);
+ new_temp = make_ssa_name (new_var, init_stmt);
+ gimple_assign_set_lhs (init_stmt, new_temp);
+ vect_init_vector_1 (stmt, init_stmt, gsi);
+ val = new_temp;
+ }
+ }
+ val = build_elem_fn_linear_vector_from_val (type, val, step_size);
+ }
+
+ new_var = vect_get_new_vect_var (type, vect_simple_var, "cst_");
+ add_referenced_var (new_var);
+ init_stmt = gimple_build_assign (new_var, val);
+ new_temp = make_ssa_name (new_var, init_stmt);
+ gimple_assign_set_lhs (init_stmt, new_temp);
+ vect_init_vector_1 (stmt, init_stmt, gsi);
+ vec_oprnd = gimple_assign_lhs (init_stmt);
+ return vec_oprnd;
+}
@@ -861,6 +861,8 @@ extern bool vect_supportable_shift (enum tree_code, tree);
extern void vect_get_vec_defs (tree, tree, gimple, VEC (tree, heap) **,
VEC (tree, heap) **, slp_tree, int);
extern tree vect_gen_perm_mask (tree, unsigned char *);
+extern tree elem_fn_linear_init_vector (gimple, tree, tree, tree,
+ gimple_stmt_iterator *);
/* In tree-vect-data-refs.c. */
extern bool vect_can_force_dr_alignment_p (const_tree, unsigned int);
@@ -11624,6 +11624,51 @@ build_call_list (tree return_type, tree fn, tree arglist)
}
+/* Build a vector of type VECTYPE where all the elements are SCs. */
+tree
+build_elem_fn_linear_vector_from_val (tree vectype, tree sc, tree step_size)
+{
+ int i, nunits = TYPE_VECTOR_SUBPARTS (vectype);
+
+ if (sc == error_mark_node)
+ return sc;
+
+ /* Verify that the vector type is suitable for SC. Note that there
+ is some inconsistency in the type-system with respect to restrict
+ qualifications of pointers. Vector types always have a main-variant
+ element type and the qualification is applied to the vector-type.
+ So TREE_TYPE (vector-type) does not return a properly qualified
+ vector element-type. */
+ gcc_checking_assert (types_compatible_p (TYPE_MAIN_VARIANT (TREE_TYPE (sc)),
+ TREE_TYPE (vectype)));
+
+ if (CONSTANT_CLASS_P (sc))
+ {
+ tree *v = XALLOCAVEC (tree, nunits);
+ for (i = 0; i < nunits; ++i)
+ // v[i] = sc;
+ v[i] = build2 (PLUS_EXPR, TREE_TYPE (sc), sc,
+ fold_build2 (MULT_EXPR, TREE_TYPE (step_size), step_size,
+ build_int_cst (integer_type_node, i)));
+ return build_vector (vectype, v);
+ }
+ else
+ {
+ VEC(constructor_elt, gc) *v = VEC_alloc (constructor_elt, gc, nunits);
+ for (i = 0; i < nunits; ++i)
+ {
+ // CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, sc);
+ tree tmp = NULL_TREE;
+ tmp = build2 (PLUS_EXPR, TREE_TYPE (sc), sc,
+ fold_build2 (MULT_EXPR, TREE_TYPE (step_size),
+ step_size,
+ build_int_cst (integer_type_node, i)));
+ CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, tmp);
+ }
+ return build_constructor (vectype, v);
+ }
+}
+
@@ -4530,7 +4530,7 @@ extern tree build_call_valist (tree, tree, int, va_list);
build_call_array_loc (UNKNOWN_LOCATION, T1, T2, N, T3)
extern tree build_call_array_loc (location_t, tree, tree, int, const tree *);
extern tree build_call_vec (tree, tree, VEC(tree,gc) *);
-
+extern tree build_elem_fn_linear_vector_from_val (tree, tree, tree);
/* Construct various nodes representing data types. */
extern tree make_signed_type (int);