aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree-vect-stmts.c
diff options
context:
space:
mode:
authorIlya Enkovich <ilya.enkovich@intel.com>2016-06-22 14:05:55 +0000
committerIlya Enkovich <ienkovich@gcc.gnu.org>2016-06-22 14:05:55 +0000
commit49e76ff114c94634f01ec0e2406b9ece7d58ce2d (patch)
treec1a0b13225e17bbb58b4370baf22278fd1c0ffec /gcc/tree-vect-stmts.c
parent79c94ff7965fe8b8615b77fbaacdce73c0f37b4a (diff)
downloadgcc-49e76ff114c94634f01ec0e2406b9ece7d58ce2d.zip
gcc-49e76ff114c94634f01ec0e2406b9ece7d58ce2d.tar.gz
gcc-49e76ff114c94634f01ec0e2406b9ece7d58ce2d.tar.bz2
re PR tree-optimization/71488 (Wrong code for vector comparisons with ivybridge and westmere targets)
gcc/ PR middle-end/71488 * tree-vect-patterns.c (vect_recog_mask_conversion_pattern): Support comparison of boolean vectors. * tree-vect-stmts.c (vectorizable_comparison): Vectorize comparison of boolean vectors using bitwise operations. gcc/testsuite/ PR middle-end/71488 * g++.dg/pr71488.C: New test. * gcc.dg/vect/vect-bool-cmp.c: New test. From-SVN: r237706
Diffstat (limited to 'gcc/tree-vect-stmts.c')
-rw-r--r--gcc/tree-vect-stmts.c96
1 files changed, 91 insertions, 5 deletions
diff --git a/gcc/tree-vect-stmts.c b/gcc/tree-vect-stmts.c
index c74f14f..5c65502 100644
--- a/gcc/tree-vect-stmts.c
+++ b/gcc/tree-vect-stmts.c
@@ -7756,7 +7756,7 @@ vectorizable_comparison (gimple *stmt, gimple_stmt_iterator *gsi,
enum vect_def_type dts[2] = {vect_unknown_def_type, vect_unknown_def_type};
unsigned nunits;
int ncopies;
- enum tree_code code;
+ enum tree_code code, bitop1 = NOP_EXPR, bitop2 = NOP_EXPR;
stmt_vec_info prev_stmt_info = NULL;
int i, j;
bb_vec_info bb_vinfo = STMT_VINFO_BB_VINFO (stmt_info);
@@ -7829,11 +7829,74 @@ vectorizable_comparison (gimple *stmt, gimple_stmt_iterator *gsi,
else if (nunits != TYPE_VECTOR_SUBPARTS (vectype))
return false;
+ /* Can't compare mask and non-mask types. */
+ if (vectype1 && vectype2
+ && (VECTOR_BOOLEAN_TYPE_P (vectype1) ^ VECTOR_BOOLEAN_TYPE_P (vectype2)))
+ return false;
+
+ /* Boolean values may have another representation in vectors
+ and therefore we prefer bit operations over comparison for
+ them (which also works for scalar masks). We store opcodes
+ to use in bitop1 and bitop2. Statement is vectorized as
+ BITOP2 (rhs1 BITOP1 rhs2) or
+ rhs1 BITOP2 (BITOP1 rhs2)
+ depending on bitop1 and bitop2 arity. */
+ if (VECTOR_BOOLEAN_TYPE_P (vectype))
+ {
+ if (code == GT_EXPR)
+ {
+ bitop1 = BIT_NOT_EXPR;
+ bitop2 = BIT_AND_EXPR;
+ }
+ else if (code == GE_EXPR)
+ {
+ bitop1 = BIT_NOT_EXPR;
+ bitop2 = BIT_IOR_EXPR;
+ }
+ else if (code == LT_EXPR)
+ {
+ bitop1 = BIT_NOT_EXPR;
+ bitop2 = BIT_AND_EXPR;
+ std::swap (rhs1, rhs2);
+ }
+ else if (code == LE_EXPR)
+ {
+ bitop1 = BIT_NOT_EXPR;
+ bitop2 = BIT_IOR_EXPR;
+ std::swap (rhs1, rhs2);
+ }
+ else
+ {
+ bitop1 = BIT_XOR_EXPR;
+ if (code == EQ_EXPR)
+ bitop2 = BIT_NOT_EXPR;
+ }
+ }
+
if (!vec_stmt)
{
STMT_VINFO_TYPE (stmt_info) = comparison_vec_info_type;
- vect_model_simple_cost (stmt_info, ncopies, dts, NULL, NULL);
- return expand_vec_cmp_expr_p (vectype, mask_type);
+ vect_model_simple_cost (stmt_info, ncopies * (1 + (bitop2 != NOP_EXPR)),
+ dts, NULL, NULL);
+ if (bitop1 == NOP_EXPR)
+ return expand_vec_cmp_expr_p (vectype, mask_type);
+ else
+ {
+ machine_mode mode = TYPE_MODE (vectype);
+ optab optab;
+
+ optab = optab_for_tree_code (bitop1, vectype, optab_default);
+ if (!optab || optab_handler (optab, mode) == CODE_FOR_nothing)
+ return false;
+
+ if (bitop2 != NOP_EXPR)
+ {
+ optab = optab_for_tree_code (bitop2, vectype, optab_default);
+ if (!optab || optab_handler (optab, mode) == CODE_FOR_nothing)
+ return false;
+ }
+ return true;
+ }
}
/* Transform. */
@@ -7890,8 +7953,31 @@ vectorizable_comparison (gimple *stmt, gimple_stmt_iterator *gsi,
vec_rhs2 = vec_oprnds1[i];
new_temp = make_ssa_name (mask);
- new_stmt = gimple_build_assign (new_temp, code, vec_rhs1, vec_rhs2);
- vect_finish_stmt_generation (stmt, new_stmt, gsi);
+ if (bitop1 == NOP_EXPR)
+ {
+ new_stmt = gimple_build_assign (new_temp, code,
+ vec_rhs1, vec_rhs2);
+ vect_finish_stmt_generation (stmt, new_stmt, gsi);
+ }
+ else
+ {
+ if (bitop1 == BIT_NOT_EXPR)
+ new_stmt = gimple_build_assign (new_temp, bitop1, vec_rhs2);
+ else
+ new_stmt = gimple_build_assign (new_temp, bitop1, vec_rhs1,
+ vec_rhs2);
+ vect_finish_stmt_generation (stmt, new_stmt, gsi);
+ if (bitop2 != NOP_EXPR)
+ {
+ tree res = make_ssa_name (mask);
+ if (bitop2 == BIT_NOT_EXPR)
+ new_stmt = gimple_build_assign (res, bitop2, new_temp);
+ else
+ new_stmt = gimple_build_assign (res, bitop2, vec_rhs1,
+ new_temp);
+ vect_finish_stmt_generation (stmt, new_stmt, gsi);
+ }
+ }
if (slp_node)
SLP_TREE_VEC_STMTS (slp_node).quick_push (new_stmt);
}