diff options
author | Michael Matz <matz@suse.de> | 2012-04-17 13:54:26 +0000 |
---|---|---|
committer | Michael Matz <matz@gcc.gnu.org> | 2012-04-17 13:54:26 +0000 |
commit | 7d75abc8ea408019c1c004150bfbce42bfbffa71 (patch) | |
tree | 86bb9df647b69f4246a856e415af27fe41e37b32 /gcc/tree-vect-data-refs.c | |
parent | efa26eaae377bf2a5ce9b02b84f3963a0166e280 (diff) | |
download | gcc-7d75abc8ea408019c1c004150bfbce42bfbffa71.zip gcc-7d75abc8ea408019c1c004150bfbce42bfbffa71.tar.gz gcc-7d75abc8ea408019c1c004150bfbce42bfbffa71.tar.bz2 |
re PR tree-optimization/18437 (vectorizer failed for matrix multiplication)
PR tree-optimization/18437
* tree-vectorizer.h (_stmt_vec_info.stride_load_p): New member.
(STMT_VINFO_STRIDE_LOAD_P): New accessor.
(vect_check_strided_load): Declare.
* tree-vect-data-refs.c (vect_check_strided_load): New function.
(vect_analyze_data_refs): Use it to accept strided loads.
* tree-vect-stmts.c (vectorizable_load): Ditto and handle them.
testsuite/
* gfortran.dg/vect/rnflow-trs2a2.f90: New test.
From-SVN: r186530
Diffstat (limited to 'gcc/tree-vect-data-refs.c')
-rw-r--r-- | gcc/tree-vect-data-refs.c | 65 |
1 files changed, 60 insertions, 5 deletions
diff --git a/gcc/tree-vect-data-refs.c b/gcc/tree-vect-data-refs.c index 4d550a4..37df7ab 100644 --- a/gcc/tree-vect-data-refs.c +++ b/gcc/tree-vect-data-refs.c @@ -2690,6 +2690,53 @@ vect_check_gather (gimple stmt, loop_vec_info loop_vinfo, tree *basep, return decl; } +/* Check wether a non-affine load in STMT (being in the loop referred to + in LOOP_VINFO) is suitable for handling as strided load. That is the case + if its address is a simple induction variable. If so return the base + of that induction variable in *BASEP and the (loop-invariant) step + in *STEPP, both only when that pointer is non-zero. + + This handles ARRAY_REFs (with variant index) and MEM_REFs (with variant + base pointer) only. */ + +bool +vect_check_strided_load (gimple stmt, loop_vec_info loop_vinfo, tree *basep, + tree *stepp) +{ + struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo); + stmt_vec_info stmt_info = vinfo_for_stmt (stmt); + struct data_reference *dr = STMT_VINFO_DATA_REF (stmt_info); + tree base, off; + affine_iv iv; + + base = DR_REF (dr); + + if (TREE_CODE (base) == ARRAY_REF) + { + off = TREE_OPERAND (base, 1); + base = TREE_OPERAND (base, 0); + } + else if (TREE_CODE (base) == MEM_REF) + { + off = TREE_OPERAND (base, 0); + base = TREE_OPERAND (base, 1); + } + else + return false; + + if (TREE_CODE (off) != SSA_NAME) + return false; + + if (!expr_invariant_in_loop_p (loop, base) + || !simple_iv (loop, loop_containing_stmt (stmt), off, &iv, true)) + return false; + + if (basep) + *basep = iv.base; + if (stepp) + *stepp = iv.step; + return true; +} /* Function vect_analyze_data_refs. @@ -3090,16 +3137,21 @@ vect_analyze_data_refs (loop_vec_info loop_vinfo, VEC (ddr_p, heap) *ddrs = LOOP_VINFO_DDRS (loop_vinfo); struct data_dependence_relation *ddr, *newddr; bool bad = false; + bool strided_load = false; tree off; VEC (loop_p, heap) *nest = LOOP_VINFO_LOOP_NEST (loop_vinfo); - if (!vect_check_gather (stmt, loop_vinfo, NULL, &off, NULL) - || get_vectype_for_scalar_type (TREE_TYPE (off)) == NULL_TREE) + strided_load = vect_check_strided_load (stmt, loop_vinfo, NULL, NULL); + gather = 0 != vect_check_gather (stmt, loop_vinfo, NULL, &off, NULL); + if (gather + && get_vectype_for_scalar_type (TREE_TYPE (off)) == NULL_TREE) + gather = false; + if (!gather && !strided_load) { if (vect_print_dump_info (REPORT_UNVECTORIZED_LOCATIONS)) { fprintf (vect_dump, - "not vectorized: not suitable for gather "); + "not vectorized: not suitable for gather/strided load "); print_gimple_stmt (vect_dump, stmt, 0, TDF_SLIM); } return false; @@ -3152,13 +3204,16 @@ vect_analyze_data_refs (loop_vec_info loop_vinfo, { fprintf (vect_dump, "not vectorized: data dependence conflict" - " prevents gather"); + " prevents gather/strided load"); print_gimple_stmt (vect_dump, stmt, 0, TDF_SLIM); } return false; } - STMT_VINFO_GATHER_P (stmt_info) = true; + if (gather) + STMT_VINFO_GATHER_P (stmt_info) = true; + else if (strided_load) + STMT_VINFO_STRIDE_LOAD_P (stmt_info) = true; } } |