From: Ira Rosen Date: Sat, 23 Aug 2008 17:04:12 +0000 (+0000) Subject: re PR middle-end/37161 (Revision 139225 caused gfortran.dg/vect/pr33301.f -O) X-Git-Tag: releases/gcc-4.4.0~2909 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=8b7b9d66fe761fb42a55d016c90a4790f301f6c0;p=thirdparty%2Fgcc.git re PR middle-end/37161 (Revision 139225 caused gfortran.dg/vect/pr33301.f -O) PR tree-optimization/37161 * tree-vectorizer.h (vect_get_smallest_scalar_type): Declare. * tree-vect-analyze.c (vect_get_smallest_scalar_type): New function. (vect_determine_vectorization_factor): Move the scalar type retrieval to vect_get_smallest_scalar_type. (vect_build_slp_tree): Call vect_get_smallest_scalar_type to get scalar type. Remove redundant computation. * tree-vect-transform.c (vect_get_constant_vectors): Add argument. (vect_get_slp_defs): Take the type of RHS into account if necessary by calling vect_get_smallest_scalar_type. Call vect_get_constant_vectors with additional argument. From-SVN: r139518 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 8f291e83f3fa..1e1deebced5d 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,17 @@ +2008-08-23 Ira Rosen + + PR tree-optimization/37161 + * tree-vectorizer.h (vect_get_smallest_scalar_type): Declare. + * tree-vect-analyze.c (vect_get_smallest_scalar_type): New function. + (vect_determine_vectorization_factor): Move the scalar type + retrieval to vect_get_smallest_scalar_type. + (vect_build_slp_tree): Call vect_get_smallest_scalar_type to get + scalar type. Remove redundant computation. + * tree-vect-transform.c (vect_get_constant_vectors): Add argument. + (vect_get_slp_defs): Take the type of RHS into account if + necessary by calling vect_get_smallest_scalar_type. Call + vect_get_constant_vectors with additional argument. + 2008-08-23 Manuel Lopez-Ibanez PR 35648 diff --git a/gcc/tree-vect-analyze.c b/gcc/tree-vect-analyze.c index 0f2efd85ed52..305ba4c66037 100644 --- a/gcc/tree-vect-analyze.c +++ b/gcc/tree-vect-analyze.c @@ -44,6 +44,50 @@ along with GCC; see the file COPYING3. If not see static bool vect_can_advance_ivs_p (loop_vec_info); +/* Return the smallest scalar part of STMT. + This is used to determine the vectype of the stmt. We generally set the + vectype according to the type of the result (lhs). For stmts whose + result-type is different than the type of the arguments (e.g., demotion, + promotion), vectype will be reset appropriately (later). Note that we have + to visit the smallest datatype in this function, because that determines the + VF. If the smallest datatype in the loop is present only as the rhs of a + promotion operation - we'd miss it. + Such a case, where a variable of this datatype does not appear in the lhs + anywhere in the loop, can only occur if it's an invariant: e.g.: + 'int_x = (int) short_inv', which we'd expect to have been optimized away by + invariant motion. However, we cannot rely on invariant motion to always take + invariants out of the loop, and so in the case of promotion we also have to + check the rhs. + LHS_SIZE_UNIT and RHS_SIZE_UNIT contain the sizes of the corresponding + types. */ + +tree +vect_get_smallest_scalar_type (gimple stmt, HOST_WIDE_INT *lhs_size_unit, + HOST_WIDE_INT *rhs_size_unit) +{ + tree scalar_type = gimple_expr_type (stmt); + HOST_WIDE_INT lhs, rhs; + + lhs = rhs = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (scalar_type)); + + if (is_gimple_assign (stmt) + && (gimple_assign_cast_p (stmt) + || gimple_assign_rhs_code (stmt) == WIDEN_MULT_EXPR + || gimple_assign_rhs_code (stmt) == FLOAT_EXPR)) + { + tree rhs_type = TREE_TYPE (gimple_assign_rhs1 (stmt)); + + rhs = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (rhs_type)); + if (rhs < lhs) + scalar_type = rhs_type; + } + + *lhs_size_unit = lhs; + *rhs_size_unit = rhs; + return scalar_type; +} + + /* Function vect_determine_vectorization_factor Determine the vectorization factor (VF). VF is the number of data elements @@ -83,6 +127,7 @@ vect_determine_vectorization_factor (loop_vec_info loop_vinfo) unsigned int nunits; stmt_vec_info stmt_info; int i; + HOST_WIDE_INT dummy; if (vect_print_dump_info (REPORT_DETAILS)) fprintf (vect_dump, "=== vect_determine_vectorization_factor ==="); @@ -200,34 +245,8 @@ vect_determine_vectorization_factor (loop_vec_info loop_vinfo) gcc_assert (! STMT_VINFO_DATA_REF (stmt_info) && !is_pattern_stmt_p (stmt_info)); - /* We generally set the vectype according to the type of the - result (lhs). - For stmts whose result-type is different than the type of the - arguments (e.g. demotion, promotion), vectype will be reset - appropriately (later). Note that we have to visit the smallest - datatype in this function, because that determines the VF. - If the smallest datatype in the loop is present only as the - rhs of a promotion operation - we'd miss it here. - Such a case, where a variable of this datatype does not appear - in the lhs anywhere in the loop, can only occur if it's an - invariant: e.g.: 'int_x = (int) short_inv', which we'd expect - to have been optimized away by invariant motion. However, we - cannot rely on invariant motion to always take invariants out - of the loop, and so in the case of promotion we also have to - check the rhs. */ - scalar_type = gimple_expr_type (stmt); - - if (is_gimple_assign (stmt) - && (gimple_assign_cast_p (stmt) - || gimple_assign_rhs_code (stmt) == WIDEN_MULT_EXPR - || gimple_assign_rhs_code (stmt) == FLOAT_EXPR)) - { - tree rhs_type = TREE_TYPE (gimple_assign_rhs1 (stmt)); - if (TREE_INT_CST_LOW (TYPE_SIZE_UNIT (rhs_type)) - < TREE_INT_CST_LOW (TYPE_SIZE_UNIT (scalar_type))) - scalar_type = rhs_type; - } - + scalar_type = vect_get_smallest_scalar_type (stmt, &dummy, + &dummy); if (vect_print_dump_info (REPORT_DETAILS)) { fprintf (vect_dump, "get vectype for scalar type: "); @@ -2708,6 +2727,7 @@ vect_build_slp_tree (loop_vec_info loop_vinfo, slp_tree *node, tree first_stmt_const_oprnd = NULL_TREE; struct data_reference *first_dr; bool pattern0 = false, pattern1 = false; + HOST_WIDE_INT dummy; /* For every stmt in NODE find its def stmt/s. */ for (i = 0; VEC_iterate (gimple, stmts, i, stmt); i++) @@ -2731,7 +2751,7 @@ vect_build_slp_tree (loop_vec_info loop_vinfo, slp_tree *node, return false; } - scalar_type = TREE_TYPE (lhs); + scalar_type = vect_get_smallest_scalar_type (stmt, &dummy, &dummy); vectype = get_vectype_for_scalar_type (scalar_type); if (!vectype) { @@ -2860,11 +2880,6 @@ vect_build_slp_tree (loop_vec_info loop_vinfo, slp_tree *node, /* Load. */ if (i == 0) { - /* In case of multiple types we need to detect the smallest - type. */ - if (*max_nunits < TYPE_VECTOR_SUBPARTS (vectype)) - *max_nunits = TYPE_VECTOR_SUBPARTS (vectype); - /* First stmt of the SLP group should be the first load of the interleaving loop if data permutation is not allowed. Check that there is no gap between the loads. */ diff --git a/gcc/tree-vect-transform.c b/gcc/tree-vect-transform.c index c0c299b18fa5..0744527794dd 100644 --- a/gcc/tree-vect-transform.c +++ b/gcc/tree-vect-transform.c @@ -1385,11 +1385,11 @@ vect_init_vector (gimple stmt, tree vector_var, tree vector_type, /* For constant and loop invariant defs of SLP_NODE this function returns (vector) defs (VEC_OPRNDS) that will be used in the vectorized stmts. OP_NUM determines if we gather defs for operand 0 or operand 1 of the scalar - stmts. */ + stmts. NUMBER_OF_VECTORS is the number of vector defs to create. */ static void vect_get_constant_vectors (slp_tree slp_node, VEC(tree,heap) **vec_oprnds, - unsigned int op_num) + unsigned int op_num, unsigned int number_of_vectors) { VEC (gimple, heap) *stmts = SLP_TREE_SCALAR_STMTS (slp_node); gimple stmt = VEC_index (gimple, stmts, 0); @@ -1405,7 +1405,6 @@ vect_get_constant_vectors (slp_tree slp_node, VEC(tree,heap) **vec_oprnds, unsigned int vec_num, i; int number_of_copies = 1; bool is_store = false; - unsigned int number_of_vectors = SLP_TREE_NUMBER_OF_VEC_STMTS (slp_node); VEC (tree, heap) *voprnds = VEC_alloc (tree, heap, number_of_vectors); bool constant_p; @@ -1529,13 +1528,27 @@ vect_get_slp_defs (slp_tree slp_node, VEC (tree,heap) **vec_oprnds0, gimple first_stmt; enum tree_code code; int number_of_vects; + HOST_WIDE_INT lhs_size_unit, rhs_size_unit; + first_stmt = VEC_index (gimple, SLP_TREE_SCALAR_STMTS (slp_node), 0); /* The number of vector defs is determined by the number of vector statements in the node from which we get those statements. */ if (SLP_TREE_LEFT (slp_node)) number_of_vects = SLP_TREE_NUMBER_OF_VEC_STMTS (SLP_TREE_LEFT (slp_node)); else - number_of_vects = SLP_TREE_NUMBER_OF_VEC_STMTS (slp_node); + { + number_of_vects = SLP_TREE_NUMBER_OF_VEC_STMTS (slp_node); + /* Number of vector stmts was calculated according to LHS in + vect_schedule_slp_instance(), fix it by replacing LHS with RHS, if + necessary. See vect_get_smallest_scalar_type() for details. */ + vect_get_smallest_scalar_type (first_stmt, &lhs_size_unit, + &rhs_size_unit); + if (rhs_size_unit != lhs_size_unit) + { + number_of_vects *= rhs_size_unit; + number_of_vects /= lhs_size_unit; + } + } /* Allocate memory for vectorized defs. */ *vec_oprnds0 = VEC_alloc (tree, heap, number_of_vects); @@ -1547,9 +1560,8 @@ vect_get_slp_defs (slp_tree slp_node, VEC (tree,heap) **vec_oprnds0, vect_get_slp_vect_defs (SLP_TREE_LEFT (slp_node), vec_oprnds0); else /* Build vectors from scalar defs. */ - vect_get_constant_vectors (slp_node, vec_oprnds0, 0); + vect_get_constant_vectors (slp_node, vec_oprnds0, 0, number_of_vects); - first_stmt = VEC_index (gimple, SLP_TREE_SCALAR_STMTS (slp_node), 0); if (STMT_VINFO_DATA_REF (vinfo_for_stmt (first_stmt))) /* Since we don't call this function with loads, this is a group of stores. */ @@ -1573,7 +1585,7 @@ vect_get_slp_defs (slp_tree slp_node, VEC (tree,heap) **vec_oprnds0, vect_get_slp_vect_defs (SLP_TREE_RIGHT (slp_node), vec_oprnds1); else /* Build vectors from scalar defs. */ - vect_get_constant_vectors (slp_node, vec_oprnds1, 1); + vect_get_constant_vectors (slp_node, vec_oprnds1, 1, number_of_vects); } diff --git a/gcc/tree-vectorizer.h b/gcc/tree-vectorizer.h index a22353ccefe3..10e7aa309004 100644 --- a/gcc/tree-vectorizer.h +++ b/gcc/tree-vectorizer.h @@ -702,6 +702,8 @@ extern void free_stmt_vec_info (gimple stmt); extern loop_vec_info vect_analyze_loop (struct loop *); extern void vect_free_slp_tree (slp_tree); extern loop_vec_info vect_analyze_loop_form (struct loop *); +extern tree vect_get_smallest_scalar_type (gimple, HOST_WIDE_INT *, + HOST_WIDE_INT *); /** In tree-vect-patterns.c **/ /* Pattern recognition functions.