* tree.def (VEC_EXTRACT_EVEN_EXPR, VEC_EXTRACT_ODD_EXPR): Remove.
* cfgexpand.c (expand_debug_expr): Don't handle them.
* expr.c (expand_expr_real_2): Likewise.
* fold-const.c (fold_binary_loc): Likewise.
* gimple-pretty-print.c (dump_binary_rhs): 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-vect-generic.c (expand_vector_operations_1): Likewise.
* optabs.c (optab_for_tree_code): Likewise.
(can_vec_perm_for_code_p): Remove.
(expand_binop): Don't try it.
(init_optabs): Don't init vec_extract_even/odd_optab.
* genopinit.c (optabs): Likewise.
* optabs.h (OTI_vec_extract_even, OTI_vec_extract_odd): Remove.
(vec_extract_even_optab, vec_extract_odd_optab): Remove.
* tree-vect-data-refs.c (vect_strided_store_supported): Tidy code.
(vect_permute_store_chain): Use TYPE_VECTOR_SUBPARTS instead of
GET_MODE_NUNITS; check vect_gen_perm_mask return value instead of
asserting vect_strided_store_supported.
(vect_strided_load_supported): Use can_vec_perm_p.
(vect_permute_load_chain): Use VEC_PERM_EXPR.
* doc/generic.texi (VEC_EXTRACT_EVEN_EXPR): Remove.
(VEC_EXTRACT_ODD_EXPR): Remove.
* doc/md.texi (vec_extract_even, vec_extract_odd): Remove.
From-SVN: r182669
+2011-12-23 Richard Henderson <rth@redhat.com>
+
+ * tree.def (VEC_EXTRACT_EVEN_EXPR, VEC_EXTRACT_ODD_EXPR): Remove.
+ * cfgexpand.c (expand_debug_expr): Don't handle them.
+ * expr.c (expand_expr_real_2): Likewise.
+ * fold-const.c (fold_binary_loc): Likewise.
+ * gimple-pretty-print.c (dump_binary_rhs): 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-vect-generic.c (expand_vector_operations_1): Likewise.
+ * optabs.c (optab_for_tree_code): Likewise.
+ (can_vec_perm_for_code_p): Remove.
+ (expand_binop): Don't try it.
+ (init_optabs): Don't init vec_extract_even/odd_optab.
+ * genopinit.c (optabs): Likewise.
+ * optabs.h (OTI_vec_extract_even, OTI_vec_extract_odd): Remove.
+ (vec_extract_even_optab, vec_extract_odd_optab): Remove.
+ * tree-vect-data-refs.c (vect_strided_store_supported): Tidy code.
+ (vect_permute_store_chain): Use TYPE_VECTOR_SUBPARTS instead of
+ GET_MODE_NUNITS; check vect_gen_perm_mask return value instead of
+ asserting vect_strided_store_supported.
+ (vect_strided_load_supported): Use can_vec_perm_p.
+ (vect_permute_load_chain): Use VEC_PERM_EXPR.
+
+ * doc/generic.texi (VEC_EXTRACT_EVEN_EXPR): Remove.
+ (VEC_EXTRACT_ODD_EXPR): Remove.
+ * doc/md.texi (vec_extract_even, vec_extract_odd): Remove.
+
2011-12-23 Anatoly Sokolov <aesok@post.ru>
* config/score/score.h (REGISTER_MOVE_COST, MEMORY_MOVE_COST): Remove.
case REDUC_MIN_EXPR:
case REDUC_PLUS_EXPR:
case VEC_COND_EXPR:
- case VEC_EXTRACT_EVEN_EXPR:
- case VEC_EXTRACT_ODD_EXPR:
case VEC_LSHIFT_EXPR:
case VEC_PACK_FIX_TRUNC_EXPR:
case VEC_PACK_SAT_EXPR:
@tindex VEC_PACK_TRUNC_EXPR
@tindex VEC_PACK_SAT_EXPR
@tindex VEC_PACK_FIX_TRUNC_EXPR
-@tindex VEC_EXTRACT_EVEN_EXPR
-@tindex VEC_EXTRACT_ODD_EXPR
@table @code
@item VEC_LSHIFT_EXPR
twice as many elements of an integral type whose size is half as wide. The
elements of the two vectors are merged (concatenated) to form the output
vector.
-
-@item VEC_EXTRACT_EVEN_EXPR
-@itemx VEC_EXTRACT_ODD_EXPR
-These nodes represent extracting of the even/odd elements of the two input
-vectors, respectively. Their operands and result are vectors that contain the
-same number of elements of the same type.
-
@end table
Extract given field from the vector value. Operand 1 is the vector, operand 2
specify field index and operand 0 place to store value into.
-@cindex @code{vec_extract_even@var{m}} instruction pattern
-@item @samp{vec_extract_even@var{m}}
-Extract even elements from the input vectors (operand 1 and operand 2).
-The even elements of operand 2 are concatenated to the even elements of operand
-1 in their original order. The result is stored in operand 0.
-The output and input vectors should have the same modes.
-
-@cindex @code{vec_extract_odd@var{m}} instruction pattern
-@item @samp{vec_extract_odd@var{m}}
-Extract odd elements from the input vectors (operand 1 and operand 2).
-The odd elements of operand 2 are concatenated to the odd elements of operand
-1 in their original order. The result is stored in operand 0.
-The output and input vectors should have the same modes.
-
@cindex @code{vec_init@var{m}} instruction pattern
@item @samp{vec_init@var{m}}
Initialize the vector to given values. Operand 0 is the vector to initialize
return temp;
}
- case VEC_EXTRACT_EVEN_EXPR:
- case VEC_EXTRACT_ODD_EXPR:
- goto binop;
-
case VEC_LSHIFT_EXPR:
case VEC_RSHIFT_EXPR:
{
/* An ASSERT_EXPR should never be passed to fold_binary. */
gcc_unreachable ();
- case VEC_EXTRACT_EVEN_EXPR:
- case VEC_EXTRACT_ODD_EXPR:
- if ((TREE_CODE (arg0) == VECTOR_CST
- || TREE_CODE (arg0) == CONSTRUCTOR)
- && (TREE_CODE (arg1) == VECTOR_CST
- || TREE_CODE (arg1) == CONSTRUCTOR))
- {
- unsigned int nelts = TYPE_VECTOR_SUBPARTS (type), i;
- unsigned char *sel = XALLOCAVEC (unsigned char, nelts);
-
- for (i = 0; i < nelts; i++)
- switch (code)
- {
- case VEC_EXTRACT_EVEN_EXPR:
- sel[i] = i * 2;
- break;
- case VEC_EXTRACT_ODD_EXPR:
- sel[i] = i * 2 + 1;
- break;
- default:
- gcc_unreachable ();
- }
-
- return fold_vec_perm (type, arg0, arg1, sel);
- }
- return NULL_TREE;
-
case VEC_PACK_TRUNC_EXPR:
case VEC_PACK_FIX_TRUNC_EXPR:
{
"set_direct_optab_handler (atomic_or_optab, $A, CODE_FOR_$(atomic_or$I$a$))",
"set_optab_handler (vec_set_optab, $A, CODE_FOR_$(vec_set$a$))",
"set_optab_handler (vec_extract_optab, $A, CODE_FOR_$(vec_extract$a$))",
- "set_optab_handler (vec_extract_even_optab, $A, CODE_FOR_$(vec_extract_even$a$))",
- "set_optab_handler (vec_extract_odd_optab, $A, CODE_FOR_$(vec_extract_odd$a$))",
"set_optab_handler (vec_init_optab, $A, CODE_FOR_$(vec_init$a$))",
"set_optab_handler (vec_shl_optab, $A, CODE_FOR_$(vec_shl_$a$))",
"set_optab_handler (vec_shr_optab, $A, CODE_FOR_$(vec_shr_$a$))",
case VEC_PACK_TRUNC_EXPR:
case VEC_PACK_SAT_EXPR:
case VEC_PACK_FIX_TRUNC_EXPR:
- case VEC_EXTRACT_EVEN_EXPR:
- case VEC_EXTRACT_ODD_EXPR:
case VEC_WIDEN_LSHIFT_HI_EXPR:
case VEC_WIDEN_LSHIFT_LO_EXPR:
for (p = tree_code_name [(int) code]; *p; p++)
case ABS_EXPR:
return trapv ? absv_optab : abs_optab;
- case VEC_EXTRACT_EVEN_EXPR:
- return vec_extract_even_optab;
-
- case VEC_EXTRACT_ODD_EXPR:
- return vec_extract_odd_optab;
-
default:
return NULL;
}
}
}
- /* Certain vector operations can be implemented with vector permutation. */
- if (VECTOR_MODE_P (mode))
- {
- enum tree_code tcode = ERROR_MARK;
- rtx sel;
-
- if (binoptab == vec_extract_even_optab)
- tcode = VEC_EXTRACT_EVEN_EXPR;
- else if (binoptab == vec_extract_odd_optab)
- tcode = VEC_EXTRACT_ODD_EXPR;
-
- if (tcode != ERROR_MARK
- && can_vec_perm_for_code_p (tcode, mode, &sel))
- {
- temp = expand_vec_perm (mode, op0, op1, sel, target);
- gcc_assert (temp != NULL);
- return temp;
- }
- }
-
/* Look for a wider mode of the same class for which we think we
can open-code the operation. Check for a widening multiply at the
wider mode as well. */
init_optab (udot_prod_optab, UNKNOWN);
init_optab (vec_extract_optab, UNKNOWN);
- init_optab (vec_extract_even_optab, UNKNOWN);
- init_optab (vec_extract_odd_optab, UNKNOWN);
init_optab (vec_set_optab, UNKNOWN);
init_optab (vec_init_optab, UNKNOWN);
init_optab (vec_shl_optab, UNKNOWN);
return true;
}
-/* Return true if we can implement with VEC_PERM_EXPR for this target.
- If PSEL is non-null, return the selector for the permutation. */
-
-bool
-can_vec_perm_for_code_p (enum tree_code code, enum machine_mode mode,
- rtx *psel)
-{
- bool need_sel_test = false;
- enum insn_code icode;
-
- /* If the target doesn't implement a vector mode for the vector type,
- then no operations are supported. */
- if (!VECTOR_MODE_P (mode))
- return false;
-
- /* Do as many tests as possible without reqiring the selector. */
- icode = direct_optab_handler (vec_perm_optab, mode);
- if (icode == CODE_FOR_nothing && GET_MODE_INNER (mode) != QImode)
- {
- enum machine_mode qimode
- = mode_for_vector (QImode, GET_MODE_SIZE (mode));
- if (VECTOR_MODE_P (qimode))
- icode = direct_optab_handler (vec_perm_optab, qimode);
- }
- if (icode == CODE_FOR_nothing)
- {
- icode = direct_optab_handler (vec_perm_const_optab, mode);
- if (icode != CODE_FOR_nothing
- && targetm.vectorize.vec_perm_const_ok != NULL)
- need_sel_test = true;
- }
- if (icode == CODE_FOR_nothing)
- return false;
-
- /* If the selector is required, or if we need to test it, build it. */
- if (psel || need_sel_test)
- {
- int i, nelt = GET_MODE_NUNITS (mode), alt = 0;
- unsigned char *data = XALLOCAVEC (unsigned char, nelt);
-
- switch (code)
- {
- case VEC_EXTRACT_ODD_EXPR:
- alt = 1;
- /* FALLTHRU */
- case VEC_EXTRACT_EVEN_EXPR:
- for (i = 0; i < nelt; ++i)
- data[i] = i * 2 + alt;
- break;
-
- default:
- gcc_unreachable ();
- }
-
- if (need_sel_test
- && !targetm.vectorize.vec_perm_const_ok (mode, data))
- return false;
-
- if (psel)
- {
- rtvec vec = rtvec_alloc (nelt);
- enum machine_mode imode = mode;
-
- for (i = 0; i < nelt; ++i)
- RTVEC_ELT (vec, i) = GEN_INT (data[i]);
-
- if (GET_MODE_CLASS (mode) != MODE_VECTOR_INT)
- {
- imode = int_mode_for_mode (GET_MODE_INNER (mode));
- imode = mode_for_vector (imode, nelt);
- gcc_assert (GET_MODE_CLASS (imode) == MODE_VECTOR_INT);
- }
-
- *psel = gen_rtx_CONST_VECTOR (imode, vec);
- }
- }
-
- return true;
-}
-
/* A subroutine of expand_vec_perm for expanding one vec_perm insn. */
static rtx
OTI_vec_set,
/* Extract specified field of vector operand. */
OTI_vec_extract,
- /* Extract even/odd fields of vector operands. */
- OTI_vec_extract_even,
- OTI_vec_extract_odd,
/* Initialize vector operand. */
OTI_vec_init,
/* Whole vector shift. The shift amount is in bits. */
#define vec_set_optab (&optab_table[OTI_vec_set])
#define vec_extract_optab (&optab_table[OTI_vec_extract])
-#define vec_extract_even_optab (&optab_table[OTI_vec_extract_even])
-#define vec_extract_odd_optab (&optab_table[OTI_vec_extract_odd])
#define vec_init_optab (&optab_table[OTI_vec_init])
#define vec_shl_optab (&optab_table[OTI_vec_shl])
#define vec_shr_optab (&optab_table[OTI_vec_shr])
/* Return tree if target supports vector operations for VEC_PERM_EXPR. */
extern bool can_vec_perm_p (enum machine_mode, bool, const unsigned char *);
-/* Return true if target supports vector operations using VEC_PERM_EXPR. */
-extern bool can_vec_perm_for_code_p (enum tree_code, enum machine_mode, rtx *);
-
/* Generate code for VEC_PERM_EXPR. */
extern rtx expand_vec_perm (enum machine_mode, rtx, rtx, rtx, rtx);
case VEC_PACK_TRUNC_EXPR:
case VEC_PACK_SAT_EXPR:
case VEC_PACK_FIX_TRUNC_EXPR:
- case VEC_EXTRACT_EVEN_EXPR:
- case VEC_EXTRACT_ODD_EXPR:
/* FIXME. */
return false;
case VEC_PACK_TRUNC_EXPR:
case VEC_PACK_SAT_EXPR:
case VEC_PACK_FIX_TRUNC_EXPR:
- case VEC_EXTRACT_EVEN_EXPR:
- case VEC_EXTRACT_ODD_EXPR:
case VEC_WIDEN_LSHIFT_HI_EXPR:
case VEC_WIDEN_LSHIFT_LO_EXPR:
dump_block_node (buffer, node, spc, flags);
break;
- case VEC_EXTRACT_EVEN_EXPR:
- pp_string (buffer, " VEC_EXTRACT_EVEN_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_EXTRACT_ODD_EXPR:
- pp_string (buffer, " VEC_EXTRACT_ODD_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;
-
default:
NIY;
}
/* Function vect_strided_store_supported.
- Returns TRUE is INTERLEAVE_HIGH and INTERLEAVE_LOW operations are supported,
- and FALSE otherwise. */
+ Returns TRUE if interleave high and interleave low permutations
+ are supported, and FALSE otherwise. */
bool
vect_strided_store_supported (tree vectype, unsigned HOST_WIDE_INT count)
{
- enum machine_mode mode;
-
- mode = TYPE_MODE (vectype);
+ enum machine_mode mode = TYPE_MODE (vectype);
/* vect_permute_store_chain requires the group size to be a power of two. */
if (exact_log2 (count) == -1)
return false;
}
- /* Check that the operation is supported. */
+ /* Check that the permutation is supported. */
if (VECTOR_MODE_P (mode))
{
unsigned int i, nelt = GET_MODE_NUNITS (mode);
tree vectype = STMT_VINFO_VECTYPE (vinfo_for_stmt (stmt));
tree perm_mask_low, perm_mask_high;
unsigned int i, n;
- unsigned int j, nelt = GET_MODE_NUNITS (TYPE_MODE (vectype));
+ unsigned int j, nelt = TYPE_VECTOR_SUBPARTS (vectype);
unsigned char *sel = XALLOCAVEC (unsigned char, nelt);
- gcc_assert (vect_strided_store_supported (vectype, length));
-
*result_chain = VEC_copy (tree, heap, dr_chain);
for (i = 0, n = nelt / 2; i < n; i++)
sel[i * 2 + 1] = i + nelt;
}
perm_mask_high = vect_gen_perm_mask (vectype, sel);
+ gcc_assert (perm_mask_high != NULL);
+
for (i = 0; i < nelt; i++)
sel[i] += nelt / 2;
perm_mask_low = vect_gen_perm_mask (vectype, sel);
+ gcc_assert (perm_mask_low != NULL);
for (i = 0, n = exact_log2 (length); i < n; i++)
{
/* Function vect_strided_load_supported.
- Returns TRUE is EXTRACT_EVEN and EXTRACT_ODD operations are supported,
+ Returns TRUE if even and odd permutations are supported,
and FALSE otherwise. */
bool
vect_strided_load_supported (tree vectype, unsigned HOST_WIDE_INT count)
{
- optab ee_optab, eo_optab;
- enum machine_mode mode;
-
- mode = TYPE_MODE (vectype);
+ enum machine_mode mode = TYPE_MODE (vectype);
/* vect_permute_load_chain requires the group size to be a power of two. */
if (exact_log2 (count) == -1)
return false;
}
- ee_optab = optab_for_tree_code (VEC_EXTRACT_EVEN_EXPR,
- vectype, optab_default);
- eo_optab = optab_for_tree_code (VEC_EXTRACT_ODD_EXPR,
- vectype, optab_default);
- if (ee_optab && eo_optab
- && optab_handler (ee_optab, mode) != CODE_FOR_nothing
- && optab_handler (eo_optab, mode) != CODE_FOR_nothing)
- return true;
+ /* Check that the permutation is supported. */
+ if (VECTOR_MODE_P (mode))
+ {
+ unsigned int i, nelt = GET_MODE_NUNITS (mode);
+ unsigned char *sel = XALLOCAVEC (unsigned char, nelt);
- if (can_vec_perm_for_code_p (VEC_EXTRACT_EVEN_EXPR, mode, NULL)
- && can_vec_perm_for_code_p (VEC_EXTRACT_ODD_EXPR, mode, NULL))
- return true;
+ for (i = 0; i < nelt; i++)
+ sel[i] = i * 2;
+ if (can_vec_perm_p (mode, false, sel))
+ {
+ for (i = 0; i < nelt; i++)
+ sel[i] = i * 2 + 1;
+ if (can_vec_perm_p (mode, false, sel))
+ return true;
+ }
+ }
if (vect_print_dump_info (REPORT_DETAILS))
fprintf (vect_dump, "extract even/odd not supported by target");
VEC(tree,heap) **result_chain)
{
tree perm_dest, data_ref, first_vect, second_vect;
+ tree perm_mask_even, perm_mask_odd;
gimple perm_stmt;
tree vectype = STMT_VINFO_VECTYPE (vinfo_for_stmt (stmt));
- int i;
- unsigned int j;
-
- gcc_assert (vect_strided_load_supported (vectype, length));
+ unsigned int i, j, log_length = exact_log2 (length);
+ unsigned nelt = TYPE_VECTOR_SUBPARTS (vectype);
+ unsigned char *sel = XALLOCAVEC (unsigned char, nelt);
*result_chain = VEC_copy (tree, heap, dr_chain);
- for (i = 0; i < exact_log2 (length); i++)
+
+ for (i = 0; i < nelt; ++i)
+ sel[i] = i * 2;
+ perm_mask_even = vect_gen_perm_mask (vectype, sel);
+ gcc_assert (perm_mask_even != NULL);
+
+ for (i = 0; i < nelt; ++i)
+ sel[i] = i * 2 + 1;
+ perm_mask_odd = vect_gen_perm_mask (vectype, sel);
+ gcc_assert (perm_mask_odd != NULL);
+
+ for (i = 0; i < log_length; i++)
{
- for (j = 0; j < length; j +=2)
+ for (j = 0; j < length; j += 2)
{
first_vect = VEC_index (tree, dr_chain, j);
second_vect = VEC_index (tree, dr_chain, j+1);
DECL_GIMPLE_REG_P (perm_dest) = 1;
add_referenced_var (perm_dest);
- perm_stmt = gimple_build_assign_with_ops (VEC_EXTRACT_EVEN_EXPR,
- perm_dest, first_vect,
- second_vect);
+ perm_stmt = gimple_build_assign_with_ops3 (VEC_PERM_EXPR, perm_dest,
+ first_vect, second_vect,
+ perm_mask_even);
data_ref = make_ssa_name (perm_dest, perm_stmt);
gimple_assign_set_lhs (perm_stmt, data_ref);
DECL_GIMPLE_REG_P (perm_dest) = 1;
add_referenced_var (perm_dest);
- perm_stmt = gimple_build_assign_with_ops (VEC_EXTRACT_ODD_EXPR,
- perm_dest, first_vect,
- second_vect);
+ perm_stmt = gimple_build_assign_with_ops3 (VEC_PERM_EXPR, perm_dest,
+ first_vect, second_vect,
+ perm_mask_odd);
+
data_ref = make_ssa_name (perm_dest, perm_stmt);
gimple_assign_set_lhs (perm_stmt, data_ref);
vect_finish_stmt_generation (stmt, perm_stmt, gsi);
|| code == VIEW_CONVERT_EXPR)
return;
- /* These are only created by the vectorizer, after having queried
- the target support. It's more than just looking at the optab,
- and there's no need to do it again. */
- if (code == VEC_EXTRACT_EVEN_EXPR
- || code == VEC_EXTRACT_ODD_EXPR)
- return;
-
gcc_assert (code != CONVERT_EXPR);
/* The signedness is determined from input argument. */
Then permutation statements are generated:
- VS5: vx5 = VEC_EXTRACT_EVEN_EXPR < vx0, vx1 >
- VS6: vx6 = VEC_EXTRACT_ODD_EXPR < vx0, vx1 >
+ VS5: vx5 = VEC_PERM_EXPR < vx0, vx1, { 0, 2, ..., i*2 } >
+ VS6: vx6 = VEC_PERM_EXPR < vx0, vx1, { 1, 3, ..., i*2+1 } >
...
And they are put in STMT_VINFO_VEC_STMT of the corresponding scalar stmts
the output vector. */
DEFTREECODE (VEC_PACK_FIX_TRUNC_EXPR, "vec_pack_fix_trunc_expr", tcc_binary, 2)
-/* Extract even/odd fields from vectors. */
-DEFTREECODE (VEC_EXTRACT_EVEN_EXPR, "vec_extract_even_expr", tcc_binary, 2)
-DEFTREECODE (VEC_EXTRACT_ODD_EXPR, "vec_extract_odd_expr", tcc_binary, 2)
-
/* Widening vector shift left in bits.
Operand 0 is a vector to be shifted with N elements of size S.
Operand 1 is an integer shift amount in bits.