diff mbox

Pattern recognize shifts with different rhs1/rhs2 types

Message ID 20111028184441.GW1052@tyan-ft48-01.lab.bos.redhat.com
State New
Headers show

Commit Message

Jakub Jelinek Oct. 28, 2011, 6:44 p.m. UTC
Hi!

This patch implements what I've talked about, with this we can now
with -mavx2 as well as -mxop vectorize long long/unsigned long long
shifts by int or long long/unsigned long long shifts by long long
(where the FE casts it to int first).  Already covered by the *vshift-*
testcases I've committed recently (eyeballed for -mxop plus link tested,
for -mavx2 tested on sde).

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

2011-10-28  Jakub Jelinek  <jakub@redhat.com>

	* tree-vectorizer.h (NUM_PATTERNS): Bump to 9.
	* tree-vect-patterns.c (vect_recog_vector_vector_shift_pattern): New
	function.
	(vect_vect_recog_func_ptrs): Add it.


	Jakub

Comments

Ira Rosen Oct. 30, 2011, 8:51 a.m. UTC | #1
On 28 October 2011 20:44, Jakub Jelinek <jakub@redhat.com> wrote:
> Hi!

Hi,

>
> This patch implements what I've talked about, with this we can now
> with -mavx2 as well as -mxop vectorize long long/unsigned long long
> shifts by int or long long/unsigned long long shifts by long long
> (where the FE casts it to int first).  Already covered by the *vshift-*
> testcases I've committed recently (eyeballed for -mxop plus link tested,
> for -mavx2 tested on sde).
>
> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

OK.

Thanks,
Ira

>
> 2011-10-28  Jakub Jelinek  <jakub@redhat.com>
>
>        * tree-vectorizer.h (NUM_PATTERNS): Bump to 9.
>        * tree-vect-patterns.c (vect_recog_vector_vector_shift_pattern): New
>        function.
>        (vect_vect_recog_func_ptrs): Add it.
>
> --- gcc/tree-vectorizer.h.jj    2011-10-27 08:42:51.000000000 +0200
> +++ gcc/tree-vectorizer.h       2011-10-28 16:26:30.000000000 +0200
> @@ -902,7 +902,7 @@ extern void vect_slp_transform_bb (basic
>    Additional pattern recognition functions can (and will) be added
>    in the future.  */
>  typedef gimple (* vect_recog_func_ptr) (VEC (gimple, heap) **, tree *, tree *);
> -#define NUM_PATTERNS 8
> +#define NUM_PATTERNS 9
>  void vect_pattern_recog (loop_vec_info);
>
>  /* In tree-vectorizer.c.  */
> --- gcc/tree-vect-patterns.c.jj 2011-10-26 14:19:11.000000000 +0200
> +++ gcc/tree-vect-patterns.c    2011-10-28 17:41:26.000000000 +0200
> @@ -51,6 +51,8 @@ static gimple vect_recog_over_widening_p
>                                                  tree *);
>  static gimple vect_recog_widen_shift_pattern (VEC (gimple, heap) **,
>                                        tree *, tree *);
> +static gimple vect_recog_vector_vector_shift_pattern (VEC (gimple, heap) **,
> +                                                     tree *, tree *);
>  static gimple vect_recog_mixed_size_cond_pattern (VEC (gimple, heap) **,
>                                                  tree *, tree *);
>  static gimple vect_recog_bool_pattern (VEC (gimple, heap) **, tree *, tree *);
> @@ -61,6 +63,7 @@ static vect_recog_func_ptr vect_vect_rec
>        vect_recog_pow_pattern,
>        vect_recog_over_widening_pattern,
>        vect_recog_widen_shift_pattern,
> +       vect_recog_vector_vector_shift_pattern,
>        vect_recog_mixed_size_cond_pattern,
>        vect_recog_bool_pattern};
>
> @@ -1439,6 +1442,133 @@ vect_recog_widen_shift_pattern (VEC (gim
>   return pattern_stmt;
>  }
>
> +/* Detect a vector by vector shift pattern that wouldn't be otherwise
> +   vectorized:
> +
> +   type a_t;
> +   TYPE b_T, res_T;
> +
> +   S1 a_t = ;
> +   S2 b_T = ;
> +   S3 res_T = b_T op a_t;
> +
> +  where type 'TYPE' is a type with different size than 'type',
> +  and op is <<, >> or rotate.
> +
> +  Also detect cases:
> +
> +   type a_t;
> +   TYPE b_T, c_T, res_T;
> +
> +   S0 c_T = ;
> +   S1 a_t = (type) c_T;
> +   S2 b_T = ;
> +   S3 res_T = b_T op a_t;
> +
> +  Input/Output:
> +
> +  * STMTS: Contains a stmt from which the pattern search begins,
> +    i.e. the shift/rotate stmt.  The original stmt (S3) is replaced
> +    with a shift/rotate which has same type on both operands, in the
> +    second case just b_T op c_T, in the first case with added cast
> +    from a_t to c_T in STMT_VINFO_PATTERN_DEF_STMT.
> +
> +  Output:
> +
> +  * TYPE_IN: The type of the input arguments to the pattern.
> +
> +  * TYPE_OUT: The type of the output of this pattern.
> +
> +  * Return value: A new stmt that will be used to replace the shift/rotate
> +    S3 stmt.  */
> +
> +static gimple
> +vect_recog_vector_vector_shift_pattern (VEC (gimple, heap) **stmts,
> +                                       tree *type_in, tree *type_out)
> +{
> +  gimple last_stmt = VEC_pop (gimple, *stmts);
> +  tree oprnd0, oprnd1, lhs, var;
> +  gimple pattern_stmt, def_stmt;
> +  enum tree_code rhs_code;
> +  stmt_vec_info stmt_vinfo = vinfo_for_stmt (last_stmt);
> +  loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_vinfo);
> +  enum vect_def_type dt;
> +  tree def;
> +
> +  if (!is_gimple_assign (last_stmt))
> +    return NULL;
> +
> +  rhs_code = gimple_assign_rhs_code (last_stmt);
> +  switch (rhs_code)
> +    {
> +    case LSHIFT_EXPR:
> +    case RSHIFT_EXPR:
> +    case LROTATE_EXPR:
> +    case RROTATE_EXPR:
> +      break;
> +    default:
> +      return NULL;
> +    }
> +
> +  if (STMT_VINFO_IN_PATTERN_P (stmt_vinfo))
> +    return NULL;
> +
> +  lhs = gimple_assign_lhs (last_stmt);
> +  oprnd0 = gimple_assign_rhs1 (last_stmt);
> +  oprnd1 = gimple_assign_rhs2 (last_stmt);
> +  if (TREE_CODE (oprnd0) != SSA_NAME
> +      || TREE_CODE (oprnd1) != SSA_NAME
> +      || TYPE_MODE (TREE_TYPE (oprnd0)) == TYPE_MODE (TREE_TYPE (oprnd1))
> +      || TYPE_PRECISION (TREE_TYPE (oprnd1))
> +        != GET_MODE_PRECISION (TYPE_MODE (TREE_TYPE (oprnd1)))
> +      || TYPE_PRECISION (TREE_TYPE (lhs))
> +        != TYPE_PRECISION (TREE_TYPE (oprnd0)))
> +    return NULL;
> +
> +  if (!vect_is_simple_use (oprnd1, loop_vinfo, NULL, &def_stmt, &def, &dt))
> +    return NULL;
> +
> +  if (dt != vect_internal_def)
> +    return NULL;
> +
> +  *type_in = get_vectype_for_scalar_type (TREE_TYPE (oprnd0));
> +  *type_out = *type_in;
> +  if (*type_in == NULL_TREE)
> +    return NULL;
> +
> +  def = NULL_TREE;
> +  if (gimple_assign_cast_p (def_stmt))
> +    {
> +      tree rhs1 = gimple_assign_rhs1 (def_stmt);
> +      if (TYPE_MODE (TREE_TYPE (rhs1)) == TYPE_MODE (TREE_TYPE (oprnd0))
> +         && TYPE_PRECISION (TREE_TYPE (rhs1))
> +            == TYPE_PRECISION (TREE_TYPE (oprnd0)))
> +       def = rhs1;
> +    }
> +
> +  if (def == NULL_TREE)
> +    {
> +      def = vect_recog_temp_ssa_var (TREE_TYPE (oprnd0), NULL);
> +      def_stmt = gimple_build_assign_with_ops (NOP_EXPR, def, oprnd1,
> +                                              NULL_TREE);
> +      STMT_VINFO_PATTERN_DEF_STMT (stmt_vinfo) = def_stmt;
> +    }
> +
> +  /* Pattern detected.  */
> +  if (vect_print_dump_info (REPORT_DETAILS))
> +    fprintf (vect_dump, "vect_recog_vector_vector_shift_pattern: detected: ");
> +
> +  /* Pattern supported.  Create a stmt to be used to replace the pattern.  */
> +  var = vect_recog_temp_ssa_var (TREE_TYPE (oprnd0), NULL);
> +  pattern_stmt = gimple_build_assign_with_ops (rhs_code, var, oprnd0, def);
> +
> +  if (vect_print_dump_info (REPORT_DETAILS))
> +    print_gimple_stmt (vect_dump, pattern_stmt, 0, TDF_SLIM);
> +
> +  VEC_safe_push (gimple, heap, *stmts, last_stmt);
> +  return pattern_stmt;
> +}
> +
>  /* Function vect_recog_mixed_size_cond_pattern
>
>    Try to find the following pattern:
>
>        Jakub
>
diff mbox

Patch

--- gcc/tree-vectorizer.h.jj	2011-10-27 08:42:51.000000000 +0200
+++ gcc/tree-vectorizer.h	2011-10-28 16:26:30.000000000 +0200
@@ -902,7 +902,7 @@  extern void vect_slp_transform_bb (basic
    Additional pattern recognition functions can (and will) be added
    in the future.  */
 typedef gimple (* vect_recog_func_ptr) (VEC (gimple, heap) **, tree *, tree *);
-#define NUM_PATTERNS 8
+#define NUM_PATTERNS 9
 void vect_pattern_recog (loop_vec_info);
 
 /* In tree-vectorizer.c.  */
--- gcc/tree-vect-patterns.c.jj	2011-10-26 14:19:11.000000000 +0200
+++ gcc/tree-vect-patterns.c	2011-10-28 17:41:26.000000000 +0200
@@ -51,6 +51,8 @@  static gimple vect_recog_over_widening_p
                                                  tree *);
 static gimple vect_recog_widen_shift_pattern (VEC (gimple, heap) **,
 	                                tree *, tree *);
+static gimple vect_recog_vector_vector_shift_pattern (VEC (gimple, heap) **,
+						      tree *, tree *);
 static gimple vect_recog_mixed_size_cond_pattern (VEC (gimple, heap) **,
 						  tree *, tree *);
 static gimple vect_recog_bool_pattern (VEC (gimple, heap) **, tree *, tree *);
@@ -61,6 +63,7 @@  static vect_recog_func_ptr vect_vect_rec
 	vect_recog_pow_pattern,
 	vect_recog_over_widening_pattern,
 	vect_recog_widen_shift_pattern,
+	vect_recog_vector_vector_shift_pattern,
 	vect_recog_mixed_size_cond_pattern,
 	vect_recog_bool_pattern};
 
@@ -1439,6 +1442,133 @@  vect_recog_widen_shift_pattern (VEC (gim
   return pattern_stmt;
 }
 
+/* Detect a vector by vector shift pattern that wouldn't be otherwise
+   vectorized:
+
+   type a_t;
+   TYPE b_T, res_T;
+
+   S1 a_t = ;
+   S2 b_T = ;
+   S3 res_T = b_T op a_t;
+
+  where type 'TYPE' is a type with different size than 'type',
+  and op is <<, >> or rotate.
+
+  Also detect cases:
+
+   type a_t;
+   TYPE b_T, c_T, res_T;
+
+   S0 c_T = ;
+   S1 a_t = (type) c_T;
+   S2 b_T = ;
+   S3 res_T = b_T op a_t;
+
+  Input/Output:
+
+  * STMTS: Contains a stmt from which the pattern search begins,
+    i.e. the shift/rotate stmt.  The original stmt (S3) is replaced
+    with a shift/rotate which has same type on both operands, in the
+    second case just b_T op c_T, in the first case with added cast
+    from a_t to c_T in STMT_VINFO_PATTERN_DEF_STMT.
+
+  Output:
+
+  * TYPE_IN: The type of the input arguments to the pattern.
+
+  * TYPE_OUT: The type of the output of this pattern.
+
+  * Return value: A new stmt that will be used to replace the shift/rotate
+    S3 stmt.  */
+
+static gimple
+vect_recog_vector_vector_shift_pattern (VEC (gimple, heap) **stmts,
+					tree *type_in, tree *type_out)
+{
+  gimple last_stmt = VEC_pop (gimple, *stmts);
+  tree oprnd0, oprnd1, lhs, var;
+  gimple pattern_stmt, def_stmt;
+  enum tree_code rhs_code;
+  stmt_vec_info stmt_vinfo = vinfo_for_stmt (last_stmt);
+  loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_vinfo);
+  enum vect_def_type dt;
+  tree def;
+
+  if (!is_gimple_assign (last_stmt))
+    return NULL;
+
+  rhs_code = gimple_assign_rhs_code (last_stmt);
+  switch (rhs_code)
+    {
+    case LSHIFT_EXPR:
+    case RSHIFT_EXPR:
+    case LROTATE_EXPR:
+    case RROTATE_EXPR:
+      break;
+    default:
+      return NULL;
+    }
+
+  if (STMT_VINFO_IN_PATTERN_P (stmt_vinfo))
+    return NULL;
+
+  lhs = gimple_assign_lhs (last_stmt);
+  oprnd0 = gimple_assign_rhs1 (last_stmt);
+  oprnd1 = gimple_assign_rhs2 (last_stmt);
+  if (TREE_CODE (oprnd0) != SSA_NAME
+      || TREE_CODE (oprnd1) != SSA_NAME
+      || TYPE_MODE (TREE_TYPE (oprnd0)) == TYPE_MODE (TREE_TYPE (oprnd1))
+      || TYPE_PRECISION (TREE_TYPE (oprnd1))
+	 != GET_MODE_PRECISION (TYPE_MODE (TREE_TYPE (oprnd1)))
+      || TYPE_PRECISION (TREE_TYPE (lhs))
+	 != TYPE_PRECISION (TREE_TYPE (oprnd0)))
+    return NULL;
+
+  if (!vect_is_simple_use (oprnd1, loop_vinfo, NULL, &def_stmt, &def, &dt))
+    return NULL;
+
+  if (dt != vect_internal_def)
+    return NULL;
+
+  *type_in = get_vectype_for_scalar_type (TREE_TYPE (oprnd0));
+  *type_out = *type_in;
+  if (*type_in == NULL_TREE)
+    return NULL;
+
+  def = NULL_TREE;
+  if (gimple_assign_cast_p (def_stmt))
+    {
+      tree rhs1 = gimple_assign_rhs1 (def_stmt);
+      if (TYPE_MODE (TREE_TYPE (rhs1)) == TYPE_MODE (TREE_TYPE (oprnd0))
+	  && TYPE_PRECISION (TREE_TYPE (rhs1))
+	     == TYPE_PRECISION (TREE_TYPE (oprnd0)))
+	def = rhs1;
+    }
+
+  if (def == NULL_TREE)
+    {
+      def = vect_recog_temp_ssa_var (TREE_TYPE (oprnd0), NULL);
+      def_stmt = gimple_build_assign_with_ops (NOP_EXPR, def, oprnd1,
+					       NULL_TREE);
+      STMT_VINFO_PATTERN_DEF_STMT (stmt_vinfo) = def_stmt;
+    }
+
+  /* Pattern detected.  */
+  if (vect_print_dump_info (REPORT_DETAILS))
+    fprintf (vect_dump, "vect_recog_vector_vector_shift_pattern: detected: ");
+
+  /* Pattern supported.  Create a stmt to be used to replace the pattern.  */
+  var = vect_recog_temp_ssa_var (TREE_TYPE (oprnd0), NULL);
+  pattern_stmt = gimple_build_assign_with_ops (rhs_code, var, oprnd0, def);
+
+  if (vect_print_dump_info (REPORT_DETAILS))
+    print_gimple_stmt (vect_dump, pattern_stmt, 0, TDF_SLIM);
+
+  VEC_safe_push (gimple, heap, *stmts, last_stmt);
+  return pattern_stmt;
+}
+
 /* Function vect_recog_mixed_size_cond_pattern
 
    Try to find the following pattern: