From 4a8841c0413d52261a8d024577381582d07a866a Mon Sep 17 00:00:00 2001 From: Richard Biener Date: Wed, 9 Oct 2019 13:36:33 +0000 Subject: [PATCH] tree-vect-loop.c (vect_is_simple_reduction): Simplify and allow stmts other than GIMPLE_ASSIGN in nested cycles. 2019-10-09 Richard Biener * 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 --- gcc/ChangeLog | 5 ++ gcc/testsuite/ChangeLog | 4 ++ gcc/testsuite/gcc.dg/vect/vect-outer-call-1.c | 22 +++++++ gcc/tree-vect-loop.c | 89 +++++++++------------------ 4 files changed, 59 insertions(+), 61 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/vect/vect-outer-call-1.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 0214310..330e13b 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,8 @@ +2019-10-09 Richard Biener + + * tree-vect-loop.c (vect_is_simple_reduction): Simplify and + allow stmts other than GIMPLE_ASSIGN in nested cycles. + 2019-10-08 Richard Biener * tree-vectorizer.h (_stmt_vec_info::reduc_vectype_in): New. diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index a1f3966..4c7dfe7 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2019-10-09 Richard Biener + + * gcc.dg/vect/vect-outer-call-1.c: New testcase. + 2019-10-08 Alexandre Oliva * gcc.target/i386/20060512-1.c (sse2_test): Use a diff --git a/gcc/testsuite/gcc.dg/vect/vect-outer-call-1.c b/gcc/testsuite/gcc.dg/vect/vect-outer-call-1.c new file mode 100644 index 0000000..f26d422 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/vect-outer-call-1.c @@ -0,0 +1,22 @@ +/* { 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 } } } } */ diff --git a/gcc/tree-vect-loop.c b/gcc/tree-vect-loop.c index a9ea0ca..1435210 100644 --- a/gcc/tree-vect-loop.c +++ b/gcc/tree-vect-loop.c @@ -2756,10 +2756,8 @@ vect_is_simple_reduction (loop_vec_info loop_info, stmt_vec_info phi_info, enum tree_code orig_code, code; tree op1, op2, op3 = NULL_TREE, op4 = NULL_TREE; tree type; - tree name; imm_use_iterator imm_iter; use_operand_p use_p; - bool phi_def; *double_reduc = false; 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, phi_use_stmt = use_stmt; } - edge latch_e = loop_latch_edge (loop); - tree loop_arg = PHI_ARG_DEF_FROM_EDGE (phi, latch_e); - if (TREE_CODE (loop_arg) != SSA_NAME) + tree latch_def = PHI_ARG_DEF_FROM_EDGE (phi, loop_latch_edge (loop)); + if (TREE_CODE (latch_def) != SSA_NAME) { if (dump_enabled_p ()) 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; } - 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 || !flow_bb_inside_loop_p (loop, gimple_bb (def_stmt_info->stmt))) return NULL; - if (gassign *def_stmt = dyn_cast (def_stmt_info->stmt)) - { - name = gimple_assign_lhs (def_stmt); - phi_def = false; - } - else if (gphi *def_stmt = dyn_cast (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; auto_vec lcphis; 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); if (is_gimple_debug (use_stmt)) @@ -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 is used ouside of the inner loop we cannot handle uses of the reduction value. */ - if ((!nested_in_vect_loop || inner_loop_of_double_reduc) - && (nlatch_def_loop_uses > 1 || nphi_def_loop_uses > 1)) + if (nlatch_def_loop_uses > 1 || nphi_def_loop_uses > 1) { if (dump_enabled_p ()) 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, /* If DEF_STMT is a phi node itself, we expect it to have a single argument defined in the inner loop. */ - if (phi_def) + if (gphi *def_stmt = dyn_cast (def_stmt_info->stmt)) { - gphi *def_stmt = as_a (def_stmt_info->stmt); op1 = PHI_ARG_DEF (def_stmt, 0); 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, return NULL; } - /* 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. */ - 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 (def_stmt_info->stmt); - code = orig_code = gimple_assign_rhs_code (def_stmt); - - if (nested_in_vect_loop && !check_reduction) + gassign *def_stmt = dyn_cast (def_stmt_info->stmt); + if (!def_stmt) { if (dump_enabled_p ()) - report_vect_op (MSG_NOTE, def_stmt, "detected nested cycle: "); - return def_stmt_info; + dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, + "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 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, vectorizing an outer-loop: the inner-loop is executed sequentially, and therefore vectorizing reductions in the inner-loop during outer-loop vectorization is safe. */ - if (check_reduction - && STMT_VINFO_REDUC_TYPE (phi_info) == TREE_CODE_REDUCTION + if (STMT_VINFO_REDUC_TYPE (phi_info) == TREE_CODE_REDUCTION && needs_fold_left_reduction_p (type, code)) 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, 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 > path; - if (check_reduction_path (vect_location, loop, phi, loop_arg, code, + if (check_reduction_path (vect_location, loop, phi, latch_def, code, path)) { /* Try building an SLP reduction chain for which the additional -- 2.7.4