On Thu, Dec 8, 2011 at 10:06 PM, Richard Henderson <r...@redhat.com> wrote: > Slightly modified version of a patch Jakub posted earlier.
Ok (given the target specific patches are approved). Thanks for this cleanup, Richard. > > * tree.def (VEC_INTERLEAVE_HIGH_EXPR, VEC_INTERLEAVE_LOW_EXPR): Remove. > * gimple-pretty-print.c (dump_binary_rhs): Don't handle > VEC_INTERLEAVE_HIGH_EXPR and VEC_INTERLEAVE_LOW_EXPR. > * expr.c (expand_expr_real_2): Likewise. > * tree-cfg.c (verify_gimple_assign_binary): Likewise. > * cfgexpand.c (expand_debug_expr): 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. > * fold-const.c (fold_binary_loc): Likewise. > * doc/generic.texi (VEC_INTERLEAVE_HIGH_EXPR, > VEC_INTERLEAVE_LOW_EXPR): Remove documentation. > * optabs.c (optab_for_tree_code): Don't handle > VEC_INTERLEAVE_HIGH_EXPR and VEC_INTERLEAVE_LOW_EXPR. > (expand_binop, init_optabs): Remove vec_interleave_high_optab > and vec_interleave_low_optab. > * genopinit.c (optabs): Likewise. > * optabs.h (OTI_vec_interleave_high, OTI_vec_interleave_low): Remove. > (vec_interleave_high_optab, vec_interleave_low_optab): Remove. > * doc/md.texi (vec_interleave_high, vec_interleave_low): Remove > documentation. > * tree-vect-stmts.c (gen_perm_mask): Renamed to... > (vect_gen_perm_mask): ... this. No longer static. > (perm_mask_for_reverse, vectorizable_load): Adjust callers. > * tree-vectorizer.h (vect_gen_perm_mask): New prototype. > * tree-vect-data-refs.c (vect_strided_store_supported): Don't try > VEC_INTERLEAVE_*_EXPR, use can_vec_perm_p instead of > can_vec_perm_for_code_p. > (vect_permute_store_chain): Generate VEC_PERM_EXPR with interleaving > masks instead of VEC_INTERLEAVE_HIGH_EXPR and VEC_INTERLEAVE_LOW_EXPR. > * config/i386/i386.c (expand_vec_perm_interleave2): If > expand_vec_perm_interleave3 would handle it, return false. > (expand_vec_perm_broadcast_1): Don't use vec_interleave_*_optab. > --- > gcc/cfgexpand.c | 2 - > gcc/config/i386/i386.c | 26 +++++++++++-- > gcc/doc/generic.texi | 13 ------- > gcc/doc/md.texi | 14 ------- > gcc/expr.c | 2 - > gcc/fold-const.c | 10 ----- > gcc/genopinit.c | 4 +-- > gcc/gimple-pretty-print.c | 2 - > gcc/optabs.c | 28 +------------- > gcc/optabs.h | 5 --- > gcc/tree-cfg.c | 2 - > gcc/tree-inline.c | 2 - > gcc/tree-pretty-print.c | 16 -------- > gcc/tree-vect-data-refs.c | 86 ++++++++++++++++++++++---------------------- > gcc/tree-vect-generic.c | 4 +-- > gcc/tree-vect-stmts.c | 14 ++++---- > gcc/tree-vectorizer.h | 1 + > gcc/tree.def | 4 -- > 18 files changed, 77 insertions(+), 158 deletions(-) > > diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c > index 8684721..8d2d34d 100644 > --- a/gcc/cfgexpand.c > +++ b/gcc/cfgexpand.c > @@ -3449,8 +3449,6 @@ expand_debug_expr (tree exp) > case VEC_COND_EXPR: > case VEC_EXTRACT_EVEN_EXPR: > case VEC_EXTRACT_ODD_EXPR: > - case VEC_INTERLEAVE_HIGH_EXPR: > - case VEC_INTERLEAVE_LOW_EXPR: > case VEC_LSHIFT_EXPR: > case VEC_PACK_FIX_TRUNC_EXPR: > case VEC_PACK_SAT_EXPR: > diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c > index 1638799..439c55f 100644 > --- a/gcc/config/i386/i386.c > +++ b/gcc/config/i386/i386.c > @@ -36013,6 +36013,8 @@ expand_vec_perm_palignr (struct expand_vec_perm_d *d) > return ok; > } > > +static bool expand_vec_perm_interleave3 (struct expand_vec_perm_d *d); > + > /* A subroutine of ix86_expand_vec_perm_builtin_1. Try to simplify > a two vector permutation into a single vector permutation by using > an interleave operation to merge the vectors. */ > @@ -36039,6 +36041,17 @@ expand_vec_perm_interleave2 (struct > expand_vec_perm_d *d) > /* For 32-byte modes allow even d->op0 == d->op1. > The lack of cross-lane shuffling in some instructions > might prevent a single insn shuffle. */ > + dfinal = *d; > + dfinal.testing_p = true; > + /* If expand_vec_perm_interleave3 can expand this into > + a 3 insn sequence, give up and let it be expanded as > + 3 insn sequence. While that is one insn longer, > + it doesn't need a memory operand and in the common > + case that both interleave low and high permutations > + with the same operands are adjacent needs 4 insns > + for both after CSE. */ > + if (expand_vec_perm_interleave3 (&dfinal)) > + return false; > } > else > return false; > @@ -36878,18 +36891,23 @@ expand_vec_perm_broadcast_1 (struct > expand_vec_perm_d *d) > stopping once we have promoted to V4SImode and then use pshufd. */ > do > { > - optab otab = vec_interleave_low_optab; > + rtx dest; > + rtx (*gen) (rtx, rtx, rtx) > + = vmode == V16QImode ? gen_vec_interleave_lowv16qi > + : gen_vec_interleave_lowv8hi; > > if (elt >= nelt2) > { > - otab = vec_interleave_high_optab; > + gen = vmode == V16QImode ? gen_vec_interleave_highv16qi > + : gen_vec_interleave_highv8hi; > elt -= nelt2; > } > nelt2 /= 2; > > - op0 = expand_binop (vmode, otab, op0, op0, NULL, 0, OPTAB_DIRECT); > + dest = gen_reg_rtx (vmode); > + emit_insn (gen (dest, op0, op0)); > vmode = get_mode_wider_vector (vmode); > - op0 = gen_lowpart (vmode, op0); > + op0 = gen_lowpart (vmode, dest); > } > while (vmode != V4SImode); > > diff --git a/gcc/doc/generic.texi b/gcc/doc/generic.texi > index 82b2663..4f26238 100644 > --- a/gcc/doc/generic.texi > +++ b/gcc/doc/generic.texi > @@ -1697,8 +1697,6 @@ its sole argument yields the representation for > @code{ap}. > @tindex VEC_PACK_FIX_TRUNC_EXPR > @tindex VEC_EXTRACT_EVEN_EXPR > @tindex VEC_EXTRACT_ODD_EXPR > -@tindex VEC_INTERLEAVE_HIGH_EXPR > -@tindex VEC_INTERLEAVE_LOW_EXPR > > @table @code > @item VEC_LSHIFT_EXPR > @@ -1774,17 +1772,6 @@ 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. > > -@item VEC_INTERLEAVE_HIGH_EXPR > -@itemx VEC_INTERLEAVE_LOW_EXPR > -These nodes represent merging and interleaving of the high/low elements of > the > -two input vectors, respectively. The operands and the result are vectors that > -contain the same number of elements (@code{N}) of the same type. > -In the case of @code{VEC_INTERLEAVE_HIGH_EXPR}, the high @code{N/2} elements > of > -the first input vector are interleaved with the high @code{N/2} elements of > the > -second input vector. In the case of @code{VEC_INTERLEAVE_LOW_EXPR}, the low > -@code{N/2} elements of the first input vector are interleaved with the low > -@code{N/2} elements of the second input vector. > - > @end table > > > diff --git a/gcc/doc/md.texi b/gcc/doc/md.texi > index dc87ca7..6dd6a58 100644 > --- a/gcc/doc/md.texi > +++ b/gcc/doc/md.texi > @@ -4159,20 +4159,6 @@ 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_interleave_high@var{m}} instruction pattern > -@item @samp{vec_interleave_high@var{m}} > -Merge high elements of the two input vectors into the output vector. The > output > -and input vectors should have the same modes (@code{N} elements). The high > -@code{N/2} elements of the first input vector are interleaved with the high > -@code{N/2} elements of the second input vector. > - > -@cindex @code{vec_interleave_low@var{m}} instruction pattern > -@item @samp{vec_interleave_low@var{m}} > -Merge low elements of the two input vectors into the output vector. The > output > -and input vectors should have the same modes (@code{N} elements). The low > -@code{N/2} elements of the first input vector are interleaved with the low > -@code{N/2} elements of the second input vector. > - > @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 > diff --git a/gcc/expr.c b/gcc/expr.c > index 6722af0..bc07c86 100644 > --- a/gcc/expr.c > +++ b/gcc/expr.c > @@ -8668,8 +8668,6 @@ expand_expr_real_2 (sepops ops, rtx target, enum > machine_mode tmode, > > case VEC_EXTRACT_EVEN_EXPR: > case VEC_EXTRACT_ODD_EXPR: > - case VEC_INTERLEAVE_HIGH_EXPR: > - case VEC_INTERLEAVE_LOW_EXPR: > goto binop; > > case VEC_LSHIFT_EXPR: > diff --git a/gcc/fold-const.c b/gcc/fold-const.c > index a32ea90..89c68cf 100644 > --- a/gcc/fold-const.c > +++ b/gcc/fold-const.c > @@ -13503,8 +13503,6 @@ fold_binary_loc (location_t loc, > > case VEC_EXTRACT_EVEN_EXPR: > case VEC_EXTRACT_ODD_EXPR: > - case VEC_INTERLEAVE_HIGH_EXPR: > - case VEC_INTERLEAVE_LOW_EXPR: > if ((TREE_CODE (arg0) == VECTOR_CST > || TREE_CODE (arg0) == CONSTRUCTOR) > && (TREE_CODE (arg1) == VECTOR_CST > @@ -13522,14 +13520,6 @@ fold_binary_loc (location_t loc, > case VEC_EXTRACT_ODD_EXPR: > sel[i] = i * 2 + 1; > break; > - case VEC_INTERLEAVE_HIGH_EXPR: > - sel[i] = (i + (BYTES_BIG_ENDIAN ? 0 : nelts)) / 2 > - + ((i & 1) ? nelts : 0); > - break; > - case VEC_INTERLEAVE_LOW_EXPR: > - sel[i] = (i + (BYTES_BIG_ENDIAN ? nelts : 0)) / 2 > - + ((i & 1) ? nelts : 0); > - break; > default: > gcc_unreachable (); > } > diff --git a/gcc/genopinit.c b/gcc/genopinit.c > index 63c58a8..9cd77fa 100644 > --- a/gcc/genopinit.c > +++ b/gcc/genopinit.c > @@ -1,6 +1,6 @@ > /* Generate code to initialize optabs from machine description. > Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, > - 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2010 > + 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2010, 2011 > Free Software Foundation, Inc. > > This file is part of GCC. > @@ -269,8 +269,6 @@ static const char * const optabs[] = > "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_interleave_high_optab, $A, > CODE_FOR_$(vec_interleave_high$a$))", > - "set_optab_handler (vec_interleave_low_optab, $A, > CODE_FOR_$(vec_interleave_low$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$))", > diff --git a/gcc/gimple-pretty-print.c b/gcc/gimple-pretty-print.c > index 3b5f670..b93d66d 100644 > --- a/gcc/gimple-pretty-print.c > +++ b/gcc/gimple-pretty-print.c > @@ -347,8 +347,6 @@ dump_binary_rhs (pretty_printer *buffer, gimple gs, int > spc, int flags) > case VEC_PACK_FIX_TRUNC_EXPR: > case VEC_EXTRACT_EVEN_EXPR: > case VEC_EXTRACT_ODD_EXPR: > - case VEC_INTERLEAVE_HIGH_EXPR: > - case VEC_INTERLEAVE_LOW_EXPR: > case VEC_WIDEN_LSHIFT_HI_EXPR: > case VEC_WIDEN_LSHIFT_LO_EXPR: > for (p = tree_code_name [(int) code]; *p; p++) > diff --git a/gcc/optabs.c b/gcc/optabs.c > index 55cfe8c..6edc3ad 100644 > --- a/gcc/optabs.c > +++ b/gcc/optabs.c > @@ -553,12 +553,6 @@ optab_for_tree_code (enum tree_code code, const_tree > type, > case VEC_EXTRACT_ODD_EXPR: > return vec_extract_odd_optab; > > - case VEC_INTERLEAVE_HIGH_EXPR: > - return vec_interleave_high_optab; > - > - case VEC_INTERLEAVE_LOW_EXPR: > - return vec_interleave_low_optab; > - > default: > return NULL; > } > @@ -1612,11 +1606,7 @@ expand_binop (enum machine_mode mode, optab binoptab, > rtx op0, rtx op1, > enum tree_code tcode = ERROR_MARK; > rtx sel; > > - if (binoptab == vec_interleave_high_optab) > - tcode = VEC_INTERLEAVE_HIGH_EXPR; > - else if (binoptab == vec_interleave_low_optab) > - tcode = VEC_INTERLEAVE_LOW_EXPR; > - else if (binoptab == vec_extract_even_optab) > + if (binoptab == vec_extract_even_optab) > tcode = VEC_EXTRACT_EVEN_EXPR; > else if (binoptab == vec_extract_odd_optab) > tcode = VEC_EXTRACT_ODD_EXPR; > @@ -6271,8 +6261,6 @@ init_optabs (void) > init_optab (vec_extract_optab, UNKNOWN); > init_optab (vec_extract_even_optab, UNKNOWN); > init_optab (vec_extract_odd_optab, UNKNOWN); > - init_optab (vec_interleave_high_optab, UNKNOWN); > - init_optab (vec_interleave_low_optab, UNKNOWN); > init_optab (vec_set_optab, UNKNOWN); > init_optab (vec_init_optab, UNKNOWN); > init_optab (vec_shl_optab, UNKNOWN); > @@ -6880,8 +6868,7 @@ can_vec_perm_p (enum machine_mode mode, bool variable, > return true; > } > > -/* Return true if we can implement VEC_INTERLEAVE_{HIGH,LOW}_EXPR or > - VEC_EXTRACT_{EVEN,ODD}_EXPR with VEC_PERM_EXPR for this target. > +/* 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 > @@ -6931,17 +6918,6 @@ can_vec_perm_for_code_p (enum tree_code code, enum > machine_mode mode, > data[i] = i * 2 + alt; > break; > > - case VEC_INTERLEAVE_HIGH_EXPR: > - case VEC_INTERLEAVE_LOW_EXPR: > - if ((BYTES_BIG_ENDIAN != 0) ^ (code == VEC_INTERLEAVE_HIGH_EXPR)) > - alt = nelt / 2; > - for (i = 0; i < nelt / 2; ++i) > - { > - data[i * 2] = i + alt; > - data[i * 2 + 1] = i + nelt + alt; > - } > - break; > - > default: > gcc_unreachable (); > } > diff --git a/gcc/optabs.h b/gcc/optabs.h > index ec13f6f..a7c43ac 100644 > --- a/gcc/optabs.h > +++ b/gcc/optabs.h > @@ -335,9 +335,6 @@ enum optab_index > /* Extract even/odd fields of vector operands. */ > OTI_vec_extract_even, > OTI_vec_extract_odd, > - /* Interleave fields of vector operands. */ > - OTI_vec_interleave_high, > - OTI_vec_interleave_low, > /* Initialize vector operand. */ > OTI_vec_init, > /* Whole vector shift. The shift amount is in bits. */ > @@ -564,8 +561,6 @@ enum optab_index > #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_interleave_high_optab (&optab_table[OTI_vec_interleave_high]) > -#define vec_interleave_low_optab (&optab_table[OTI_vec_interleave_low]) > #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]) > diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c > index d81cc67..77f5a46 100644 > --- a/gcc/tree-cfg.c > +++ b/gcc/tree-cfg.c > @@ -3703,8 +3703,6 @@ do_pointer_plus_expr_check: > case VEC_PACK_FIX_TRUNC_EXPR: > case VEC_EXTRACT_EVEN_EXPR: > case VEC_EXTRACT_ODD_EXPR: > - case VEC_INTERLEAVE_HIGH_EXPR: > - case VEC_INTERLEAVE_LOW_EXPR: > /* FIXME. */ > return false; > > diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c > index 2260403..a98909c 100644 > --- a/gcc/tree-inline.c > +++ b/gcc/tree-inline.c > @@ -3401,8 +3401,6 @@ estimate_operator_cost (enum tree_code code, > eni_weights *weights, > case VEC_PACK_FIX_TRUNC_EXPR: > case VEC_EXTRACT_EVEN_EXPR: > case VEC_EXTRACT_ODD_EXPR: > - case VEC_INTERLEAVE_HIGH_EXPR: > - case VEC_INTERLEAVE_LOW_EXPR: > case VEC_WIDEN_LSHIFT_HI_EXPR: > case VEC_WIDEN_LSHIFT_LO_EXPR: > > diff --git a/gcc/tree-pretty-print.c b/gcc/tree-pretty-print.c > index 9abe004..9363aea 100644 > --- a/gcc/tree-pretty-print.c > +++ b/gcc/tree-pretty-print.c > @@ -2404,22 +2404,6 @@ dump_generic_node (pretty_printer *buffer, tree node, > int spc, int flags, > pp_string (buffer, " > "); > break; > > - case VEC_INTERLEAVE_HIGH_EXPR: > - pp_string (buffer, " VEC_INTERLEAVE_HIGH_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_INTERLEAVE_LOW_EXPR: > - pp_string (buffer, " VEC_INTERLEAVE_LOW_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; > } > diff --git a/gcc/tree-vect-data-refs.c b/gcc/tree-vect-data-refs.c > index 8111bdc..23813de 100644 > --- a/gcc/tree-vect-data-refs.c > +++ b/gcc/tree-vect-data-refs.c > @@ -3780,7 +3780,6 @@ vect_create_destination_var (tree scalar_dest, tree > vectype) > bool > vect_strided_store_supported (tree vectype, unsigned HOST_WIDE_INT count) > { > - optab ih_optab, il_optab; > enum machine_mode mode; > > mode = TYPE_MODE (vectype); > @@ -3795,18 +3794,23 @@ vect_strided_store_supported (tree vectype, unsigned > HOST_WIDE_INT count) > } > > /* Check that the operation is supported. */ > - ih_optab = optab_for_tree_code (VEC_INTERLEAVE_HIGH_EXPR, > - vectype, optab_default); > - il_optab = optab_for_tree_code (VEC_INTERLEAVE_LOW_EXPR, > - vectype, optab_default); > - if (il_optab && ih_optab > - && optab_handler (ih_optab, mode) != CODE_FOR_nothing > - && optab_handler (il_optab, mode) != CODE_FOR_nothing) > - return true; > - > - if (can_vec_perm_for_code_p (VEC_INTERLEAVE_HIGH_EXPR, mode, NULL) > - && can_vec_perm_for_code_p (VEC_INTERLEAVE_LOW_EXPR, mode, NULL)) > - return true; > + if (VECTOR_MODE_P (mode)) > + { > + unsigned int i, nelt = GET_MODE_NUNITS (mode); > + unsigned char *sel = XALLOCAVEC (unsigned char, nelt); > + for (i = 0; i < nelt / 2; i++) > + { > + sel[i * 2] = i; > + sel[i * 2 + 1] = i + nelt; > + } > + if (can_vec_perm_p (mode, false, sel)) > + { > + for (i = 0; i < nelt; i++) > + sel[i] += nelt / 2; > + if (can_vec_perm_p (mode, false, sel)) > + return true; > + } > + } > > if (vect_print_dump_info (REPORT_DETAILS)) > fprintf (vect_dump, "interleave op not supported by target."); > @@ -3897,15 +3901,26 @@ vect_permute_store_chain (VEC(tree,heap) *dr_chain, > tree perm_dest, vect1, vect2, high, low; > gimple perm_stmt; > tree vectype = STMT_VINFO_VECTYPE (vinfo_for_stmt (stmt)); > - int i; > - unsigned int j; > - enum tree_code high_code, low_code; > + tree perm_mask_low, perm_mask_high; > + unsigned int i, n; > + unsigned int j, nelt = GET_MODE_NUNITS (TYPE_MODE (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; i < exact_log2 (length); i++) > + for (i = 0, n = nelt / 2; i < n; i++) > + { > + sel[i * 2] = i; > + sel[i * 2 + 1] = i + nelt; > + } > + perm_mask_high = vect_gen_perm_mask (vectype, sel); > + for (i = 0; i < nelt; i++) > + sel[i] += nelt / 2; > + perm_mask_low = vect_gen_perm_mask (vectype, sel); > + > + for (i = 0, n = exact_log2 (length); i < n; i++) > { > for (j = 0; j < length/2; j++) > { > @@ -3913,42 +3928,27 @@ vect_permute_store_chain (VEC(tree,heap) *dr_chain, > vect2 = VEC_index (tree, dr_chain, j+length/2); > > /* Create interleaving stmt: > - in the case of big endian: > - high = interleave_high (vect1, vect2) > - and in the case of little endian: > - high = interleave_low (vect1, vect2). */ > + high = VEC_PERM_EXPR <vect1, vect2, {0, nelt, 1, nelt+1, ...}> > */ > perm_dest = create_tmp_var (vectype, "vect_inter_high"); > DECL_GIMPLE_REG_P (perm_dest) = 1; > add_referenced_var (perm_dest); > - if (BYTES_BIG_ENDIAN) > - { > - high_code = VEC_INTERLEAVE_HIGH_EXPR; > - low_code = VEC_INTERLEAVE_LOW_EXPR; > - } > - else > - { > - low_code = VEC_INTERLEAVE_HIGH_EXPR; > - high_code = VEC_INTERLEAVE_LOW_EXPR; > - } > - perm_stmt = gimple_build_assign_with_ops (high_code, perm_dest, > - vect1, vect2); > - high = make_ssa_name (perm_dest, perm_stmt); > - gimple_assign_set_lhs (perm_stmt, high); > + high = make_ssa_name (perm_dest, NULL); > + perm_stmt > + = gimple_build_assign_with_ops3 (VEC_PERM_EXPR, high, > + vect1, vect2, perm_mask_high); > vect_finish_stmt_generation (stmt, perm_stmt, gsi); > VEC_replace (tree, *result_chain, 2*j, high); > > /* Create interleaving stmt: > - in the case of big endian: > - low = interleave_low (vect1, vect2) > - and in the case of little endian: > - low = interleave_high (vect1, vect2). */ > + low = VEC_PERM_EXPR <vect1, vect2, {nelt/2, nelt*3/2, nelt/2+1, > + nelt*3/2+1, ...}> */ > perm_dest = create_tmp_var (vectype, "vect_inter_low"); > DECL_GIMPLE_REG_P (perm_dest) = 1; > add_referenced_var (perm_dest); > - perm_stmt = gimple_build_assign_with_ops (low_code, perm_dest, > - vect1, vect2); > - low = make_ssa_name (perm_dest, perm_stmt); > - gimple_assign_set_lhs (perm_stmt, low); > + low = make_ssa_name (perm_dest, NULL); > + perm_stmt > + = gimple_build_assign_with_ops3 (VEC_PERM_EXPR, low, > + vect1, vect2, perm_mask_low); > vect_finish_stmt_generation (stmt, perm_stmt, gsi); > VEC_replace (tree, *result_chain, 2*j+1, low); > } > diff --git a/gcc/tree-vect-generic.c b/gcc/tree-vect-generic.c > index dc01ce7..bc917d9 100644 > --- a/gcc/tree-vect-generic.c > +++ b/gcc/tree-vect-generic.c > @@ -776,9 +776,7 @@ expand_vector_operations_1 (gimple_stmt_iterator *gsi) > /* 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_INTERLEAVE_HIGH_EXPR > - || code == VEC_INTERLEAVE_LOW_EXPR > - || code == VEC_EXTRACT_EVEN_EXPR > + if (code == VEC_EXTRACT_EVEN_EXPR > || code == VEC_EXTRACT_ODD_EXPR) > return; > > diff --git a/gcc/tree-vect-stmts.c b/gcc/tree-vect-stmts.c > index 8589a85..db559d7 100644 > --- a/gcc/tree-vect-stmts.c > +++ b/gcc/tree-vect-stmts.c > @@ -3828,8 +3828,8 @@ vectorizable_store (gimple stmt, gimple_stmt_iterator > *gsi, gimple *vec_stmt, > > Then permutation statements are generated: > > - VS5: vx5 = VEC_INTERLEAVE_HIGH_EXPR < vx0, vx3 > > - VS6: vx6 = VEC_INTERLEAVE_LOW_EXPR < vx0, vx3 > > + VS5: vx5 = VEC_PERM_EXPR < vx0, vx3, {0, 8, 1, 9, 2, 10, 3, 11} > > + VS6: vx6 = VEC_PERM_EXPR < vx0, vx3, {4, 12, 5, 13, 6, 14, 7, 15} > > ... > > And they are put in STMT_VINFO_VEC_STMT of the corresponding scalar stmts > @@ -4026,8 +4026,8 @@ vectorizable_store (gimple stmt, gimple_stmt_iterator > *gsi, gimple *vec_stmt, > the VECTOR_CST mask that implements the permutation of the > vector elements. If that is impossible to do, returns NULL. */ > > -static tree > -gen_perm_mask (tree vectype, unsigned char *sel) > +tree > +vect_gen_perm_mask (tree vectype, unsigned char *sel) > { > tree mask_elt_type, mask_type, mask_vec; > int i, nunits; > @@ -4067,7 +4067,7 @@ perm_mask_for_reverse (tree vectype) > for (i = 0; i < nunits; ++i) > sel[i] = nunits - 1 - i; > > - return gen_perm_mask (vectype, sel); > + return vect_gen_perm_mask (vectype, sel); > } > > /* Given a vector variable X and Y, that was generated for the scalar > @@ -4314,7 +4314,7 @@ vectorizable_load (gimple stmt, gimple_stmt_iterator > *gsi, gimple *vec_stmt, > for (i = 0; i < gather_off_nunits; ++i) > sel[i] = i | nunits; > > - perm_mask = gen_perm_mask (gather_off_vectype, sel); > + perm_mask = vect_gen_perm_mask (gather_off_vectype, sel); > gcc_assert (perm_mask != NULL_TREE); > } > else if (nunits == gather_off_nunits * 2) > @@ -4326,7 +4326,7 @@ vectorizable_load (gimple stmt, gimple_stmt_iterator > *gsi, gimple *vec_stmt, > sel[i] = i < gather_off_nunits > ? i : i + nunits - gather_off_nunits; > > - perm_mask = gen_perm_mask (vectype, sel); > + perm_mask = vect_gen_perm_mask (vectype, sel); > gcc_assert (perm_mask != NULL_TREE); > ncopies *= 2; > } > diff --git a/gcc/tree-vectorizer.h b/gcc/tree-vectorizer.h > index 927c0bd..fe1a6bc 100644 > --- a/gcc/tree-vectorizer.h > +++ b/gcc/tree-vectorizer.h > @@ -848,6 +848,7 @@ extern void vect_get_store_cost (struct data_reference *, > int, unsigned int *); > extern bool vect_supportable_shift (enum tree_code, tree); > extern void vect_get_vec_defs (tree, tree, gimple, VEC (tree, heap) **, > VEC (tree, heap) **, slp_tree, int); > +extern tree vect_gen_perm_mask (tree, unsigned char *); > > /* In tree-vect-data-refs.c. */ > extern bool vect_can_force_dr_alignment_p (const_tree, unsigned int); > diff --git a/gcc/tree.def b/gcc/tree.def > index 11ce8b5..2f096f9 100644 > --- a/gcc/tree.def > +++ b/gcc/tree.def > @@ -1192,10 +1192,6 @@ DEFTREECODE (VEC_PACK_FIX_TRUNC_EXPR, > "vec_pack_fix_trunc_expr", tcc_binary, 2) > DEFTREECODE (VEC_EXTRACT_EVEN_EXPR, "vec_extract_even_expr", tcc_binary, 2) > DEFTREECODE (VEC_EXTRACT_ODD_EXPR, "vec_extract_odd_expr", tcc_binary, 2) > > -/* Merge input vectors interleaving their fields. */ > -DEFTREECODE (VEC_INTERLEAVE_HIGH_EXPR, "vec_interleave_high_expr", > tcc_binary, 2) > -DEFTREECODE (VEC_INTERLEAVE_LOW_EXPR, "vec_interleave_low_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. > -- > 1.7.7.3 >