Commit 4a8841c0 by Richard Biener Committed by Richard Biener

tree-vect-loop.c (vect_is_simple_reduction): Simplify and allow stmts other than…

tree-vect-loop.c (vect_is_simple_reduction): Simplify and allow stmts other than GIMPLE_ASSIGN in nested cycles.

2019-10-09  Richard Biener  <rguenther@suse.de>

	* tree-vect-loop.c (vect_is_simple_reduction): Simplify and
	allow stmts other than GIMPLE_ASSIGN in nested cycles.

	* gcc.dg/vect/vect-outer-call-1.c: New testcase.

From-SVN: r276760
parent 531b0a31
2019-10-09 Richard Biener <rguenther@suse.de>
* tree-vect-loop.c (vect_is_simple_reduction): Simplify and
allow stmts other than GIMPLE_ASSIGN in nested cycles.
2019-10-08 Richard Biener <rguenther@suse.de> 2019-10-08 Richard Biener <rguenther@suse.de>
* tree-vectorizer.h (_stmt_vec_info::reduc_vectype_in): New. * tree-vectorizer.h (_stmt_vec_info::reduc_vectype_in): New.
......
2019-10-09 Richard Biener <rguenther@suse.de>
* gcc.dg/vect/vect-outer-call-1.c: New testcase.
2019-10-08 Alexandre Oliva <oliva@adacore.com> 2019-10-08 Alexandre Oliva <oliva@adacore.com>
* gcc.target/i386/20060512-1.c (sse2_test): Use a * gcc.target/i386/20060512-1.c (sse2_test): Use a
......
/* { dg-do compile } */
/* { dg-require-effective-target vect_float } */
/* { dg-additional-options "-fno-math-errno" } */
void
foo (float * __restrict x, float *y, int n, int m)
{
if (m > 0)
for (int i = 0; i < n; ++i)
{
float tem = x[i], tem1;
for (int j = 0; j < m; ++j)
{
tem += y[j];
tem1 = tem;
tem = __builtin_sqrtf (tem);
}
x[i] = tem - tem1;
}
}
/* { dg-final { scan-tree-dump "OUTER LOOP VECTORIZED" "vect" { target { vect_call_sqrtf } } } } */
...@@ -2756,10 +2756,8 @@ vect_is_simple_reduction (loop_vec_info loop_info, stmt_vec_info phi_info, ...@@ -2756,10 +2756,8 @@ vect_is_simple_reduction (loop_vec_info loop_info, stmt_vec_info phi_info,
enum tree_code orig_code, code; enum tree_code orig_code, code;
tree op1, op2, op3 = NULL_TREE, op4 = NULL_TREE; tree op1, op2, op3 = NULL_TREE, op4 = NULL_TREE;
tree type; tree type;
tree name;
imm_use_iterator imm_iter; imm_use_iterator imm_iter;
use_operand_p use_p; use_operand_p use_p;
bool phi_def;
*double_reduc = false; *double_reduc = false;
STMT_VINFO_REDUC_TYPE (phi_info) = TREE_CODE_REDUCTION; STMT_VINFO_REDUC_TYPE (phi_info) = TREE_CODE_REDUCTION;
...@@ -2791,44 +2789,24 @@ vect_is_simple_reduction (loop_vec_info loop_info, stmt_vec_info phi_info, ...@@ -2791,44 +2789,24 @@ vect_is_simple_reduction (loop_vec_info loop_info, stmt_vec_info phi_info,
phi_use_stmt = use_stmt; phi_use_stmt = use_stmt;
} }
edge latch_e = loop_latch_edge (loop); tree latch_def = PHI_ARG_DEF_FROM_EDGE (phi, loop_latch_edge (loop));
tree loop_arg = PHI_ARG_DEF_FROM_EDGE (phi, latch_e); if (TREE_CODE (latch_def) != SSA_NAME)
if (TREE_CODE (loop_arg) != SSA_NAME)
{ {
if (dump_enabled_p ()) if (dump_enabled_p ())
dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
"reduction: not ssa_name: %T\n", loop_arg); "reduction: not ssa_name: %T\n", latch_def);
return NULL; return NULL;
} }
stmt_vec_info def_stmt_info = loop_info->lookup_def (loop_arg); stmt_vec_info def_stmt_info = loop_info->lookup_def (latch_def);
if (!def_stmt_info if (!def_stmt_info
|| !flow_bb_inside_loop_p (loop, gimple_bb (def_stmt_info->stmt))) || !flow_bb_inside_loop_p (loop, gimple_bb (def_stmt_info->stmt)))
return NULL; return NULL;
if (gassign *def_stmt = dyn_cast <gassign *> (def_stmt_info->stmt))
{
name = gimple_assign_lhs (def_stmt);
phi_def = false;
}
else if (gphi *def_stmt = dyn_cast <gphi *> (def_stmt_info->stmt))
{
name = PHI_RESULT (def_stmt);
phi_def = true;
}
else
{
if (dump_enabled_p ())
dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
"reduction: unhandled reduction operation: %G",
def_stmt_info->stmt);
return NULL;
}
unsigned nlatch_def_loop_uses = 0; unsigned nlatch_def_loop_uses = 0;
auto_vec<gphi *, 3> lcphis; auto_vec<gphi *, 3> lcphis;
bool inner_loop_of_double_reduc = false; bool inner_loop_of_double_reduc = false;
FOR_EACH_IMM_USE_FAST (use_p, imm_iter, name) FOR_EACH_IMM_USE_FAST (use_p, imm_iter, latch_def)
{ {
gimple *use_stmt = USE_STMT (use_p); gimple *use_stmt = USE_STMT (use_p);
if (is_gimple_debug (use_stmt)) if (is_gimple_debug (use_stmt))
...@@ -2846,11 +2824,21 @@ vect_is_simple_reduction (loop_vec_info loop_info, stmt_vec_info phi_info, ...@@ -2846,11 +2824,21 @@ vect_is_simple_reduction (loop_vec_info loop_info, stmt_vec_info phi_info,
} }
} }
/* If we are vectorizing an inner reduction we are executing that
in the original order only in case we are not dealing with a
double reduction. */
if (nested_in_vect_loop && !inner_loop_of_double_reduc)
{
if (dump_enabled_p ())
report_vect_op (MSG_NOTE, def_stmt_info->stmt,
"detected nested cycle: ");
return def_stmt_info;
}
/* If this isn't a nested cycle or if the nested cycle reduction value /* If this isn't a nested cycle or if the nested cycle reduction value
is used ouside of the inner loop we cannot handle uses of the reduction is used ouside of the inner loop we cannot handle uses of the reduction
value. */ value. */
if ((!nested_in_vect_loop || inner_loop_of_double_reduc) if (nlatch_def_loop_uses > 1 || nphi_def_loop_uses > 1)
&& (nlatch_def_loop_uses > 1 || nphi_def_loop_uses > 1))
{ {
if (dump_enabled_p ()) if (dump_enabled_p ())
dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
...@@ -2860,9 +2848,8 @@ vect_is_simple_reduction (loop_vec_info loop_info, stmt_vec_info phi_info, ...@@ -2860,9 +2848,8 @@ vect_is_simple_reduction (loop_vec_info loop_info, stmt_vec_info phi_info,
/* If DEF_STMT is a phi node itself, we expect it to have a single argument /* If DEF_STMT is a phi node itself, we expect it to have a single argument
defined in the inner loop. */ defined in the inner loop. */
if (phi_def) if (gphi *def_stmt = dyn_cast <gphi *> (def_stmt_info->stmt))
{ {
gphi *def_stmt = as_a <gphi *> (def_stmt_info->stmt);
op1 = PHI_ARG_DEF (def_stmt, 0); op1 = PHI_ARG_DEF (def_stmt, 0);
if (gimple_phi_num_args (def_stmt) != 1 if (gimple_phi_num_args (def_stmt) != 1
...@@ -2895,35 +2882,16 @@ vect_is_simple_reduction (loop_vec_info loop_info, stmt_vec_info phi_info, ...@@ -2895,35 +2882,16 @@ vect_is_simple_reduction (loop_vec_info loop_info, stmt_vec_info phi_info,
return NULL; return NULL;
} }
/* If we are vectorizing an inner reduction we are executing that gassign *def_stmt = dyn_cast <gassign *> (def_stmt_info->stmt);
in the original order only in case we are not dealing with a if (!def_stmt)
double reduction. */
bool check_reduction = true;
if (flow_loop_nested_p (vect_loop, loop))
{
gphi *lcphi;
unsigned i;
check_reduction = false;
FOR_EACH_VEC_ELT (lcphis, i, lcphi)
FOR_EACH_IMM_USE_FAST (use_p, imm_iter, gimple_phi_result (lcphi))
{
gimple *use_stmt = USE_STMT (use_p);
if (is_gimple_debug (use_stmt))
continue;
if (! flow_bb_inside_loop_p (vect_loop, gimple_bb (use_stmt)))
check_reduction = true;
}
}
gassign *def_stmt = as_a <gassign *> (def_stmt_info->stmt);
code = orig_code = gimple_assign_rhs_code (def_stmt);
if (nested_in_vect_loop && !check_reduction)
{ {
if (dump_enabled_p ()) if (dump_enabled_p ())
report_vect_op (MSG_NOTE, def_stmt, "detected nested cycle: "); dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
return def_stmt_info; "reduction: unhandled reduction operation: %G",
def_stmt_info->stmt);
return NULL;
} }
code = orig_code = gimple_assign_rhs_code (def_stmt);
/* We can handle "res -= x[i]", which is non-associative by /* We can handle "res -= x[i]", which is non-associative by
simply rewriting this into "res += -x[i]". Avoid changing simply rewriting this into "res += -x[i]". Avoid changing
...@@ -3018,8 +2986,7 @@ vect_is_simple_reduction (loop_vec_info loop_info, stmt_vec_info phi_info, ...@@ -3018,8 +2986,7 @@ vect_is_simple_reduction (loop_vec_info loop_info, stmt_vec_info phi_info,
vectorizing an outer-loop: the inner-loop is executed sequentially, vectorizing an outer-loop: the inner-loop is executed sequentially,
and therefore vectorizing reductions in the inner-loop during and therefore vectorizing reductions in the inner-loop during
outer-loop vectorization is safe. */ outer-loop vectorization is safe. */
if (check_reduction if (STMT_VINFO_REDUC_TYPE (phi_info) == TREE_CODE_REDUCTION
&& STMT_VINFO_REDUC_TYPE (phi_info) == TREE_CODE_REDUCTION
&& needs_fold_left_reduction_p (type, code)) && needs_fold_left_reduction_p (type, code))
STMT_VINFO_REDUC_TYPE (phi_info) = FOLD_LEFT_REDUCTION; STMT_VINFO_REDUC_TYPE (phi_info) = FOLD_LEFT_REDUCTION;
...@@ -3066,9 +3033,9 @@ vect_is_simple_reduction (loop_vec_info loop_info, stmt_vec_info phi_info, ...@@ -3066,9 +3033,9 @@ vect_is_simple_reduction (loop_vec_info loop_info, stmt_vec_info phi_info,
return def_stmt_info; return def_stmt_info;
} }
/* Look for the expression computing loop_arg from loop PHI result. */ /* Look for the expression computing latch_def from loop PHI result. */
auto_vec<std::pair<ssa_op_iter, use_operand_p> > path; auto_vec<std::pair<ssa_op_iter, use_operand_p> > path;
if (check_reduction_path (vect_location, loop, phi, loop_arg, code, if (check_reduction_path (vect_location, loop, phi, latch_def, code,
path)) path))
{ {
/* Try building an SLP reduction chain for which the additional /* Try building an SLP reduction chain for which the additional
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment