Re: [PATCH] Fix PR44214

2012-04-23 Thread William J. Schmidt
On Mon, 2012-04-23 at 11:09 +0200, Richard Guenther wrote:
> On Fri, 20 Apr 2012, William J. Schmidt wrote:
> 
> > On Fri, 2012-04-20 at 11:32 -0700, H.J. Lu wrote:
> > > On Thu, Apr 19, 2012 at 6:58 PM, William J. Schmidt
> > >  wrote:
> > > > This enhances constant folding for division by complex and vector
> > > > constants.  When -freciprocal-math is present, such divisions are
> > > > converted into multiplies by the constant reciprocal.  When an exact
> > > > reciprocal is available, this is done for vector constants when
> > > > optimizing.  I did not implement logic for exact reciprocals of complex
> > > > constants because either (a) the complexity doesn't justify the
> > > > likelihood of occurrence, or (b) I'm lazy.  Your choice. ;)
> > > >
> > > > Bootstrapped with no new regressions on powerpc64-unknown-linux-gnu.  Ok
> > > > for trunk?
> > > >
> > > > Thanks,
> > > > Bill
> > > >
> > > >
> > > > gcc:
> > > >
> > > > 2012-04-19  Bill Schmidt  
> > > >
> > > >PR rtl-optimization/44214
> > > >* fold-const.c (exact_inverse): New function.
> > > >(fold_binary_loc): Fold vector and complex division by constant 
> > > > into
> > > >multiply by recripocal with flag_reciprocal_math; fold vector 
> > > > division
> > > >by constant into multiply by reciprocal with exact inverse.
> > > >
> > > > gcc/testsuite:
> > > >
> > > 
> > > It caused:
> > > 
> > > FAIL: gcc.dg/torture/builtin-explog-1.c  -O0  (test for excess errors)
> > > FAIL: gcc.dg/torture/builtin-power-1.c  -O0  (test for excess errors)
> > > 
> > > on x86.
> > > 
> > 
> > Hm, sorry, I don't know how that escaped my testing.  This was due to
> > the suggestion to have the "optimize" test encompass the
> > -freciprocal-math test.  Looks like this changes some expected behavior,
> > at least for these two tests.  
> > 
> > Two options: Revert the move of the "optimize" test, or change the tests
> > to require -O1 or above.  Richard, what's your preference?
> 
> Change the test to require -O1 or above.
> 
> Richard.
> 

OK, following committed as obvious.

Thanks,
Bill


gcc-testsuite:

2012-04-23  Bill Schmidt  

PR regression/53076
* gcc.dg/torture/builtin-explog-1.c: Skip if -O0.
* gcc.dg/torture/builtin-power-1.c: Likewise.


Index: gcc/testsuite/gcc.dg/torture/builtin-explog-1.c
===
--- gcc/testsuite/gcc.dg/torture/builtin-explog-1.c (revision 186624)
+++ gcc/testsuite/gcc.dg/torture/builtin-explog-1.c (working copy)
@@ -7,6 +7,7 @@
 
 /* { dg-do link } */
 /* { dg-options "-ffast-math" } */
+/* { dg-skip-if "PR44214" { *-*-* } { "-O0" } { "" } } */
 
 /* Define "e" with as many bits as found in builtins.c:dconste.  */
 #define M_E  
2.7182818284590452353602874713526624977572470936999595749669676277241
Index: gcc/testsuite/gcc.dg/torture/builtin-power-1.c
===
--- gcc/testsuite/gcc.dg/torture/builtin-power-1.c  (revision 186624)
+++ gcc/testsuite/gcc.dg/torture/builtin-power-1.c  (working copy)
@@ -8,6 +8,7 @@
 /* { dg-do link } */
 /* { dg-options "-ffast-math" } */
 /* { dg-add-options c99_runtime } */
+/* { dg-skip-if "PR44214" { *-*-* } { "-O0" } { "" } } */
 
 #include "../builtins-config.h"
 




Re: [PATCH] Fix PR44214

2012-04-23 Thread Richard Guenther
On Fri, 20 Apr 2012, William J. Schmidt wrote:

> On Fri, 2012-04-20 at 11:32 -0700, H.J. Lu wrote:
> > On Thu, Apr 19, 2012 at 6:58 PM, William J. Schmidt
> >  wrote:
> > > This enhances constant folding for division by complex and vector
> > > constants.  When -freciprocal-math is present, such divisions are
> > > converted into multiplies by the constant reciprocal.  When an exact
> > > reciprocal is available, this is done for vector constants when
> > > optimizing.  I did not implement logic for exact reciprocals of complex
> > > constants because either (a) the complexity doesn't justify the
> > > likelihood of occurrence, or (b) I'm lazy.  Your choice. ;)
> > >
> > > Bootstrapped with no new regressions on powerpc64-unknown-linux-gnu.  Ok
> > > for trunk?
> > >
> > > Thanks,
> > > Bill
> > >
> > >
> > > gcc:
> > >
> > > 2012-04-19  Bill Schmidt  
> > >
> > >PR rtl-optimization/44214
> > >* fold-const.c (exact_inverse): New function.
> > >(fold_binary_loc): Fold vector and complex division by constant 
> > > into
> > >multiply by recripocal with flag_reciprocal_math; fold vector 
> > > division
> > >by constant into multiply by reciprocal with exact inverse.
> > >
> > > gcc/testsuite:
> > >
> > 
> > It caused:
> > 
> > FAIL: gcc.dg/torture/builtin-explog-1.c  -O0  (test for excess errors)
> > FAIL: gcc.dg/torture/builtin-power-1.c  -O0  (test for excess errors)
> > 
> > on x86.
> > 
> 
> Hm, sorry, I don't know how that escaped my testing.  This was due to
> the suggestion to have the "optimize" test encompass the
> -freciprocal-math test.  Looks like this changes some expected behavior,
> at least for these two tests.  
> 
> Two options: Revert the move of the "optimize" test, or change the tests
> to require -O1 or above.  Richard, what's your preference?

Change the test to require -O1 or above.

Richard.


Re: [PATCH] Fix PR44214

2012-04-20 Thread William J. Schmidt
On Fri, 2012-04-20 at 11:32 -0700, H.J. Lu wrote:
> On Thu, Apr 19, 2012 at 6:58 PM, William J. Schmidt
>  wrote:
> > This enhances constant folding for division by complex and vector
> > constants.  When -freciprocal-math is present, such divisions are
> > converted into multiplies by the constant reciprocal.  When an exact
> > reciprocal is available, this is done for vector constants when
> > optimizing.  I did not implement logic for exact reciprocals of complex
> > constants because either (a) the complexity doesn't justify the
> > likelihood of occurrence, or (b) I'm lazy.  Your choice. ;)
> >
> > Bootstrapped with no new regressions on powerpc64-unknown-linux-gnu.  Ok
> > for trunk?
> >
> > Thanks,
> > Bill
> >
> >
> > gcc:
> >
> > 2012-04-19  Bill Schmidt  
> >
> >PR rtl-optimization/44214
> >* fold-const.c (exact_inverse): New function.
> >(fold_binary_loc): Fold vector and complex division by constant into
> >multiply by recripocal with flag_reciprocal_math; fold vector 
> > division
> >by constant into multiply by reciprocal with exact inverse.
> >
> > gcc/testsuite:
> >
> 
> It caused:
> 
> FAIL: gcc.dg/torture/builtin-explog-1.c  -O0  (test for excess errors)
> FAIL: gcc.dg/torture/builtin-power-1.c  -O0  (test for excess errors)
> 
> on x86.
> 

Hm, sorry, I don't know how that escaped my testing.  This was due to
the suggestion to have the "optimize" test encompass the
-freciprocal-math test.  Looks like this changes some expected behavior,
at least for these two tests.  

Two options: Revert the move of the "optimize" test, or change the tests
to require -O1 or above.  Richard, what's your preference?

Thanks,
Bill



Re: [PATCH] Fix PR44214

2012-04-20 Thread H.J. Lu
On Thu, Apr 19, 2012 at 6:58 PM, William J. Schmidt
 wrote:
> This enhances constant folding for division by complex and vector
> constants.  When -freciprocal-math is present, such divisions are
> converted into multiplies by the constant reciprocal.  When an exact
> reciprocal is available, this is done for vector constants when
> optimizing.  I did not implement logic for exact reciprocals of complex
> constants because either (a) the complexity doesn't justify the
> likelihood of occurrence, or (b) I'm lazy.  Your choice. ;)
>
> Bootstrapped with no new regressions on powerpc64-unknown-linux-gnu.  Ok
> for trunk?
>
> Thanks,
> Bill
>
>
> gcc:
>
> 2012-04-19  Bill Schmidt  
>
>        PR rtl-optimization/44214
>        * fold-const.c (exact_inverse): New function.
>        (fold_binary_loc): Fold vector and complex division by constant into
>        multiply by recripocal with flag_reciprocal_math; fold vector division
>        by constant into multiply by reciprocal with exact inverse.
>
> gcc/testsuite:
>

It caused:

FAIL: gcc.dg/torture/builtin-explog-1.c  -O0  (test for excess errors)
FAIL: gcc.dg/torture/builtin-power-1.c  -O0  (test for excess errors)

on x86.

-- 
H.J.


Re: [PATCH] Fix PR44214

2012-04-20 Thread Richard Guenther
On Fri, 20 Apr 2012, William J. Schmidt wrote:

> On Fri, 2012-04-20 at 10:04 +0200, Richard Guenther wrote:
> > On Thu, 19 Apr 2012, William J. Schmidt wrote:
> > 
> > > This enhances constant folding for division by complex and vector
> > > constants.  When -freciprocal-math is present, such divisions are
> > > converted into multiplies by the constant reciprocal.  When an exact
> > > reciprocal is available, this is done for vector constants when
> > > optimizing.  I did not implement logic for exact reciprocals of complex
> > > constants because either (a) the complexity doesn't justify the
> > > likelihood of occurrence, or (b) I'm lazy.  Your choice. ;)
> > > 
> > > Bootstrapped with no new regressions on powerpc64-unknown-linux-gnu.  Ok
> > > for trunk?
> > 
> > See below ...
> > 
> > > Thanks,
> > > Bill
> > > 
> > > 
> > > gcc:
> > > 
> > > 2012-04-19  Bill Schmidt  
> > > 
> > >   PR rtl-optimization/44214
> > >   * fold-const.c (exact_inverse): New function.
> > >   (fold_binary_loc): Fold vector and complex division by constant into
> > >   multiply by recripocal with flag_reciprocal_math; fold vector division
> > >   by constant into multiply by reciprocal with exact inverse.
> > > 
> > > gcc/testsuite:
> > > 
> > > 2012-04-19  Bill Schmidt  
> > > 
> > >   PR rtl-optimization/44214
> > >   * gcc.target/powerpc/pr44214-1.c: New test.
> > >   * gcc.dg/pr44214-2.c: Likewise.
> > >   * gcc.target/powerpc/pr44214-3.c: Likewise.
> > > 
> > > 
> > > Index: gcc/fold-const.c
> > > ===
> > > --- gcc/fold-const.c  (revision 186573)
> > > +++ gcc/fold-const.c  (working copy)
> > > @@ -9693,6 +9693,48 @@ fold_addr_of_array_ref_difference (location_t loc,
> > >return NULL_TREE;
> > >  }
> > >  
> > > +/* If the real or vector real constant CST of type TYPE has an exact
> > > +   inverse, return it, else return NULL.  */
> > > +
> > > +static tree
> > > +exact_inverse (tree type, tree cst)
> > > +{
> > > +  REAL_VALUE_TYPE r;
> > > +  tree unit_type, *elts;
> > > +  enum machine_mode mode;
> > > +  unsigned vec_nelts, i;
> > > +
> > > +  switch (TREE_CODE (cst))
> > > +{
> > > +case REAL_CST:
> > > +  r = TREE_REAL_CST (cst);
> > > +
> > > +  if (exact_real_inverse (TYPE_MODE (type), &r))
> > > + return build_real (type, r);
> > > +
> > > +  return NULL_TREE;
> > > +
> > > +case VECTOR_CST:
> > > +  vec_nelts = VECTOR_CST_NELTS (cst);
> > > +  elts = XALLOCAVEC (tree, vec_nelts);
> > > +  unit_type = TREE_TYPE (type);
> > > +  mode = TYPE_MODE (unit_type);
> > > +
> > > +  for (i = 0; i < vec_nelts; i++)
> > > + {
> > > +   r = TREE_REAL_CST (VECTOR_CST_ELT (cst, i));
> > > +   if (!exact_real_inverse (mode, &r))
> > > + return NULL_TREE;
> > > +   elts[i] = build_real (unit_type, r);
> > > + }
> > > +
> > > +  return build_vector (type, elts);
> > > +
> > > +default:
> > > +  return NULL_TREE;
> > > +}
> > > +}
> > > +
> > >  /* Fold a binary expression of code CODE and type TYPE with operands
> > > OP0 and OP1.  LOC is the location of the resulting expression.
> > > Return the folded expression if folding is successful.  Otherwise,
> > > @@ -11734,23 +11776,25 @@ fold_binary_loc (location_t loc,
> > >so only do this if -freciprocal-math.  We can actually
> > >always safely do it if ARG1 is a power of two, but it's hard to
> > >tell if it is or not in a portable manner.  */
> > > -  if (TREE_CODE (arg1) == REAL_CST)
> > > +  if (TREE_CODE (arg1) == REAL_CST
> > > +   || (TREE_CODE (arg1) == COMPLEX_CST
> > > +   && COMPLEX_FLOAT_TYPE_P (TREE_TYPE (arg1)))
> > > +   || (TREE_CODE (arg1) == VECTOR_CST
> > > +   && VECTOR_FLOAT_TYPE_P (TREE_TYPE (arg1
> > >   {
> > > if (flag_reciprocal_math
> > > -   && 0 != (tem = const_binop (code, build_real (type, dconst1),
> > > +   && 0 != (tem = fold_binary (code, type, build_one_cst (type),
> > > arg1)))
> > 
> > Any reason for not using const_binop?
> 
> As it turns out, no.  I (blindly) made this change based on your comment
> in the PR...
> 
> "The fold code should probably simply use fold_binary to do the constant
> folding (which already should handle 1/x for x vector and complex. There
> is a build_one_cst to build the constant 1 for any type)."
> 
> ...but now that I've looked at it that was unnecessary, so I must have
> misinterpreted this.  I'll revert to using const_binop.
> 
> > 
> > >   return fold_build2_loc (loc, MULT_EXPR, type, arg0, tem);
> > > -   /* Find the reciprocal if optimizing and the result is exact.  */
> > > -   if (optimize)
> > > +   /* Find the reciprocal if optimizing and the result is exact.
> > > +  TODO: Complex reciprocal not implemented.  */
> > > +   if (optimize
> > > +   && TREE_CODE (arg1) != COMPLEX_CST)
> > 
> > I know this is all pre-existing, but really the flag_reciprocal_math
> > case 

Re: [PATCH] Fix PR44214

2012-04-20 Thread William J. Schmidt
On Fri, 2012-04-20 at 10:04 +0200, Richard Guenther wrote:
> On Thu, 19 Apr 2012, William J. Schmidt wrote:
> 
> > This enhances constant folding for division by complex and vector
> > constants.  When -freciprocal-math is present, such divisions are
> > converted into multiplies by the constant reciprocal.  When an exact
> > reciprocal is available, this is done for vector constants when
> > optimizing.  I did not implement logic for exact reciprocals of complex
> > constants because either (a) the complexity doesn't justify the
> > likelihood of occurrence, or (b) I'm lazy.  Your choice. ;)
> > 
> > Bootstrapped with no new regressions on powerpc64-unknown-linux-gnu.  Ok
> > for trunk?
> 
> See below ...
> 
> > Thanks,
> > Bill
> > 
> > 
> > gcc:
> > 
> > 2012-04-19  Bill Schmidt  
> > 
> > PR rtl-optimization/44214
> > * fold-const.c (exact_inverse): New function.
> > (fold_binary_loc): Fold vector and complex division by constant into
> > multiply by recripocal with flag_reciprocal_math; fold vector division
> > by constant into multiply by reciprocal with exact inverse.
> > 
> > gcc/testsuite:
> > 
> > 2012-04-19  Bill Schmidt  
> > 
> > PR rtl-optimization/44214
> > * gcc.target/powerpc/pr44214-1.c: New test.
> > * gcc.dg/pr44214-2.c: Likewise.
> > * gcc.target/powerpc/pr44214-3.c: Likewise.
> > 
> > 
> > Index: gcc/fold-const.c
> > ===
> > --- gcc/fold-const.c(revision 186573)
> > +++ gcc/fold-const.c(working copy)
> > @@ -9693,6 +9693,48 @@ fold_addr_of_array_ref_difference (location_t loc,
> >return NULL_TREE;
> >  }
> >  
> > +/* If the real or vector real constant CST of type TYPE has an exact
> > +   inverse, return it, else return NULL.  */
> > +
> > +static tree
> > +exact_inverse (tree type, tree cst)
> > +{
> > +  REAL_VALUE_TYPE r;
> > +  tree unit_type, *elts;
> > +  enum machine_mode mode;
> > +  unsigned vec_nelts, i;
> > +
> > +  switch (TREE_CODE (cst))
> > +{
> > +case REAL_CST:
> > +  r = TREE_REAL_CST (cst);
> > +
> > +  if (exact_real_inverse (TYPE_MODE (type), &r))
> > +   return build_real (type, r);
> > +
> > +  return NULL_TREE;
> > +
> > +case VECTOR_CST:
> > +  vec_nelts = VECTOR_CST_NELTS (cst);
> > +  elts = XALLOCAVEC (tree, vec_nelts);
> > +  unit_type = TREE_TYPE (type);
> > +  mode = TYPE_MODE (unit_type);
> > +
> > +  for (i = 0; i < vec_nelts; i++)
> > +   {
> > + r = TREE_REAL_CST (VECTOR_CST_ELT (cst, i));
> > + if (!exact_real_inverse (mode, &r))
> > +   return NULL_TREE;
> > + elts[i] = build_real (unit_type, r);
> > +   }
> > +
> > +  return build_vector (type, elts);
> > +
> > +default:
> > +  return NULL_TREE;
> > +}
> > +}
> > +
> >  /* Fold a binary expression of code CODE and type TYPE with operands
> > OP0 and OP1.  LOC is the location of the resulting expression.
> > Return the folded expression if folding is successful.  Otherwise,
> > @@ -11734,23 +11776,25 @@ fold_binary_loc (location_t loc,
> >  so only do this if -freciprocal-math.  We can actually
> >  always safely do it if ARG1 is a power of two, but it's hard to
> >  tell if it is or not in a portable manner.  */
> > -  if (TREE_CODE (arg1) == REAL_CST)
> > +  if (TREE_CODE (arg1) == REAL_CST
> > + || (TREE_CODE (arg1) == COMPLEX_CST
> > + && COMPLEX_FLOAT_TYPE_P (TREE_TYPE (arg1)))
> > + || (TREE_CODE (arg1) == VECTOR_CST
> > + && VECTOR_FLOAT_TYPE_P (TREE_TYPE (arg1
> > {
> >   if (flag_reciprocal_math
> > - && 0 != (tem = const_binop (code, build_real (type, dconst1),
> > + && 0 != (tem = fold_binary (code, type, build_one_cst (type),
> >   arg1)))
> 
> Any reason for not using const_binop?

As it turns out, no.  I (blindly) made this change based on your comment
in the PR...

"The fold code should probably simply use fold_binary to do the constant
folding (which already should handle 1/x for x vector and complex. There
is a build_one_cst to build the constant 1 for any type)."

...but now that I've looked at it that was unnecessary, so I must have
misinterpreted this.  I'll revert to using const_binop.

> 
> > return fold_build2_loc (loc, MULT_EXPR, type, arg0, tem);
> > - /* Find the reciprocal if optimizing and the result is exact.  */
> > - if (optimize)
> > + /* Find the reciprocal if optimizing and the result is exact.
> > +TODO: Complex reciprocal not implemented.  */
> > + if (optimize
> > + && TREE_CODE (arg1) != COMPLEX_CST)
> 
> I know this is all pre-existing, but really the flag_reciprocal_math
> case should be under if (optimize), too.  So, can you move this check
> to the toplevel covering both cases?

Sure.

> 
> The testcases should apply to generic vectors, too, and should scan
> the .original dump (where folding first applied).  

Re: [PATCH] Fix PR44214

2012-04-20 Thread Richard Guenther
On Thu, 19 Apr 2012, William J. Schmidt wrote:

> This enhances constant folding for division by complex and vector
> constants.  When -freciprocal-math is present, such divisions are
> converted into multiplies by the constant reciprocal.  When an exact
> reciprocal is available, this is done for vector constants when
> optimizing.  I did not implement logic for exact reciprocals of complex
> constants because either (a) the complexity doesn't justify the
> likelihood of occurrence, or (b) I'm lazy.  Your choice. ;)
> 
> Bootstrapped with no new regressions on powerpc64-unknown-linux-gnu.  Ok
> for trunk?

See below ...

> Thanks,
> Bill
> 
> 
> gcc:
> 
> 2012-04-19  Bill Schmidt  
> 
>   PR rtl-optimization/44214
>   * fold-const.c (exact_inverse): New function.
>   (fold_binary_loc): Fold vector and complex division by constant into
>   multiply by recripocal with flag_reciprocal_math; fold vector division
>   by constant into multiply by reciprocal with exact inverse.
> 
> gcc/testsuite:
> 
> 2012-04-19  Bill Schmidt  
> 
>   PR rtl-optimization/44214
>   * gcc.target/powerpc/pr44214-1.c: New test.
>   * gcc.dg/pr44214-2.c: Likewise.
>   * gcc.target/powerpc/pr44214-3.c: Likewise.
> 
> 
> Index: gcc/fold-const.c
> ===
> --- gcc/fold-const.c  (revision 186573)
> +++ gcc/fold-const.c  (working copy)
> @@ -9693,6 +9693,48 @@ fold_addr_of_array_ref_difference (location_t loc,
>return NULL_TREE;
>  }
>  
> +/* If the real or vector real constant CST of type TYPE has an exact
> +   inverse, return it, else return NULL.  */
> +
> +static tree
> +exact_inverse (tree type, tree cst)
> +{
> +  REAL_VALUE_TYPE r;
> +  tree unit_type, *elts;
> +  enum machine_mode mode;
> +  unsigned vec_nelts, i;
> +
> +  switch (TREE_CODE (cst))
> +{
> +case REAL_CST:
> +  r = TREE_REAL_CST (cst);
> +
> +  if (exact_real_inverse (TYPE_MODE (type), &r))
> + return build_real (type, r);
> +
> +  return NULL_TREE;
> +
> +case VECTOR_CST:
> +  vec_nelts = VECTOR_CST_NELTS (cst);
> +  elts = XALLOCAVEC (tree, vec_nelts);
> +  unit_type = TREE_TYPE (type);
> +  mode = TYPE_MODE (unit_type);
> +
> +  for (i = 0; i < vec_nelts; i++)
> + {
> +   r = TREE_REAL_CST (VECTOR_CST_ELT (cst, i));
> +   if (!exact_real_inverse (mode, &r))
> + return NULL_TREE;
> +   elts[i] = build_real (unit_type, r);
> + }
> +
> +  return build_vector (type, elts);
> +
> +default:
> +  return NULL_TREE;
> +}
> +}
> +
>  /* Fold a binary expression of code CODE and type TYPE with operands
> OP0 and OP1.  LOC is the location of the resulting expression.
> Return the folded expression if folding is successful.  Otherwise,
> @@ -11734,23 +11776,25 @@ fold_binary_loc (location_t loc,
>so only do this if -freciprocal-math.  We can actually
>always safely do it if ARG1 is a power of two, but it's hard to
>tell if it is or not in a portable manner.  */
> -  if (TREE_CODE (arg1) == REAL_CST)
> +  if (TREE_CODE (arg1) == REAL_CST
> +   || (TREE_CODE (arg1) == COMPLEX_CST
> +   && COMPLEX_FLOAT_TYPE_P (TREE_TYPE (arg1)))
> +   || (TREE_CODE (arg1) == VECTOR_CST
> +   && VECTOR_FLOAT_TYPE_P (TREE_TYPE (arg1
>   {
> if (flag_reciprocal_math
> -   && 0 != (tem = const_binop (code, build_real (type, dconst1),
> +   && 0 != (tem = fold_binary (code, type, build_one_cst (type),
> arg1)))

Any reason for not using const_binop?

>   return fold_build2_loc (loc, MULT_EXPR, type, arg0, tem);
> -   /* Find the reciprocal if optimizing and the result is exact.  */
> -   if (optimize)
> +   /* Find the reciprocal if optimizing and the result is exact.
> +  TODO: Complex reciprocal not implemented.  */
> +   if (optimize
> +   && TREE_CODE (arg1) != COMPLEX_CST)

I know this is all pre-existing, but really the flag_reciprocal_math
case should be under if (optimize), too.  So, can you move this check
to the toplevel covering both cases?

The testcases should apply to generic vectors, too, and should scan
the .original dump (where folding first applied).  So they should
not be target specific (and they should use -freciprocal-math).

Ok with those changes.

Thanks,
Richard.

>   {
> -   REAL_VALUE_TYPE r;
> -   r = TREE_REAL_CST (arg1);
> -   if (exact_real_inverse (TYPE_MODE(TREE_TYPE(arg0)), &r))
> - {
> -   tem = build_real (type, r);
> -   return fold_build2_loc (loc, MULT_EXPR, type,
> -   fold_convert_loc (loc, type, arg0), tem);
> - }
> +   tree inverse = exact_inverse (TREE_TYPE (arg0), arg1);
> +
> +   if (inverse)
> + return fold_build2_loc (loc, MULT_EXPR, type, arg0, inver

[PATCH] Fix PR44214

2012-04-19 Thread William J. Schmidt
This enhances constant folding for division by complex and vector
constants.  When -freciprocal-math is present, such divisions are
converted into multiplies by the constant reciprocal.  When an exact
reciprocal is available, this is done for vector constants when
optimizing.  I did not implement logic for exact reciprocals of complex
constants because either (a) the complexity doesn't justify the
likelihood of occurrence, or (b) I'm lazy.  Your choice. ;)

Bootstrapped with no new regressions on powerpc64-unknown-linux-gnu.  Ok
for trunk?

Thanks,
Bill


gcc:

2012-04-19  Bill Schmidt  

PR rtl-optimization/44214
* fold-const.c (exact_inverse): New function.
(fold_binary_loc): Fold vector and complex division by constant into
multiply by recripocal with flag_reciprocal_math; fold vector division
by constant into multiply by reciprocal with exact inverse.

gcc/testsuite:

2012-04-19  Bill Schmidt  

PR rtl-optimization/44214
* gcc.target/powerpc/pr44214-1.c: New test.
* gcc.dg/pr44214-2.c: Likewise.
* gcc.target/powerpc/pr44214-3.c: Likewise.


Index: gcc/fold-const.c
===
--- gcc/fold-const.c(revision 186573)
+++ gcc/fold-const.c(working copy)
@@ -9693,6 +9693,48 @@ fold_addr_of_array_ref_difference (location_t loc,
   return NULL_TREE;
 }
 
+/* If the real or vector real constant CST of type TYPE has an exact
+   inverse, return it, else return NULL.  */
+
+static tree
+exact_inverse (tree type, tree cst)
+{
+  REAL_VALUE_TYPE r;
+  tree unit_type, *elts;
+  enum machine_mode mode;
+  unsigned vec_nelts, i;
+
+  switch (TREE_CODE (cst))
+{
+case REAL_CST:
+  r = TREE_REAL_CST (cst);
+
+  if (exact_real_inverse (TYPE_MODE (type), &r))
+   return build_real (type, r);
+
+  return NULL_TREE;
+
+case VECTOR_CST:
+  vec_nelts = VECTOR_CST_NELTS (cst);
+  elts = XALLOCAVEC (tree, vec_nelts);
+  unit_type = TREE_TYPE (type);
+  mode = TYPE_MODE (unit_type);
+
+  for (i = 0; i < vec_nelts; i++)
+   {
+ r = TREE_REAL_CST (VECTOR_CST_ELT (cst, i));
+ if (!exact_real_inverse (mode, &r))
+   return NULL_TREE;
+ elts[i] = build_real (unit_type, r);
+   }
+
+  return build_vector (type, elts);
+
+default:
+  return NULL_TREE;
+}
+}
+
 /* Fold a binary expression of code CODE and type TYPE with operands
OP0 and OP1.  LOC is the location of the resulting expression.
Return the folded expression if folding is successful.  Otherwise,
@@ -11734,23 +11776,25 @@ fold_binary_loc (location_t loc,
 so only do this if -freciprocal-math.  We can actually
 always safely do it if ARG1 is a power of two, but it's hard to
 tell if it is or not in a portable manner.  */
-  if (TREE_CODE (arg1) == REAL_CST)
+  if (TREE_CODE (arg1) == REAL_CST
+ || (TREE_CODE (arg1) == COMPLEX_CST
+ && COMPLEX_FLOAT_TYPE_P (TREE_TYPE (arg1)))
+ || (TREE_CODE (arg1) == VECTOR_CST
+ && VECTOR_FLOAT_TYPE_P (TREE_TYPE (arg1
{
  if (flag_reciprocal_math
- && 0 != (tem = const_binop (code, build_real (type, dconst1),
+ && 0 != (tem = fold_binary (code, type, build_one_cst (type),
  arg1)))
return fold_build2_loc (loc, MULT_EXPR, type, arg0, tem);
- /* Find the reciprocal if optimizing and the result is exact.  */
- if (optimize)
+ /* Find the reciprocal if optimizing and the result is exact.
+TODO: Complex reciprocal not implemented.  */
+ if (optimize
+ && TREE_CODE (arg1) != COMPLEX_CST)
{
- REAL_VALUE_TYPE r;
- r = TREE_REAL_CST (arg1);
- if (exact_real_inverse (TYPE_MODE(TREE_TYPE(arg0)), &r))
-   {
- tem = build_real (type, r);
- return fold_build2_loc (loc, MULT_EXPR, type,
- fold_convert_loc (loc, type, arg0), tem);
-   }
+ tree inverse = exact_inverse (TREE_TYPE (arg0), arg1);
+
+ if (inverse)
+   return fold_build2_loc (loc, MULT_EXPR, type, arg0, inverse);
}
}
   /* Convert A/B/C to A/(B*C).  */
Index: gcc/testsuite/gcc.target/powerpc/pr44214-3.c
===
--- gcc/testsuite/gcc.target/powerpc/pr44214-3.c(revision 0)
+++ gcc/testsuite/gcc.target/powerpc/pr44214-3.c(revision 0)
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mcpu=power7 -fdump-tree-optimized" } */
+
+void do_div (vector double *a, vector double *b)
+{
+  *a = *b / (vector double) { 2.0, 2.0 };
+}
+
+/* Since 2.0 has an exact reciprocal, constant folding should multiply *b
+   by the reciprocals of the vector elements.  As a resul