real_zerop for vectors

Submitted by Marc Glisse on Oct. 28, 2012, 3:14 p.m.

Details

Message ID alpine.DEB.2.02.1210281554180.4597@stedding.saclay.inria.fr
State New
Headers show

Commit Message

Marc Glisse Oct. 28, 2012, 3:14 p.m.
Hello,

this patch lets some predicates on floating point constants answer true 
for vectors, so optimizations are applied.

Tested bootstrap + testsuite (default languages).

2012-10-29  Marc Glisse  <marc.glisse@inria.fr>

 	PR middle-end/55027

gcc/
 	* tree.c (real_zerop, real_onep, real_twop, real_minus_onep):
 	Handle VECTOR_CST.

testsuite/
 	* gcc.dg/pr55027.c: New testcase.

Comments

Paolo Carlini Oct. 28, 2012, 3:46 p.m.
On 10/28/2012 04:14 PM, Marc Glisse wrote:
> Hello,
>
> this patch lets some predicates on floating point constants answer 
> true for vectors, so optimizations are applied.
Great.

I wonder how are we doing lately in terms of function pointer inlining?! 
If the current optimizers can already able to smoothly inline real_zerop 
& co we could have a single helper function and avoid all this 
redundancy... In case, I suppose other code could also benefit.

Thanks,
Paolo.
Paolo Carlini Oct. 28, 2012, 3:54 p.m.
On 10/28/2012 04:46 PM, Paolo Carlini wrote:
> On 10/28/2012 04:14 PM, Marc Glisse wrote:
>> Hello,
>>
>> this patch lets some predicates on floating point constants answer 
>> true for vectors, so optimizations are applied.
> Great.
>
> I wonder how are we doing lately in terms of function pointer 
> inlining?! If the current optimizers can already able to smoothly 
> inline real_zerop & co we could have a single helper function and 
> avoid all this redundancy... In case, I suppose other code could also 
> benefit.
Uhm, sorry, I didn't notice the functions are recursive. The situation 
seems hopeless, too bad.

Paolo.
Marc Glisse Oct. 28, 2012, 4:34 p.m.
On Sun, 28 Oct 2012, Paolo Carlini wrote:

> On 10/28/2012 04:46 PM, Paolo Carlini wrote:
>> On 10/28/2012 04:14 PM, Marc Glisse wrote:
>>> Hello,
>>> 
>>> this patch lets some predicates on floating point constants answer true 
>>> for vectors, so optimizations are applied.
>> Great.
>> 
>> I wonder how are we doing lately in terms of function pointer inlining?! If 
>> the current optimizers can already able to smoothly inline real_zerop & co

Inlining real_zerop can only happen in lto builds.

>> we could have a single helper function and avoid all this redundancy... In 
>> case, I suppose other code could also benefit.
> Uhm, sorry, I didn't notice the functions are recursive. The situation seems 
> hopeless, too bad.

The recursion has a bounded depth of 2 ;-)

It is true that we could have a single function in tree.c:
bool real_intcstp (const_tree, int);

with possible trivial wrappers in tree.h.
Marc Glisse Oct. 28, 2012, 4:51 p.m.
On Sun, 28 Oct 2012, Marc Glisse wrote:

[there are 4 real_*p that only differ by 1 character]

> It is true that we could have a single function in tree.c:
> bool real_intcstp (const_tree, int);

The helper function could even take a REAL_VALUE_TYPE as second 
argument, so the non-inline part doesn't have more work than currently.

Trying to also merge the real_*p predicates with the integer_*p predicates 
seems harder (in fancy C++, we'd have a number of ways of writing the code 
for complex and vectors only once, but I don't think we want to go there).

> with possible trivial wrappers in tree.h.
Richard Guenther Oct. 29, 2012, 2:05 p.m.
On Sun, Oct 28, 2012 at 4:14 PM, Marc Glisse <marc.glisse@inria.fr> wrote:
> Hello,
>
> this patch lets some predicates on floating point constants answer true for
> vectors, so optimizations are applied.
>
> Tested bootstrap + testsuite (default languages).

Ok.  Bonus points if you quickly eyed users of whether they may be surprised
in vectors coming through now.

Thanks,
Richard.

> 2012-10-29  Marc Glisse  <marc.glisse@inria.fr>
>
>         PR middle-end/55027
>
> gcc/
>         * tree.c (real_zerop, real_onep, real_twop, real_minus_onep):
>         Handle VECTOR_CST.
>
> testsuite/
>         * gcc.dg/pr55027.c: New testcase.
>
> --
> Marc Glisse
> Index: gcc/testsuite/gcc.dg/pr55027.c
> ===================================================================
> --- gcc/testsuite/gcc.dg/pr55027.c      (revision 0)
> +++ gcc/testsuite/gcc.dg/pr55027.c      (revision 0)
> @@ -0,0 +1,12 @@
> +/* { dg-do compile } */
> +/* { dg-options "-Ofast -fdump-tree-optimized-raw" } */
> +
> +typedef double v2df __attribute__ ((__vector_size__ (2 * sizeof
> (double))));
> +
> +void f (v2df *x)
> +{
> +  *x = 0 + 1 * *x;
> +}
> +
> +/* { dg-final { scan-tree-dump-not "gimple_assign" "optimized" } } */
> +/* { dg-final { cleanup-tree-dump "optimized" } } */
>
> Property changes on: gcc/testsuite/gcc.dg/pr55027.c
> ___________________________________________________________________
> Added: svn:keywords
>    + Author Date Id Revision URL
> Added: svn:eol-style
>    + native
>
> Index: gcc/tree.c
> ===================================================================
> --- gcc/tree.c  (revision 192894)
> +++ gcc/tree.c  (working copy)
> @@ -1985,75 +1985,127 @@ tree_floor_log2 (const_tree expr)
>  }
>
>  /* Return 1 if EXPR is the real constant zero.  Trailing zeroes matter for
>     decimal float constants, so don't return 1 for them.  */
>
>  int
>  real_zerop (const_tree expr)
>  {
>    STRIP_NOPS (expr);
>
> -  return ((TREE_CODE (expr) == REAL_CST
> -          && REAL_VALUES_EQUAL (TREE_REAL_CST (expr), dconst0)
> -          && !(DECIMAL_FLOAT_MODE_P (TYPE_MODE (TREE_TYPE (expr)))))
> -         || (TREE_CODE (expr) == COMPLEX_CST
> -             && real_zerop (TREE_REALPART (expr))
> -             && real_zerop (TREE_IMAGPART (expr))));
> +  switch (TREE_CODE (expr))
> +    {
> +    case REAL_CST:
> +      return REAL_VALUES_EQUAL (TREE_REAL_CST (expr), dconst0)
> +            && !(DECIMAL_FLOAT_MODE_P (TYPE_MODE (TREE_TYPE (expr))));
> +    case COMPLEX_CST:
> +      return real_zerop (TREE_REALPART (expr))
> +            && real_zerop (TREE_IMAGPART (expr));
> +    case VECTOR_CST:
> +      {
> +       unsigned i;
> +       for (i = 0; i < VECTOR_CST_NELTS (expr); ++i)
> +         if (!real_zerop (VECTOR_CST_ELT (expr, i)))
> +           return false;
> +       return true;
> +      }
> +    default:
> +      return false;
> +    }
>  }
>
>  /* Return 1 if EXPR is the real constant one in real or complex form.
>     Trailing zeroes matter for decimal float constants, so don't return
>     1 for them.  */
>
>  int
>  real_onep (const_tree expr)
>  {
>    STRIP_NOPS (expr);
>
> -  return ((TREE_CODE (expr) == REAL_CST
> -          && REAL_VALUES_EQUAL (TREE_REAL_CST (expr), dconst1)
> -          && !(DECIMAL_FLOAT_MODE_P (TYPE_MODE (TREE_TYPE (expr)))))
> -         || (TREE_CODE (expr) == COMPLEX_CST
> -             && real_onep (TREE_REALPART (expr))
> -             && real_zerop (TREE_IMAGPART (expr))));
> +  switch (TREE_CODE (expr))
> +    {
> +    case REAL_CST:
> +      return REAL_VALUES_EQUAL (TREE_REAL_CST (expr), dconst1)
> +            && !(DECIMAL_FLOAT_MODE_P (TYPE_MODE (TREE_TYPE (expr))));
> +    case COMPLEX_CST:
> +      return real_onep (TREE_REALPART (expr))
> +            && real_zerop (TREE_IMAGPART (expr));
> +    case VECTOR_CST:
> +      {
> +       unsigned i;
> +       for (i = 0; i < VECTOR_CST_NELTS (expr); ++i)
> +         if (!real_onep (VECTOR_CST_ELT (expr, i)))
> +           return false;
> +       return true;
> +      }
> +    default:
> +      return false;
> +    }
>  }
>
>  /* Return 1 if EXPR is the real constant two.  Trailing zeroes matter
>     for decimal float constants, so don't return 1 for them.  */
>
>  int
>  real_twop (const_tree expr)
>  {
>    STRIP_NOPS (expr);
>
> -  return ((TREE_CODE (expr) == REAL_CST
> -          && REAL_VALUES_EQUAL (TREE_REAL_CST (expr), dconst2)
> -          && !(DECIMAL_FLOAT_MODE_P (TYPE_MODE (TREE_TYPE (expr)))))
> -         || (TREE_CODE (expr) == COMPLEX_CST
> -             && real_twop (TREE_REALPART (expr))
> -             && real_zerop (TREE_IMAGPART (expr))));
> +  switch (TREE_CODE (expr))
> +    {
> +    case REAL_CST:
> +      return REAL_VALUES_EQUAL (TREE_REAL_CST (expr), dconst2)
> +            && !(DECIMAL_FLOAT_MODE_P (TYPE_MODE (TREE_TYPE (expr))));
> +    case COMPLEX_CST:
> +      return real_twop (TREE_REALPART (expr))
> +            && real_zerop (TREE_IMAGPART (expr));
> +    case VECTOR_CST:
> +      {
> +       unsigned i;
> +       for (i = 0; i < VECTOR_CST_NELTS (expr); ++i)
> +         if (!real_twop (VECTOR_CST_ELT (expr, i)))
> +           return false;
> +       return true;
> +      }
> +    default:
> +      return false;
> +    }
>  }
>
>  /* Return 1 if EXPR is the real constant minus one.  Trailing zeroes
>     matter for decimal float constants, so don't return 1 for them.  */
>
>  int
>  real_minus_onep (const_tree expr)
>  {
>    STRIP_NOPS (expr);
>
> -  return ((TREE_CODE (expr) == REAL_CST
> -          && REAL_VALUES_EQUAL (TREE_REAL_CST (expr), dconstm1)
> -          && !(DECIMAL_FLOAT_MODE_P (TYPE_MODE (TREE_TYPE (expr)))))
> -         || (TREE_CODE (expr) == COMPLEX_CST
> -             && real_minus_onep (TREE_REALPART (expr))
> -             && real_zerop (TREE_IMAGPART (expr))));
> +  switch (TREE_CODE (expr))
> +    {
> +    case REAL_CST:
> +      return REAL_VALUES_EQUAL (TREE_REAL_CST (expr), dconstm1)
> +            && !(DECIMAL_FLOAT_MODE_P (TYPE_MODE (TREE_TYPE (expr))));
> +    case COMPLEX_CST:
> +      return real_minus_onep (TREE_REALPART (expr))
> +            && real_zerop (TREE_IMAGPART (expr));
> +    case VECTOR_CST:
> +      {
> +       unsigned i;
> +       for (i = 0; i < VECTOR_CST_NELTS (expr); ++i)
> +         if (!real_minus_onep (VECTOR_CST_ELT (expr, i)))
> +           return false;
> +       return true;
> +      }
> +    default:
> +      return false;
> +    }
>  }
>
>  /* Nonzero if EXP is a constant or a cast of a constant.  */
>
>  int
>  really_constant_p (const_tree exp)
>  {
>    /* This is not quite the same as STRIP_NOPS.  It does more.  */
>    while (CONVERT_EXPR_P (exp)
>          || TREE_CODE (exp) == NON_LVALUE_EXPR)
>
Marc Glisse Oct. 29, 2012, 2:37 p.m.
On Mon, 29 Oct 2012, Richard Biener wrote:

> On Sun, Oct 28, 2012 at 4:14 PM, Marc Glisse <marc.glisse@inria.fr> wrote:
>> Hello,
>>
>> this patch lets some predicates on floating point constants answer true for
>> vectors, so optimizations are applied.
>>
>> Tested bootstrap + testsuite (default languages).
>
> Ok.  Bonus points if you quickly eyed users of whether they may be surprised
> in vectors coming through now.

I did (that's why I didn't also change integer_twop), but I won't claim 
the bonus points, because in fold-const.c:
* there is probably an issue with signed zero in fold_real_zero_addition_p
* the RDIV_EXPR case would like real_zerop to mean "at least one is zero"
* abs(x)>=0 or <0 doesn't seem ready

but that's not much compared to the broken integer vector optimizations 
;-)

Patch hide | download patch | download mbox

Index: gcc/testsuite/gcc.dg/pr55027.c
===================================================================
--- gcc/testsuite/gcc.dg/pr55027.c	(revision 0)
+++ gcc/testsuite/gcc.dg/pr55027.c	(revision 0)
@@ -0,0 +1,12 @@ 
+/* { dg-do compile } */
+/* { dg-options "-Ofast -fdump-tree-optimized-raw" } */
+
+typedef double v2df __attribute__ ((__vector_size__ (2 * sizeof (double))));
+
+void f (v2df *x)
+{
+  *x = 0 + 1 * *x;
+}
+
+/* { dg-final { scan-tree-dump-not "gimple_assign" "optimized" } } */
+/* { dg-final { cleanup-tree-dump "optimized" } } */

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

Index: gcc/tree.c
===================================================================
--- gcc/tree.c	(revision 192894)
+++ gcc/tree.c	(working copy)
@@ -1985,75 +1985,127 @@  tree_floor_log2 (const_tree expr)
 }
 
 /* Return 1 if EXPR is the real constant zero.  Trailing zeroes matter for
    decimal float constants, so don't return 1 for them.  */
 
 int
 real_zerop (const_tree expr)
 {
   STRIP_NOPS (expr);
 
-  return ((TREE_CODE (expr) == REAL_CST
-	   && REAL_VALUES_EQUAL (TREE_REAL_CST (expr), dconst0)
-	   && !(DECIMAL_FLOAT_MODE_P (TYPE_MODE (TREE_TYPE (expr)))))
-	  || (TREE_CODE (expr) == COMPLEX_CST
-	      && real_zerop (TREE_REALPART (expr))
-	      && real_zerop (TREE_IMAGPART (expr))));
+  switch (TREE_CODE (expr))
+    {
+    case REAL_CST:
+      return REAL_VALUES_EQUAL (TREE_REAL_CST (expr), dconst0)
+	     && !(DECIMAL_FLOAT_MODE_P (TYPE_MODE (TREE_TYPE (expr))));
+    case COMPLEX_CST:
+      return real_zerop (TREE_REALPART (expr))
+	     && real_zerop (TREE_IMAGPART (expr));
+    case VECTOR_CST:
+      {
+	unsigned i;
+	for (i = 0; i < VECTOR_CST_NELTS (expr); ++i)
+	  if (!real_zerop (VECTOR_CST_ELT (expr, i)))
+	    return false;
+	return true;
+      }
+    default:
+      return false;
+    }
 }
 
 /* Return 1 if EXPR is the real constant one in real or complex form.
    Trailing zeroes matter for decimal float constants, so don't return
    1 for them.  */
 
 int
 real_onep (const_tree expr)
 {
   STRIP_NOPS (expr);
 
-  return ((TREE_CODE (expr) == REAL_CST
-	   && REAL_VALUES_EQUAL (TREE_REAL_CST (expr), dconst1)
-	   && !(DECIMAL_FLOAT_MODE_P (TYPE_MODE (TREE_TYPE (expr)))))
-	  || (TREE_CODE (expr) == COMPLEX_CST
-	      && real_onep (TREE_REALPART (expr))
-	      && real_zerop (TREE_IMAGPART (expr))));
+  switch (TREE_CODE (expr))
+    {
+    case REAL_CST:
+      return REAL_VALUES_EQUAL (TREE_REAL_CST (expr), dconst1)
+	     && !(DECIMAL_FLOAT_MODE_P (TYPE_MODE (TREE_TYPE (expr))));
+    case COMPLEX_CST:
+      return real_onep (TREE_REALPART (expr))
+	     && real_zerop (TREE_IMAGPART (expr));
+    case VECTOR_CST:
+      {
+	unsigned i;
+	for (i = 0; i < VECTOR_CST_NELTS (expr); ++i)
+	  if (!real_onep (VECTOR_CST_ELT (expr, i)))
+	    return false;
+	return true;
+      }
+    default:
+      return false;
+    }
 }
 
 /* Return 1 if EXPR is the real constant two.  Trailing zeroes matter
    for decimal float constants, so don't return 1 for them.  */
 
 int
 real_twop (const_tree expr)
 {
   STRIP_NOPS (expr);
 
-  return ((TREE_CODE (expr) == REAL_CST
-	   && REAL_VALUES_EQUAL (TREE_REAL_CST (expr), dconst2)
-	   && !(DECIMAL_FLOAT_MODE_P (TYPE_MODE (TREE_TYPE (expr)))))
-	  || (TREE_CODE (expr) == COMPLEX_CST
-	      && real_twop (TREE_REALPART (expr))
-	      && real_zerop (TREE_IMAGPART (expr))));
+  switch (TREE_CODE (expr))
+    {
+    case REAL_CST:
+      return REAL_VALUES_EQUAL (TREE_REAL_CST (expr), dconst2)
+	     && !(DECIMAL_FLOAT_MODE_P (TYPE_MODE (TREE_TYPE (expr))));
+    case COMPLEX_CST:
+      return real_twop (TREE_REALPART (expr))
+	     && real_zerop (TREE_IMAGPART (expr));
+    case VECTOR_CST:
+      {
+	unsigned i;
+	for (i = 0; i < VECTOR_CST_NELTS (expr); ++i)
+	  if (!real_twop (VECTOR_CST_ELT (expr, i)))
+	    return false;
+	return true;
+      }
+    default:
+      return false;
+    }
 }
 
 /* Return 1 if EXPR is the real constant minus one.  Trailing zeroes
    matter for decimal float constants, so don't return 1 for them.  */
 
 int
 real_minus_onep (const_tree expr)
 {
   STRIP_NOPS (expr);
 
-  return ((TREE_CODE (expr) == REAL_CST
-	   && REAL_VALUES_EQUAL (TREE_REAL_CST (expr), dconstm1)
-	   && !(DECIMAL_FLOAT_MODE_P (TYPE_MODE (TREE_TYPE (expr)))))
-	  || (TREE_CODE (expr) == COMPLEX_CST
-	      && real_minus_onep (TREE_REALPART (expr))
-	      && real_zerop (TREE_IMAGPART (expr))));
+  switch (TREE_CODE (expr))
+    {
+    case REAL_CST:
+      return REAL_VALUES_EQUAL (TREE_REAL_CST (expr), dconstm1)
+	     && !(DECIMAL_FLOAT_MODE_P (TYPE_MODE (TREE_TYPE (expr))));
+    case COMPLEX_CST:
+      return real_minus_onep (TREE_REALPART (expr))
+	     && real_zerop (TREE_IMAGPART (expr));
+    case VECTOR_CST:
+      {
+	unsigned i;
+	for (i = 0; i < VECTOR_CST_NELTS (expr); ++i)
+	  if (!real_minus_onep (VECTOR_CST_ELT (expr, i)))
+	    return false;
+	return true;
+      }
+    default:
+      return false;
+    }
 }
 
 /* Nonzero if EXP is a constant or a cast of a constant.  */
 
 int
 really_constant_p (const_tree exp)
 {
   /* This is not quite the same as STRIP_NOPS.  It does more.  */
   while (CONVERT_EXPR_P (exp)
 	 || TREE_CODE (exp) == NON_LVALUE_EXPR)