Add VEC_WIDEN_MULT_EVEN/ODD_EXPR

* tree.def (VEC_WIDEN_MULT_EVEN_EXPR, VEC_WIDEN_MULT_ODD_EXPR): New.
        * cfgexpand.c (expand_debug_expr): Handle them.
        * expr.c (expand_expr_real_2): Likewise.
        * fold-const.c (fold_binary_loc): Likewise.
        * gimple-pretty-print.c (dump_binary_rhs): Likewise.
        * optabs.c (optab_for_tree_code): Likewise.
        * tree-cfg.c (verify_gimple_assign_binary): Likewise.
        * tree-inline.c (estimate_operator_cost): Likewise.
        * tree-pretty-print.c (dump_generic_node): Likewise.
        * tree.c (commutative_tree_code): Likewise.
        * tree-vect-generic.c (expand_vector_operations_1): Likewise.
        Handle type change before looking up optab.
        * optabs.h (OTI_vec_widen_umult_even, OTI_vec_widen_umult_odd): New.
        (OTI_vec_widen_smult_even, OTI_vec_widen_smult_odd): New.
        (vec_widen_umult_even_optab, vec_widen_umult_odd_optab): New.
        (vec_widen_smult_even_optab, vec_widen_smult_odd_optab): New.
        * genopinit.c (optabs): Initialize them.
        * doc/md.texi: Document them.

From-SVN: r189403
This commit is contained in:
Richard Henderson 2012-07-10 01:23:39 -07:00 committed by Richard Henderson
parent e53a3e778e
commit 3f30a9a6aa
15 changed files with 124 additions and 77 deletions

View File

@ -1,3 +1,24 @@
2012-07-10 Richard Henderson <rth@redhat.com>
* tree.def (VEC_WIDEN_MULT_EVEN_EXPR, VEC_WIDEN_MULT_ODD_EXPR): New.
* cfgexpand.c (expand_debug_expr): Handle them.
* expr.c (expand_expr_real_2): Likewise.
* fold-const.c (fold_binary_loc): Likewise.
* gimple-pretty-print.c (dump_binary_rhs): Likewise.
* optabs.c (optab_for_tree_code): Likewise.
* tree-cfg.c (verify_gimple_assign_binary): Likewise.
* tree-inline.c (estimate_operator_cost): Likewise.
* tree-pretty-print.c (dump_generic_node): Likewise.
* tree.c (commutative_tree_code): Likewise.
* tree-vect-generic.c (expand_vector_operations_1): Likewise.
Handle type change before looking up optab.
* optabs.h (OTI_vec_widen_umult_even, OTI_vec_widen_umult_odd): New.
(OTI_vec_widen_smult_even, OTI_vec_widen_smult_odd): New.
(vec_widen_umult_even_optab, vec_widen_umult_odd_optab): New.
(vec_widen_smult_even_optab, vec_widen_smult_odd_optab): New.
* genopinit.c (optabs): Initialize them.
* doc/md.texi: Document them.
2012-07-10 Dehao Chen <dehao@google.com>
* tree.h (phi_arg_d): New field.

View File

@ -1,5 +1,5 @@
/* A pass for lowering trees to RTL.
Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
Free Software Foundation, Inc.
This file is part of GCC.
@ -3410,6 +3410,8 @@ expand_debug_expr (tree exp)
case VEC_UNPACK_LO_EXPR:
case VEC_WIDEN_MULT_HI_EXPR:
case VEC_WIDEN_MULT_LO_EXPR:
case VEC_WIDEN_MULT_EVEN_EXPR:
case VEC_WIDEN_MULT_ODD_EXPR:
case VEC_WIDEN_LSHIFT_HI_EXPR:
case VEC_WIDEN_LSHIFT_LO_EXPR:
case VEC_PERM_EXPR:

View File

@ -4561,15 +4561,21 @@ floating point conversion and place the resulting N/2 values of size 2*S in
the output vector (operand 0).
@cindex @code{vec_widen_umult_hi_@var{m}} instruction pattern
@cindex @code{vec_widen_umult_lo__@var{m}} instruction pattern
@cindex @code{vec_widen_umult_lo_@var{m}} instruction pattern
@cindex @code{vec_widen_smult_hi_@var{m}} instruction pattern
@cindex @code{vec_widen_smult_lo_@var{m}} instruction pattern
@cindex @code{vec_widen_umult_even_@var{m}} instruction pattern
@cindex @code{vec_widen_umult_odd_@var{m}} instruction pattern
@cindex @code{vec_widen_smult_even_@var{m}} instruction pattern
@cindex @code{vec_widen_smult_odd_@var{m}} instruction pattern
@item @samp{vec_widen_umult_hi_@var{m}}, @samp{vec_widen_umult_lo_@var{m}}
@itemx @samp{vec_widen_smult_hi_@var{m}}, @samp{vec_widen_smult_lo_@var{m}}
@itemx @samp{vec_widen_umult_even_@var{m}}, @samp{vec_widen_umult_odd_@var{m}}
@itemx @samp{vec_widen_smult_even_@var{m}}, @samp{vec_widen_smult_odd_@var{m}}
Signed/Unsigned widening multiplication. The two inputs (operands 1 and 2)
are vectors with N signed/unsigned elements of size S@. Multiply the high/low
elements of the two vectors, and put the N/2 products of size 2*S in the
output vector (operand 0).
or even/odd elements of the two vectors, and put the N/2 products of size 2*S
in the output vector (operand 0).
@cindex @code{vec_widen_ushiftl_hi_@var{m}} instruction pattern
@cindex @code{vec_widen_ushiftl_lo_@var{m}} instruction pattern

View File

@ -8917,29 +8917,15 @@ expand_expr_real_2 (sepops ops, rtx target, enum machine_mode tmode,
case VEC_WIDEN_MULT_HI_EXPR:
case VEC_WIDEN_MULT_LO_EXPR:
{
tree oprnd0 = treeop0;
tree oprnd1 = treeop1;
expand_operands (oprnd0, oprnd1, NULL_RTX, &op0, &op1, EXPAND_NORMAL);
target = expand_widen_pattern_expr (ops, op0, op1, NULL_RTX,
target, unsignedp);
gcc_assert (target);
return target;
}
case VEC_WIDEN_MULT_EVEN_EXPR:
case VEC_WIDEN_MULT_ODD_EXPR:
case VEC_WIDEN_LSHIFT_HI_EXPR:
case VEC_WIDEN_LSHIFT_LO_EXPR:
{
tree oprnd0 = treeop0;
tree oprnd1 = treeop1;
expand_operands (oprnd0, oprnd1, NULL_RTX, &op0, &op1, EXPAND_NORMAL);
target = expand_widen_pattern_expr (ops, op0, op1, NULL_RTX,
target, unsignedp);
gcc_assert (target);
return target;
}
expand_operands (treeop0, treeop1, NULL_RTX, &op0, &op1, EXPAND_NORMAL);
target = expand_widen_pattern_expr (ops, op0, op1, NULL_RTX,
target, unsignedp);
gcc_assert (target);
return target;
case VEC_PACK_TRUNC_EXPR:
case VEC_PACK_SAT_EXPR:

View File

@ -13657,8 +13657,11 @@ fold_binary_loc (location_t loc,
case VEC_WIDEN_MULT_LO_EXPR:
case VEC_WIDEN_MULT_HI_EXPR:
case VEC_WIDEN_MULT_EVEN_EXPR:
case VEC_WIDEN_MULT_ODD_EXPR:
{
unsigned int nelts = TYPE_VECTOR_SUBPARTS (type), i;
unsigned int nelts = TYPE_VECTOR_SUBPARTS (type);
unsigned int out, ofs, scale;
tree *elts;
gcc_assert (TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg0)) == nelts * 2
@ -13671,19 +13674,28 @@ fold_binary_loc (location_t loc,
|| !vec_cst_ctor_to_array (arg1, elts + nelts * 2))
return NULL_TREE;
if ((!BYTES_BIG_ENDIAN) ^ (code == VEC_WIDEN_MULT_LO_EXPR))
elts += nelts;
for (i = 0; i < nelts; i++)
if (code == VEC_WIDEN_MULT_LO_EXPR)
scale = 0, ofs = BYTES_BIG_ENDIAN ? nelts : 0;
else if (code == VEC_WIDEN_MULT_HI_EXPR)
scale = 0, ofs = BYTES_BIG_ENDIAN ? 0 : nelts;
else if (code == VEC_WIDEN_MULT_EVEN_EXPR)
scale = 1, ofs = 0;
else /* if (code == VEC_WIDEN_MULT_ODD_EXPR) */
scale = 1, ofs = 1;
for (out = 0; out < nelts; out++)
{
elts[i] = fold_convert_const (NOP_EXPR, TREE_TYPE (type), elts[i]);
elts[i + nelts * 2]
= fold_convert_const (NOP_EXPR, TREE_TYPE (type),
elts[i + nelts * 2]);
if (elts[i] == NULL_TREE || elts[i + nelts * 2] == NULL_TREE)
unsigned int in1 = (out << scale) + ofs;
unsigned int in2 = in1 + nelts * 2;
tree t1, t2;
t1 = fold_convert_const (NOP_EXPR, TREE_TYPE (type), elts[in1]);
t2 = fold_convert_const (NOP_EXPR, TREE_TYPE (type), elts[in2]);
if (t1 == NULL_TREE || t2 == NULL_TREE)
return NULL_TREE;
elts[i] = const_binop (MULT_EXPR, elts[i], elts[i + nelts * 2]);
if (elts[i] == NULL_TREE || !CONSTANT_CLASS_P (elts[i]))
elts[out] = const_binop (MULT_EXPR, t1, t2);
if (elts[out] == NULL_TREE || !CONSTANT_CLASS_P (elts[out]))
return NULL_TREE;
}

View File

@ -289,6 +289,10 @@ static const char * const optabs[] =
"set_optab_handler (vec_widen_umult_lo_optab, $A, CODE_FOR_$(vec_widen_umult_lo_$a$))",
"set_optab_handler (vec_widen_smult_hi_optab, $A, CODE_FOR_$(vec_widen_smult_hi_$a$))",
"set_optab_handler (vec_widen_smult_lo_optab, $A, CODE_FOR_$(vec_widen_smult_lo_$a$))",
"set_optab_handler (vec_widen_umult_even_optab, $A, CODE_FOR_$(vec_widen_umult_even_$a$))",
"set_optab_handler (vec_widen_umult_odd_optab, $A, CODE_FOR_$(vec_widen_umult_odd_$a$))",
"set_optab_handler (vec_widen_smult_even_optab, $A, CODE_FOR_$(vec_widen_smult_even_$a$))",
"set_optab_handler (vec_widen_smult_odd_optab, $A, CODE_FOR_$(vec_widen_smult_odd_$a$))",
"set_optab_handler (vec_widen_ushiftl_hi_optab, $A, CODE_FOR_$(vec_widen_ushiftl_hi_$a$))",
"set_optab_handler (vec_widen_ushiftl_lo_optab, $A, CODE_FOR_$(vec_widen_ushiftl_lo_$a$))",
"set_optab_handler (vec_widen_sshiftl_hi_optab, $A, CODE_FOR_$(vec_widen_sshiftl_hi_$a$))",

View File

@ -342,6 +342,8 @@ dump_binary_rhs (pretty_printer *buffer, gimple gs, int spc, int flags)
case MAX_EXPR:
case VEC_WIDEN_MULT_HI_EXPR:
case VEC_WIDEN_MULT_LO_EXPR:
case VEC_WIDEN_MULT_EVEN_EXPR:
case VEC_WIDEN_MULT_ODD_EXPR:
case VEC_PACK_TRUNC_EXPR:
case VEC_PACK_SAT_EXPR:
case VEC_PACK_FIX_TRUNC_EXPR:

View File

@ -483,6 +483,14 @@ optab_for_tree_code (enum tree_code code, const_tree type,
return TYPE_UNSIGNED (type) ?
vec_widen_umult_lo_optab : vec_widen_smult_lo_optab;
case VEC_WIDEN_MULT_EVEN_EXPR:
return TYPE_UNSIGNED (type) ?
vec_widen_umult_even_optab : vec_widen_smult_even_optab;
case VEC_WIDEN_MULT_ODD_EXPR:
return TYPE_UNSIGNED (type) ?
vec_widen_umult_odd_optab : vec_widen_smult_odd_optab;
case VEC_WIDEN_LSHIFT_HI_EXPR:
return TYPE_UNSIGNED (type) ?
vec_widen_ushiftl_hi_optab : vec_widen_sshiftl_hi_optab;

View File

@ -340,12 +340,16 @@ enum optab_index
OTI_vec_shr,
/* Extract specified elements from vectors, for vector load. */
OTI_vec_realign_load,
/* Widening multiplication.
The high/low part of the resulting vector of products is returned. */
/* Widening multiplication. The high/low/even/odd part of the
resulting vector of products is returned. */
OTI_vec_widen_umult_hi,
OTI_vec_widen_umult_lo,
OTI_vec_widen_smult_hi,
OTI_vec_widen_smult_lo,
OTI_vec_widen_umult_even,
OTI_vec_widen_umult_odd,
OTI_vec_widen_smult_even,
OTI_vec_widen_smult_odd,
/* Widening shift left.
The high/low part of the resulting vector is returned. */
OTI_vec_widen_ushiftl_hi,
@ -565,6 +569,10 @@ enum optab_index
#define vec_widen_umult_lo_optab (&optab_table[OTI_vec_widen_umult_lo])
#define vec_widen_smult_hi_optab (&optab_table[OTI_vec_widen_smult_hi])
#define vec_widen_smult_lo_optab (&optab_table[OTI_vec_widen_smult_lo])
#define vec_widen_umult_even_optab (&optab_table[OTI_vec_widen_umult_even])
#define vec_widen_umult_odd_optab (&optab_table[OTI_vec_widen_umult_odd])
#define vec_widen_smult_even_optab (&optab_table[OTI_vec_widen_smult_even])
#define vec_widen_smult_odd_optab (&optab_table[OTI_vec_widen_smult_odd])
#define vec_widen_ushiftl_hi_optab (&optab_table[OTI_vec_widen_ushiftl_hi])
#define vec_widen_ushiftl_lo_optab (&optab_table[OTI_vec_widen_ushiftl_lo])
#define vec_widen_sshiftl_hi_optab (&optab_table[OTI_vec_widen_sshiftl_hi])

View File

@ -3724,6 +3724,8 @@ do_pointer_plus_expr_check:
case WIDEN_SUM_EXPR:
case VEC_WIDEN_MULT_HI_EXPR:
case VEC_WIDEN_MULT_LO_EXPR:
case VEC_WIDEN_MULT_EVEN_EXPR:
case VEC_WIDEN_MULT_ODD_EXPR:
case VEC_PACK_TRUNC_EXPR:
case VEC_PACK_SAT_EXPR:
case VEC_PACK_FIX_TRUNC_EXPR:

View File

@ -3456,6 +3456,8 @@ estimate_operator_cost (enum tree_code code, eni_weights *weights,
case VEC_WIDEN_MULT_HI_EXPR:
case VEC_WIDEN_MULT_LO_EXPR:
case VEC_WIDEN_MULT_EVEN_EXPR:
case VEC_WIDEN_MULT_ODD_EXPR:
case VEC_UNPACK_HI_EXPR:
case VEC_UNPACK_LO_EXPR:
case VEC_UNPACK_FLOAT_HI_EXPR:

View File

@ -602,6 +602,7 @@ dump_generic_node (pretty_printer *buffer, tree node, int spc, int flags,
tree op0, op1;
const char *str;
bool is_expr;
enum tree_code code;
if (node == NULL_TREE)
return spc;
@ -614,7 +615,8 @@ dump_generic_node (pretty_printer *buffer, tree node, int spc, int flags,
if ((flags & TDF_LINENO) && EXPR_HAS_LOCATION (node))
dump_location (buffer, EXPR_LOCATION (node));
switch (TREE_CODE (node))
code = TREE_CODE (node);
switch (code)
{
case ERROR_MARK:
pp_string (buffer, "<<< error >>>");
@ -2336,31 +2338,15 @@ dump_generic_node (pretty_printer *buffer, tree node, int spc, int flags,
break;
case VEC_WIDEN_MULT_HI_EXPR:
pp_string (buffer, " VEC_WIDEN_MULT_HI_EXPR < ");
dump_generic_node (buffer, TREE_OPERAND (node, 0), spc, flags, false);
pp_string (buffer, ", ");
dump_generic_node (buffer, TREE_OPERAND (node, 1), spc, flags, false);
pp_string (buffer, " > ");
break;
case VEC_WIDEN_MULT_LO_EXPR:
pp_string (buffer, " VEC_WIDEN_MULT_LO_EXPR < ");
dump_generic_node (buffer, TREE_OPERAND (node, 0), spc, flags, false);
pp_string (buffer, ", ");
dump_generic_node (buffer, TREE_OPERAND (node, 1), spc, flags, false);
pp_string (buffer, " > ");
break;
case VEC_WIDEN_MULT_EVEN_EXPR:
case VEC_WIDEN_MULT_ODD_EXPR:
case VEC_WIDEN_LSHIFT_HI_EXPR:
pp_string (buffer, " VEC_WIDEN_LSHIFT_HI_EXPR < ");
dump_generic_node (buffer, TREE_OPERAND (node, 0), spc, flags, false);
pp_string (buffer, ", ");
dump_generic_node (buffer, TREE_OPERAND (node, 1), spc, flags, false);
pp_string (buffer, " > ");
break;
case VEC_WIDEN_LSHIFT_LO_EXPR:
pp_string (buffer, " VEC_WIDEN_LSHIFT_HI_EXPR < ");
pp_character (buffer, ' ');
for (str = tree_code_name [code]; *str; str++)
pp_character (buffer, TOUPPER (*str));
pp_string (buffer, " < ");
dump_generic_node (buffer, TREE_OPERAND (node, 0), spc, flags, false);
pp_string (buffer, ", ");
dump_generic_node (buffer, TREE_OPERAND (node, 1), spc, flags, false);

View File

@ -1361,6 +1361,23 @@ expand_vector_operations_1 (gimple_stmt_iterator *gsi)
|| code == VEC_UNPACK_FLOAT_LO_EXPR)
type = TREE_TYPE (rhs1);
/* For widening/narrowing vector operations, the relevant type is of the
arguments, not the widened result. VEC_UNPACK_FLOAT_*_EXPR is
calculated in the same way above. */
if (code == WIDEN_SUM_EXPR
|| code == VEC_WIDEN_MULT_HI_EXPR
|| code == VEC_WIDEN_MULT_LO_EXPR
|| code == VEC_WIDEN_MULT_EVEN_EXPR
|| code == VEC_WIDEN_MULT_ODD_EXPR
|| code == VEC_UNPACK_HI_EXPR
|| code == VEC_UNPACK_LO_EXPR
|| code == VEC_PACK_TRUNC_EXPR
|| code == VEC_PACK_SAT_EXPR
|| code == VEC_PACK_FIX_TRUNC_EXPR
|| code == VEC_WIDEN_LSHIFT_HI_EXPR
|| code == VEC_WIDEN_LSHIFT_LO_EXPR)
type = TREE_TYPE (rhs1);
/* Choose between vector shift/rotate by vector and vector shift/rotate by
scalar */
if (code == LSHIFT_EXPR
@ -1409,21 +1426,6 @@ expand_vector_operations_1 (gimple_stmt_iterator *gsi)
else
op = optab_for_tree_code (code, type, optab_default);
/* For widening/narrowing vector operations, the relevant type is of the
arguments, not the widened result. VEC_UNPACK_FLOAT_*_EXPR is
calculated in the same way above. */
if (code == WIDEN_SUM_EXPR
|| code == VEC_WIDEN_MULT_HI_EXPR
|| code == VEC_WIDEN_MULT_LO_EXPR
|| code == VEC_UNPACK_HI_EXPR
|| code == VEC_UNPACK_LO_EXPR
|| code == VEC_PACK_TRUNC_EXPR
|| code == VEC_PACK_SAT_EXPR
|| code == VEC_PACK_FIX_TRUNC_EXPR
|| code == VEC_WIDEN_LSHIFT_HI_EXPR
|| code == VEC_WIDEN_LSHIFT_LO_EXPR)
type = TREE_TYPE (rhs1);
/* Optabs will try converting a negation into a subtraction, so
look for it as well. TODO: negation of floating-point vectors
might be turned into an exclusive OR toggling the sign bit. */

View File

@ -6927,6 +6927,8 @@ commutative_tree_code (enum tree_code code)
case WIDEN_MULT_EXPR:
case VEC_WIDEN_MULT_HI_EXPR:
case VEC_WIDEN_MULT_LO_EXPR:
case VEC_WIDEN_MULT_EVEN_EXPR:
case VEC_WIDEN_MULT_ODD_EXPR:
return true;
default:

View File

@ -1171,6 +1171,10 @@ DEFTREECODE (VEC_RSHIFT_EXPR, "vec_rshift_expr", tcc_binary, 2)
DEFTREECODE (VEC_WIDEN_MULT_HI_EXPR, "widen_mult_hi_expr", tcc_binary, 2)
DEFTREECODE (VEC_WIDEN_MULT_LO_EXPR, "widen_mult_lo_expr", tcc_binary, 2)
/* Similarly, but return the even or odd N/2 products. */
DEFTREECODE (VEC_WIDEN_MULT_EVEN_EXPR, "widen_mult_even_expr", tcc_binary, 2)
DEFTREECODE (VEC_WIDEN_MULT_ODD_EXPR, "widen_mult_odd_expr", tcc_binary, 2)
/* Unpack (extract and promote/widen) the high/low elements of the input
vector into the output vector. The input vector has twice as many
elements as the output vector, that are half the size of the elements