Patchwork PR tree-optimization/52633 - ICE due to vectorizer pattern detection collision

login
register
mail settings
Submitter Ulrich Weigand
Date May 4, 2012, 12:37 p.m.
Message ID <201205041237.q44Cb5wg023975@d06av02.portsmouth.uk.ibm.com>
Download mbox | patch
Permalink /patch/156902/
State New
Headers show

Comments

Ulrich Weigand - May 4, 2012, 12:37 p.m.
Richard Guenther wrote:
> On Tue, 24 Apr 2012, Ulrich Weigand wrote:
> > However, even so, it might actually be preferable to just handle such
> > cases within vect_recog_widen_shift_pattern itself.  Indeed, the routine
> > already looks for another subsequent type cast, in order to handle
> > unsigned shift variants.  Maybe it simply ought to always look for
> > another cast, and detect over-widening situations itself?
> > 
> > 
> > Does this look reasonable?  Any comments or suggestions appreciated!
> 
> Yes, getting rid of this fragile interaction by doing more work in
> vect_recog_widen_shift_pattern sounds like the correct thing to do.

The following patch implements this.  Tested with no regressions on
armv7l-linux-gnueabi and i686-linux-gnu; a couple of vectorizer tests
had to be adapted since now the widening-shift patttern matches
instead of the over-widening pattern (as expected).

Performance testing on ARM showed no regressions (and possible minor
improvements in some cases).

OK for mainline?

Bye,
Ulrich


ChangeLog:

	gcc/
	PR tree-optimization/52633
	* tree-vect-patterns.c (vect_vect_recog_func_ptrs): Swap order of
	vect_recog_widen_shift_pattern and vect_recog_over_widening_pattern.
	(vect_recog_over_widening_pattern): Remove handling of code that was
	already detected as over-widening pattern.  Remove special handling
	of "unsigned" cases.  Instead, support general case of conversion
	of the shift result to another type.

	gcc/testsuite/
	PR tree-optimization/52633
	* gcc.dg/vect/vect-over-widen-1.c: Two patterns should now be
	recognized as widening shifts instead of over-widening.
	* gcc.dg/vect/vect-over-widen-1-big-array.c: Likewise.
	* gcc.dg/vect/vect-over-widen-4.c: Likewise.
	* gcc.dg/vect/vect-over-widen-4-big-array.c: Likewise.
	* gcc.target/arm/pr52633.c: New test.
Richard Guenther - May 4, 2012, 12:41 p.m.
On Fri, 4 May 2012, Ulrich Weigand wrote:

> Richard Guenther wrote:
> > On Tue, 24 Apr 2012, Ulrich Weigand wrote:
> > > However, even so, it might actually be preferable to just handle such
> > > cases within vect_recog_widen_shift_pattern itself.  Indeed, the routine
> > > already looks for another subsequent type cast, in order to handle
> > > unsigned shift variants.  Maybe it simply ought to always look for
> > > another cast, and detect over-widening situations itself?
> > > 
> > > 
> > > Does this look reasonable?  Any comments or suggestions appreciated!
> > 
> > Yes, getting rid of this fragile interaction by doing more work in
> > vect_recog_widen_shift_pattern sounds like the correct thing to do.
> 
> The following patch implements this.  Tested with no regressions on
> armv7l-linux-gnueabi and i686-linux-gnu; a couple of vectorizer tests
> had to be adapted since now the widening-shift patttern matches
> instead of the over-widening pattern (as expected).
> 
> Performance testing on ARM showed no regressions (and possible minor
> improvements in some cases).
> 
> OK for mainline?

Ok.

Thanks,
Richard.

> Bye,
> Ulrich
> 
> 
> ChangeLog:
> 
> 	gcc/
> 	PR tree-optimization/52633
> 	* tree-vect-patterns.c (vect_vect_recog_func_ptrs): Swap order of
> 	vect_recog_widen_shift_pattern and vect_recog_over_widening_pattern.
> 	(vect_recog_over_widening_pattern): Remove handling of code that was
> 	already detected as over-widening pattern.  Remove special handling
> 	of "unsigned" cases.  Instead, support general case of conversion
> 	of the shift result to another type.
> 
> 	gcc/testsuite/
> 	PR tree-optimization/52633
> 	* gcc.dg/vect/vect-over-widen-1.c: Two patterns should now be
> 	recognized as widening shifts instead of over-widening.
> 	* gcc.dg/vect/vect-over-widen-1-big-array.c: Likewise.
> 	* gcc.dg/vect/vect-over-widen-4.c: Likewise.
> 	* gcc.dg/vect/vect-over-widen-4-big-array.c: Likewise.
> 	* gcc.target/arm/pr52633.c: New test.
> 
> 
> Index: gcc-head/gcc/tree-vect-patterns.c
> ===================================================================
> --- gcc-head.orig/gcc/tree-vect-patterns.c	2012-05-04 14:23:38.000000000 +0200
> +++ gcc-head/gcc/tree-vect-patterns.c	2012-05-04 14:24:06.000000000 +0200
> @@ -63,8 +63,8 @@ static vect_recog_func_ptr vect_vect_rec
>  	vect_recog_widen_sum_pattern,
>  	vect_recog_dot_prod_pattern,
>  	vect_recog_pow_pattern,
> -	vect_recog_over_widening_pattern,
>  	vect_recog_widen_shift_pattern,
> +	vect_recog_over_widening_pattern,
>  	vect_recog_vector_vector_shift_pattern,
>  	vect_recog_sdivmod_pow2_pattern,
>  	vect_recog_mixed_size_cond_pattern,
> @@ -1309,16 +1309,20 @@ vect_recog_over_widening_pattern (VEC (g
>  
>    where type 'TYPE' is at least double the size of type 'type'.
>  
> -  Also detect unsigned cases:
> +  Also detect cases where the shift result is immediately converted
> +  to another type 'result_type' that is no larger in size than 'TYPE'.
> +  In those cases we perform a widen-shift that directly results in
> +  'result_type', to avoid a possible over-widening situation:
>  
> -  unsigned type a_t;
> -  unsigned TYPE u_res_T;
> +  type a_t;
>    TYPE a_T, res_T;
> +  result_type res_result;
>  
>    S1 a_t = ;
>    S2 a_T = (TYPE) a_t;
>    S3 res_T = a_T << CONST;
> -  S4 u_res_T = (unsigned TYPE) res_T;
> +  S4 res_result = (result_type) res_T;
> +      '--> res_result' = a_t w<< CONST;
>  
>    And a case when 'TYPE' is 4 times bigger than 'type'.  In that case we
>    create an additional pattern stmt for S2 to create a variable of an
> @@ -1359,60 +1363,21 @@ vect_recog_widen_shift_pattern (VEC (gim
>    gimple def_stmt0;
>    tree oprnd0, oprnd1;
>    tree type, half_type0;
> -  gimple pattern_stmt, orig_stmt = NULL;
> +  gimple pattern_stmt;
>    tree vectype, vectype_out = NULL_TREE;
>    tree dummy;
>    tree var;
>    enum tree_code dummy_code;
>    int dummy_int;
>    VEC (tree, heap) * dummy_vec;
> -  gimple use_stmt = NULL;
> -  bool over_widen = false;
> +  gimple use_stmt;
>    bool promotion;
>  
>    if (!is_gimple_assign (last_stmt) || !vinfo_for_stmt (last_stmt))
>      return NULL;
>  
> -  orig_stmt = last_stmt;
>    if (STMT_VINFO_IN_PATTERN_P (vinfo_for_stmt (last_stmt)))
> -    {
> -      /* This statement was also detected as over-widening operation (it can't
> -         be any other pattern, because only over-widening detects shifts).
> -         LAST_STMT is the final type demotion statement, but its related
> -         statement is shift.  We analyze the related statement to catch cases:
> -
> -         orig code:
> -          type a_t;
> -          itype res;
> -          TYPE a_T, res_T;
> -
> -          S1 a_T = (TYPE) a_t;
> -          S2 res_T = a_T << CONST;
> -          S3 res = (itype)res_T;
> -
> -          (size of type * 2 <= size of itype
> -           and size of itype * 2 <= size of TYPE)
> -
> -         code after over-widening pattern detection:
> -
> -          S1 a_T = (TYPE) a_t;
> -               --> a_it = (itype) a_t;
> -          S2 res_T = a_T << CONST;
> -          S3 res = (itype)res_T;  <--- LAST_STMT
> -               --> res = a_it << CONST;
> -
> -         after widen_shift:
> -
> -          S1 a_T = (TYPE) a_t;
> -               --> a_it = (itype) a_t; - redundant
> -          S2 res_T = a_T << CONST;
> -          S3 res = (itype)res_T;
> -               --> res = a_t w<< CONST;
> -
> -      i.e., we replace the three statements with res = a_t w<< CONST.  */
> -      last_stmt = STMT_VINFO_RELATED_STMT (vinfo_for_stmt (last_stmt));
> -      over_widen = true;
> -    }
> +    return NULL;
>  
>    if (gimple_assign_rhs_code (last_stmt) != LSHIFT_EXPR)
>      return NULL;
> @@ -1436,49 +1401,29 @@ vect_recog_widen_shift_pattern (VEC (gim
>    oprnd0 = gimple_assign_rhs1 (def_stmt0);
>    type = gimple_expr_type (last_stmt);
>  
> +  /* Check for subsequent conversion to another type.  */
> +  use_stmt = vect_single_imm_use (last_stmt);
> +  if (use_stmt && is_gimple_assign (use_stmt)
> +      && CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (use_stmt))
> +      && !STMT_VINFO_IN_PATTERN_P (vinfo_for_stmt (use_stmt)))
> +    {
> +      tree use_lhs = gimple_assign_lhs (use_stmt);
> +      tree use_type = TREE_TYPE (use_lhs);
> +
> +      if (INTEGRAL_TYPE_P (use_type)
> +	  && TYPE_PRECISION (use_type) <= TYPE_PRECISION (type))
> +	{
> +	  last_stmt = use_stmt;
> +	  type = use_type;
> +	}
> +    }
> +
>    /* Check if this a widening operation.  */
>    if (!vect_handle_widen_op_by_const (last_stmt, LSHIFT_EXPR, oprnd1,
>         				      &oprnd0, stmts,
>  	                              type, &half_type0, def_stmt0))
>      return NULL;
>  
> -  /* Handle unsigned case.  Look for
> -     S4  u_res_T = (unsigned TYPE) res_T;
> -     Use unsigned TYPE as the type for WIDEN_LSHIFT_EXPR.  */
> -  if (TYPE_UNSIGNED (type) != TYPE_UNSIGNED (half_type0))
> -    {
> -      if (over_widen)
> -        {
> -          /* In case of over-widening pattern, S4 should be ORIG_STMT itself.
> -             We check here that TYPE is the correct type for the operation,
> -             i.e., it's the type of the original result.  */
> -          tree orig_type = gimple_expr_type (orig_stmt);
> -          if ((TYPE_UNSIGNED (type) != TYPE_UNSIGNED (orig_type))
> -              || (TYPE_PRECISION (type) != TYPE_PRECISION (orig_type)))
> -            return NULL;
> -        }
> -      else
> -        {
> -	  tree use_type;
> -	  tree use_lhs;
> -
> -	  use_stmt = vect_single_imm_use (last_stmt);
> -	  if (!use_stmt || !is_gimple_assign (use_stmt)
> -	      || !CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (use_stmt)))
> -	    return NULL;
> -
> -          use_lhs = gimple_assign_lhs (use_stmt);
> -          use_type = TREE_TYPE (use_lhs);
> -
> -          if (!INTEGRAL_TYPE_P (use_type)
> -              || (TYPE_UNSIGNED (type) == TYPE_UNSIGNED (use_type))
> -              || (TYPE_PRECISION (type) != TYPE_PRECISION (use_type)))
> -            return NULL;
> -
> -          type = use_type;
> -        }
> -    }
> -
>    /* Pattern detected.  */
>    if (vect_print_dump_info (REPORT_DETAILS))
>      fprintf (vect_dump, "vect_recog_widen_shift_pattern: detected: ");
> @@ -1507,11 +1452,6 @@ vect_recog_widen_shift_pattern (VEC (gim
>    if (vect_print_dump_info (REPORT_DETAILS))
>      print_gimple_stmt (vect_dump, pattern_stmt, 0, TDF_SLIM);
>  
> -  if (use_stmt)
> -    last_stmt = use_stmt;
> -  else
> -    last_stmt = orig_stmt;
> -
>    VEC_safe_push (gimple, heap, *stmts, last_stmt);
>    return pattern_stmt;
>  }
> Index: gcc-head/gcc/testsuite/gcc.dg/vect/vect-over-widen-1-big-array.c
> ===================================================================
> --- gcc-head.orig/gcc/testsuite/gcc.dg/vect/vect-over-widen-1-big-array.c	2012-05-04 14:04:24.000000000 +0200
> +++ gcc-head/gcc/testsuite/gcc.dg/vect/vect-over-widen-1-big-array.c	2012-05-04 14:24:06.000000000 +0200
> @@ -58,7 +58,9 @@ int main (void)
>    return 0;
>  }
>  
> -/* { dg-final { scan-tree-dump-times "vect_recog_over_widening_pattern: detected" 4 "vect" } } */
> +/* { dg-final { scan-tree-dump-times "vect_recog_widen_shift_pattern: detected" 2 "vect" { target vect_widen_shift } } } */
> +/* { dg-final { scan-tree-dump-times "vect_recog_over_widening_pattern: detected" 2 "vect" { target vect_widen_shift } } } */
> +/* { dg-final { scan-tree-dump-times "vect_recog_over_widening_pattern: detected" 4 "vect" { target { ! vect_widen_shift } } } } */
>  /* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" } } */
>  /* { dg-final { cleanup-tree-dump "vect" } } */
>  
> Index: gcc-head/gcc/testsuite/gcc.dg/vect/vect-over-widen-1.c
> ===================================================================
> --- gcc-head.orig/gcc/testsuite/gcc.dg/vect/vect-over-widen-1.c	2012-05-04 14:04:24.000000000 +0200
> +++ gcc-head/gcc/testsuite/gcc.dg/vect/vect-over-widen-1.c	2012-05-04 14:24:07.000000000 +0200
> @@ -58,7 +58,9 @@ int main (void)
>    return 0;
>  }
>  
> -/* { dg-final { scan-tree-dump-times "vect_recog_over_widening_pattern: detected" 4 "vect" { target {! vect_sizes_32B_16B} } } } */
> +/* { dg-final { scan-tree-dump-times "vect_recog_widen_shift_pattern: detected" 2 "vect" { target vect_widen_shift } } } */
> +/* { dg-final { scan-tree-dump-times "vect_recog_over_widening_pattern: detected" 2 "vect" { target vect_widen_shift } } } */
> +/* { dg-final { scan-tree-dump-times "vect_recog_over_widening_pattern: detected" 4 "vect" { target { { ! vect_sizes_32B_16B } && { ! vect_widen_shift } } } } } */
>  /* { dg-final { scan-tree-dump-times "vect_recog_over_widening_pattern: detected" 8 "vect" { target vect_sizes_32B_16B } } } */
>  /* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" } } */
>  /* { dg-final { cleanup-tree-dump "vect" } } */
> Index: gcc-head/gcc/testsuite/gcc.dg/vect/vect-over-widen-4-big-array.c
> ===================================================================
> --- gcc-head.orig/gcc/testsuite/gcc.dg/vect/vect-over-widen-4-big-array.c	2012-05-04 14:04:24.000000000 +0200
> +++ gcc-head/gcc/testsuite/gcc.dg/vect/vect-over-widen-4-big-array.c	2012-05-04 14:24:07.000000000 +0200
> @@ -62,7 +62,9 @@ int main (void)
>    return 0;
>  }
>  
> -/* { dg-final { scan-tree-dump-times "vect_recog_over_widening_pattern: detected" 4 "vect" } } */
> +/* { dg-final { scan-tree-dump-times "vect_recog_widen_shift_pattern: detected" 2 "vect" { target vect_widen_shift } } } */
> +/* { dg-final { scan-tree-dump-times "vect_recog_over_widening_pattern: detected" 2 "vect" { target vect_widen_shift } } } */
> +/* { dg-final { scan-tree-dump-times "vect_recog_over_widening_pattern: detected" 4 "vect" { target { ! vect_widen_shift } } } } */
>  /* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" } } */
>  /* { dg-final { cleanup-tree-dump "vect" } } */
>  
> Index: gcc-head/gcc/testsuite/gcc.dg/vect/vect-over-widen-4.c
> ===================================================================
> --- gcc-head.orig/gcc/testsuite/gcc.dg/vect/vect-over-widen-4.c	2012-05-04 14:04:24.000000000 +0200
> +++ gcc-head/gcc/testsuite/gcc.dg/vect/vect-over-widen-4.c	2012-05-04 14:24:07.000000000 +0200
> @@ -62,7 +62,9 @@ int main (void)
>    return 0;
>  }
>  
> -/* { dg-final { scan-tree-dump-times "vect_recog_over_widening_pattern: detected" 4 "vect" { target {! vect_sizes_32B_16B } } } } */
> +/* { dg-final { scan-tree-dump-times "vect_recog_widen_shift_pattern: detected" 2 "vect" { target vect_widen_shift } } } */
> +/* { dg-final { scan-tree-dump-times "vect_recog_over_widening_pattern: detected" 2 "vect" { target vect_widen_shift } } } */
> +/* { dg-final { scan-tree-dump-times "vect_recog_over_widening_pattern: detected" 4 "vect" { target { { ! vect_sizes_32B_16B } && { ! vect_widen_shift } } } } } */
>  /* { dg-final { scan-tree-dump-times "vect_recog_over_widening_pattern: detected" 8 "vect" { target vect_sizes_32B_16B } } } */
>  /* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" } } */
>  /* { dg-final { cleanup-tree-dump "vect" } } */
> Index: gcc-head/gcc/testsuite/gcc.target/arm/pr52633.c
> ===================================================================
> --- /dev/null	1970-01-01 00:00:00.000000000 +0000
> +++ gcc-head/gcc/testsuite/gcc.target/arm/pr52633.c	2012-05-04 14:24:07.000000000 +0200
> @@ -0,0 +1,13 @@
> +/* PR tree-optimization/52633 */
> +/* { dg-do compile } */
> +/* { dg-require-effective-target arm_neon_ok } */
> +/* { dg-options "-march=armv7-a -mfloat-abi=softfp -mfpu=neon -O -ftree-vectorize" } */
> +
> +void
> +test (unsigned short *x, signed char *y)
> +{
> +  int i;
> +  for (i = 0; i < 32; i++)
> +    x[i] = (short) (y[i] << 5);
> +}
> +
> 
>

Patch

Index: gcc-head/gcc/tree-vect-patterns.c
===================================================================
--- gcc-head.orig/gcc/tree-vect-patterns.c	2012-05-04 14:23:38.000000000 +0200
+++ gcc-head/gcc/tree-vect-patterns.c	2012-05-04 14:24:06.000000000 +0200
@@ -63,8 +63,8 @@  static vect_recog_func_ptr vect_vect_rec
 	vect_recog_widen_sum_pattern,
 	vect_recog_dot_prod_pattern,
 	vect_recog_pow_pattern,
-	vect_recog_over_widening_pattern,
 	vect_recog_widen_shift_pattern,
+	vect_recog_over_widening_pattern,
 	vect_recog_vector_vector_shift_pattern,
 	vect_recog_sdivmod_pow2_pattern,
 	vect_recog_mixed_size_cond_pattern,
@@ -1309,16 +1309,20 @@  vect_recog_over_widening_pattern (VEC (g
 
   where type 'TYPE' is at least double the size of type 'type'.
 
-  Also detect unsigned cases:
+  Also detect cases where the shift result is immediately converted
+  to another type 'result_type' that is no larger in size than 'TYPE'.
+  In those cases we perform a widen-shift that directly results in
+  'result_type', to avoid a possible over-widening situation:
 
-  unsigned type a_t;
-  unsigned TYPE u_res_T;
+  type a_t;
   TYPE a_T, res_T;
+  result_type res_result;
 
   S1 a_t = ;
   S2 a_T = (TYPE) a_t;
   S3 res_T = a_T << CONST;
-  S4 u_res_T = (unsigned TYPE) res_T;
+  S4 res_result = (result_type) res_T;
+      '--> res_result' = a_t w<< CONST;
 
   And a case when 'TYPE' is 4 times bigger than 'type'.  In that case we
   create an additional pattern stmt for S2 to create a variable of an
@@ -1359,60 +1363,21 @@  vect_recog_widen_shift_pattern (VEC (gim
   gimple def_stmt0;
   tree oprnd0, oprnd1;
   tree type, half_type0;
-  gimple pattern_stmt, orig_stmt = NULL;
+  gimple pattern_stmt;
   tree vectype, vectype_out = NULL_TREE;
   tree dummy;
   tree var;
   enum tree_code dummy_code;
   int dummy_int;
   VEC (tree, heap) * dummy_vec;
-  gimple use_stmt = NULL;
-  bool over_widen = false;
+  gimple use_stmt;
   bool promotion;
 
   if (!is_gimple_assign (last_stmt) || !vinfo_for_stmt (last_stmt))
     return NULL;
 
-  orig_stmt = last_stmt;
   if (STMT_VINFO_IN_PATTERN_P (vinfo_for_stmt (last_stmt)))
-    {
-      /* This statement was also detected as over-widening operation (it can't
-         be any other pattern, because only over-widening detects shifts).
-         LAST_STMT is the final type demotion statement, but its related
-         statement is shift.  We analyze the related statement to catch cases:
-
-         orig code:
-          type a_t;
-          itype res;
-          TYPE a_T, res_T;
-
-          S1 a_T = (TYPE) a_t;
-          S2 res_T = a_T << CONST;
-          S3 res = (itype)res_T;
-
-          (size of type * 2 <= size of itype
-           and size of itype * 2 <= size of TYPE)
-
-         code after over-widening pattern detection:
-
-          S1 a_T = (TYPE) a_t;
-               --> a_it = (itype) a_t;
-          S2 res_T = a_T << CONST;
-          S3 res = (itype)res_T;  <--- LAST_STMT
-               --> res = a_it << CONST;
-
-         after widen_shift:
-
-          S1 a_T = (TYPE) a_t;
-               --> a_it = (itype) a_t; - redundant
-          S2 res_T = a_T << CONST;
-          S3 res = (itype)res_T;
-               --> res = a_t w<< CONST;
-
-      i.e., we replace the three statements with res = a_t w<< CONST.  */
-      last_stmt = STMT_VINFO_RELATED_STMT (vinfo_for_stmt (last_stmt));
-      over_widen = true;
-    }
+    return NULL;
 
   if (gimple_assign_rhs_code (last_stmt) != LSHIFT_EXPR)
     return NULL;
@@ -1436,49 +1401,29 @@  vect_recog_widen_shift_pattern (VEC (gim
   oprnd0 = gimple_assign_rhs1 (def_stmt0);
   type = gimple_expr_type (last_stmt);
 
+  /* Check for subsequent conversion to another type.  */
+  use_stmt = vect_single_imm_use (last_stmt);
+  if (use_stmt && is_gimple_assign (use_stmt)
+      && CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (use_stmt))
+      && !STMT_VINFO_IN_PATTERN_P (vinfo_for_stmt (use_stmt)))
+    {
+      tree use_lhs = gimple_assign_lhs (use_stmt);
+      tree use_type = TREE_TYPE (use_lhs);
+
+      if (INTEGRAL_TYPE_P (use_type)
+	  && TYPE_PRECISION (use_type) <= TYPE_PRECISION (type))
+	{
+	  last_stmt = use_stmt;
+	  type = use_type;
+	}
+    }
+
   /* Check if this a widening operation.  */
   if (!vect_handle_widen_op_by_const (last_stmt, LSHIFT_EXPR, oprnd1,
        				      &oprnd0, stmts,
 	                              type, &half_type0, def_stmt0))
     return NULL;
 
-  /* Handle unsigned case.  Look for
-     S4  u_res_T = (unsigned TYPE) res_T;
-     Use unsigned TYPE as the type for WIDEN_LSHIFT_EXPR.  */
-  if (TYPE_UNSIGNED (type) != TYPE_UNSIGNED (half_type0))
-    {
-      if (over_widen)
-        {
-          /* In case of over-widening pattern, S4 should be ORIG_STMT itself.
-             We check here that TYPE is the correct type for the operation,
-             i.e., it's the type of the original result.  */
-          tree orig_type = gimple_expr_type (orig_stmt);
-          if ((TYPE_UNSIGNED (type) != TYPE_UNSIGNED (orig_type))
-              || (TYPE_PRECISION (type) != TYPE_PRECISION (orig_type)))
-            return NULL;
-        }
-      else
-        {
-	  tree use_type;
-	  tree use_lhs;
-
-	  use_stmt = vect_single_imm_use (last_stmt);
-	  if (!use_stmt || !is_gimple_assign (use_stmt)
-	      || !CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (use_stmt)))
-	    return NULL;
-
-          use_lhs = gimple_assign_lhs (use_stmt);
-          use_type = TREE_TYPE (use_lhs);
-
-          if (!INTEGRAL_TYPE_P (use_type)
-              || (TYPE_UNSIGNED (type) == TYPE_UNSIGNED (use_type))
-              || (TYPE_PRECISION (type) != TYPE_PRECISION (use_type)))
-            return NULL;
-
-          type = use_type;
-        }
-    }
-
   /* Pattern detected.  */
   if (vect_print_dump_info (REPORT_DETAILS))
     fprintf (vect_dump, "vect_recog_widen_shift_pattern: detected: ");
@@ -1507,11 +1452,6 @@  vect_recog_widen_shift_pattern (VEC (gim
   if (vect_print_dump_info (REPORT_DETAILS))
     print_gimple_stmt (vect_dump, pattern_stmt, 0, TDF_SLIM);
 
-  if (use_stmt)
-    last_stmt = use_stmt;
-  else
-    last_stmt = orig_stmt;
-
   VEC_safe_push (gimple, heap, *stmts, last_stmt);
   return pattern_stmt;
 }
Index: gcc-head/gcc/testsuite/gcc.dg/vect/vect-over-widen-1-big-array.c
===================================================================
--- gcc-head.orig/gcc/testsuite/gcc.dg/vect/vect-over-widen-1-big-array.c	2012-05-04 14:04:24.000000000 +0200
+++ gcc-head/gcc/testsuite/gcc.dg/vect/vect-over-widen-1-big-array.c	2012-05-04 14:24:06.000000000 +0200
@@ -58,7 +58,9 @@  int main (void)
   return 0;
 }
 
-/* { dg-final { scan-tree-dump-times "vect_recog_over_widening_pattern: detected" 4 "vect" } } */
+/* { dg-final { scan-tree-dump-times "vect_recog_widen_shift_pattern: detected" 2 "vect" { target vect_widen_shift } } } */
+/* { dg-final { scan-tree-dump-times "vect_recog_over_widening_pattern: detected" 2 "vect" { target vect_widen_shift } } } */
+/* { dg-final { scan-tree-dump-times "vect_recog_over_widening_pattern: detected" 4 "vect" { target { ! vect_widen_shift } } } } */
 /* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" } } */
 /* { dg-final { cleanup-tree-dump "vect" } } */
 
Index: gcc-head/gcc/testsuite/gcc.dg/vect/vect-over-widen-1.c
===================================================================
--- gcc-head.orig/gcc/testsuite/gcc.dg/vect/vect-over-widen-1.c	2012-05-04 14:04:24.000000000 +0200
+++ gcc-head/gcc/testsuite/gcc.dg/vect/vect-over-widen-1.c	2012-05-04 14:24:07.000000000 +0200
@@ -58,7 +58,9 @@  int main (void)
   return 0;
 }
 
-/* { dg-final { scan-tree-dump-times "vect_recog_over_widening_pattern: detected" 4 "vect" { target {! vect_sizes_32B_16B} } } } */
+/* { dg-final { scan-tree-dump-times "vect_recog_widen_shift_pattern: detected" 2 "vect" { target vect_widen_shift } } } */
+/* { dg-final { scan-tree-dump-times "vect_recog_over_widening_pattern: detected" 2 "vect" { target vect_widen_shift } } } */
+/* { dg-final { scan-tree-dump-times "vect_recog_over_widening_pattern: detected" 4 "vect" { target { { ! vect_sizes_32B_16B } && { ! vect_widen_shift } } } } } */
 /* { dg-final { scan-tree-dump-times "vect_recog_over_widening_pattern: detected" 8 "vect" { target vect_sizes_32B_16B } } } */
 /* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" } } */
 /* { dg-final { cleanup-tree-dump "vect" } } */
Index: gcc-head/gcc/testsuite/gcc.dg/vect/vect-over-widen-4-big-array.c
===================================================================
--- gcc-head.orig/gcc/testsuite/gcc.dg/vect/vect-over-widen-4-big-array.c	2012-05-04 14:04:24.000000000 +0200
+++ gcc-head/gcc/testsuite/gcc.dg/vect/vect-over-widen-4-big-array.c	2012-05-04 14:24:07.000000000 +0200
@@ -62,7 +62,9 @@  int main (void)
   return 0;
 }
 
-/* { dg-final { scan-tree-dump-times "vect_recog_over_widening_pattern: detected" 4 "vect" } } */
+/* { dg-final { scan-tree-dump-times "vect_recog_widen_shift_pattern: detected" 2 "vect" { target vect_widen_shift } } } */
+/* { dg-final { scan-tree-dump-times "vect_recog_over_widening_pattern: detected" 2 "vect" { target vect_widen_shift } } } */
+/* { dg-final { scan-tree-dump-times "vect_recog_over_widening_pattern: detected" 4 "vect" { target { ! vect_widen_shift } } } } */
 /* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" } } */
 /* { dg-final { cleanup-tree-dump "vect" } } */
 
Index: gcc-head/gcc/testsuite/gcc.dg/vect/vect-over-widen-4.c
===================================================================
--- gcc-head.orig/gcc/testsuite/gcc.dg/vect/vect-over-widen-4.c	2012-05-04 14:04:24.000000000 +0200
+++ gcc-head/gcc/testsuite/gcc.dg/vect/vect-over-widen-4.c	2012-05-04 14:24:07.000000000 +0200
@@ -62,7 +62,9 @@  int main (void)
   return 0;
 }
 
-/* { dg-final { scan-tree-dump-times "vect_recog_over_widening_pattern: detected" 4 "vect" { target {! vect_sizes_32B_16B } } } } */
+/* { dg-final { scan-tree-dump-times "vect_recog_widen_shift_pattern: detected" 2 "vect" { target vect_widen_shift } } } */
+/* { dg-final { scan-tree-dump-times "vect_recog_over_widening_pattern: detected" 2 "vect" { target vect_widen_shift } } } */
+/* { dg-final { scan-tree-dump-times "vect_recog_over_widening_pattern: detected" 4 "vect" { target { { ! vect_sizes_32B_16B } && { ! vect_widen_shift } } } } } */
 /* { dg-final { scan-tree-dump-times "vect_recog_over_widening_pattern: detected" 8 "vect" { target vect_sizes_32B_16B } } } */
 /* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" } } */
 /* { dg-final { cleanup-tree-dump "vect" } } */
Index: gcc-head/gcc/testsuite/gcc.target/arm/pr52633.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ gcc-head/gcc/testsuite/gcc.target/arm/pr52633.c	2012-05-04 14:24:07.000000000 +0200
@@ -0,0 +1,13 @@ 
+/* PR tree-optimization/52633 */
+/* { dg-do compile } */
+/* { dg-require-effective-target arm_neon_ok } */
+/* { dg-options "-march=armv7-a -mfloat-abi=softfp -mfpu=neon -O -ftree-vectorize" } */
+
+void
+test (unsigned short *x, signed char *y)
+{
+  int i;
+  for (i = 0; i < 32; i++)
+    x[i] = (short) (y[i] << 5);
+}
+