diff options
Diffstat (limited to 'toolchain-layer/recipes-devtools/gcc/gcc-4.6/linaro/gcc-4.6-linaro-r106840.patch')
-rw-r--r-- | toolchain-layer/recipes-devtools/gcc/gcc-4.6/linaro/gcc-4.6-linaro-r106840.patch | 1400 |
1 files changed, 1400 insertions, 0 deletions
diff --git a/toolchain-layer/recipes-devtools/gcc/gcc-4.6/linaro/gcc-4.6-linaro-r106840.patch b/toolchain-layer/recipes-devtools/gcc/gcc-4.6/linaro/gcc-4.6-linaro-r106840.patch new file mode 100644 index 0000000000..70a7bdfa2b --- /dev/null +++ b/toolchain-layer/recipes-devtools/gcc/gcc-4.6/linaro/gcc-4.6-linaro-r106840.patch @@ -0,0 +1,1400 @@ +2011-11-17 Ira Rosen <ira.rosen@linaro.org> + + Backport from mainline: + + 2011-11-03 Ira Rosen <ira.rosen@linaro.org> + + gcc/ + * tree-vectorizer.h (slp_void_p): New. + (struct _slp_tree): Replace left and right with children. Update + documentation. + (struct _slp_oprnd_info): New. + (vect_get_vec_defs): Declare. + (vect_get_slp_defs): Update arguments. + * tree-vect-loop.c (vect_create_epilog_for_reduction): Call + vect_get_vec_defs instead of vect_get_slp_defs. + (vectorizable_reduction): Likewise. + * tree-vect-stmts.c (vect_get_vec_defs): Remove static, add argument. + Update call to vect_get_slp_defs. + (vectorizable_conversion): Update call to vect_get_vec_defs. + (vectorizable_assignment, vectorizable_shift, + vectorizable_operation): Likewise. + (vectorizable_type_demotion): Call vect_get_vec_defs instead of + vect_get_slp_defs. + (vectorizable_type_promotion, vectorizable_store): Likewise. + (vect_analyze_stmt): Fix typo. + * tree-vect-slp.c (vect_free_slp_tree): Update SLP tree traversal. + (vect_print_slp_tree, vect_mark_slp_stmts, + vect_mark_slp_stmts_relevant, vect_slp_rearrange_stmts, + vect_detect_hybrid_slp_stmts, vect_slp_analyze_node_operations, + vect_schedule_slp_instance): Likewise. + (vect_create_new_slp_node): New. + (vect_create_oprnd_info, vect_free_oprnd_info): Likewise. + (vect_get_and_check_slp_defs): Pass information about defs using + oprnds_info, allow any number of operands. + (vect_build_slp_tree): Likewise. Update calls to + vect_get_and_check_slp_defs. Fix comments. + (vect_analyze_slp_instance): Move node creation to + vect_create_new_slp_node. + (vect_get_slp_defs): Allow any number of operands. + + 2011-11-11 Jakub Jelinek <jakub@redhat.com> + + gcc/ + * tree-vect-slp.c (vect_free_slp_tree): Also free SLP_TREE_CHILDREN + vector. + (vect_create_new_slp_node): Don't allocate node before checking stmt + type. + (vect_free_oprnd_info): Remove FREE_DEF_STMTS argument, always + free def_stmts vectors and additionally free oprnd_info. + (vect_build_slp_tree): Adjust callers. Call it even if + stop_recursion. If vect_create_new_slp_node or + vect_build_slp_tree fails, properly handle freeing memory. + If it succeeded, clear def_stmts in oprnd_info. + +=== modified file 'gcc/tree-vect-loop.c' +--- old/gcc/tree-vect-loop.c 2011-09-05 06:23:37 +0000 ++++ new/gcc/tree-vect-loop.c 2011-11-14 11:38:08 +0000 +@@ -3282,8 +3282,8 @@ + + /* Get the loop-entry arguments. */ + if (slp_node) +- vect_get_slp_defs (reduction_op, NULL_TREE, slp_node, &vec_initial_defs, +- NULL, reduc_index); ++ vect_get_vec_defs (reduction_op, NULL_TREE, stmt, &vec_initial_defs, ++ NULL, slp_node, reduc_index); + else + { + vec_initial_defs = VEC_alloc (tree, heap, 1); +@@ -4451,8 +4451,8 @@ + } + + if (slp_node) +- vect_get_slp_defs (op0, op1, slp_node, &vec_oprnds0, &vec_oprnds1, +- -1); ++ vect_get_vec_defs (op0, op1, stmt, &vec_oprnds0, &vec_oprnds1, ++ slp_node, -1); + else + { + loop_vec_def0 = vect_get_vec_def_for_operand (ops[!reduc_index], + +=== modified file 'gcc/tree-vect-slp.c' +--- old/gcc/tree-vect-slp.c 2011-10-27 11:27:59 +0000 ++++ new/gcc/tree-vect-slp.c 2011-11-14 11:38:08 +0000 +@@ -67,15 +67,16 @@ + static void + vect_free_slp_tree (slp_tree node) + { ++ int i; ++ slp_void_p child; ++ + if (!node) + return; + +- if (SLP_TREE_LEFT (node)) +- vect_free_slp_tree (SLP_TREE_LEFT (node)); +- +- if (SLP_TREE_RIGHT (node)) +- vect_free_slp_tree (SLP_TREE_RIGHT (node)); +- ++ FOR_EACH_VEC_ELT (slp_void_p, SLP_TREE_CHILDREN (node), i, child) ++ vect_free_slp_tree ((slp_tree) child); ++ ++ VEC_free (slp_void_p, heap, SLP_TREE_CHILDREN (node)); + VEC_free (gimple, heap, SLP_TREE_SCALAR_STMTS (node)); + + if (SLP_TREE_VEC_STMTS (node)) +@@ -96,48 +97,116 @@ + } + + +-/* Get the defs for the rhs of STMT (collect them in DEF_STMTS0/1), check that +- they are of a legal type and that they match the defs of the first stmt of +- the SLP group (stored in FIRST_STMT_...). */ ++/* Create an SLP node for SCALAR_STMTS. */ ++ ++static slp_tree ++vect_create_new_slp_node (VEC (gimple, heap) *scalar_stmts) ++{ ++ slp_tree node; ++ gimple stmt = VEC_index (gimple, scalar_stmts, 0); ++ unsigned int nops; ++ ++ if (is_gimple_call (stmt)) ++ nops = gimple_call_num_args (stmt); ++ else if (is_gimple_assign (stmt)) ++ nops = gimple_num_ops (stmt) - 1; ++ else ++ return NULL; ++ ++ node = XNEW (struct _slp_tree); ++ SLP_TREE_SCALAR_STMTS (node) = scalar_stmts; ++ SLP_TREE_VEC_STMTS (node) = NULL; ++ SLP_TREE_CHILDREN (node) = VEC_alloc (slp_void_p, heap, nops); ++ SLP_TREE_OUTSIDE_OF_LOOP_COST (node) = 0; ++ SLP_TREE_INSIDE_OF_LOOP_COST (node) = 0; ++ ++ return node; ++} ++ ++ ++/* Allocate operands info for NOPS operands, and GROUP_SIZE def-stmts for each ++ operand. */ ++static VEC (slp_oprnd_info, heap) * ++vect_create_oprnd_info (int nops, int group_size) ++{ ++ int i; ++ slp_oprnd_info oprnd_info; ++ VEC (slp_oprnd_info, heap) *oprnds_info; ++ ++ oprnds_info = VEC_alloc (slp_oprnd_info, heap, nops); ++ for (i = 0; i < nops; i++) ++ { ++ oprnd_info = XNEW (struct _slp_oprnd_info); ++ oprnd_info->def_stmts = VEC_alloc (gimple, heap, group_size); ++ oprnd_info->first_dt = vect_uninitialized_def; ++ oprnd_info->first_def_type = NULL_TREE; ++ oprnd_info->first_const_oprnd = NULL_TREE; ++ oprnd_info->first_pattern = false; ++ VEC_quick_push (slp_oprnd_info, oprnds_info, oprnd_info); ++ } ++ ++ return oprnds_info; ++} ++ ++ ++/* Free operands info. */ ++ ++static void ++vect_free_oprnd_info (VEC (slp_oprnd_info, heap) **oprnds_info) ++{ ++ int i; ++ slp_oprnd_info oprnd_info; ++ ++ FOR_EACH_VEC_ELT (slp_oprnd_info, *oprnds_info, i, oprnd_info) ++ { ++ VEC_free (gimple, heap, oprnd_info->def_stmts); ++ XDELETE (oprnd_info); ++ } ++ ++ VEC_free (slp_oprnd_info, heap, *oprnds_info); ++} ++ ++ ++/* Get the defs for the rhs of STMT (collect them in OPRNDS_INFO), check that ++ they are of a valid type and that they match the defs of the first stmt of ++ the SLP group (stored in OPRNDS_INFO). */ + + static bool + vect_get_and_check_slp_defs (loop_vec_info loop_vinfo, bb_vec_info bb_vinfo, + slp_tree slp_node, gimple stmt, +- VEC (gimple, heap) **def_stmts0, +- VEC (gimple, heap) **def_stmts1, +- enum vect_def_type *first_stmt_dt0, +- enum vect_def_type *first_stmt_dt1, +- tree *first_stmt_def0_type, +- tree *first_stmt_def1_type, +- tree *first_stmt_const_oprnd, +- int ncopies_for_cost, +- bool *pattern0, bool *pattern1) ++ int ncopies_for_cost, bool first, ++ VEC (slp_oprnd_info, heap) **oprnds_info) + { + tree oprnd; + unsigned int i, number_of_oprnds; +- tree def[2]; ++ tree def, def_op0 = NULL_TREE; + gimple def_stmt; +- enum vect_def_type dt[2] = {vect_unknown_def_type, vect_unknown_def_type}; +- stmt_vec_info stmt_info = +- vinfo_for_stmt (VEC_index (gimple, SLP_TREE_SCALAR_STMTS (slp_node), 0)); +- enum gimple_rhs_class rhs_class; ++ enum vect_def_type dt = vect_uninitialized_def; ++ enum vect_def_type dt_op0 = vect_uninitialized_def; ++ stmt_vec_info stmt_info = vinfo_for_stmt (stmt); ++ tree lhs = gimple_get_lhs (stmt); + struct loop *loop = NULL; + enum tree_code rhs_code; + bool different_types = false; ++ bool pattern = false; ++ slp_oprnd_info oprnd_info, oprnd0_info, oprnd1_info; + + if (loop_vinfo) + loop = LOOP_VINFO_LOOP (loop_vinfo); + +- rhs_class = get_gimple_rhs_class (gimple_assign_rhs_code (stmt)); +- number_of_oprnds = gimple_num_ops (stmt) - 1; /* RHS only */ ++ if (is_gimple_call (stmt)) ++ number_of_oprnds = gimple_call_num_args (stmt); ++ else ++ number_of_oprnds = gimple_num_ops (stmt) - 1; + + for (i = 0; i < number_of_oprnds; i++) + { + oprnd = gimple_op (stmt, i + 1); ++ oprnd_info = VEC_index (slp_oprnd_info, *oprnds_info, i); + +- if (!vect_is_simple_use (oprnd, loop_vinfo, bb_vinfo, &def_stmt, &def[i], +- &dt[i]) +- || (!def_stmt && dt[i] != vect_constant_def)) ++ if (!vect_is_simple_use (oprnd, loop_vinfo, bb_vinfo, &def_stmt, &def, ++ &dt) ++ || (!def_stmt && dt != vect_constant_def)) + { + if (vect_print_dump_info (REPORT_SLP)) + { +@@ -158,29 +227,24 @@ + && !STMT_VINFO_RELEVANT (vinfo_for_stmt (def_stmt)) + && !STMT_VINFO_LIVE_P (vinfo_for_stmt (def_stmt))) + { +- if (!*first_stmt_dt0) +- *pattern0 = true; +- else +- { +- if (i == 1 && !*first_stmt_dt1) +- *pattern1 = true; +- else if ((i == 0 && !*pattern0) || (i == 1 && !*pattern1)) +- { +- if (vect_print_dump_info (REPORT_DETAILS)) +- { +- fprintf (vect_dump, "Build SLP failed: some of the stmts" +- " are in a pattern, and others are not "); +- print_generic_expr (vect_dump, oprnd, TDF_SLIM); +- } ++ pattern = true; ++ if (!first && !oprnd_info->first_pattern) ++ { ++ if (vect_print_dump_info (REPORT_DETAILS)) ++ { ++ fprintf (vect_dump, "Build SLP failed: some of the stmts" ++ " are in a pattern, and others are not "); ++ print_generic_expr (vect_dump, oprnd, TDF_SLIM); ++ } + +- return false; +- } ++ return false; + } + + def_stmt = STMT_VINFO_RELATED_STMT (vinfo_for_stmt (def_stmt)); +- dt[i] = STMT_VINFO_DEF_TYPE (vinfo_for_stmt (def_stmt)); ++ dt = STMT_VINFO_DEF_TYPE (vinfo_for_stmt (def_stmt)); + +- if (*dt == vect_unknown_def_type) ++ if (dt == vect_unknown_def_type ++ || STMT_VINFO_PATTERN_DEF_STMT (vinfo_for_stmt (def_stmt))) + { + if (vect_print_dump_info (REPORT_DETAILS)) + fprintf (vect_dump, "Unsupported pattern."); +@@ -190,11 +254,11 @@ + switch (gimple_code (def_stmt)) + { + case GIMPLE_PHI: +- def[i] = gimple_phi_result (def_stmt); ++ def = gimple_phi_result (def_stmt); + break; + + case GIMPLE_ASSIGN: +- def[i] = gimple_assign_lhs (def_stmt); ++ def = gimple_assign_lhs (def_stmt); + break; + + default: +@@ -204,117 +268,125 @@ + } + } + +- if (!*first_stmt_dt0) ++ if (first) + { +- /* op0 of the first stmt of the group - store its info. */ +- *first_stmt_dt0 = dt[i]; +- if (def[i]) +- *first_stmt_def0_type = TREE_TYPE (def[i]); +- else +- *first_stmt_const_oprnd = oprnd; ++ oprnd_info->first_dt = dt; ++ oprnd_info->first_pattern = pattern; ++ if (def) ++ { ++ oprnd_info->first_def_type = TREE_TYPE (def); ++ oprnd_info->first_const_oprnd = NULL_TREE; ++ } ++ else ++ { ++ oprnd_info->first_def_type = NULL_TREE; ++ oprnd_info->first_const_oprnd = oprnd; ++ } + +- /* Analyze costs (for the first stmt of the group only). */ +- if (rhs_class != GIMPLE_SINGLE_RHS) +- /* Not memory operation (we don't call this functions for loads). */ +- vect_model_simple_cost (stmt_info, ncopies_for_cost, dt, slp_node); +- else +- /* Store. */ +- vect_model_store_cost (stmt_info, ncopies_for_cost, false, +- dt[0], slp_node); ++ if (i == 0) ++ { ++ def_op0 = def; ++ dt_op0 = dt; ++ /* Analyze costs (for the first stmt of the group only). */ ++ if (REFERENCE_CLASS_P (lhs)) ++ /* Store. */ ++ vect_model_store_cost (stmt_info, ncopies_for_cost, false, ++ dt, slp_node); ++ else ++ /* Not memory operation (we don't call this function for ++ loads). */ ++ vect_model_simple_cost (stmt_info, ncopies_for_cost, &dt, ++ slp_node); ++ } + } + + else + { +- if (!*first_stmt_dt1 && i == 1) +- { +- /* op1 of the first stmt of the group - store its info. */ +- *first_stmt_dt1 = dt[i]; +- if (def[i]) +- *first_stmt_def1_type = TREE_TYPE (def[i]); +- else +- { +- /* We assume that the stmt contains only one constant +- operand. We fail otherwise, to be on the safe side. */ +- if (*first_stmt_const_oprnd) +- { +- if (vect_print_dump_info (REPORT_SLP)) +- fprintf (vect_dump, "Build SLP failed: two constant " +- "oprnds in stmt"); +- return false; +- } +- *first_stmt_const_oprnd = oprnd; +- } +- } +- else +- { +- /* Not first stmt of the group, check that the def-stmt/s match +- the def-stmt/s of the first stmt. */ +- if ((i == 0 +- && (*first_stmt_dt0 != dt[i] +- || (*first_stmt_def0_type && def[0] +- && !types_compatible_p (*first_stmt_def0_type, +- TREE_TYPE (def[0]))))) +- || (i == 1 +- && (*first_stmt_dt1 != dt[i] +- || (*first_stmt_def1_type && def[1] +- && !types_compatible_p (*first_stmt_def1_type, +- TREE_TYPE (def[1]))))) +- || (!def[i] +- && !types_compatible_p (TREE_TYPE (*first_stmt_const_oprnd), +- TREE_TYPE (oprnd))) +- || different_types) +- { +- if (i != number_of_oprnds - 1) +- different_types = true; ++ /* Not first stmt of the group, check that the def-stmt/s match ++ the def-stmt/s of the first stmt. Allow different definition ++ types for reduction chains: the first stmt must be a ++ vect_reduction_def (a phi node), and the rest ++ vect_internal_def. */ ++ if (((oprnd_info->first_dt != dt ++ && !(oprnd_info->first_dt == vect_reduction_def ++ && dt == vect_internal_def)) ++ || (oprnd_info->first_def_type != NULL_TREE ++ && def ++ && !types_compatible_p (oprnd_info->first_def_type, ++ TREE_TYPE (def)))) ++ || (!def ++ && !types_compatible_p (TREE_TYPE (oprnd_info->first_const_oprnd), ++ TREE_TYPE (oprnd))) ++ || different_types) ++ { ++ if (number_of_oprnds != 2) ++ { ++ if (vect_print_dump_info (REPORT_SLP)) ++ fprintf (vect_dump, "Build SLP failed: different types "); ++ ++ return false; ++ } ++ ++ /* Try to swap operands in case of binary operation. */ ++ if (i == 0) ++ different_types = true; ++ else ++ { ++ oprnd0_info = VEC_index (slp_oprnd_info, *oprnds_info, 0); ++ if (is_gimple_assign (stmt) ++ && (rhs_code = gimple_assign_rhs_code (stmt)) ++ && TREE_CODE_CLASS (rhs_code) == tcc_binary ++ && commutative_tree_code (rhs_code) ++ && oprnd0_info->first_dt == dt ++ && oprnd_info->first_dt == dt_op0 ++ && def_op0 && def ++ && !(oprnd0_info->first_def_type ++ && !types_compatible_p (oprnd0_info->first_def_type, ++ TREE_TYPE (def))) ++ && !(oprnd_info->first_def_type ++ && !types_compatible_p (oprnd_info->first_def_type, ++ TREE_TYPE (def_op0)))) ++ { ++ if (vect_print_dump_info (REPORT_SLP)) ++ { ++ fprintf (vect_dump, "Swapping operands of "); ++ print_gimple_stmt (vect_dump, stmt, 0, TDF_SLIM); ++ } ++ ++ swap_tree_operands (stmt, gimple_assign_rhs1_ptr (stmt), ++ gimple_assign_rhs2_ptr (stmt)); ++ } + else +- { +- if (is_gimple_assign (stmt) +- && (rhs_code = gimple_assign_rhs_code (stmt)) +- && TREE_CODE_CLASS (rhs_code) == tcc_binary +- && commutative_tree_code (rhs_code) +- && *first_stmt_dt0 == dt[1] +- && *first_stmt_dt1 == dt[0] +- && def[0] && def[1] +- && !(*first_stmt_def0_type +- && !types_compatible_p (*first_stmt_def0_type, +- TREE_TYPE (def[1]))) +- && !(*first_stmt_def1_type +- && !types_compatible_p (*first_stmt_def1_type, +- TREE_TYPE (def[0])))) +- { +- if (vect_print_dump_info (REPORT_SLP)) +- { +- fprintf (vect_dump, "Swapping operands of "); +- print_gimple_stmt (vect_dump, stmt, 0, TDF_SLIM); +- } +- swap_tree_operands (stmt, gimple_assign_rhs1_ptr (stmt), +- gimple_assign_rhs2_ptr (stmt)); +- } +- else +- { +- if (vect_print_dump_info (REPORT_SLP)) +- fprintf (vect_dump, "Build SLP failed: different types "); +- +- return false; +- } +- } ++ { ++ if (vect_print_dump_info (REPORT_SLP)) ++ fprintf (vect_dump, "Build SLP failed: different types "); ++ ++ return false; ++ } + } + } + } + + /* Check the types of the definitions. */ +- switch (dt[i]) ++ switch (dt) + { + case vect_constant_def: + case vect_external_def: ++ case vect_reduction_def: + break; + + case vect_internal_def: +- case vect_reduction_def: +- if ((i == 0 && !different_types) || (i == 1 && different_types)) +- VEC_safe_push (gimple, heap, *def_stmts0, def_stmt); ++ if (different_types) ++ { ++ oprnd0_info = VEC_index (slp_oprnd_info, *oprnds_info, 0); ++ oprnd1_info = VEC_index (slp_oprnd_info, *oprnds_info, 0); ++ if (i == 0) ++ VEC_quick_push (gimple, oprnd1_info->def_stmts, def_stmt); ++ else ++ VEC_quick_push (gimple, oprnd0_info->def_stmts, def_stmt); ++ } + else +- VEC_safe_push (gimple, heap, *def_stmts1, def_stmt); ++ VEC_quick_push (gimple, oprnd_info->def_stmts, def_stmt); + break; + + default: +@@ -322,7 +394,7 @@ + if (vect_print_dump_info (REPORT_SLP)) + { + fprintf (vect_dump, "Build SLP failed: illegal type of def "); +- print_generic_expr (vect_dump, def[i], TDF_SLIM); ++ print_generic_expr (vect_dump, def, TDF_SLIM); + } + + return false; +@@ -347,15 +419,10 @@ + VEC (slp_tree, heap) **loads, + unsigned int vectorization_factor, bool *loads_permuted) + { +- VEC (gimple, heap) *def_stmts0 = VEC_alloc (gimple, heap, group_size); +- VEC (gimple, heap) *def_stmts1 = VEC_alloc (gimple, heap, group_size); + unsigned int i; + VEC (gimple, heap) *stmts = SLP_TREE_SCALAR_STMTS (*node); + gimple stmt = VEC_index (gimple, stmts, 0); +- enum vect_def_type first_stmt_dt0 = vect_uninitialized_def; +- enum vect_def_type first_stmt_dt1 = vect_uninitialized_def; + enum tree_code first_stmt_code = ERROR_MARK, rhs_code = ERROR_MARK; +- tree first_stmt_def1_type = NULL_TREE, first_stmt_def0_type = NULL_TREE; + tree lhs; + bool stop_recursion = false, need_same_oprnds = false; + tree vectype, scalar_type, first_op1 = NULL_TREE; +@@ -364,13 +431,21 @@ + int icode; + enum machine_mode optab_op2_mode; + enum machine_mode vec_mode; +- tree first_stmt_const_oprnd = NULL_TREE; + struct data_reference *first_dr; +- bool pattern0 = false, pattern1 = false; + HOST_WIDE_INT dummy; + bool permutation = false; + unsigned int load_place; + gimple first_load, prev_first_load = NULL; ++ VEC (slp_oprnd_info, heap) *oprnds_info; ++ unsigned int nops; ++ slp_oprnd_info oprnd_info; ++ ++ if (is_gimple_call (stmt)) ++ nops = gimple_call_num_args (stmt); ++ else ++ nops = gimple_num_ops (stmt) - 1; ++ ++ oprnds_info = vect_create_oprnd_info (nops, group_size); + + /* For every stmt in NODE find its def stmt/s. */ + FOR_EACH_VEC_ELT (gimple, stmts, i, stmt) +@@ -391,6 +466,7 @@ + print_gimple_stmt (vect_dump, stmt, 0, TDF_SLIM); + } + ++ vect_free_oprnd_info (&oprnds_info); + return false; + } + +@@ -400,10 +476,11 @@ + if (vect_print_dump_info (REPORT_SLP)) + { + fprintf (vect_dump, +- "Build SLP failed: not GIMPLE_ASSIGN nor GIMPLE_CALL"); ++ "Build SLP failed: not GIMPLE_ASSIGN nor GIMPLE_CALL "); + print_gimple_stmt (vect_dump, stmt, 0, TDF_SLIM); + } + ++ vect_free_oprnd_info (&oprnds_info); + return false; + } + +@@ -416,6 +493,8 @@ + fprintf (vect_dump, "Build SLP failed: unsupported data-type "); + print_generic_expr (vect_dump, scalar_type, TDF_SLIM); + } ++ ++ vect_free_oprnd_info (&oprnds_info); + return false; + } + +@@ -462,6 +541,7 @@ + { + if (vect_print_dump_info (REPORT_SLP)) + fprintf (vect_dump, "Build SLP failed: no optab."); ++ vect_free_oprnd_info (&oprnds_info); + return false; + } + icode = (int) optab_handler (optab, vec_mode); +@@ -470,6 +550,7 @@ + if (vect_print_dump_info (REPORT_SLP)) + fprintf (vect_dump, "Build SLP failed: " + "op not supported by target."); ++ vect_free_oprnd_info (&oprnds_info); + return false; + } + optab_op2_mode = insn_data[icode].operand[2].mode; +@@ -506,6 +587,7 @@ + print_gimple_stmt (vect_dump, stmt, 0, TDF_SLIM); + } + ++ vect_free_oprnd_info (&oprnds_info); + return false; + } + +@@ -519,6 +601,7 @@ + print_gimple_stmt (vect_dump, stmt, 0, TDF_SLIM); + } + ++ vect_free_oprnd_info (&oprnds_info); + return false; + } + } +@@ -530,15 +613,12 @@ + { + /* Store. */ + if (!vect_get_and_check_slp_defs (loop_vinfo, bb_vinfo, *node, +- stmt, &def_stmts0, &def_stmts1, +- &first_stmt_dt0, +- &first_stmt_dt1, +- &first_stmt_def0_type, +- &first_stmt_def1_type, +- &first_stmt_const_oprnd, +- ncopies_for_cost, +- &pattern0, &pattern1)) +- return false; ++ stmt, ncopies_for_cost, ++ (i == 0), &oprnds_info)) ++ { ++ vect_free_oprnd_info (&oprnds_info); ++ return false; ++ } + } + else + { +@@ -556,6 +636,7 @@ + print_gimple_stmt (vect_dump, stmt, 0, TDF_SLIM); + } + ++ vect_free_oprnd_info (&oprnds_info); + return false; + } + +@@ -573,6 +654,7 @@ + print_gimple_stmt (vect_dump, stmt, 0, TDF_SLIM); + } + ++ vect_free_oprnd_info (&oprnds_info); + return false; + } + +@@ -593,6 +675,7 @@ + print_gimple_stmt (vect_dump, stmt, 0, TDF_SLIM); + } + ++ vect_free_oprnd_info (&oprnds_info); + return false; + } + } +@@ -612,6 +695,7 @@ + print_gimple_stmt (vect_dump, stmt, 0, TDF_SLIM); + } + ++ vect_free_oprnd_info (&oprnds_info); + return false; + } + +@@ -639,7 +723,7 @@ + { + if (TREE_CODE_CLASS (rhs_code) == tcc_reference) + { +- /* Not strided load. */ ++ /* Not strided load. */ + if (vect_print_dump_info (REPORT_SLP)) + { + fprintf (vect_dump, "Build SLP failed: not strided load "); +@@ -647,6 +731,7 @@ + } + + /* FORNOW: Not strided loads are not supported. */ ++ vect_free_oprnd_info (&oprnds_info); + return false; + } + +@@ -661,19 +746,18 @@ + print_gimple_stmt (vect_dump, stmt, 0, TDF_SLIM); + } + ++ vect_free_oprnd_info (&oprnds_info); + return false; + } + + /* Find the def-stmts. */ + if (!vect_get_and_check_slp_defs (loop_vinfo, bb_vinfo, *node, stmt, +- &def_stmts0, &def_stmts1, +- &first_stmt_dt0, &first_stmt_dt1, +- &first_stmt_def0_type, +- &first_stmt_def1_type, +- &first_stmt_const_oprnd, +- ncopies_for_cost, +- &pattern0, &pattern1)) +- return false; ++ ncopies_for_cost, (i == 0), ++ &oprnds_info)) ++ { ++ vect_free_oprnd_info (&oprnds_info); ++ return false; ++ } + } + } + +@@ -702,46 +786,37 @@ + *loads_permuted = true; + } + ++ vect_free_oprnd_info (&oprnds_info); + return true; + } + + /* Create SLP_TREE nodes for the definition node/s. */ +- if (first_stmt_dt0 == vect_internal_def) +- { +- slp_tree left_node = XNEW (struct _slp_tree); +- SLP_TREE_SCALAR_STMTS (left_node) = def_stmts0; +- SLP_TREE_VEC_STMTS (left_node) = NULL; +- SLP_TREE_LEFT (left_node) = NULL; +- SLP_TREE_RIGHT (left_node) = NULL; +- SLP_TREE_OUTSIDE_OF_LOOP_COST (left_node) = 0; +- SLP_TREE_INSIDE_OF_LOOP_COST (left_node) = 0; +- if (!vect_build_slp_tree (loop_vinfo, bb_vinfo, &left_node, group_size, +- inside_cost, outside_cost, ncopies_for_cost, +- max_nunits, load_permutation, loads, +- vectorization_factor, loads_permuted)) +- return false; +- +- SLP_TREE_LEFT (*node) = left_node; +- } +- +- if (first_stmt_dt1 == vect_internal_def) +- { +- slp_tree right_node = XNEW (struct _slp_tree); +- SLP_TREE_SCALAR_STMTS (right_node) = def_stmts1; +- SLP_TREE_VEC_STMTS (right_node) = NULL; +- SLP_TREE_LEFT (right_node) = NULL; +- SLP_TREE_RIGHT (right_node) = NULL; +- SLP_TREE_OUTSIDE_OF_LOOP_COST (right_node) = 0; +- SLP_TREE_INSIDE_OF_LOOP_COST (right_node) = 0; +- if (!vect_build_slp_tree (loop_vinfo, bb_vinfo, &right_node, group_size, +- inside_cost, outside_cost, ncopies_for_cost, +- max_nunits, load_permutation, loads, +- vectorization_factor, loads_permuted)) +- return false; +- +- SLP_TREE_RIGHT (*node) = right_node; +- } +- ++ FOR_EACH_VEC_ELT (slp_oprnd_info, oprnds_info, i, oprnd_info) ++ { ++ slp_tree child; ++ ++ if (oprnd_info->first_dt != vect_internal_def) ++ continue; ++ ++ child = vect_create_new_slp_node (oprnd_info->def_stmts); ++ if (!child ++ || !vect_build_slp_tree (loop_vinfo, bb_vinfo, &child, group_size, ++ inside_cost, outside_cost, ncopies_for_cost, ++ max_nunits, load_permutation, loads, ++ vectorization_factor, loads_permuted)) ++ { ++ if (child) ++ oprnd_info->def_stmts = NULL; ++ vect_free_slp_tree (child); ++ vect_free_oprnd_info (&oprnds_info); ++ return false; ++ } ++ ++ oprnd_info->def_stmts = NULL; ++ VEC_quick_push (slp_void_p, SLP_TREE_CHILDREN (*node), child); ++ } ++ ++ vect_free_oprnd_info (&oprnds_info); + return true; + } + +@@ -751,6 +826,7 @@ + { + int i; + gimple stmt; ++ slp_void_p child; + + if (!node) + return; +@@ -763,8 +839,8 @@ + } + fprintf (vect_dump, "\n"); + +- vect_print_slp_tree (SLP_TREE_LEFT (node)); +- vect_print_slp_tree (SLP_TREE_RIGHT (node)); ++ FOR_EACH_VEC_ELT (slp_void_p, SLP_TREE_CHILDREN (node), i, child) ++ vect_print_slp_tree ((slp_tree) child); + } + + +@@ -778,6 +854,7 @@ + { + int i; + gimple stmt; ++ slp_void_p child; + + if (!node) + return; +@@ -786,8 +863,8 @@ + if (j < 0 || i == j) + STMT_SLP_TYPE (vinfo_for_stmt (stmt)) = mark; + +- vect_mark_slp_stmts (SLP_TREE_LEFT (node), mark, j); +- vect_mark_slp_stmts (SLP_TREE_RIGHT (node), mark, j); ++ FOR_EACH_VEC_ELT (slp_void_p, SLP_TREE_CHILDREN (node), i, child) ++ vect_mark_slp_stmts ((slp_tree) child, mark, j); + } + + +@@ -799,6 +876,7 @@ + int i; + gimple stmt; + stmt_vec_info stmt_info; ++ slp_void_p child; + + if (!node) + return; +@@ -811,8 +889,8 @@ + STMT_VINFO_RELEVANT (stmt_info) = vect_used_in_scope; + } + +- vect_mark_slp_stmts_relevant (SLP_TREE_LEFT (node)); +- vect_mark_slp_stmts_relevant (SLP_TREE_RIGHT (node)); ++ FOR_EACH_VEC_ELT (slp_void_p, SLP_TREE_CHILDREN (node), i, child) ++ vect_mark_slp_stmts_relevant ((slp_tree) child); + } + + +@@ -885,12 +963,13 @@ + gimple stmt; + VEC (gimple, heap) *tmp_stmts; + unsigned int index, i; ++ slp_void_p child; + + if (!node) + return; + +- vect_slp_rearrange_stmts (SLP_TREE_LEFT (node), group_size, permutation); +- vect_slp_rearrange_stmts (SLP_TREE_RIGHT (node), group_size, permutation); ++ FOR_EACH_VEC_ELT (slp_void_p, SLP_TREE_CHILDREN (node), i, child) ++ vect_slp_rearrange_stmts ((slp_tree) child, group_size, permutation); + + gcc_assert (group_size == VEC_length (gimple, SLP_TREE_SCALAR_STMTS (node))); + tmp_stmts = VEC_alloc (gimple, heap, group_size); +@@ -1253,7 +1332,7 @@ + gimple stmt) + { + slp_instance new_instance; +- slp_tree node = XNEW (struct _slp_tree); ++ slp_tree node; + unsigned int group_size = DR_GROUP_SIZE (vinfo_for_stmt (stmt)); + unsigned int unrolling_factor = 1, nunits; + tree vectype, scalar_type = NULL_TREE; +@@ -1265,6 +1344,7 @@ + VEC (slp_tree, heap) *loads; + struct data_reference *dr = STMT_VINFO_DATA_REF (vinfo_for_stmt (stmt)); + bool loads_permuted = false; ++ VEC (gimple, heap) *scalar_stmts; + + if (dr) + { +@@ -1308,39 +1388,26 @@ + } + + /* Create a node (a root of the SLP tree) for the packed strided stores. */ +- SLP_TREE_SCALAR_STMTS (node) = VEC_alloc (gimple, heap, group_size); ++ scalar_stmts = VEC_alloc (gimple, heap, group_size); + next = stmt; + if (dr) + { + /* Collect the stores and store them in SLP_TREE_SCALAR_STMTS. */ + while (next) + { +- VEC_safe_push (gimple, heap, SLP_TREE_SCALAR_STMTS (node), next); ++ VEC_safe_push (gimple, heap, scalar_stmts, next); + next = DR_GROUP_NEXT_DR (vinfo_for_stmt (next)); + } + } + else + { + /* Collect reduction statements. */ +- for (i = 0; VEC_iterate (gimple, LOOP_VINFO_REDUCTIONS (loop_vinfo), i, +- next); +- i++) +- { +- VEC_safe_push (gimple, heap, SLP_TREE_SCALAR_STMTS (node), next); +- if (vect_print_dump_info (REPORT_DETAILS)) +- { +- fprintf (vect_dump, "pushing reduction into node: "); +- print_gimple_stmt (vect_dump, next, 0, TDF_SLIM); +- } +- } ++ VEC (gimple, heap) *reductions = LOOP_VINFO_REDUCTIONS (loop_vinfo); ++ for (i = 0; VEC_iterate (gimple, reductions, i, next); i++) ++ VEC_safe_push (gimple, heap, scalar_stmts, next); + } + +- SLP_TREE_VEC_STMTS (node) = NULL; +- SLP_TREE_NUMBER_OF_VEC_STMTS (node) = 0; +- SLP_TREE_LEFT (node) = NULL; +- SLP_TREE_RIGHT (node) = NULL; +- SLP_TREE_OUTSIDE_OF_LOOP_COST (node) = 0; +- SLP_TREE_INSIDE_OF_LOOP_COST (node) = 0; ++ node = vect_create_new_slp_node (scalar_stmts); + + /* Calculate the number of vector stmts to create based on the unrolling + factor (number of vectors is 1 if NUNITS >= GROUP_SIZE, and is +@@ -1517,6 +1584,7 @@ + imm_use_iterator imm_iter; + gimple use_stmt; + stmt_vec_info stmt_vinfo; ++ slp_void_p child; + + if (!node) + return; +@@ -1534,8 +1602,8 @@ + == vect_reduction_def)) + vect_mark_slp_stmts (node, hybrid, i); + +- vect_detect_hybrid_slp_stmts (SLP_TREE_LEFT (node)); +- vect_detect_hybrid_slp_stmts (SLP_TREE_RIGHT (node)); ++ FOR_EACH_VEC_ELT (slp_void_p, SLP_TREE_CHILDREN (node), i, child) ++ vect_detect_hybrid_slp_stmts ((slp_tree) child); + } + + +@@ -1625,13 +1693,14 @@ + bool dummy; + int i; + gimple stmt; ++ slp_void_p child; + + if (!node) + return true; + +- if (!vect_slp_analyze_node_operations (bb_vinfo, SLP_TREE_LEFT (node)) +- || !vect_slp_analyze_node_operations (bb_vinfo, SLP_TREE_RIGHT (node))) +- return false; ++ FOR_EACH_VEC_ELT (slp_void_p, SLP_TREE_CHILDREN (node), i, child) ++ if (!vect_slp_analyze_node_operations (bb_vinfo, (slp_tree) child)) ++ return false; + + FOR_EACH_VEC_ELT (gimple, SLP_TREE_SCALAR_STMTS (node), i, stmt) + { +@@ -2207,88 +2276,102 @@ + If the scalar definitions are loop invariants or constants, collect them and + call vect_get_constant_vectors() to create vector stmts. + Otherwise, the def-stmts must be already vectorized and the vectorized stmts +- must be stored in the LEFT/RIGHT node of SLP_NODE, and we call +- vect_get_slp_vect_defs() to retrieve them. +- If VEC_OPRNDS1 is NULL, don't get vector defs for the second operand (from +- the right node. This is used when the second operand must remain scalar. */ ++ must be stored in the corresponding child of SLP_NODE, and we call ++ vect_get_slp_vect_defs () to retrieve them. */ + + void +-vect_get_slp_defs (tree op0, tree op1, slp_tree slp_node, +- VEC (tree,heap) **vec_oprnds0, +- VEC (tree,heap) **vec_oprnds1, int reduc_index) ++vect_get_slp_defs (VEC (tree, heap) *ops, slp_tree slp_node, ++ VEC (slp_void_p, heap) **vec_oprnds, int reduc_index) + { +- gimple first_stmt; +- enum tree_code code; +- int number_of_vects; ++ gimple first_stmt, first_def; ++ int number_of_vects = 0, i; ++ unsigned int child_index = 0; + HOST_WIDE_INT lhs_size_unit, rhs_size_unit; ++ slp_tree child = NULL; ++ VEC (tree, heap) *vec_defs; ++ tree oprnd, def_lhs; ++ bool vectorized_defs; + + 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 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; +- } ++ FOR_EACH_VEC_ELT (tree, ops, i, oprnd) ++ { ++ /* For each operand we check if it has vectorized definitions in a child ++ node or we need to create them (for invariants and constants). We ++ check if the LHS of the first stmt of the next child matches OPRND. ++ If it does, we found the correct child. Otherwise, we call ++ vect_get_constant_vectors (), and not advance CHILD_INDEX in order ++ to check this child node for the next operand. */ ++ vectorized_defs = false; ++ if (VEC_length (slp_void_p, SLP_TREE_CHILDREN (slp_node)) > child_index) ++ { ++ child = (slp_tree) VEC_index (slp_void_p, ++ SLP_TREE_CHILDREN (slp_node), ++ child_index); ++ first_def = VEC_index (gimple, SLP_TREE_SCALAR_STMTS (child), 0); ++ ++ /* In the end of a pattern sequence we have a use of the original stmt, ++ so we need to compare OPRND with the original def. */ ++ if (is_pattern_stmt_p (vinfo_for_stmt (first_def)) ++ && !STMT_VINFO_IN_PATTERN_P (vinfo_for_stmt (first_stmt)) ++ && !is_pattern_stmt_p (vinfo_for_stmt (first_stmt))) ++ first_def = STMT_VINFO_RELATED_STMT (vinfo_for_stmt (first_def)); ++ ++ if (is_gimple_call (first_def)) ++ def_lhs = gimple_call_lhs (first_def); ++ else ++ def_lhs = gimple_assign_lhs (first_def); ++ ++ if (operand_equal_p (oprnd, def_lhs, 0)) ++ { ++ /* The number of vector defs is determined by the number of ++ vector statements in the node from which we get those ++ statements. */ ++ number_of_vects = SLP_TREE_NUMBER_OF_VEC_STMTS (child); ++ vectorized_defs = true; ++ child_index++; ++ } ++ } ++ ++ if (!vectorized_defs) ++ { ++ if (i == 0) ++ { ++ 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_defs = VEC_alloc (tree, heap, number_of_vects); ++ ++ /* For reduction defs we call vect_get_constant_vectors (), since we are ++ looking for initial loop invariant values. */ ++ if (vectorized_defs && reduc_index == -1) ++ /* The defs are already vectorized. */ ++ vect_get_slp_vect_defs (child, &vec_defs); ++ else ++ /* Build vectors from scalar defs. */ ++ vect_get_constant_vectors (oprnd, slp_node, &vec_defs, i, ++ number_of_vects, reduc_index); ++ ++ VEC_quick_push (slp_void_p, *vec_oprnds, (slp_void_p) vec_defs); ++ ++ /* For reductions, we only need initial values. */ ++ if (reduc_index != -1) ++ return; + } +- +- /* Allocate memory for vectorized defs. */ +- *vec_oprnds0 = VEC_alloc (tree, heap, number_of_vects); +- +- /* SLP_NODE corresponds either to a group of stores or to a group of +- unary/binary operations. We don't call this function for loads. +- For reduction defs we call vect_get_constant_vectors(), since we are +- looking for initial loop invariant values. */ +- if (SLP_TREE_LEFT (slp_node) && reduc_index == -1) +- /* The defs are already vectorized. */ +- vect_get_slp_vect_defs (SLP_TREE_LEFT (slp_node), vec_oprnds0); +- else +- /* Build vectors from scalar defs. */ +- vect_get_constant_vectors (op0, slp_node, vec_oprnds0, 0, number_of_vects, +- reduc_index); +- +- 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. */ +- return; +- +- /* For reductions, we only need initial values. */ +- if (reduc_index != -1) +- return; +- +- code = gimple_assign_rhs_code (first_stmt); +- if (get_gimple_rhs_class (code) != GIMPLE_BINARY_RHS || !vec_oprnds1) +- return; +- +- /* 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_RIGHT (slp_node)) +- number_of_vects = SLP_TREE_NUMBER_OF_VEC_STMTS (SLP_TREE_RIGHT (slp_node)); +- else +- number_of_vects = SLP_TREE_NUMBER_OF_VEC_STMTS (slp_node); +- +- *vec_oprnds1 = VEC_alloc (tree, heap, number_of_vects); +- +- if (SLP_TREE_RIGHT (slp_node)) +- /* The defs are already vectorized. */ +- vect_get_slp_vect_defs (SLP_TREE_RIGHT (slp_node), vec_oprnds1); +- else +- /* Build vectors from scalar defs. */ +- vect_get_constant_vectors (op1, slp_node, vec_oprnds1, 1, number_of_vects, +- -1); + } + +- + /* Create NCOPIES permutation statements using the mask MASK_BYTES (by + building a vector of type MASK_TYPE from it) and two input vectors placed in + DR_CHAIN at FIRST_VEC_INDX and SECOND_VEC_INDX for the first copy and +@@ -2605,14 +2688,14 @@ + tree vectype; + int i; + slp_tree loads_node; ++ slp_void_p child; + + if (!node) + return false; + +- vect_schedule_slp_instance (SLP_TREE_LEFT (node), instance, +- vectorization_factor); +- vect_schedule_slp_instance (SLP_TREE_RIGHT (node), instance, +- vectorization_factor); ++ FOR_EACH_VEC_ELT (slp_void_p, SLP_TREE_CHILDREN (node), i, child) ++ vect_schedule_slp_instance ((slp_tree) child, instance, ++ vectorization_factor); + + stmt = VEC_index (gimple, SLP_TREE_SCALAR_STMTS (node), 0); + stmt_info = vinfo_for_stmt (stmt); + +=== modified file 'gcc/tree-vect-stmts.c' +--- old/gcc/tree-vect-stmts.c 2011-10-27 11:27:59 +0000 ++++ new/gcc/tree-vect-stmts.c 2011-11-14 11:38:08 +0000 +@@ -1419,16 +1419,35 @@ + } + + +-/* Get vectorized definitions for OP0 and OP1, or SLP_NODE if it is not +- NULL. */ ++/* Get vectorized definitions for OP0 and OP1. ++ REDUC_INDEX is the index of reduction operand in case of reduction, ++ and -1 otherwise. */ + +-static void ++void + vect_get_vec_defs (tree op0, tree op1, gimple stmt, +- VEC(tree,heap) **vec_oprnds0, VEC(tree,heap) **vec_oprnds1, +- slp_tree slp_node) ++ VEC (tree, heap) **vec_oprnds0, ++ VEC (tree, heap) **vec_oprnds1, ++ slp_tree slp_node, int reduc_index) + { + if (slp_node) +- vect_get_slp_defs (op0, op1, slp_node, vec_oprnds0, vec_oprnds1, -1); ++ { ++ int nops = (op1 == NULL_TREE) ? 1 : 2; ++ VEC (tree, heap) *ops = VEC_alloc (tree, heap, nops); ++ VEC (slp_void_p, heap) *vec_defs = VEC_alloc (slp_void_p, heap, nops); ++ ++ VEC_quick_push (tree, ops, op0); ++ if (op1) ++ VEC_quick_push (tree, ops, op1); ++ ++ vect_get_slp_defs (ops, slp_node, &vec_defs, reduc_index); ++ ++ *vec_oprnds0 = (VEC (tree, heap) *) VEC_index (slp_void_p, vec_defs, 0); ++ if (op1) ++ *vec_oprnds1 = (VEC (tree, heap) *) VEC_index (slp_void_p, vec_defs, 1); ++ ++ VEC_free (tree, heap, ops); ++ VEC_free (slp_void_p, heap, vec_defs); ++ } + else + { + tree vec_oprnd; +@@ -2016,7 +2035,8 @@ + for (j = 0; j < ncopies; j++) + { + if (j == 0) +- vect_get_vec_defs (op0, NULL, stmt, &vec_oprnds0, NULL, slp_node); ++ vect_get_vec_defs (op0, NULL, stmt, &vec_oprnds0, NULL, slp_node, ++ -1); + else + vect_get_vec_defs_for_stmt_copy (dt, &vec_oprnds0, NULL); + +@@ -2221,7 +2241,7 @@ + { + /* Handle uses. */ + if (j == 0) +- vect_get_vec_defs (op, NULL, stmt, &vec_oprnds, NULL, slp_node); ++ vect_get_vec_defs (op, NULL, stmt, &vec_oprnds, NULL, slp_node, -1); + else + vect_get_vec_defs_for_stmt_copy (dt, &vec_oprnds, NULL); + +@@ -2576,10 +2596,10 @@ + operand 1 should be of a vector type (the usual case). */ + if (vec_oprnd1) + vect_get_vec_defs (op0, NULL_TREE, stmt, &vec_oprnds0, NULL, +- slp_node); ++ slp_node, -1); + else + vect_get_vec_defs (op0, op1, stmt, &vec_oprnds0, &vec_oprnds1, +- slp_node); ++ slp_node, -1); + } + else + vect_get_vec_defs_for_stmt_copy (dt, &vec_oprnds0, &vec_oprnds1); +@@ -2887,10 +2907,10 @@ + { + if (op_type == binary_op || op_type == ternary_op) + vect_get_vec_defs (op0, op1, stmt, &vec_oprnds0, &vec_oprnds1, +- slp_node); ++ slp_node, -1); + else + vect_get_vec_defs (op0, NULL_TREE, stmt, &vec_oprnds0, NULL, +- slp_node); ++ slp_node, -1); + if (op_type == ternary_op) + { + vec_oprnds2 = VEC_alloc (tree, heap, 1); +@@ -3202,7 +3222,8 @@ + { + /* Handle uses. */ + if (slp_node) +- vect_get_slp_defs (op0, NULL_TREE, slp_node, &vec_oprnds0, NULL, -1); ++ vect_get_vec_defs (op0, NULL_TREE, stmt, &vec_oprnds0, NULL, ++ slp_node, -1); + else + { + VEC_free (tree, heap, vec_oprnds0); +@@ -3548,12 +3569,12 @@ + for (k = 0; k < slp_node->vec_stmts_size - 1; k++) + VEC_quick_push (tree, vec_oprnds1, vec_oprnd1); + +- vect_get_slp_defs (op0, NULL_TREE, slp_node, &vec_oprnds0, NULL, +- -1); ++ vect_get_vec_defs (op0, NULL_TREE, stmt, &vec_oprnds0, NULL, ++ slp_node, -1); + } + else +- vect_get_slp_defs (op0, op1, slp_node, &vec_oprnds0, +- &vec_oprnds1, -1); ++ vect_get_vec_defs (op0, op1, stmt, &vec_oprnds0, ++ &vec_oprnds1, slp_node, -1); + } + else + { +@@ -3796,6 +3817,7 @@ + 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)); ++ op = gimple_assign_rhs1 (first_stmt); + } + else + /* VEC_NUM is the number of vect stmts to be created for this +@@ -3878,8 +3900,8 @@ + if (slp) + { + /* Get vectorized arguments for SLP_NODE. */ +- vect_get_slp_defs (NULL_TREE, NULL_TREE, slp_node, &vec_oprnds, +- NULL, -1); ++ vect_get_vec_defs (op, NULL_TREE, stmt, &vec_oprnds, ++ NULL, slp_node, -1); + + vec_oprnd = VEC_index (tree, vec_oprnds, 0); + } +@@ -5040,7 +5062,7 @@ + In basic blocks we only analyze statements that are a part of some SLP + instance, therefore, all the statements are relevant. + +- Pattern statement need to be analyzed instead of the original statement ++ Pattern statement needs to be analyzed instead of the original statement + if the original statement is not relevant. Otherwise, we analyze both + statements. */ + + +=== modified file 'gcc/tree-vectorizer.h' +--- old/gcc/tree-vectorizer.h 2011-10-23 13:33:07 +0000 ++++ new/gcc/tree-vectorizer.h 2011-11-14 11:38:08 +0000 +@@ -73,15 +73,15 @@ + /************************************************************************ + SLP + ************************************************************************/ ++typedef void *slp_void_p; ++DEF_VEC_P (slp_void_p); ++DEF_VEC_ALLOC_P (slp_void_p, heap); + +-/* A computation tree of an SLP instance. Each node corresponds to a group of ++/* A computation tree of an SLP instance. Each node corresponds to a group of + stmts to be packed in a SIMD stmt. */ + typedef struct _slp_tree { +- /* Only binary and unary operations are supported. LEFT child corresponds to +- the first operand and RIGHT child to the second if the operation is +- binary. */ +- struct _slp_tree *left; +- struct _slp_tree *right; ++ /* Nodes that contain def-stmts of this node statements operands. */ ++ VEC (slp_void_p, heap) *children; + /* A group of scalar stmts to be vectorized together. */ + VEC (gimple, heap) *stmts; + /* Vectorized stmt/s. */ +@@ -146,14 +146,32 @@ + #define SLP_INSTANCE_LOADS(S) (S)->loads + #define SLP_INSTANCE_FIRST_LOAD_STMT(S) (S)->first_load + +-#define SLP_TREE_LEFT(S) (S)->left +-#define SLP_TREE_RIGHT(S) (S)->right ++#define SLP_TREE_CHILDREN(S) (S)->children + #define SLP_TREE_SCALAR_STMTS(S) (S)->stmts + #define SLP_TREE_VEC_STMTS(S) (S)->vec_stmts + #define SLP_TREE_NUMBER_OF_VEC_STMTS(S) (S)->vec_stmts_size + #define SLP_TREE_OUTSIDE_OF_LOOP_COST(S) (S)->cost.outside_of_loop + #define SLP_TREE_INSIDE_OF_LOOP_COST(S) (S)->cost.inside_of_loop + ++/* This structure is used in creation of an SLP tree. Each instance ++ corresponds to the same operand in a group of scalar stmts in an SLP ++ node. */ ++typedef struct _slp_oprnd_info ++{ ++ /* Def-stmts for the operands. */ ++ VEC (gimple, heap) *def_stmts; ++ /* Information about the first statement, its vector def-type, type, the ++ operand itself in case it's constant, and an indication if it's a pattern ++ stmt. */ ++ enum vect_def_type first_dt; ++ tree first_def_type; ++ tree first_const_oprnd; ++ bool first_pattern; ++} *slp_oprnd_info; ++ ++DEF_VEC_P(slp_oprnd_info); ++DEF_VEC_ALLOC_P(slp_oprnd_info, heap); ++ + + typedef struct _vect_peel_info + { +@@ -819,6 +837,8 @@ + unsigned int *, unsigned int *); + extern void vect_get_store_cost (struct data_reference *, int, unsigned int *); + 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); + + /* In tree-vect-data-refs.c. */ + extern bool vect_can_force_dr_alignment_p (const_tree, unsigned int); +@@ -885,8 +905,9 @@ + extern bool vect_analyze_slp (loop_vec_info, bb_vec_info); + extern void vect_make_slp_decision (loop_vec_info); + extern void vect_detect_hybrid_slp (loop_vec_info); +-extern void vect_get_slp_defs (tree, tree, slp_tree, VEC (tree,heap) **, +- VEC (tree,heap) **, int); ++extern void vect_get_slp_defs (VEC (tree, heap) *, slp_tree, ++ VEC (slp_void_p, heap) **, int); ++ + extern LOC find_bb_location (basic_block); + extern bb_vec_info vect_slp_analyze_bb (basic_block); + extern void vect_slp_transform_bb (basic_block); + |