On Mon, 29 Aug 2011, Richard Guenther wrote:
>
> This patch makes a conversion optab from the direct optabs vcond
> and vcondu. This allows to specify different modes for the
> actual comparison and the value that is selected.
>
> All targets but i386 are trivially converted by
> s/vcond<mode>/vcond<mode><mode>/. The i386 port is enhanced
> to support a OP b ? c : d as ({ mask = a OP b; (c & mask) | (d & ~mask);
> }), constraining it to what the middle-end constrained itself to
> (matching number of vector elements in the comparison operands with
> the result vector types) would explode patterns too much.
> Thus, only a subset of mode combinations will be excercised
> (but none at the moment - a followup will fix the vectorizer,
> and generic vectors from the C extensions have a patch pending).
>
> Bootstrapped on x86_64-unknown-linux-gnu, tests are currently
> running for {,-m32}.
>
> Ok if that succeeds?
And this is the followup implementing the auto-vectorization part.
For i386 I avoided to rewrite the vector comparison insn patterns
to allow any result mode by doing a separate conversion emitted
from ix86_expand_sse_cmp.
Bootstrap and regtest pending on x86_64-unknown-linux-gnu.
I'm considering to merge the two patches to avoid the unexcercisable
new code.
Comments? Ok?
Thanks,
Richard.
2011-08-29 Richard Guenther <[email protected]>
PR tree-optimization/27460
* gcc/config/i386/i386.c (ix86_expand_sse_cmp): Use proper mode
for the comparison.
* tree-vect-stmts.c (vect_is_simple_cond): Return the comparison
vector type.
(vectorizable_condition): Allow differing types for comparison
and result.
* gcc.dg/vect/vect-cond-7.c: New testcase.
Index: trunk/gcc/config/i386/i386.c
===================================================================
*** trunk.orig/gcc/config/i386/i386.c 2011-08-29 16:57:30.000000000 +0200
--- trunk/gcc/config/i386/i386.c 2011-08-29 17:05:32.000000000 +0200
*************** ix86_expand_sse_cmp (rtx dest, enum rtx_
*** 18412,18430 ****
rtx op_true, rtx op_false)
{
enum machine_mode mode = GET_MODE (dest);
rtx x;
! cmp_op0 = force_reg (mode, cmp_op0);
! if (!nonimmediate_operand (cmp_op1, mode))
! cmp_op1 = force_reg (mode, cmp_op1);
if (optimize
|| reg_overlap_mentioned_p (dest, op_true)
|| reg_overlap_mentioned_p (dest, op_false))
dest = gen_reg_rtx (mode);
! x = gen_rtx_fmt_ee (code, mode, cmp_op0, cmp_op1);
! emit_insn (gen_rtx_SET (VOIDmode, dest, x));
return dest;
}
--- 18412,18437 ----
rtx op_true, rtx op_false)
{
enum machine_mode mode = GET_MODE (dest);
+ enum machine_mode cmp_mode = GET_MODE (cmp_op0);
rtx x;
! cmp_op0 = force_reg (cmp_mode, cmp_op0);
! if (!nonimmediate_operand (cmp_op1, cmp_mode))
! cmp_op1 = force_reg (cmp_mode, cmp_op1);
if (optimize
|| reg_overlap_mentioned_p (dest, op_true)
|| reg_overlap_mentioned_p (dest, op_false))
dest = gen_reg_rtx (mode);
! x = gen_rtx_fmt_ee (code, cmp_mode, cmp_op0, cmp_op1);
! if (cmp_mode != mode)
! {
! x = force_reg (cmp_mode, x);
! convert_move (dest, x, false);
! }
! else
! emit_insn (gen_rtx_SET (VOIDmode, dest, x));
return dest;
}
Index: trunk/gcc/tree-vect-stmts.c
===================================================================
*** trunk.orig/gcc/tree-vect-stmts.c 2011-08-29 16:57:29.000000000 +0200
--- trunk/gcc/tree-vect-stmts.c 2011-08-29 16:57:41.000000000 +0200
*************** vectorizable_load (gimple stmt, gimple_s
*** 4680,4694 ****
LOOP - the loop that is being vectorized.
COND - Condition that is checked for simple use.
Returns whether a COND can be vectorized. Checks whether
condition operands are supportable using vec_is_simple_use. */
static bool
! vect_is_simple_cond (tree cond, loop_vec_info loop_vinfo)
{
tree lhs, rhs;
tree def;
enum vect_def_type dt;
if (!COMPARISON_CLASS_P (cond))
return false;
--- 4680,4698 ----
LOOP - the loop that is being vectorized.
COND - Condition that is checked for simple use.
+ Output:
+ *COMP_VECTYPE - the vector type for the comparison.
+
Returns whether a COND can be vectorized. Checks whether
condition operands are supportable using vec_is_simple_use. */
static bool
! vect_is_simple_cond (tree cond, loop_vec_info loop_vinfo, tree *comp_vectype)
{
tree lhs, rhs;
tree def;
enum vect_def_type dt;
+ tree vectype1 = NULL_TREE, vectype2 = NULL_TREE;
if (!COMPARISON_CLASS_P (cond))
return false;
*************** vect_is_simple_cond (tree cond, loop_vec
*** 4699,4706 ****
if (TREE_CODE (lhs) == SSA_NAME)
{
gimple lhs_def_stmt = SSA_NAME_DEF_STMT (lhs);
! if (!vect_is_simple_use (lhs, loop_vinfo, NULL, &lhs_def_stmt, &def,
! &dt))
return false;
}
else if (TREE_CODE (lhs) != INTEGER_CST && TREE_CODE (lhs) != REAL_CST
--- 4703,4710 ----
if (TREE_CODE (lhs) == SSA_NAME)
{
gimple lhs_def_stmt = SSA_NAME_DEF_STMT (lhs);
! if (!vect_is_simple_use_1 (lhs, loop_vinfo, NULL, &lhs_def_stmt, &def,
! &dt, &vectype1))
return false;
}
else if (TREE_CODE (lhs) != INTEGER_CST && TREE_CODE (lhs) != REAL_CST
*************** vect_is_simple_cond (tree cond, loop_vec
*** 4710,4723 ****
if (TREE_CODE (rhs) == SSA_NAME)
{
gimple rhs_def_stmt = SSA_NAME_DEF_STMT (rhs);
! if (!vect_is_simple_use (rhs, loop_vinfo, NULL, &rhs_def_stmt, &def,
! &dt))
return false;
}
else if (TREE_CODE (rhs) != INTEGER_CST && TREE_CODE (rhs) != REAL_CST
&& TREE_CODE (rhs) != FIXED_CST)
return false;
return true;
}
--- 4714,4728 ----
if (TREE_CODE (rhs) == SSA_NAME)
{
gimple rhs_def_stmt = SSA_NAME_DEF_STMT (rhs);
! if (!vect_is_simple_use_1 (rhs, loop_vinfo, NULL, &rhs_def_stmt, &def,
! &dt, &vectype2))
return false;
}
else if (TREE_CODE (rhs) != INTEGER_CST && TREE_CODE (rhs) != REAL_CST
&& TREE_CODE (rhs) != FIXED_CST)
return false;
+ *comp_vectype = vectype1 ? vectype1 : vectype2;
return true;
}
*************** vectorizable_condition (gimple stmt, gim
*** 4744,4749 ****
--- 4749,4755 ----
tree cond_expr, then_clause, else_clause;
stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
tree vectype = STMT_VINFO_VECTYPE (stmt_info);
+ tree comp_vectype;
tree vec_cond_lhs = NULL_TREE, vec_cond_rhs = NULL_TREE;
tree vec_then_clause = NULL_TREE, vec_else_clause = NULL_TREE;
tree vec_compare, vec_cond_expr;
*************** vectorizable_condition (gimple stmt, gim
*** 4799,4811 ****
then_clause = TREE_OPERAND (op, 1);
else_clause = TREE_OPERAND (op, 2);
! if (!vect_is_simple_cond (cond_expr, loop_vinfo))
! return false;
!
! /* We do not handle two different vector types for the condition
! and the values. */
! if (!types_compatible_p (TREE_TYPE (TREE_OPERAND (cond_expr, 0)),
! TREE_TYPE (vectype)))
return false;
if (TREE_CODE (then_clause) == SSA_NAME)
--- 4805,4812 ----
then_clause = TREE_OPERAND (op, 1);
else_clause = TREE_OPERAND (op, 2);
! if (!vect_is_simple_cond (cond_expr, loop_vinfo, &comp_vectype)
! || !comp_vectype)
return false;
if (TREE_CODE (then_clause) == SSA_NAME)
*************** vectorizable_condition (gimple stmt, gim
*** 4835,4841 ****
if (!vec_stmt)
{
STMT_VINFO_TYPE (stmt_info) = condition_vec_info_type;
! return expand_vec_cond_expr_p (vectype, vectype);
}
/* Transform */
--- 4836,4842 ----
if (!vec_stmt)
{
STMT_VINFO_TYPE (stmt_info) = condition_vec_info_type;
! return expand_vec_cond_expr_p (vectype, comp_vectype);
}
/* Transform */
Index: trunk/gcc/testsuite/gcc.dg/vect/vect-cond-7.c
===================================================================
*** /dev/null 1970-01-01 00:00:00.000000000 +0000
--- trunk/gcc/testsuite/gcc.dg/vect/vect-cond-7.c 2011-08-29
17:04:38.000000000 +0200
***************
*** 0 ****
--- 1,14 ----
+ /* { dg-do compile } */
+ /* { dg-require-effective-target vect_condition } */
+
+ int vis_type[128];
+ float vs_data[128];
+ void vis_clear_data ()
+ {
+ int i;
+ for (i = 0; i < 128; i++)
+ vs_data[i] = (vis_type[i] == 1);
+ }
+
+ /* { dg-final { scan-tree-dump "vectorized 1 loops" "vect" } } */
+ /* { dg-final { cleanup-tree-dump "vect" } } */