===================================================================
@@ -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;
+}
===================================================================
@@ -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: ");