Mercurial > hg > CbC > CbC_gcc
diff gcc/tree-vect-stmts.c @ 63:b7f97abdc517 gcc-4.6-20100522
update gcc from gcc-4.5.0 to gcc-4.6
author | ryoma <e075725@ie.u-ryukyu.ac.jp> |
---|---|
date | Mon, 24 May 2010 12:47:05 +0900 |
parents | 77e2b8dfacca |
children | f6334be47118 |
line wrap: on
line diff
--- a/gcc/tree-vect-stmts.c Fri Feb 12 23:41:23 2010 +0900 +++ b/gcc/tree-vect-stmts.c Mon May 24 12:47:05 2010 +0900 @@ -1,6 +1,6 @@ /* Statement Analysis and Transformation for Vectorization - Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software - Foundation, Inc. + Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 + Free Software Foundation, Inc. Contributed by Dorit Naishlos <dorit@il.ibm.com> and Ira Rosen <irar@il.ibm.com> @@ -29,6 +29,8 @@ #include "target.h" #include "basic-block.h" #include "diagnostic.h" +#include "tree-pretty-print.h" +#include "gimple-pretty-print.h" #include "tree-flow.h" #include "tree-dump.h" #include "cfgloop.h" @@ -1134,7 +1136,7 @@ slp_tree slp_node) { if (slp_node) - vect_get_slp_defs (slp_node, vec_oprnds0, vec_oprnds1); + vect_get_slp_defs (slp_node, vec_oprnds0, vec_oprnds1, -1); else { tree vec_oprnd; @@ -1189,7 +1191,6 @@ vectorizable_function (gimple call, tree vectype_out, tree vectype_in) { tree fndecl = gimple_call_fndecl (call); - enum built_in_function code; /* We only handle functions that do not read or clobber memory -- i.e. const or novops ones. */ @@ -1201,8 +1202,7 @@ || !DECL_BUILT_IN (fndecl)) return NULL_TREE; - code = DECL_FUNCTION_CODE (fndecl); - return targetm.vectorize.builtin_vectorized_function (code, vectype_out, + return targetm.vectorize.builtin_vectorized_function (fndecl, vectype_out, vectype_in); } @@ -1225,7 +1225,7 @@ int nunits_in; int nunits_out; loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info); - tree fndecl, new_temp, def, rhs_type, lhs_type; + tree fndecl, new_temp, def, rhs_type; gimple def_stmt; enum vect_def_type dt[2] = {vect_unknown_def_type, vect_unknown_def_type}; gimple new_stmt = NULL; @@ -1254,8 +1254,11 @@ if (TREE_CODE (gimple_call_lhs (stmt)) != SSA_NAME) return false; + vectype_out = STMT_VINFO_VECTYPE (stmt_info); + /* Process function arguments. */ rhs_type = NULL_TREE; + vectype_in = NULL_TREE; nargs = gimple_call_num_args (stmt); /* Bail out if the function has more than two arguments, we @@ -1266,38 +1269,59 @@ for (i = 0; i < nargs; i++) { + tree opvectype; + op = gimple_call_arg (stmt, i); /* We can only handle calls with arguments of the same type. */ if (rhs_type - && rhs_type != TREE_TYPE (op)) + && !types_compatible_p (rhs_type, TREE_TYPE (op))) { if (vect_print_dump_info (REPORT_DETAILS)) fprintf (vect_dump, "argument types differ."); return false; } - rhs_type = TREE_TYPE (op); - - if (!vect_is_simple_use (op, loop_vinfo, NULL, &def_stmt, &def, &dt[i])) + if (!rhs_type) + rhs_type = TREE_TYPE (op); + + if (!vect_is_simple_use_1 (op, loop_vinfo, NULL, + &def_stmt, &def, &dt[i], &opvectype)) { if (vect_print_dump_info (REPORT_DETAILS)) fprintf (vect_dump, "use not simple."); return false; } + + if (!vectype_in) + vectype_in = opvectype; + else if (opvectype + && opvectype != vectype_in) + { + if (vect_print_dump_info (REPORT_DETAILS)) + fprintf (vect_dump, "argument vector types differ."); + return false; + } } - - vectype_in = get_vectype_for_scalar_type (rhs_type); + /* If all arguments are external or constant defs use a vector type with + the same size as the output vector type. */ if (!vectype_in) - return false; - nunits_in = TYPE_VECTOR_SUBPARTS (vectype_in); - - lhs_type = TREE_TYPE (gimple_call_lhs (stmt)); - vectype_out = get_vectype_for_scalar_type (lhs_type); - if (!vectype_out) - return false; - nunits_out = TYPE_VECTOR_SUBPARTS (vectype_out); + vectype_in = get_same_sized_vectype (rhs_type, vectype_out); + if (vec_stmt) + gcc_assert (vectype_in); + if (!vectype_in) + { + if (vect_print_dump_info (REPORT_DETAILS)) + { + fprintf (vect_dump, "no vectype for scalar type "); + print_generic_expr (vect_dump, rhs_type, TDF_SLIM); + } + + return false; + } /* FORNOW */ + nunits_in = TYPE_VECTOR_SUBPARTS (vectype_in); + nunits_out = TYPE_VECTOR_SUBPARTS (vectype_out); if (nunits_in == nunits_out / 2) modifier = NARROW; else if (nunits_out == nunits_in) @@ -1548,13 +1572,12 @@ int nunits_out; tree vectype_out, vectype_in; int ncopies, j; - tree rhs_type, lhs_type; + tree rhs_type; tree builtin_decl; enum { NARROW, NONE, WIDEN } modifier; int i; VEC(tree,heap) *vec_oprnds0 = NULL; tree vop0; - tree integral_type; VEC(tree,heap) *dummy = NULL; int dummy_int; @@ -1580,21 +1603,39 @@ return false; /* Check types of lhs and rhs. */ + scalar_dest = gimple_assign_lhs (stmt); + vectype_out = STMT_VINFO_VECTYPE (stmt_info); + op0 = gimple_assign_rhs1 (stmt); rhs_type = TREE_TYPE (op0); - vectype_in = get_vectype_for_scalar_type (rhs_type); + /* Check the operands of the operation. */ + if (!vect_is_simple_use_1 (op0, loop_vinfo, NULL, + &def_stmt, &def, &dt[0], &vectype_in)) + { + if (vect_print_dump_info (REPORT_DETAILS)) + fprintf (vect_dump, "use not simple."); + return false; + } + /* If op0 is an external or constant defs use a vector type of + the same size as the output vector type. */ if (!vectype_in) - return false; - nunits_in = TYPE_VECTOR_SUBPARTS (vectype_in); - - scalar_dest = gimple_assign_lhs (stmt); - lhs_type = TREE_TYPE (scalar_dest); - vectype_out = get_vectype_for_scalar_type (lhs_type); - if (!vectype_out) - return false; - nunits_out = TYPE_VECTOR_SUBPARTS (vectype_out); + vectype_in = get_same_sized_vectype (rhs_type, vectype_out); + if (vec_stmt) + gcc_assert (vectype_in); + if (!vectype_in) + { + if (vect_print_dump_info (REPORT_DETAILS)) + { + fprintf (vect_dump, "no vectype for scalar type "); + print_generic_expr (vect_dump, rhs_type, TDF_SLIM); + } + + return false; + } /* FORNOW */ + nunits_in = TYPE_VECTOR_SUBPARTS (vectype_in); + nunits_out = TYPE_VECTOR_SUBPARTS (vectype_out); if (nunits_in == nunits_out / 2) modifier = NARROW; else if (nunits_out == nunits_in) @@ -1604,16 +1645,6 @@ else return false; - if (modifier == NONE) - gcc_assert (STMT_VINFO_VECTYPE (stmt_info) == vectype_out); - - /* Bail out if the types are both integral or non-integral. */ - if ((INTEGRAL_TYPE_P (rhs_type) && INTEGRAL_TYPE_P (lhs_type)) - || (!INTEGRAL_TYPE_P (rhs_type) && !INTEGRAL_TYPE_P (lhs_type))) - return false; - - integral_type = INTEGRAL_TYPE_P (rhs_type) ? vectype_in : vectype_out; - if (modifier == NARROW) ncopies = LOOP_VINFO_VECT_FACTOR (loop_vinfo) / nunits_out; else @@ -1628,24 +1659,17 @@ needs to be generated. */ gcc_assert (ncopies >= 1); - /* Check the operands of the operation. */ - if (!vect_is_simple_use (op0, loop_vinfo, NULL, &def_stmt, &def, &dt[0])) - { - if (vect_print_dump_info (REPORT_DETAILS)) - fprintf (vect_dump, "use not simple."); - return false; - } - /* Supportable by target? */ if ((modifier == NONE - && !targetm.vectorize.builtin_conversion (code, integral_type)) + && !targetm.vectorize.builtin_conversion (code, vectype_out, vectype_in)) || (modifier == WIDEN - && !supportable_widening_operation (code, stmt, vectype_in, + && !supportable_widening_operation (code, stmt, + vectype_out, vectype_in, &decl1, &decl2, &code1, &code2, &dummy_int, &dummy)) || (modifier == NARROW - && !supportable_narrowing_operation (code, stmt, vectype_in, + && !supportable_narrowing_operation (code, vectype_out, vectype_in, &code1, &dummy_int, &dummy))) { if (vect_print_dump_info (REPORT_DETAILS)) @@ -1655,7 +1679,6 @@ if (modifier != NONE) { - STMT_VINFO_VECTYPE (stmt_info) = vectype_in; /* FORNOW: SLP not supported. */ if (STMT_SLP_TYPE (stmt_info)) return false; @@ -1689,7 +1712,8 @@ vect_get_vec_defs_for_stmt_copy (dt, &vec_oprnds0, NULL); builtin_decl = - targetm.vectorize.builtin_conversion (code, integral_type); + targetm.vectorize.builtin_conversion (code, + vectype_out, vectype_in); for (i = 0; VEC_iterate (tree, vec_oprnds0, i, vop0); i++) { /* Arguments are ready. create the new vector stmt. */ @@ -1721,8 +1745,6 @@ else vec_oprnd0 = vect_get_vec_def_for_stmt_copy (dt[0], vec_oprnd0); - STMT_VINFO_VECTYPE (stmt_info) = vectype_in; - /* Generate first half of the widened result: */ new_stmt = vect_gen_widened_results_half (code1, decl1, @@ -1920,7 +1942,7 @@ tree op0, op1 = NULL; tree vec_oprnd1 = NULL_TREE; stmt_vec_info stmt_info = vinfo_for_stmt (stmt); - tree vectype = STMT_VINFO_VECTYPE (stmt_info); + tree vectype; loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info); enum tree_code code; enum machine_mode vec_mode; @@ -1934,7 +1956,7 @@ enum vect_def_type dt[2] = {vect_unknown_def_type, vect_unknown_def_type}; gimple new_stmt = NULL; stmt_vec_info prev_stmt_info; - int nunits_in = TYPE_VECTOR_SUBPARTS (vectype); + int nunits_in; int nunits_out; tree vectype_out; int ncopies; @@ -1946,21 +1968,6 @@ bb_vec_info bb_vinfo = STMT_VINFO_BB_VINFO (stmt_info); int vf; - if (loop_vinfo) - vf = LOOP_VINFO_VECT_FACTOR (loop_vinfo); - else - vf = 1; - - /* Multiple types in SLP are handled by creating the appropriate number of - vectorized stmts for each SLP node. Hence, NCOPIES is always 1 in - case of SLP. */ - if (slp_node) - ncopies = 1; - else - ncopies = LOOP_VINFO_VECT_FACTOR (loop_vinfo) / nunits_in; - - gcc_assert (ncopies >= 1); - if (!STMT_VINFO_RELEVANT_P (stmt_info) && !bb_vinfo) return false; @@ -1974,14 +1981,6 @@ if (TREE_CODE (gimple_assign_lhs (stmt)) != SSA_NAME) return false; - scalar_dest = gimple_assign_lhs (stmt); - vectype_out = get_vectype_for_scalar_type (TREE_TYPE (scalar_dest)); - if (!vectype_out) - return false; - nunits_out = TYPE_VECTOR_SUBPARTS (vectype_out); - if (nunits_out != nunits_in) - return false; - code = gimple_assign_rhs_code (stmt); /* For pointer addition, we should use the normal plus for @@ -1998,13 +1997,38 @@ return false; } + scalar_dest = gimple_assign_lhs (stmt); + vectype_out = STMT_VINFO_VECTYPE (stmt_info); + op0 = gimple_assign_rhs1 (stmt); - if (!vect_is_simple_use (op0, loop_vinfo, bb_vinfo, &def_stmt, &def, &dt[0])) + if (!vect_is_simple_use_1 (op0, loop_vinfo, bb_vinfo, + &def_stmt, &def, &dt[0], &vectype)) { if (vect_print_dump_info (REPORT_DETAILS)) fprintf (vect_dump, "use not simple."); return false; } + /* If op0 is an external or constant def use a vector type with + the same size as the output vector type. */ + if (!vectype) + vectype = get_same_sized_vectype (TREE_TYPE (op0), vectype_out); + if (vec_stmt) + gcc_assert (vectype); + if (!vectype) + { + if (vect_print_dump_info (REPORT_DETAILS)) + { + fprintf (vect_dump, "no vectype for scalar type "); + print_generic_expr (vect_dump, TREE_TYPE (op0), TDF_SLIM); + } + + return false; + } + + nunits_out = TYPE_VECTOR_SUBPARTS (vectype_out); + nunits_in = TYPE_VECTOR_SUBPARTS (vectype); + if (nunits_out != nunits_in) + return false; if (op_type == binary_op) { @@ -2018,6 +2042,21 @@ } } + if (loop_vinfo) + vf = LOOP_VINFO_VECT_FACTOR (loop_vinfo); + else + vf = 1; + + /* Multiple types in SLP are handled by creating the appropriate number of + vectorized stmts for each SLP node. Hence, NCOPIES is always 1 in + case of SLP. */ + if (slp_node) + ncopies = 1; + else + ncopies = LOOP_VINFO_VECT_FACTOR (loop_vinfo) / nunits_in; + + gcc_assert (ncopies >= 1); + /* If this is a shift/rotate, determine whether the shift amount is a vector, or scalar. If the shift/rotate amount is a vector, use the vector/vector shift optabs. */ @@ -2425,16 +2464,42 @@ if (!CONVERT_EXPR_CODE_P (code)) return false; + scalar_dest = gimple_assign_lhs (stmt); + vectype_out = STMT_VINFO_VECTYPE (stmt_info); + + /* Check the operands of the operation. */ op0 = gimple_assign_rhs1 (stmt); - vectype_in = get_vectype_for_scalar_type (TREE_TYPE (op0)); + if (! ((INTEGRAL_TYPE_P (TREE_TYPE (scalar_dest)) + && INTEGRAL_TYPE_P (TREE_TYPE (op0))) + || (SCALAR_FLOAT_TYPE_P (TREE_TYPE (scalar_dest)) + && SCALAR_FLOAT_TYPE_P (TREE_TYPE (op0)) + && CONVERT_EXPR_CODE_P (code)))) + return false; + if (!vect_is_simple_use_1 (op0, loop_vinfo, NULL, + &def_stmt, &def, &dt[0], &vectype_in)) + { + if (vect_print_dump_info (REPORT_DETAILS)) + fprintf (vect_dump, "use not simple."); + return false; + } + /* If op0 is an external def use a vector type with the + same size as the output vector type if possible. */ if (!vectype_in) - return false; + vectype_in = get_same_sized_vectype (TREE_TYPE (op0), vectype_out); + if (vec_stmt) + gcc_assert (vectype_in); + if (!vectype_in) + { + if (vect_print_dump_info (REPORT_DETAILS)) + { + fprintf (vect_dump, "no vectype for scalar type "); + print_generic_expr (vect_dump, TREE_TYPE (op0), TDF_SLIM); + } + + return false; + } + nunits_in = TYPE_VECTOR_SUBPARTS (vectype_in); - - scalar_dest = gimple_assign_lhs (stmt); - vectype_out = get_vectype_for_scalar_type (TREE_TYPE (scalar_dest)); - if (!vectype_out) - return false; nunits_out = TYPE_VECTOR_SUBPARTS (vectype_out); if (nunits_in >= nunits_out) return false; @@ -2448,28 +2513,11 @@ ncopies = LOOP_VINFO_VECT_FACTOR (loop_vinfo) / nunits_out; gcc_assert (ncopies >= 1); - if (! ((INTEGRAL_TYPE_P (TREE_TYPE (scalar_dest)) - && INTEGRAL_TYPE_P (TREE_TYPE (op0))) - || (SCALAR_FLOAT_TYPE_P (TREE_TYPE (scalar_dest)) - && SCALAR_FLOAT_TYPE_P (TREE_TYPE (op0)) - && CONVERT_EXPR_CODE_P (code)))) + /* Supportable by target? */ + if (!supportable_narrowing_operation (code, vectype_out, vectype_in, + &code1, &multi_step_cvt, &interm_types)) return false; - /* Check the operands of the operation. */ - if (!vect_is_simple_use (op0, loop_vinfo, NULL, &def_stmt, &def, &dt[0])) - { - if (vect_print_dump_info (REPORT_DETAILS)) - fprintf (vect_dump, "use not simple."); - return false; - } - - /* Supportable by target? */ - if (!supportable_narrowing_operation (code, stmt, vectype_in, &code1, - &multi_step_cvt, &interm_types)) - return false; - - STMT_VINFO_VECTYPE (stmt_info) = vectype_in; - if (!vec_stmt) /* transformation not required. */ { STMT_VINFO_TYPE (stmt_info) = type_demotion_vec_info_type; @@ -2518,7 +2566,7 @@ { /* Handle uses. */ if (slp_node) - vect_get_slp_defs (slp_node, &vec_oprnds0, NULL); + vect_get_slp_defs (slp_node, &vec_oprnds0, NULL, -1); else { VEC_free (tree, heap, vec_oprnds0); @@ -2695,16 +2743,42 @@ && code != WIDEN_MULT_EXPR) return false; + scalar_dest = gimple_assign_lhs (stmt); + vectype_out = STMT_VINFO_VECTYPE (stmt_info); + + /* Check the operands of the operation. */ op0 = gimple_assign_rhs1 (stmt); - vectype_in = get_vectype_for_scalar_type (TREE_TYPE (op0)); + if (! ((INTEGRAL_TYPE_P (TREE_TYPE (scalar_dest)) + && INTEGRAL_TYPE_P (TREE_TYPE (op0))) + || (SCALAR_FLOAT_TYPE_P (TREE_TYPE (scalar_dest)) + && SCALAR_FLOAT_TYPE_P (TREE_TYPE (op0)) + && CONVERT_EXPR_CODE_P (code)))) + return false; + if (!vect_is_simple_use_1 (op0, loop_vinfo, NULL, + &def_stmt, &def, &dt[0], &vectype_in)) + { + if (vect_print_dump_info (REPORT_DETAILS)) + fprintf (vect_dump, "use not simple."); + return false; + } + /* If op0 is an external or constant def use a vector type with + the same size as the output vector type. */ if (!vectype_in) - return false; + vectype_in = get_same_sized_vectype (TREE_TYPE (op0), vectype_out); + if (vec_stmt) + gcc_assert (vectype_in); + if (!vectype_in) + { + if (vect_print_dump_info (REPORT_DETAILS)) + { + fprintf (vect_dump, "no vectype for scalar type "); + print_generic_expr (vect_dump, TREE_TYPE (op0), TDF_SLIM); + } + + return false; + } + nunits_in = TYPE_VECTOR_SUBPARTS (vectype_in); - - scalar_dest = gimple_assign_lhs (stmt); - vectype_out = get_vectype_for_scalar_type (TREE_TYPE (scalar_dest)); - if (!vectype_out) - return false; nunits_out = TYPE_VECTOR_SUBPARTS (vectype_out); if (nunits_in <= nunits_out) return false; @@ -2719,21 +2793,6 @@ gcc_assert (ncopies >= 1); - if (! ((INTEGRAL_TYPE_P (TREE_TYPE (scalar_dest)) - && INTEGRAL_TYPE_P (TREE_TYPE (op0))) - || (SCALAR_FLOAT_TYPE_P (TREE_TYPE (scalar_dest)) - && SCALAR_FLOAT_TYPE_P (TREE_TYPE (op0)) - && CONVERT_EXPR_CODE_P (code)))) - return false; - - /* Check the operands of the operation. */ - if (!vect_is_simple_use (op0, loop_vinfo, NULL, &def_stmt, &def, &dt[0])) - { - if (vect_print_dump_info (REPORT_DETAILS)) - fprintf (vect_dump, "use not simple."); - return false; - } - op_type = TREE_CODE_LENGTH (code); if (op_type == binary_op) { @@ -2747,7 +2806,7 @@ } /* Supportable by target? */ - if (!supportable_widening_operation (code, stmt, vectype_in, + if (!supportable_widening_operation (code, stmt, vectype_out, vectype_in, &decl1, &decl2, &code1, &code2, &multi_step_cvt, &interm_types)) return false; @@ -2756,8 +2815,6 @@ architecture. */ gcc_assert (!(multi_step_cvt && op_type == binary_op)); - STMT_VINFO_VECTYPE (stmt_info) = vectype_in; - if (!vec_stmt) /* transformation not required. */ { STMT_VINFO_TYPE (stmt_info) = type_promotion_vec_info_type; @@ -2819,7 +2876,7 @@ if (j == 0) { if (slp_node) - vect_get_slp_defs (slp_node, &vec_oprnds0, &vec_oprnds1); + vect_get_slp_defs (slp_node, &vec_oprnds0, &vec_oprnds1, -1); else { vec_oprnd0 = vect_get_vec_def_for_operand (op0, stmt, NULL); @@ -3031,12 +3088,17 @@ } if (slp) - strided_store = false; - - /* VEC_NUM is the number of vect stmts to be created for this group. */ - if (slp) - vec_num = SLP_TREE_NUMBER_OF_VEC_STMTS (slp_node); + { + strided_store = false; + /* VEC_NUM is the number of vect stmts to be created for this + group. */ + vec_num = SLP_TREE_NUMBER_OF_VEC_STMTS (slp_node); + first_stmt = VEC_index (gimple, SLP_TREE_SCALAR_STMTS (slp_node), 0); + first_dr = STMT_VINFO_DATA_REF (vinfo_for_stmt (first_stmt)); + } else + /* VEC_NUM is the number of vect stmts to be created for this + group. */ vec_num = group_size; } else @@ -3105,7 +3167,7 @@ if (slp) { /* Get vectorized arguments for SLP_NODE. */ - vect_get_slp_defs (slp_node, &vec_oprnds, NULL); + vect_get_slp_defs (slp_node, &vec_oprnds, NULL, -1); vec_oprnd = VEC_index (tree, vec_oprnds, 0); } @@ -3865,7 +3927,8 @@ /* We do not handle two different vector types for the condition and the values. */ - if (TREE_TYPE (TREE_OPERAND (cond_expr, 0)) != TREE_TYPE (vectype)) + if (!types_compatible_p (TREE_TYPE (TREE_OPERAND (cond_expr, 0)), + TREE_TYPE (vectype))) return false; if (TREE_CODE (then_clause) == SSA_NAME) @@ -3945,7 +4008,6 @@ bb_vec_info bb_vinfo = STMT_VINFO_BB_VINFO (stmt_info); enum vect_relevant relevance = STMT_VINFO_RELEVANT (stmt_info); bool ok; - HOST_WIDE_INT dummy; tree scalar_type, vectype; if (vect_print_dump_info (REPORT_DETAILS)) @@ -4003,7 +4065,7 @@ { gcc_assert (PURE_SLP_STMT (stmt_info)); - scalar_type = vect_get_smallest_scalar_type (stmt, &dummy, &dummy); + scalar_type = TREE_TYPE (gimple_get_lhs (stmt)); if (vect_print_dump_info (REPORT_DETAILS)) { fprintf (vect_dump, "get vectype for scalar type: "); @@ -4049,7 +4111,7 @@ || vectorizable_load (stmt, NULL, NULL, NULL, NULL) || vectorizable_call (stmt, NULL, NULL) || vectorizable_store (stmt, NULL, NULL, NULL) - || vectorizable_reduction (stmt, NULL, NULL) + || vectorizable_reduction (stmt, NULL, NULL, NULL) || vectorizable_condition (stmt, NULL, NULL, NULL, 0)); else { @@ -4201,8 +4263,7 @@ break; case reduc_vec_info_type: - gcc_assert (!slp_node); - done = vectorizable_reduction (stmt, gsi, &vec_stmt); + done = vectorizable_reduction (stmt, gsi, &vec_stmt, slp_node); gcc_assert (done); break; @@ -4328,6 +4389,7 @@ STMT_VINFO_LIVE_P (res) = false; STMT_VINFO_VECTYPE (res) = NULL; STMT_VINFO_VEC_STMT (res) = NULL; + STMT_VINFO_VECTORIZABLE (res) = true; STMT_VINFO_IN_PATTERN_P (res) = false; STMT_VINFO_RELATED_STMT (res) = NULL; STMT_VINFO_DATA_REF (res) = NULL; @@ -4405,13 +4467,26 @@ get_vectype_for_scalar_type (tree scalar_type) { enum machine_mode inner_mode = TYPE_MODE (scalar_type); - int nbytes = GET_MODE_SIZE (inner_mode); + unsigned int nbytes = GET_MODE_SIZE (inner_mode); int nunits; tree vectype; if (nbytes == 0 || nbytes >= UNITS_PER_SIMD_WORD (inner_mode)) return NULL_TREE; + /* We can't build a vector type of elements with alignment bigger than + their size. */ + if (nbytes < TYPE_ALIGN_UNIT (scalar_type)) + return NULL_TREE; + + /* If we'd build a vector type of elements whose mode precision doesn't + match their types precision we'll get mismatched types on vector + extracts via BIT_FIELD_REFs. This effectively means we disable + vectorization of bool and/or enum types in some languages. */ + if (INTEGRAL_TYPE_P (scalar_type) + && GET_MODE_BITSIZE (inner_mode) != TYPE_PRECISION (scalar_type)) + return NULL_TREE; + /* FORNOW: Only a single vector size per mode (UNITS_PER_SIMD_WORD) is expected. */ nunits = UNITS_PER_SIMD_WORD (inner_mode) / nbytes; @@ -4443,6 +4518,17 @@ return vectype; } +/* Function get_same_sized_vectype + + Returns a vector type corresponding to SCALAR_TYPE of size + VECTOR_TYPE if supported by the target. */ + +tree +get_same_sized_vectype (tree scalar_type, tree vector_type ATTRIBUTE_UNUSED) +{ + return get_vectype_for_scalar_type (scalar_type); +} + /* Function vect_is_simple_use. Input: @@ -4576,12 +4662,55 @@ return true; } +/* Function vect_is_simple_use_1. + + Same as vect_is_simple_use_1 but also determines the vector operand + type of OPERAND and stores it to *VECTYPE. If the definition of + OPERAND is vect_uninitialized_def, vect_constant_def or + vect_external_def *VECTYPE will be set to NULL_TREE and the caller + is responsible to compute the best suited vector type for the + scalar operand. */ + +bool +vect_is_simple_use_1 (tree operand, loop_vec_info loop_vinfo, + bb_vec_info bb_vinfo, gimple *def_stmt, + tree *def, enum vect_def_type *dt, tree *vectype) +{ + if (!vect_is_simple_use (operand, loop_vinfo, bb_vinfo, def_stmt, def, dt)) + return false; + + /* Now get a vector type if the def is internal, otherwise supply + NULL_TREE and leave it up to the caller to figure out a proper + type for the use stmt. */ + if (*dt == vect_internal_def + || *dt == vect_induction_def + || *dt == vect_reduction_def + || *dt == vect_double_reduction_def + || *dt == vect_nested_cycle) + { + stmt_vec_info stmt_info = vinfo_for_stmt (*def_stmt); + if (STMT_VINFO_IN_PATTERN_P (stmt_info)) + stmt_info = vinfo_for_stmt (STMT_VINFO_RELATED_STMT (stmt_info)); + *vectype = STMT_VINFO_VECTYPE (stmt_info); + gcc_assert (*vectype != NULL_TREE); + } + else if (*dt == vect_uninitialized_def + || *dt == vect_constant_def + || *dt == vect_external_def) + *vectype = NULL_TREE; + else + gcc_unreachable (); + + return true; +} + /* Function supportable_widening_operation Check whether an operation represented by the code CODE is a widening operation that is supported by the target platform in - vector form (i.e., when operating on arguments of type VECTYPE). + vector form (i.e., when operating on arguments of type VECTYPE_IN + producing a result of type VECTYPE_OUT). Widening operations we currently support are NOP (CONVERT), FLOAT and WIDEN_MULT. This function checks if these operations are supported @@ -4601,7 +4730,8 @@ widening operation (short in the above example). */ bool -supportable_widening_operation (enum tree_code code, gimple stmt, tree vectype, +supportable_widening_operation (enum tree_code code, gimple stmt, + tree vectype_out, tree vectype_in, tree *decl1, tree *decl2, enum tree_code *code1, enum tree_code *code2, int *multi_step_cvt, @@ -4614,8 +4744,8 @@ enum machine_mode vec_mode; enum insn_code icode1, icode2; optab optab1, optab2; - tree type = gimple_expr_type (stmt); - tree wide_vectype = get_vectype_for_scalar_type (type); + tree vectype = vectype_in; + tree wide_vectype = vectype_out; enum tree_code c1, c2; /* The result of a vectorized widening operation usually requires two vectors @@ -4714,8 +4844,8 @@ if (code == FIX_TRUNC_EXPR) { /* The signedness is determined from output operand. */ - optab1 = optab_for_tree_code (c1, type, optab_default); - optab2 = optab_for_tree_code (c2, type, optab_default); + optab1 = optab_for_tree_code (c1, vectype_out, optab_default); + optab2 = optab_for_tree_code (c2, vectype_out, optab_default); } else { @@ -4797,7 +4927,8 @@ Check whether an operation represented by the code CODE is a narrowing operation that is supported by the target platform in - vector form (i.e., when operating on arguments of type VECTYPE). + vector form (i.e., when operating on arguments of type VECTYPE_IN + and producing a result of type VECTYPE_OUT). Narrowing operations we currently support are NOP (CONVERT) and FIX_TRUNC. This function checks if these operations are supported by @@ -4814,15 +4945,15 @@ bool supportable_narrowing_operation (enum tree_code code, - const_gimple stmt, tree vectype, + tree vectype_out, tree vectype_in, enum tree_code *code1, int *multi_step_cvt, VEC (tree, heap) **interm_types) { enum machine_mode vec_mode; enum insn_code icode1; optab optab1, interm_optab; - tree type = gimple_expr_type (stmt); - tree narrow_vectype = get_vectype_for_scalar_type (type); + tree vectype = vectype_in; + tree narrow_vectype = vectype_out; enum tree_code c1; tree intermediate_type, prev_type; int i; @@ -4848,7 +4979,7 @@ if (code == FIX_TRUNC_EXPR) /* The signedness is determined from output operand. */ - optab1 = optab_for_tree_code (c1, type, optab_default); + optab1 = optab_for_tree_code (c1, vectype_out, optab_default); else optab1 = optab_for_tree_code (c1, vectype, optab_default);