Patchwork More vector folding

login
register
mail settings
Submitter Marc Glisse
Date June 13, 2013, 6:06 p.m.
Message ID <alpine.DEB.2.02.1306131945080.16813@stedding.saclay.inria.fr>
Download mbox | patch
Permalink /patch/251128/
State New
Headers show

Comments

Marc Glisse - June 13, 2013, 6:06 p.m.
Hello,

an incredibly suprising patch: I am adapting yet more fold-const 
transformations to vectors... (it varies, the last patch was in forwprop)

I was quite conservative with respect to complex: I didn't want to create 
a BIT_NOT_EXPR of a complex.

As an aside, while writing this patch, I noticed the following:

double f(double x){ return -2*x; }
double g(double x){ return 2*-x; }

generates mulsd for f and xorpd+addsd for g, I should probably file a PR 
about that, the running time may be similar but it is better to 
canonicalize.


2013-06-14  Marc Glisse  <marc.glisse@inria.fr>

gcc/
 	* fold-const.c (negate_expr_p): Handle VECTOR_CST.
 	(fold_negate_expr): Likewise.
 	(fold_real_zero_addition_p): Handle vectors.
 	(fold_binary_loc) <PLUS_EXPR, MINUS_EXPR>: Likewise.

gcc/testsuite/
 	* gcc.dg/fold-minus-1.c: New testcase.

Bootstrap+testsuite on x86_64-unknown-linux-gnu.
Jeff Law - June 13, 2013, 6:44 p.m.
On 06/13/13 12:06, Marc Glisse wrote:
> Hello,
>
> an incredibly suprising patch: I am adapting yet more fold-const
> transformations to vectors... (it varies, the last patch was in forwprop)
>
> I was quite conservative with respect to complex: I didn't want to
> create a BIT_NOT_EXPR of a complex.
>
> As an aside, while writing this patch, I noticed the following:
>
> double f(double x){ return -2*x; }
> double g(double x){ return 2*-x; }
>
> generates mulsd for f and xorpd+addsd for g, I should probably file a PR
> about that, the running time may be similar but it is better to
> canonicalize.
>
>
> 2013-06-14  Marc Glisse  <marc.glisse@inria.fr>
>
> gcc/
>      * fold-const.c (negate_expr_p): Handle VECTOR_CST.
>      (fold_negate_expr): Likewise.
>      (fold_real_zero_addition_p): Handle vectors.
>      (fold_binary_loc) <PLUS_EXPR, MINUS_EXPR>: Likewise.
>
> gcc/testsuite/
>      * gcc.dg/fold-minus-1.c: New testcase.
This is good.  Please install.

Thanks,
Jeff

Patch

Index: testsuite/gcc.dg/fold-minus-1.c

===================================================================
--- testsuite/gcc.dg/fold-minus-1.c	(revision 0)

+++ testsuite/gcc.dg/fold-minus-1.c	(revision 0)

@@ -0,0 +1,20 @@ 

+/* { dg-do compile } */

+/* { dg-options "-O -fdump-tree-gimple" } */

+

+typedef int vec __attribute__((vector_size(2*sizeof(int))));

+

+void f(vec*x,vec*y){

+  *x -= *x / *y * *y;

+}

+void g(vec*x,vec*y,vec*z){

+  *x = -1 - *x;

+  *y = -*y - 1;

+  *z = -*z - 13;

+}

+

+/* { dg-final { scan-tree-dump-times "%" 1 "gimple"} } */

+/* { dg-final { scan-tree-dump-times "~" 2 "gimple"} } */

+/* { dg-final { scan-tree-dump-not "/" "gimple"} } */

+/* { dg-final { scan-tree-dump-not "\\\+" "gimple"} } */

+/* { dg-final { scan-tree-dump "{ -13, -13 }" "gimple"} } */

+/* { dg-final { cleanup-tree-dump "gimple" } } */


Property changes on: testsuite/gcc.dg/fold-minus-1.c
___________________________________________________________________
Added: svn:keywords
   + Author Date Id Revision URL
Added: svn:eol-style
   + native

Index: fold-const.c

===================================================================
--- fold-const.c	(revision 200071)

+++ fold-const.c	(working copy)

@@ -414,20 +414,34 @@  negate_expr_p (tree t)

 
     case REAL_CST:
       /* We want to canonicalize to positive real constants.  Pretend
          that only negative ones can be easily negated.  */
       return REAL_VALUE_NEGATIVE (TREE_REAL_CST (t));
 
     case COMPLEX_CST:
       return negate_expr_p (TREE_REALPART (t))
 	     && negate_expr_p (TREE_IMAGPART (t));
 
+    case VECTOR_CST:

+      {

+	if (FLOAT_TYPE_P (TREE_TYPE (type)) || TYPE_OVERFLOW_WRAPS (type))

+	  return true;

+

+	int count = TYPE_VECTOR_SUBPARTS (type), i;

+

+	for (i = 0; i < count; i++)

+	  if (!negate_expr_p (VECTOR_CST_ELT (t, i)))

+	    return false;

+

+	return true;

+      }

+

     case COMPLEX_EXPR:
       return negate_expr_p (TREE_OPERAND (t, 0))
 	     && negate_expr_p (TREE_OPERAND (t, 1));
 
     case CONJ_EXPR:
       return negate_expr_p (TREE_OPERAND (t, 0));
 
     case PLUS_EXPR:
       if (HONOR_SIGN_DEPENDENT_ROUNDING (TYPE_MODE (type))
 	  || HONOR_SIGNED_ZEROS (TYPE_MODE (type)))
@@ -553,20 +567,35 @@  fold_negate_expr (location_t loc, tree t

 	tree ipart = negate_expr (TREE_IMAGPART (t));
 
 	if ((TREE_CODE (rpart) == REAL_CST
 	     && TREE_CODE (ipart) == REAL_CST)
 	    || (TREE_CODE (rpart) == INTEGER_CST
 		&& TREE_CODE (ipart) == INTEGER_CST))
 	  return build_complex (type, rpart, ipart);
       }
       break;
 
+    case VECTOR_CST:

+      {

+	int count = TYPE_VECTOR_SUBPARTS (type), i;

+	tree *elts = XALLOCAVEC (tree, count);

+

+	for (i = 0; i < count; i++)

+	  {

+	    elts[i] = fold_negate_expr (loc, VECTOR_CST_ELT (t, i));

+	    if (elts[i] == NULL_TREE)

+	      return NULL_TREE;

+	  }

+

+	return build_vector (type, elts);

+      }

+

     case COMPLEX_EXPR:
       if (negate_expr_p (t))
 	return fold_build2_loc (loc, COMPLEX_EXPR, type,
 			    fold_negate_expr (loc, TREE_OPERAND (t, 0)),
 			    fold_negate_expr (loc, TREE_OPERAND (t, 1)));
       break;
 
     case CONJ_EXPR:
       if (negate_expr_p (t))
 	return fold_build1_loc (loc, CONJ_EXPR, type,
@@ -6161,23 +6190,26 @@  fold_real_zero_addition_p (const_tree ty

     return false;
 
   /* Don't allow the fold with -fsignaling-nans.  */
   if (HONOR_SNANS (TYPE_MODE (type)))
     return false;
 
   /* Allow the fold if zeros aren't signed, or their sign isn't important.  */
   if (!HONOR_SIGNED_ZEROS (TYPE_MODE (type)))
     return true;
 
+  /* In a vector or complex, we would need to check the sign of all zeros.  */

+  if (TREE_CODE (addend) != REAL_CST)

+    return false;

+

   /* Treat x + -0 as x - 0 and x - -0 as x + 0.  */
-  if (TREE_CODE (addend) == REAL_CST

-      && REAL_VALUE_MINUS_ZERO (TREE_REAL_CST (addend)))

+  if (REAL_VALUE_MINUS_ZERO (TREE_REAL_CST (addend)))

     negate = !negate;
 
   /* The mode has signed zeros, and we have to honor their sign.
      In this situation, there is only one case we can return true for.
      X - 0 is the same as X unless rounding towards -infinity is
      supported.  */
   return negate && !HONOR_SIGN_DEPENDENT_ROUNDING (TYPE_MODE (type));
 }
 
 /* Subroutine of fold() that checks comparisons of built-in math
@@ -10154,53 +10186,53 @@  fold_binary_loc (location_t loc,

 			    fold_convert_loc (loc, type,
 					      TREE_OPERAND (arg1, 0)));
       /* (-A) + B -> B - A */
       if (TREE_CODE (arg0) == NEGATE_EXPR
 	  && reorder_operands_p (TREE_OPERAND (arg0, 0), arg1))
 	return fold_build2_loc (loc, MINUS_EXPR, type,
 			    fold_convert_loc (loc, type, arg1),
 			    fold_convert_loc (loc, type,
 					      TREE_OPERAND (arg0, 0)));
 
-      if (INTEGRAL_TYPE_P (type))

+      if (INTEGRAL_TYPE_P (type) || VECTOR_INTEGER_TYPE_P (type))

 	{
 	  /* Convert ~A + 1 to -A.  */
 	  if (TREE_CODE (arg0) == BIT_NOT_EXPR
 	      && integer_onep (arg1))
 	    return fold_build1_loc (loc, NEGATE_EXPR, type,
 				fold_convert_loc (loc, type,
 						  TREE_OPERAND (arg0, 0)));
 
 	  /* ~X + X is -1.  */
 	  if (TREE_CODE (arg0) == BIT_NOT_EXPR
 	      && !TYPE_OVERFLOW_TRAPS (type))
 	    {
 	      tree tem = TREE_OPERAND (arg0, 0);
 
 	      STRIP_NOPS (tem);
 	      if (operand_equal_p (tem, arg1, 0))
 		{
-		  t1 = build_minus_one_cst (type);

+		  t1 = build_all_ones_cst (type);

 		  return omit_one_operand_loc (loc, type, t1, arg1);
 		}
 	    }
 
 	  /* X + ~X is -1.  */
 	  if (TREE_CODE (arg1) == BIT_NOT_EXPR
 	      && !TYPE_OVERFLOW_TRAPS (type))
 	    {
 	      tree tem = TREE_OPERAND (arg1, 0);
 
 	      STRIP_NOPS (tem);
 	      if (operand_equal_p (arg0, tem, 0))
 		{
-		  t1 = build_minus_one_cst (type);

+		  t1 = build_all_ones_cst (type);

 		  return omit_one_operand_loc (loc, type, t1, arg0);
 		}
 	    }
 
 	  /* X + (X / CST) * -CST is X % CST.  */
 	  if (TREE_CODE (arg1) == MULT_EXPR
 	      && TREE_CODE (TREE_OPERAND (arg1, 0)) == TRUNC_DIV_EXPR
 	      && operand_equal_p (arg0,
 				  TREE_OPERAND (TREE_OPERAND (arg1, 0), 0), 0))
 	    {
@@ -10667,46 +10699,44 @@  fold_binary_loc (location_t loc,

 	        return fold_build2_loc (loc, PLUS_EXPR, type, tmp, arg01);
 	    }
 	}
       /* A - (-B) -> A + B */
       if (TREE_CODE (arg1) == NEGATE_EXPR)
 	return fold_build2_loc (loc, PLUS_EXPR, type, op0,
 			    fold_convert_loc (loc, type,
 					      TREE_OPERAND (arg1, 0)));
       /* (-A) - B -> (-B) - A  where B is easily negated and we can swap.  */
       if (TREE_CODE (arg0) == NEGATE_EXPR
-	  && (FLOAT_TYPE_P (type)

-	      || INTEGRAL_TYPE_P (type))

 	  && negate_expr_p (arg1)
 	  && reorder_operands_p (arg0, arg1))
 	return fold_build2_loc (loc, MINUS_EXPR, type,
 			    fold_convert_loc (loc, type,
 					      negate_expr (arg1)),
 			    fold_convert_loc (loc, type,
 					      TREE_OPERAND (arg0, 0)));
       /* Convert -A - 1 to ~A.  */
-      if (INTEGRAL_TYPE_P (type)

+      if (TREE_CODE (type) != COMPLEX_TYPE

 	  && TREE_CODE (arg0) == NEGATE_EXPR
 	  && integer_onep (arg1)
 	  && !TYPE_OVERFLOW_TRAPS (type))
 	return fold_build1_loc (loc, BIT_NOT_EXPR, type,
 			    fold_convert_loc (loc, type,
 					      TREE_OPERAND (arg0, 0)));
 
       /* Convert -1 - A to ~A.  */
-      if (INTEGRAL_TYPE_P (type)

+      if (TREE_CODE (type) != COMPLEX_TYPE

 	  && integer_all_onesp (arg0))
 	return fold_build1_loc (loc, BIT_NOT_EXPR, type, op1);
 
 
-      /* X - (X / CST) * CST is X % CST.  */

-      if (INTEGRAL_TYPE_P (type)

+      /* X - (X / Y) * Y is X % Y.  */

+      if ((INTEGRAL_TYPE_P (type) || VECTOR_INTEGER_TYPE_P (type))

 	  && TREE_CODE (arg1) == MULT_EXPR
 	  && TREE_CODE (TREE_OPERAND (arg1, 0)) == TRUNC_DIV_EXPR
 	  && operand_equal_p (arg0,
 			      TREE_OPERAND (TREE_OPERAND (arg1, 0), 0), 0)
 	  && operand_equal_p (TREE_OPERAND (TREE_OPERAND (arg1, 0), 1),
 			      TREE_OPERAND (arg1, 1), 0))
 	return
 	  fold_convert_loc (loc, type,
 			    fold_build2_loc (loc, TRUNC_MOD_EXPR, TREE_TYPE (arg0),
 					 arg0, TREE_OPERAND (arg1, 1)));