Index: testsuite/gcc.dg/vect/pr49352.c =================================================================== --- testsuite/gcc.dg/vect/pr49352.c (revision 0) +++ testsuite/gcc.dg/vect/pr49352.c (revision 0) @@ -0,0 +1,14 @@ +/* PR tree-optimization/49352 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -ftree-vectorize -fcompare-debug" } */ + +int +foo (int *x, int *y, int n) +{ + int i, j; + int dot = 0; + for (i = 0; i < n; i++) + for (j = 0; j < 2; j++) + dot += *(x++) * *(y++); + return dot; +} Index: tree-vect-loop.c =================================================================== --- tree-vect-loop.c (revision 174981) +++ tree-vect-loop.c (working copy) @@ -1710,12 +1710,12 @@ vect_is_slp_reduction (loop_vec_info loop_info, gi struct loop *loop = (gimple_bb (phi))->loop_father; struct loop *vect_loop = LOOP_VINFO_LOOP (loop_info); enum tree_code code; - gimple current_stmt = NULL, use_stmt = NULL, first, next_stmt; + gimple current_stmt = NULL, loop_use_stmt = NULL, first, next_stmt; stmt_vec_info use_stmt_info, current_stmt_info; tree lhs; imm_use_iterator imm_iter; use_operand_p use_p; - int nloop_uses, size = 0, nuses; + int nloop_uses, size = 0; bool found = false; if (loop != vect_loop) @@ -1726,66 +1726,68 @@ vect_is_slp_reduction (loop_vec_info loop_info, gi while (1) { nloop_uses = 0; - nuses = 0; FOR_EACH_IMM_USE_FAST (use_p, imm_iter, lhs) { - use_stmt = USE_STMT (use_p); - nuses++; + gimple use_stmt = USE_STMT (use_p); if (is_gimple_debug (use_stmt)) continue; + use_stmt = USE_STMT (use_p); + /* Check if we got back to the reduction phi. */ - if (gimple_code (use_stmt) == GIMPLE_PHI - && use_stmt == phi) + if (use_stmt == phi) { + loop_use_stmt = use_stmt; found = true; break; } if (flow_bb_inside_loop_p (loop, gimple_bb (use_stmt)) && vinfo_for_stmt (use_stmt) - && !is_pattern_stmt_p (vinfo_for_stmt (use_stmt)) - && use_stmt != first_stmt) - nloop_uses++; + && !STMT_VINFO_IN_PATTERN_P (vinfo_for_stmt (use_stmt))) + { + loop_use_stmt = use_stmt; + nloop_uses++; + } if (nloop_uses > 1) return false; } - /* We reached a statement with no uses. */ - if (nuses == 0) - return false; - if (found) break; + /* We reached a statement with no loop uses. */ + if (nloop_uses == 0) + return false; + /* This is a loop exit phi, and we haven't reached the reduction phi. */ - if (gimple_code (use_stmt) == GIMPLE_PHI) + if (gimple_code (loop_use_stmt) == GIMPLE_PHI) return false; - if (!is_gimple_assign (use_stmt) - || code != gimple_assign_rhs_code (use_stmt) - || !flow_bb_inside_loop_p (loop, gimple_bb (use_stmt))) + if (!is_gimple_assign (loop_use_stmt) + || code != gimple_assign_rhs_code (loop_use_stmt) + || !flow_bb_inside_loop_p (loop, gimple_bb (loop_use_stmt))) return false; /* Insert USE_STMT into reduction chain. */ - use_stmt_info = vinfo_for_stmt (use_stmt); + use_stmt_info = vinfo_for_stmt (loop_use_stmt); if (current_stmt) { current_stmt_info = vinfo_for_stmt (current_stmt); - GROUP_NEXT_ELEMENT (current_stmt_info) = use_stmt; + GROUP_NEXT_ELEMENT (current_stmt_info) = loop_use_stmt; GROUP_FIRST_ELEMENT (use_stmt_info) = GROUP_FIRST_ELEMENT (current_stmt_info); } else - GROUP_FIRST_ELEMENT (use_stmt_info) = use_stmt; + GROUP_FIRST_ELEMENT (use_stmt_info) = loop_use_stmt; - lhs = gimple_assign_lhs (use_stmt); - current_stmt = use_stmt; + lhs = gimple_assign_lhs (loop_use_stmt); + current_stmt = loop_use_stmt; size++; } - if (!found || use_stmt != phi || size < 2) + if (!found || loop_use_stmt != phi || size < 2) return false; /* Swap the operands, if needed, to make the reduction operand be the second @@ -1794,75 +1796,70 @@ vect_is_slp_reduction (loop_vec_info loop_info, gi next_stmt = GROUP_FIRST_ELEMENT (vinfo_for_stmt (current_stmt)); while (next_stmt) { - if (get_gimple_rhs_class (code) == GIMPLE_BINARY_RHS) + if (gimple_assign_rhs2 (next_stmt) == lhs) { - if (gimple_assign_rhs2 (next_stmt) == lhs) - { - tree op = gimple_assign_rhs1 (next_stmt); - gimple def_stmt = NULL; + tree op = gimple_assign_rhs1 (next_stmt); + gimple def_stmt = NULL; - if (TREE_CODE (op) == SSA_NAME) - def_stmt = SSA_NAME_DEF_STMT (op); + if (TREE_CODE (op) == SSA_NAME) + def_stmt = SSA_NAME_DEF_STMT (op); - /* Check that the other def is either defined in the loop - ("vect_internal_def"), or it's an induction (defined by a - loop-header phi-node). */ - if (code == COND_EXPR - || (def_stmt - && flow_bb_inside_loop_p (loop, gimple_bb (def_stmt)) - && (is_gimple_assign (def_stmt) - || is_gimple_call (def_stmt) - || STMT_VINFO_DEF_TYPE (vinfo_for_stmt (def_stmt)) - == vect_induction_def - || (gimple_code (def_stmt) == GIMPLE_PHI - && STMT_VINFO_DEF_TYPE (vinfo_for_stmt (def_stmt)) + /* Check that the other def is either defined in the loop + ("vect_internal_def"), or it's an induction (defined by a + loop-header phi-node). */ + if (def_stmt + && flow_bb_inside_loop_p (loop, gimple_bb (def_stmt)) + && (is_gimple_assign (def_stmt) + || is_gimple_call (def_stmt) + || STMT_VINFO_DEF_TYPE (vinfo_for_stmt (def_stmt)) + == vect_induction_def + || (gimple_code (def_stmt) == GIMPLE_PHI + && STMT_VINFO_DEF_TYPE (vinfo_for_stmt (def_stmt)) == vect_internal_def - && !is_loop_header_bb_p (gimple_bb (def_stmt)))))) - { - lhs = gimple_assign_lhs (next_stmt); - next_stmt = GROUP_NEXT_ELEMENT (vinfo_for_stmt (next_stmt)); - continue; - } - - return false; - } - else + && !is_loop_header_bb_p (gimple_bb (def_stmt))))) { - tree op = gimple_assign_rhs2 (next_stmt); - gimple def_stmt = NULL; + lhs = gimple_assign_lhs (next_stmt); + next_stmt = GROUP_NEXT_ELEMENT (vinfo_for_stmt (next_stmt)); + continue; + } - if (TREE_CODE (op) == SSA_NAME) - def_stmt = SSA_NAME_DEF_STMT (op); + return false; + } + else + { + tree op = gimple_assign_rhs2 (next_stmt); + gimple def_stmt = NULL; - /* Check that the other def is either defined in the loop - ("vect_internal_def"), or it's an induction (defined by a - loop-header phi-node). */ - if (code == COND_EXPR - || (def_stmt - && flow_bb_inside_loop_p (loop, gimple_bb (def_stmt)) - && (is_gimple_assign (def_stmt) - || is_gimple_call (def_stmt) - || STMT_VINFO_DEF_TYPE (vinfo_for_stmt (def_stmt)) + if (TREE_CODE (op) == SSA_NAME) + def_stmt = SSA_NAME_DEF_STMT (op); + + /* Check that the other def is either defined in the loop + ("vect_internal_def"), or it's an induction (defined by a + loop-header phi-node). */ + if (def_stmt + && flow_bb_inside_loop_p (loop, gimple_bb (def_stmt)) + && (is_gimple_assign (def_stmt) + || is_gimple_call (def_stmt) + || STMT_VINFO_DEF_TYPE (vinfo_for_stmt (def_stmt)) == vect_induction_def - || (gimple_code (def_stmt) == GIMPLE_PHI - && STMT_VINFO_DEF_TYPE (vinfo_for_stmt (def_stmt)) + || (gimple_code (def_stmt) == GIMPLE_PHI + && STMT_VINFO_DEF_TYPE (vinfo_for_stmt (def_stmt)) == vect_internal_def - && !is_loop_header_bb_p (gimple_bb (def_stmt)))))) + && !is_loop_header_bb_p (gimple_bb (def_stmt))))) + { + if (vect_print_dump_info (REPORT_DETAILS)) { - if (vect_print_dump_info (REPORT_DETAILS)) - { - fprintf (vect_dump, "swapping oprnds: "); - print_gimple_stmt (vect_dump, next_stmt, 0, TDF_SLIM); - } - - swap_tree_operands (next_stmt, - gimple_assign_rhs1_ptr (next_stmt), - gimple_assign_rhs2_ptr (next_stmt)); - mark_symbols_for_renaming (next_stmt); + fprintf (vect_dump, "swapping oprnds: "); + print_gimple_stmt (vect_dump, next_stmt, 0, TDF_SLIM); } - else - return false; + + swap_tree_operands (next_stmt, + gimple_assign_rhs1_ptr (next_stmt), + gimple_assign_rhs2_ptr (next_stmt)); + mark_symbols_for_renaming (next_stmt); } + else + return false; } lhs = gimple_assign_lhs (next_stmt); @@ -2273,7 +2270,7 @@ vect_is_simple_reduction_1 (loop_vec_info loop_inf } /* Try to find SLP reduction chain. */ - if (vect_is_slp_reduction (loop_info, phi, def_stmt)) + if (check_reduction && vect_is_slp_reduction (loop_info, phi, def_stmt)) { if (vect_print_dump_info (REPORT_DETAILS)) report_vect_op (def_stmt, "reduction: detected reduction chain: ");