Patchwork Fold VEC_[LR]SHIFT_EXPR (PR tree-optimization/57051)

login
register
mail settings
Submitter Jakub Jelinek
Date April 25, 2013, 9:47 p.m.
Message ID <20130425214702.GJ28963@tucnak.redhat.com>
Download mbox | patch
Permalink /patch/239599/
State New
Headers show

Comments

Jakub Jelinek - April 25, 2013, 9:47 p.m.
Hi!

This patch adds folding of constant arguments v>> and v<<, which helps to
optimize the testcase from the PR back into constant store after vectorized
loop is unrolled.

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

2013-04-25  Jakub Jelinek  <jakub@redhat.com>

	PR tree-optimization/57051
	* fold-const.c (const_binop): Handle VEC_LSHIFT_EXPR
	and VEC_RSHIFT_EXPR if shift count is a multiple of element
	bitsize.


	Jakub
Richard Guenther - April 26, 2013, 7:39 a.m.
On Thu, 25 Apr 2013, Jakub Jelinek wrote:

> Hi!
> 
> This patch adds folding of constant arguments v>> and v<<, which helps to
> optimize the testcase from the PR back into constant store after vectorized
> loop is unrolled.
> 
> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

Ok.

Thanks,
Richard.

> 2013-04-25  Jakub Jelinek  <jakub@redhat.com>
> 
> 	PR tree-optimization/57051
> 	* fold-const.c (const_binop): Handle VEC_LSHIFT_EXPR
> 	and VEC_RSHIFT_EXPR if shift count is a multiple of element
> 	bitsize.
> 
> --- gcc/fold-const.c.jj	2013-04-12 10:16:25.000000000 +0200
> +++ gcc/fold-const.c	2013-04-24 12:37:11.789122719 +0200
> @@ -1380,17 +1380,42 @@ const_binop (enum tree_code code, tree a
>        int count = TYPE_VECTOR_SUBPARTS (type), i;
>        tree *elts = XALLOCAVEC (tree, count);
>  
> -      for (i = 0; i < count; i++)
> +      if (code == VEC_LSHIFT_EXPR
> +	  || code == VEC_RSHIFT_EXPR)
>  	{
> -	  tree elem1 = VECTOR_CST_ELT (arg1, i);
> -
> -	  elts[i] = const_binop (code, elem1, arg2);
> +	  if (!host_integerp (arg2, 1))
> +	    return NULL_TREE;
>  
> -	  /* It is possible that const_binop cannot handle the given
> -	     code and return NULL_TREE */
> -	  if (elts[i] == NULL_TREE)
> +	  unsigned HOST_WIDE_INT shiftc = tree_low_cst (arg2, 1);
> +	  unsigned HOST_WIDE_INT outerc = tree_low_cst (TYPE_SIZE (type), 1);
> +	  unsigned HOST_WIDE_INT innerc
> +	    = tree_low_cst (TYPE_SIZE (TREE_TYPE (type)), 1);
> +	  if (shiftc >= outerc || (shiftc % innerc) != 0)
>  	    return NULL_TREE;
> +	  int offset = shiftc / innerc;
> +	  if (code == VEC_LSHIFT_EXPR)
> +	    offset = -offset;
> +	  tree zero = build_zero_cst (TREE_TYPE (type));
> +	  for (i = 0; i < count; i++)
> +	    {
> +	      if (i + offset < 0 || i + offset >= count)
> +		elts[i] = zero;
> +	      else
> +		elts[i] = VECTOR_CST_ELT (arg1, i + offset);
> +	    }
>  	}
> +      else
> +	for (i = 0; i < count; i++)
> +	  {
> +	    tree elem1 = VECTOR_CST_ELT (arg1, i);
> +
> +	    elts[i] = const_binop (code, elem1, arg2);
> +
> +	    /* It is possible that const_binop cannot handle the given
> +	       code and return NULL_TREE */
> +	    if (elts[i] == NULL_TREE)
> +	      return NULL_TREE;
> +	  }
>  
>        return build_vector (type, elts);
>      }
> 
> 	Jakub
> 
>

Patch

--- gcc/fold-const.c.jj	2013-04-12 10:16:25.000000000 +0200
+++ gcc/fold-const.c	2013-04-24 12:37:11.789122719 +0200
@@ -1380,17 +1380,42 @@  const_binop (enum tree_code code, tree a
       int count = TYPE_VECTOR_SUBPARTS (type), i;
       tree *elts = XALLOCAVEC (tree, count);
 
-      for (i = 0; i < count; i++)
+      if (code == VEC_LSHIFT_EXPR
+	  || code == VEC_RSHIFT_EXPR)
 	{
-	  tree elem1 = VECTOR_CST_ELT (arg1, i);
-
-	  elts[i] = const_binop (code, elem1, arg2);
+	  if (!host_integerp (arg2, 1))
+	    return NULL_TREE;
 
-	  /* It is possible that const_binop cannot handle the given
-	     code and return NULL_TREE */
-	  if (elts[i] == NULL_TREE)
+	  unsigned HOST_WIDE_INT shiftc = tree_low_cst (arg2, 1);
+	  unsigned HOST_WIDE_INT outerc = tree_low_cst (TYPE_SIZE (type), 1);
+	  unsigned HOST_WIDE_INT innerc
+	    = tree_low_cst (TYPE_SIZE (TREE_TYPE (type)), 1);
+	  if (shiftc >= outerc || (shiftc % innerc) != 0)
 	    return NULL_TREE;
+	  int offset = shiftc / innerc;
+	  if (code == VEC_LSHIFT_EXPR)
+	    offset = -offset;
+	  tree zero = build_zero_cst (TREE_TYPE (type));
+	  for (i = 0; i < count; i++)
+	    {
+	      if (i + offset < 0 || i + offset >= count)
+		elts[i] = zero;
+	      else
+		elts[i] = VECTOR_CST_ELT (arg1, i + offset);
+	    }
 	}
+      else
+	for (i = 0; i < count; i++)
+	  {
+	    tree elem1 = VECTOR_CST_ELT (arg1, i);
+
+	    elts[i] = const_binop (code, elem1, arg2);
+
+	    /* It is possible that const_binop cannot handle the given
+	       code and return NULL_TREE */
+	    if (elts[i] == NULL_TREE)
+	      return NULL_TREE;
+	  }
 
       return build_vector (type, elts);
     }