[PATCH 1/6] Delete VEC_INTERLEAVE_*_EXPR.

Richard Henderson rth@redhat.com
Thu Dec 8 21:07:00 GMT 2011


Slightly modified version of a patch Jakub posted earlier.


	* 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



More information about the Gcc-patches mailing list