diff mbox

[1/6] Use IFN_SQRT in tree-vect-patterns.c

Message ID 87egfznnxc.fsf@e105548-lin.cambridge.arm.com
State New
Headers show

Commit Message

Richard Sandiford Nov. 9, 2015, 4:21 p.m. UTC
In practice all targets that can vectorise sqrt define the appropriate
sqrt<mode>2 optab.  The only case where this isn't immediately obvious
is the libmass support in rs6000.c, but Mike Meissner said that it shouldn't
be exercised for sqrt.

This patch therefore uses the internal function interface instead of
going via the target hook.


gcc/
	* tree-vect-patterns.c: Include internal-fn.h.
	(vect_recog_pow_pattern): Use IFN_SQRT instead of BUILT_IN_SQRT*.

Comments

Richard Biener Nov. 10, 2015, 10:21 a.m. UTC | #1
On Mon, Nov 9, 2015 at 5:21 PM, Richard Sandiford
<richard.sandiford@arm.com> wrote:
> In practice all targets that can vectorise sqrt define the appropriate
> sqrt<mode>2 optab.  The only case where this isn't immediately obvious
> is the libmass support in rs6000.c, but Mike Meissner said that it shouldn't
> be exercised for sqrt.
>
> This patch therefore uses the internal function interface instead of
> going via the target hook.
>
>
> gcc/
>         * tree-vect-patterns.c: Include internal-fn.h.
>         (vect_recog_pow_pattern): Use IFN_SQRT instead of BUILT_IN_SQRT*.
>
> diff --git a/gcc/tree-vect-patterns.c b/gcc/tree-vect-patterns.c
> index bab9a4f..a803e8c 100644
> --- a/gcc/tree-vect-patterns.c
> +++ b/gcc/tree-vect-patterns.c
> @@ -39,6 +39,7 @@ along with GCC; see the file COPYING3.  If not see
>  #include "tree-vectorizer.h"
>  #include "dumpfile.h"
>  #include "builtins.h"
> +#include "internal-fn.h"
>  #include "case-cfn-macros.h"
>
>  /* Pattern recognition functions  */
> @@ -1052,18 +1053,13 @@ vect_recog_pow_pattern (vec<gimple *> *stmts, tree *type_in,
>    if (TREE_CODE (exp) == REAL_CST
>        && real_equal (&TREE_REAL_CST (exp), &dconsthalf))
>      {
> -      tree newfn = mathfn_built_in (TREE_TYPE (base), BUILT_IN_SQRT);
>        *type_in = get_vectype_for_scalar_type (TREE_TYPE (base));
> -      if (*type_in)
> +      if (*type_in && direct_internal_fn_supported_p (IFN_SQRT, *type_in))
>         {
> -         gcall *stmt = gimple_build_call (newfn, 1, base);
> -         if (vectorizable_function (stmt, *type_in, *type_in)
> -             != NULL_TREE)
> -           {
> -             var = vect_recog_temp_ssa_var (TREE_TYPE (base), stmt);
> -             gimple_call_set_lhs (stmt, var);
> -             return stmt;
> -           }
> +         gcall *stmt = gimple_build_call_internal (IFN_SQRT, 1, base);
> +         var = vect_recog_temp_ssa_var (TREE_TYPE (base), stmt);
> +         gimple_call_set_lhs (stmt, var);
> +         return stmt;

Looks ok but I wonder if this is dead code with

(for pows (POW)
     sqrts (SQRT)
     cbrts (CBRT)
 (simplify
  (pows @0 REAL_CST@1)
  (with {
    const REAL_VALUE_TYPE *value = TREE_REAL_CST_PTR (@1);
    REAL_VALUE_TYPE tmp;
   }
   (switch
...
    /* pow(x,0.5) -> sqrt(x).  */
    (if (flag_unsafe_math_optimizations
         && canonicalize_math_p ()
         && real_equal (value, &dconsthalf))
     (sqrts @0))

also wondering here about canonicalize_math_p (), I'd expected the
reverse transform as canonicalization.  Also wondering about
flag_unsafe_math_optimizations (missing from the vectorizer pattern).

Anyway, patch is ok.

Thanks,
Richard.

>         }
>      }
>
>
Richard Sandiford Nov. 10, 2015, 10:57 a.m. UTC | #2
Richard Biener <richard.guenther@gmail.com> writes:
> On Mon, Nov 9, 2015 at 5:21 PM, Richard Sandiford
> <richard.sandiford@arm.com> wrote:
>> In practice all targets that can vectorise sqrt define the appropriate
>> sqrt<mode>2 optab.  The only case where this isn't immediately obvious
>> is the libmass support in rs6000.c, but Mike Meissner said that it shouldn't
>> be exercised for sqrt.
>>
>> This patch therefore uses the internal function interface instead of
>> going via the target hook.
>>
>>
>> gcc/
>>         * tree-vect-patterns.c: Include internal-fn.h.
>>         (vect_recog_pow_pattern): Use IFN_SQRT instead of BUILT_IN_SQRT*.
>>
>> diff --git a/gcc/tree-vect-patterns.c b/gcc/tree-vect-patterns.c
>> index bab9a4f..a803e8c 100644
>> --- a/gcc/tree-vect-patterns.c
>> +++ b/gcc/tree-vect-patterns.c
>> @@ -39,6 +39,7 @@ along with GCC; see the file COPYING3.  If not see
>>  #include "tree-vectorizer.h"
>>  #include "dumpfile.h"
>>  #include "builtins.h"
>> +#include "internal-fn.h"
>>  #include "case-cfn-macros.h"
>>
>>  /* Pattern recognition functions  */
>> @@ -1052,18 +1053,13 @@ vect_recog_pow_pattern (vec<gimple *> *stmts, tree *type_in,
>>    if (TREE_CODE (exp) == REAL_CST
>>        && real_equal (&TREE_REAL_CST (exp), &dconsthalf))
>>      {
>> -      tree newfn = mathfn_built_in (TREE_TYPE (base), BUILT_IN_SQRT);
>>        *type_in = get_vectype_for_scalar_type (TREE_TYPE (base));
>> -      if (*type_in)
>> +      if (*type_in && direct_internal_fn_supported_p (IFN_SQRT, *type_in))
>>         {
>> -         gcall *stmt = gimple_build_call (newfn, 1, base);
>> -         if (vectorizable_function (stmt, *type_in, *type_in)
>> -             != NULL_TREE)
>> -           {
>> -             var = vect_recog_temp_ssa_var (TREE_TYPE (base), stmt);
>> -             gimple_call_set_lhs (stmt, var);
>> -             return stmt;
>> -           }
>> +         gcall *stmt = gimple_build_call_internal (IFN_SQRT, 1, base);
>> +         var = vect_recog_temp_ssa_var (TREE_TYPE (base), stmt);
>> +         gimple_call_set_lhs (stmt, var);
>> +         return stmt;
>
> Looks ok but I wonder if this is dead code with
>
> (for pows (POW)
>      sqrts (SQRT)
>      cbrts (CBRT)
>  (simplify
>   (pows @0 REAL_CST@1)
>   (with {
>     const REAL_VALUE_TYPE *value = TREE_REAL_CST_PTR (@1);
>     REAL_VALUE_TYPE tmp;
>    }
>    (switch
> ...
>     /* pow(x,0.5) -> sqrt(x).  */
>     (if (flag_unsafe_math_optimizations
>          && canonicalize_math_p ()
>          && real_equal (value, &dconsthalf))
>      (sqrts @0))

Yeah, I wondered that too, although I think it's more likely to be dead
because of sincos.  In the end it just seemed like a rabiit hole too far
though.

> Anyway, patch is ok.

Thanks,
Richard
Richard Biener Nov. 10, 2015, 2:42 p.m. UTC | #3
On Tue, Nov 10, 2015 at 11:57 AM, Richard Sandiford
<richard.sandiford@arm.com> wrote:
> Richard Biener <richard.guenther@gmail.com> writes:
>> On Mon, Nov 9, 2015 at 5:21 PM, Richard Sandiford
>> <richard.sandiford@arm.com> wrote:
>>> In practice all targets that can vectorise sqrt define the appropriate
>>> sqrt<mode>2 optab.  The only case where this isn't immediately obvious
>>> is the libmass support in rs6000.c, but Mike Meissner said that it shouldn't
>>> be exercised for sqrt.
>>>
>>> This patch therefore uses the internal function interface instead of
>>> going via the target hook.
>>>
>>>
>>> gcc/
>>>         * tree-vect-patterns.c: Include internal-fn.h.
>>>         (vect_recog_pow_pattern): Use IFN_SQRT instead of BUILT_IN_SQRT*.
>>>
>>> diff --git a/gcc/tree-vect-patterns.c b/gcc/tree-vect-patterns.c
>>> index bab9a4f..a803e8c 100644
>>> --- a/gcc/tree-vect-patterns.c
>>> +++ b/gcc/tree-vect-patterns.c
>>> @@ -39,6 +39,7 @@ along with GCC; see the file COPYING3.  If not see
>>>  #include "tree-vectorizer.h"
>>>  #include "dumpfile.h"
>>>  #include "builtins.h"
>>> +#include "internal-fn.h"
>>>  #include "case-cfn-macros.h"
>>>
>>>  /* Pattern recognition functions  */
>>> @@ -1052,18 +1053,13 @@ vect_recog_pow_pattern (vec<gimple *> *stmts, tree *type_in,
>>>    if (TREE_CODE (exp) == REAL_CST
>>>        && real_equal (&TREE_REAL_CST (exp), &dconsthalf))
>>>      {
>>> -      tree newfn = mathfn_built_in (TREE_TYPE (base), BUILT_IN_SQRT);
>>>        *type_in = get_vectype_for_scalar_type (TREE_TYPE (base));
>>> -      if (*type_in)
>>> +      if (*type_in && direct_internal_fn_supported_p (IFN_SQRT, *type_in))
>>>         {
>>> -         gcall *stmt = gimple_build_call (newfn, 1, base);
>>> -         if (vectorizable_function (stmt, *type_in, *type_in)
>>> -             != NULL_TREE)
>>> -           {
>>> -             var = vect_recog_temp_ssa_var (TREE_TYPE (base), stmt);
>>> -             gimple_call_set_lhs (stmt, var);
>>> -             return stmt;
>>> -           }
>>> +         gcall *stmt = gimple_build_call_internal (IFN_SQRT, 1, base);
>>> +         var = vect_recog_temp_ssa_var (TREE_TYPE (base), stmt);
>>> +         gimple_call_set_lhs (stmt, var);
>>> +         return stmt;
>>
>> Looks ok but I wonder if this is dead code with
>>
>> (for pows (POW)
>>      sqrts (SQRT)
>>      cbrts (CBRT)
>>  (simplify
>>   (pows @0 REAL_CST@1)
>>   (with {
>>     const REAL_VALUE_TYPE *value = TREE_REAL_CST_PTR (@1);
>>     REAL_VALUE_TYPE tmp;
>>    }
>>    (switch
>> ...
>>     /* pow(x,0.5) -> sqrt(x).  */
>>     (if (flag_unsafe_math_optimizations
>>          && canonicalize_math_p ()
>>          && real_equal (value, &dconsthalf))
>>      (sqrts @0))
>
> Yeah, I wondered that too, although I think it's more likely to be dead
> because of sincos.  In the end it just seemed like a rabiit hole too far
> though.

Indeed.  sincos should also fix the pow(x, 2.) case handled.

Richard.

>> Anyway, patch is ok.
>
> Thanks,
> Richard
>
Joseph Myers Nov. 10, 2015, 5:29 p.m. UTC | #4
On Tue, 10 Nov 2015, Richard Biener wrote:

> Looks ok but I wonder if this is dead code with
> 
> (for pows (POW)
>      sqrts (SQRT)
>      cbrts (CBRT)
>  (simplify
>   (pows @0 REAL_CST@1)
>   (with {
>     const REAL_VALUE_TYPE *value = TREE_REAL_CST_PTR (@1);
>     REAL_VALUE_TYPE tmp;
>    }
>    (switch
> ...
>     /* pow(x,0.5) -> sqrt(x).  */
>     (if (flag_unsafe_math_optimizations
>          && canonicalize_math_p ()
>          && real_equal (value, &dconsthalf))
>      (sqrts @0))
> 
> also wondering here about canonicalize_math_p (), I'd expected the
> reverse transform as canonicalization.  Also wondering about
> flag_unsafe_math_optimizations (missing from the vectorizer pattern).

pow(x,0.5) -> sqrt(x) is unsafe because: pow (-0, 0.5) is specified in 
Annex F to be +0 but sqrt (-0) is -0; pow (-Inf, 0.5) is specified in 
Annex F to be +Inf, but sqrt (-Inf) is NaN with "invalid" exception 
raised.  I think it's safe in other cases (the reverse of course is not 
safe, sqrt is a fully-specified correctly-rounded IEEE operation and pow 
isn't).
Richard Biener Nov. 10, 2015, 7:09 p.m. UTC | #5
On November 10, 2015 6:29:36 PM GMT+01:00, Joseph Myers <joseph@codesourcery.com> wrote:
>On Tue, 10 Nov 2015, Richard Biener wrote:
>
>> Looks ok but I wonder if this is dead code with
>> 
>> (for pows (POW)
>>      sqrts (SQRT)
>>      cbrts (CBRT)
>>  (simplify
>>   (pows @0 REAL_CST@1)
>>   (with {
>>     const REAL_VALUE_TYPE *value = TREE_REAL_CST_PTR (@1);
>>     REAL_VALUE_TYPE tmp;
>>    }
>>    (switch
>> ...
>>     /* pow(x,0.5) -> sqrt(x).  */
>>     (if (flag_unsafe_math_optimizations
>>          && canonicalize_math_p ()
>>          && real_equal (value, &dconsthalf))
>>      (sqrts @0))
>> 
>> also wondering here about canonicalize_math_p (), I'd expected the
>> reverse transform as canonicalization.  Also wondering about
>> flag_unsafe_math_optimizations (missing from the vectorizer pattern).
>
>pow(x,0.5) -> sqrt(x) is unsafe because: pow (-0, 0.5) is specified in 
>Annex F to be +0 but sqrt (-0) is -0; pow (-Inf, 0.5) is specified in 
>Annex F to be +Inf, but sqrt (-Inf) is NaN with "invalid" exception 
>raised.  I think it's safe in other cases

So it's safe with no signed zeros and finite math rather than unsafe.  The reverse would be unsafe in addition (not fully specified and rounded).

 (the reverse of course is not
>
>safe, sqrt is a fully-specified correctly-rounded IEEE operation and
>pow 
>isn't).
diff mbox

Patch

diff --git a/gcc/tree-vect-patterns.c b/gcc/tree-vect-patterns.c
index bab9a4f..a803e8c 100644
--- a/gcc/tree-vect-patterns.c
+++ b/gcc/tree-vect-patterns.c
@@ -39,6 +39,7 @@  along with GCC; see the file COPYING3.  If not see
 #include "tree-vectorizer.h"
 #include "dumpfile.h"
 #include "builtins.h"
+#include "internal-fn.h"
 #include "case-cfn-macros.h"
 
 /* Pattern recognition functions  */
@@ -1052,18 +1053,13 @@  vect_recog_pow_pattern (vec<gimple *> *stmts, tree *type_in,
   if (TREE_CODE (exp) == REAL_CST
       && real_equal (&TREE_REAL_CST (exp), &dconsthalf))
     {
-      tree newfn = mathfn_built_in (TREE_TYPE (base), BUILT_IN_SQRT);
       *type_in = get_vectype_for_scalar_type (TREE_TYPE (base));
-      if (*type_in)
+      if (*type_in && direct_internal_fn_supported_p (IFN_SQRT, *type_in))
 	{
-	  gcall *stmt = gimple_build_call (newfn, 1, base);
-	  if (vectorizable_function (stmt, *type_in, *type_in)
-	      != NULL_TREE)
-	    {
-	      var = vect_recog_temp_ssa_var (TREE_TYPE (base), stmt);
-	      gimple_call_set_lhs (stmt, var);
-	      return stmt;
-	    }
+	  gcall *stmt = gimple_build_call_internal (IFN_SQRT, 1, base);
+	  var = vect_recog_temp_ssa_var (TREE_TYPE (base), stmt);
+	  gimple_call_set_lhs (stmt, var);
+	  return stmt;
 	}
     }