aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree-vect-data-refs.c
diff options
context:
space:
mode:
authorMichael Matz <matz@suse.de>2012-04-17 13:54:26 +0000
committerMichael Matz <matz@gcc.gnu.org>2012-04-17 13:54:26 +0000
commit7d75abc8ea408019c1c004150bfbce42bfbffa71 (patch)
tree86bb9df647b69f4246a856e415af27fe41e37b32 /gcc/tree-vect-data-refs.c
parentefa26eaae377bf2a5ce9b02b84f3963a0166e280 (diff)
downloadgcc-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.c65
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;
}
}