#
# http://gcc.gnu.org/bugzilla/show_bug.cgi?id=43430
# http://patchwork.ozlabs.org/patch/64010/
#
# patch had to be re-written because it did not apply cleanly
#
# Bug Summary: when compiling FFmpeg with -ftree-vectorizer-verbose
# certain loops are not being vectorized. This is due to the following
# comparison test in gcc/tree-vect-stmts.c:
#
# if (TREE_TYPE (TREE_OPERAND (cond_expr, 0)) != TREE_TYPE (vectype))
# return false;
#
# By replacing all the pointer equality comparisons with types_compatible_p
# comparisons, loops can now be vectorized (this is a very simplified
# description of the patch).
#
--- gcc-4.5.2/gcc/tree-vect-stmts.c 2010-11-02 05:12:56.000000000 -0700
+++ gcc-4.5.2/gcc/tree-vect-stmts.c 2013-02-12 15:35:40.852464111 -0800
@@ -4041,16 +4041,18 @@
loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
enum machine_mode vec_mode;
tree def;
- enum vect_def_type dt;
+ enum vect_def_type dt, dts[4];
int nunits = TYPE_VECTOR_SUBPARTS (vectype);
int ncopies = LOOP_VINFO_VECT_FACTOR (loop_vinfo) / nunits;
enum tree_code code;
+ stmt_vec_info prev_stmt_info = NULL;
+ int j;
/* FORNOW: unsupported in basic block SLP. */
gcc_assert (loop_vinfo);
gcc_assert (ncopies >= 1);
- if (ncopies > 1)
+ if (reduc_index && ncopies > 1)
return false; /* FORNOW */
if (!STMT_VINFO_RELEVANT_P (stmt_info))
@@ -4137,18 +4139,51 @@
vec_dest = vect_create_destination_var (scalar_dest, vectype);
/* Handle cond expr. */
+
+ for (j = 0; j < ncopies; j++)
+ {
+ gimple new_stmt;
+ if (j == 0)
+ {
+ gimple gtemp;
vec_cond_lhs =
- vect_get_vec_def_for_operand (TREE_OPERAND (cond_expr, 0), stmt, NULL);
+ vect_get_vec_def_for_operand (TREE_OPERAND (cond_expr, 0),
+ stmt, NULL);
+ vect_is_simple_use (TREE_OPERAND (cond_expr, 0), loop_vinfo,
+ NULL, &gtemp, &def, &dts[0]);
vec_cond_rhs =
- vect_get_vec_def_for_operand (TREE_OPERAND (cond_expr, 1), stmt, NULL);
+ vect_get_vec_def_for_operand (TREE_OPERAND (cond_expr, 1),
+ stmt, NULL);
+ vect_is_simple_use (TREE_OPERAND (cond_expr, 1), loop_vinfo,
+ NULL, &gtemp, &def, &dts[1]);
if (reduc_index == 1)
vec_then_clause = reduc_def;
else
- vec_then_clause = vect_get_vec_def_for_operand (then_clause, stmt, NULL);
+ {
+ vec_then_clause = vect_get_vec_def_for_operand (then_clause,
+ stmt, NULL);
+ vect_is_simple_use (then_clause, loop_vinfo,
+ NULL, &gtemp, &def, &dts[2]);
+ }
if (reduc_index == 2)
vec_else_clause = reduc_def;
else
- vec_else_clause = vect_get_vec_def_for_operand (else_clause, stmt, NULL);
+ {
+ vec_else_clause = vect_get_vec_def_for_operand (else_clause,
+ stmt, NULL);
+ vect_is_simple_use (else_clause, loop_vinfo,
+ NULL, &gtemp, &def, &dts[3]);
+ }
+ }
+ else
+ {
+ vec_cond_lhs = vect_get_vec_def_for_stmt_copy (dts[0], vec_cond_lhs);
+ vec_cond_rhs = vect_get_vec_def_for_stmt_copy (dts[1], vec_cond_rhs);
+ vec_then_clause = vect_get_vec_def_for_stmt_copy (dts[2],
+ vec_then_clause);
+ vec_else_clause = vect_get_vec_def_for_stmt_copy (dts[3],
+ vec_else_clause);
+ }
/* Arguments are ready. Create the new vector stmt. */
vec_compare = build2 (TREE_CODE (cond_expr), vectype,
@@ -4156,10 +4191,17 @@
vec_cond_expr = build3 (VEC_COND_EXPR, vectype,
vec_compare, vec_then_clause, vec_else_clause);
- *vec_stmt = gimple_build_assign (vec_dest, vec_cond_expr);
- new_temp = make_ssa_name (vec_dest, *vec_stmt);
- gimple_assign_set_lhs (*vec_stmt, new_temp);
- vect_finish_stmt_generation (stmt, *vec_stmt, gsi);
+ new_stmt = gimple_build_assign (vec_dest, vec_cond_expr);
+ new_temp = make_ssa_name (vec_dest, new_stmt);
+ gimple_assign_set_lhs (new_stmt, new_temp);
+ vect_finish_stmt_generation (stmt, new_stmt, gsi);
+ if (j == 0)
+ STMT_VINFO_VEC_STMT (stmt_info) = *vec_stmt = new_stmt;
+ else
+ STMT_VINFO_RELATED_STMT (prev_stmt_info) = new_stmt;
+
+ prev_stmt_info = vinfo_for_stmt (new_stmt);
+ }
return true;
}