diff options
-rw-r--r-- | gcc/ChangeLog | 21 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 4 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/vect/no-tree-scev-cprop-vect-iv-3.c | 27 | ||||
-rw-r--r-- | gcc/tree-vect-analyze.c | 68 | ||||
-rw-r--r-- | gcc/tree-vect-patterns.c | 4 | ||||
-rw-r--r-- | gcc/tree-vect-transform.c | 119 | ||||
-rw-r--r-- | gcc/tree-vectorizer.h | 2 |
7 files changed, 184 insertions, 61 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 5cf9903435f..d065322a2b7 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,24 @@ +2007-04-17 Dorit Nuzman <dorit@il.ibm.com> + + * tree-vectorizer.h (stmt_vec_info_type): Add enum value + induc_vec_info_type. + (vectorizable_induction): New function declaration. + * tree-vect-transform.c (get_initial_def_for_induction): No need to + check if already vectorized. Find first place in BB where new stmts + can be inserted. Takes only one argument. + (vectorizable_induction): New function. + (vect_transform_stmt): Add case for induc_vec_info_type to call + vectorizable_induction. + (vect_transform_loop): Consider phis for vectorization. + * tree-vect-analyze.c (vect_determine_vectorization_factor): Simplify + condition. + (analyze_operations): Call vectorizable_induction when analyzing phis. + Fix comment. + (vect_mark_stmts_to_be_vectorized): Remove redundant checks. + (vect_mark_relevant): Include phis in relevance analysis. + (vect_mark_stmts_to_be_vectorize): Likewise. + * tree-vect-patterns.c (widened_name_p): Remove obsolete asserts. + 2007-04-16 Lawrence Crowl <crowl@google.com> * doc/invoke.texi (Debugging Options): Add documentation for the diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 652e4cc0c94..c3d96c31fdf 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2007-04-17 Dorit Nuzman <dorit@il.ibm.com> + + * gcc.dg/vect/no-tree-scev-cprop-vect-iv-3.c: New test. + 2007-04-16 Lawrence Crowl <crowl@google.com> * g++.dg/other/fesd-any.C: Test -femit-struct-debug-detailed=any. diff --git a/gcc/testsuite/gcc.dg/vect/no-tree-scev-cprop-vect-iv-3.c b/gcc/testsuite/gcc.dg/vect/no-tree-scev-cprop-vect-iv-3.c new file mode 100644 index 00000000000..cdfaa6ff493 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/no-tree-scev-cprop-vect-iv-3.c @@ -0,0 +1,27 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target vect_int } */ + +#include <stdarg.h> +#include "tree-vect.h" + +#define N 26 + +unsigned int main1 () +{ + unsigned short i; + unsigned int intsum = 0; + + /* vectorization of reduction with induction, and widenning sum: + sum shorts into int. + Need -fno-tree-scev-cprop or else the loop is eliminated. */ + for (i = 0; i < N; i++) + { + intsum += i; + } + + return intsum; +} + +/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target vect_widen_sum_hi_to_si } } } */ +/* { dg-final { scan-tree-dump-times "vect_recog_widen_sum_pattern: detected" 1 "vect" { target vect_widen_sum_hi_to_si } } } */ +/* { dg-final { cleanup-tree-dump "vect" } } */ diff --git a/gcc/tree-vect-analyze.c b/gcc/tree-vect-analyze.c index e7dff736325..c707a025c01 100644 --- a/gcc/tree-vect-analyze.c +++ b/gcc/tree-vect-analyze.c @@ -122,13 +122,7 @@ vect_determine_vectorization_factor (loop_vec_info loop_vinfo) gcc_assert (stmt_info); - /* Two cases of "relevant" phis: those that define an - induction that is used in the loop, and those that - define a reduction. */ - if ((STMT_VINFO_RELEVANT (stmt_info) == vect_used_in_loop - && STMT_VINFO_DEF_TYPE (stmt_info) == vect_induction_def) - || (STMT_VINFO_RELEVANT (stmt_info) == vect_used_by_reduction - && STMT_VINFO_DEF_TYPE (stmt_info) == vect_reduction_def)) + if (STMT_VINFO_RELEVANT_P (stmt_info)) { gcc_assert (!STMT_VINFO_VECTYPE (stmt_info)); scalar_type = TREE_TYPE (PHI_RESULT (phi)); @@ -311,6 +305,8 @@ vect_analyze_operations (loop_vec_info loop_vinfo) for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi)) { + ok = true; + stmt_info = vinfo_for_stmt (phi); if (vect_print_dump_info (REPORT_DETAILS)) { @@ -331,15 +327,29 @@ vect_analyze_operations (loop_vec_info loop_vinfo) if (STMT_VINFO_RELEVANT (stmt_info) == vect_used_in_loop && STMT_VINFO_DEF_TYPE (stmt_info) != vect_induction_def) { - /* Most likely a reduction-like computation that is used - in the loop. */ + /* A scalar-dependence cycle that we don't support. */ if (vect_print_dump_info (REPORT_UNVECTORIZED_LOOPS)) - fprintf (vect_dump, "not vectorized: unsupported pattern."); - return false; + fprintf (vect_dump, "not vectorized: scalar dependence cycle."); + return false; } if (STMT_VINFO_RELEVANT_P (stmt_info)) - need_to_vectorize = true; + { + need_to_vectorize = true; + if (STMT_VINFO_DEF_TYPE (stmt_info) == vect_induction_def) + ok = vectorizable_induction (phi, NULL, NULL); + } + + if (!ok) + { + if (vect_print_dump_info (REPORT_UNVECTORIZED_LOOPS)) + { + fprintf (vect_dump, + "not vectorized: relevant phi not supported: "); + print_generic_expr (vect_dump, phi, TDF_SLIM); + } + return false; + } } for (si = bsi_start (bb); !bsi_end_p (si); bsi_next (&si)) @@ -2106,11 +2116,6 @@ vect_mark_relevant (VEC(tree,heap) **worklist, tree stmt, if (relevant > STMT_VINFO_RELEVANT (stmt_info)) STMT_VINFO_RELEVANT (stmt_info) = relevant; - if (TREE_CODE (stmt) == PHI_NODE) - /* Don't put phi-nodes in the worklist. Phis that are marked relevant - or live will fail vectorization later on. */ - return; - if (STMT_VINFO_RELEVANT (stmt_info) == save_relevant && STMT_VINFO_LIVE_P (stmt_info) == save_live_p) { @@ -2228,27 +2233,23 @@ vect_mark_stmts_to_be_vectorized (loop_vec_info loop_vinfo) worklist = VEC_alloc (tree, heap, 64); /* 1. Init worklist. */ - - bb = loop->header; - for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi)) - { - if (vect_print_dump_info (REPORT_DETAILS)) - { - fprintf (vect_dump, "init: phi relevant? "); - print_generic_expr (vect_dump, phi, TDF_SLIM); - } - - if (vect_stmt_relevant_p (phi, loop_vinfo, &relevant, &live_p)) - vect_mark_relevant (&worklist, phi, relevant, live_p); - } - for (i = 0; i < nbbs; i++) { bb = bbs[i]; + for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi)) + { + if (vect_print_dump_info (REPORT_DETAILS)) + { + fprintf (vect_dump, "init: phi relevant? "); + print_generic_expr (vect_dump, phi, TDF_SLIM); + } + + if (vect_stmt_relevant_p (phi, loop_vinfo, &relevant, &live_p)) + vect_mark_relevant (&worklist, phi, relevant, live_p); + } for (si = bsi_start (bb); !bsi_end_p (si); bsi_next (&si)) { stmt = bsi_stmt (si); - if (vect_print_dump_info (REPORT_DETAILS)) { fprintf (vect_dump, "init: stmt relevant? "); @@ -2279,8 +2280,6 @@ vect_mark_stmts_to_be_vectorized (loop_vec_info loop_vinfo) relevance properties of STMT. */ - gcc_assert (TREE_CODE (stmt) != PHI_NODE); - ann = stmt_ann (stmt); stmt_vinfo = vinfo_for_stmt (stmt); @@ -2318,7 +2317,6 @@ vect_mark_stmts_to_be_vectorized (loop_vec_info loop_vinfo) /* case 2.2: */ if (STMT_VINFO_DEF_TYPE (stmt_vinfo) == vect_reduction_def) { - gcc_assert (relevant == vect_unused_in_loop && live_p); relevant = vect_used_by_reduction; live_p = false; } diff --git a/gcc/tree-vect-patterns.c b/gcc/tree-vect-patterns.c index 63255bd3fb1..5773344abc5 100644 --- a/gcc/tree-vect-patterns.c +++ b/gcc/tree-vect-patterns.c @@ -109,10 +109,6 @@ widened_name_p (tree name, tree use_stmt, tree *half_type, tree *def_stmt) if (!vect_is_simple_use (oprnd0, loop_vinfo, &dummy, &dummy, &dt)) return false; - if (dt != vect_invariant_def && dt != vect_constant_def - && dt != vect_loop_def) - return false; - return true; } diff --git a/gcc/tree-vect-transform.c b/gcc/tree-vect-transform.c index 32fe626180c..a00ecdc3d6b 100644 --- a/gcc/tree-vect-transform.c +++ b/gcc/tree-vect-transform.c @@ -514,7 +514,6 @@ vect_init_vector (tree stmt, tree vector_var, tree vector_type) /* Function get_initial_def_for_induction Input: - STMT - a stmt that performs an induction operation in the loop. IV_PHI - the initial value of the induction variable Output: @@ -524,9 +523,9 @@ vect_init_vector (tree stmt, tree vector_var, tree vector_type) [X, X + S, X + 2*S, X + 3*S]. */ static tree -get_initial_def_for_induction (tree stmt, tree iv_phi) +get_initial_def_for_induction (tree iv_phi) { - stmt_vec_info stmt_vinfo = vinfo_for_stmt (stmt); + stmt_vec_info stmt_vinfo = vinfo_for_stmt (iv_phi); loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_vinfo); struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo); tree scalar_type = TREE_TYPE (iv_phi); @@ -549,27 +548,17 @@ get_initial_def_for_induction (tree stmt, tree iv_phi) tree expr; stmt_vec_info phi_info = vinfo_for_stmt (iv_phi); tree stmts; + tree stmt = NULL_TREE; + block_stmt_iterator si; + basic_block bb = bb_for_stmt (iv_phi); gcc_assert (phi_info); + gcc_assert (ncopies >= 1); - if (STMT_VINFO_VEC_STMT (phi_info)) - { - induction_phi = STMT_VINFO_VEC_STMT (phi_info); - gcc_assert (TREE_CODE (induction_phi) == PHI_NODE); - - if (vect_print_dump_info (REPORT_DETAILS)) - { - fprintf (vect_dump, "induction already vectorized:"); - print_generic_expr (vect_dump, iv_phi, TDF_SLIM); - fprintf (vect_dump, "\n"); - print_generic_expr (vect_dump, induction_phi, TDF_SLIM); - } - - return PHI_RESULT (induction_phi); - } + /* Find the first insertion point in the BB. */ + si = bsi_after_labels (bb); + stmt = bsi_stmt (si); - gcc_assert (ncopies >= 1); - access_fn = analyze_scalar_evolution (loop, PHI_RESULT (iv_phi)); gcc_assert (access_fn); ok = vect_is_simple_iv_evolution (loop->num, access_fn, &init_expr, &step_expr); @@ -833,7 +822,7 @@ vect_get_vec_def_for_operand (tree op, tree stmt, tree *scalar_def) gcc_assert (TREE_CODE (def_stmt) == PHI_NODE); /* Get the def before the loop */ - return get_initial_def_for_induction (stmt, def_stmt); + return get_initial_def_for_induction (def_stmt); } default: @@ -2233,6 +2222,59 @@ vect_min_worthwhile_factor (enum tree_code code) } +/* Function vectorizable_induction + + Check if PHI performs an induction computation that can be vectorized. + If VEC_STMT is also passed, vectorize the induction PHI: create a vectorized + phi to replace it, put it in VEC_STMT, and add it to the same basic block. + Return FALSE if not a vectorizable STMT, TRUE otherwise. */ + +bool +vectorizable_induction (tree phi, block_stmt_iterator *bsi ATTRIBUTE_UNUSED, + tree *vec_stmt) +{ + stmt_vec_info stmt_info = vinfo_for_stmt (phi); + tree vectype = STMT_VINFO_VECTYPE (stmt_info); + loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info); + int nunits = TYPE_VECTOR_SUBPARTS (vectype); + int ncopies = LOOP_VINFO_VECT_FACTOR (loop_vinfo) / nunits; + tree vec_def; + + gcc_assert (ncopies >= 1); + + if (!STMT_VINFO_RELEVANT_P (stmt_info)) + return false; + + gcc_assert (STMT_VINFO_DEF_TYPE (stmt_info) == vect_induction_def); + + if (STMT_VINFO_LIVE_P (stmt_info)) + { + /* FORNOW: not yet supported. */ + if (vect_print_dump_info (REPORT_DETAILS)) + fprintf (vect_dump, "value used after loop."); + return false; + } + + if (TREE_CODE (phi) != PHI_NODE) + return false; + + if (!vec_stmt) /* transformation not required. */ + { + STMT_VINFO_TYPE (stmt_info) = induc_vec_info_type; + return true; + } + + /** Transform. **/ + + if (vect_print_dump_info (REPORT_DETAILS)) + fprintf (vect_dump, "transform induction phi."); + + vec_def = get_initial_def_for_induction (phi); + *vec_stmt = SSA_NAME_DEF_STMT (vec_def); + return true; +} + + /* Function vectorizable_operation. Check if STMT performs a binary or unary operation that can be vectorized. @@ -4285,6 +4327,11 @@ vect_transform_stmt (tree stmt, block_stmt_iterator *bsi, bool *strided_store) gcc_assert (done); break; + case induc_vec_info_type: + done = vectorizable_induction (stmt, bsi, &vec_stmt); + gcc_assert (done); + break; + case op_vec_info_type: done = vectorizable_operation (stmt, bsi, &vec_stmt); gcc_assert (done); @@ -5192,11 +5239,39 @@ vect_transform_loop (loop_vec_info loop_vinfo) for (i = 0; i < nbbs; i++) { basic_block bb = bbs[i]; + stmt_vec_info stmt_info; + tree phi; + + for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi)) + { + if (vect_print_dump_info (REPORT_DETAILS)) + { + fprintf (vect_dump, "------>vectorizing phi: "); + print_generic_expr (vect_dump, phi, TDF_SLIM); + } + stmt_info = vinfo_for_stmt (phi); + if (!stmt_info) + continue; + if (!STMT_VINFO_RELEVANT_P (stmt_info) + && !STMT_VINFO_LIVE_P (stmt_info)) + continue; + + if ((TYPE_VECTOR_SUBPARTS (STMT_VINFO_VECTYPE (stmt_info)) + != (unsigned HOST_WIDE_INT) vectorization_factor) + && vect_print_dump_info (REPORT_DETAILS)) + fprintf (vect_dump, "multiple-types."); + + if (STMT_VINFO_DEF_TYPE (stmt_info) == vect_induction_def) + { + if (vect_print_dump_info (REPORT_DETAILS)) + fprintf (vect_dump, "transform phi."); + vect_transform_stmt (phi, NULL, NULL); + } + } for (si = bsi_start (bb); !bsi_end_p (si);) { tree stmt = bsi_stmt (si); - stmt_vec_info stmt_info; bool is_store; if (vect_print_dump_info (REPORT_DETAILS)) diff --git a/gcc/tree-vectorizer.h b/gcc/tree-vectorizer.h index 4f0e7b95e82..3d418a92304 100644 --- a/gcc/tree-vectorizer.h +++ b/gcc/tree-vectorizer.h @@ -167,6 +167,7 @@ enum stmt_vec_info_type { assignment_vec_info_type, condition_vec_info_type, reduc_vec_info_type, + induc_vec_info_type, type_promotion_vec_info_type, type_demotion_vec_info_type, type_conversion_vec_info_type @@ -428,6 +429,7 @@ extern bool vectorizable_call (tree, block_stmt_iterator *, tree *); extern bool vectorizable_condition (tree, block_stmt_iterator *, tree *); extern bool vectorizable_live_operation (tree, block_stmt_iterator *, tree *); extern bool vectorizable_reduction (tree, block_stmt_iterator *, tree *); +extern bool vectorizable_induction (tree, block_stmt_iterator *, tree *); /* Driver for transformation stage. */ extern void vect_transform_loop (loop_vec_info); |