Re: [PATCH] Fold (a > 0 ? 1.0 : -1.0) into copysign (1.0, a) and a * copysign (1.0, a) into abs(a)

2017-06-29 Thread H.J. Lu
On Sun, Jun 25, 2017 at 2:28 PM, Andrew Pinski  wrote:
> On Sun, Jun 25, 2017 at 11:18 AM, Andrew Pinski  wrote:
>> On Sun, Jun 25, 2017 at 1:28 AM, Marc Glisse  wrote:
>>> +(for cmp (gt ge lt le)
>>> + outp (convert convert negate negate)
>>> + outn (negate negate convert convert)
>>> + /* Transform (X > 0.0 ? 1.0 : -1.0) into copysign(1, X). */
>>> + /* Transform (X >= 0.0 ? 1.0 : -1.0) into copysign(1, X). */
>>> + /* Transform (X < 0.0 ? 1.0 : -1.0) into copysign(1,-X). */
>>> + /* Transform (X <= 0.0 ? 1.0 : -1.0) into copysign(1,-X). */
>>> + (simplify
>>> +  (cond (cmp @0 real_zerop) real_onep real_minus_onep)
>>> +  (if (!HONOR_NANS (type) && !HONOR_SIGNED_ZEROS (type)
>>> +   && types_match (type, TREE_TYPE (@0)))
>>> +   (switch
>>> +(if (types_match (type, float_type_node))
>>> + (BUILT_IN_COPYSIGNF { build_one_cst (type); } (outp @0)))
>>> +(if (types_match (type, double_type_node))
>>> + (BUILT_IN_COPYSIGN { build_one_cst (type); } (outp @0)))
>>> +(if (types_match (type, long_double_type_node))
>>> + (BUILT_IN_COPYSIGNL { build_one_cst (type); } (outp @0))
>>>
>>> There is already a 1.0 of the right type in the input, it would be easier to
>>> reuse it in the output than build a new one.
>>
>> Right.  Fixed.
>>
>>>
>>> Non-generic builtins like copysign are such a pain... We also end up missing
>>> the 128-bit case that way (pre-existing problem, not your patch). We seem to
>>> have a corresponding internal function, but apparently it is not used until
>>> expansion (well, maybe during vectorization).
>>
>> Yes I noticed that while working on a different patch related to
>> copysign; The generic version of a*copysign(1.0, b) [see the other
>> thread where the ARM folks started a patch for it; yes it was by pure
>> accident that I was working on this and really did not notice that
>> thread until yesterday].
>> I was looking into a nice way of creating copysign without having to
>> do the switch but I could not find one.  In the end I copied was done
>> already in a different location in match.pd; this is also the reason
>> why I had the build_one_cst there.
>>
>>>
>>> + /* Transform (X > 0.0 ? -1.0 : 1.0) into copysign(1,-X). */
>>> + /* Transform (X >= 0.0 ? -1.0 : 1.0) into copysign(1,-X). */
>>> + /* Transform (X < 0.0 ? -1.0 : 1.0) into copysign(1,X). */
>>> + /* Transform (X <= 0.0 ? -1.0 : 1.0) into copysign(1,X). */
>>> + (simplify
>>> +  (cond (cmp @0 real_zerop) real_minus_onep real_onep)
>>> +  (if (!HONOR_NANS (type) && !HONOR_SIGNED_ZEROS (type)
>>> +   && types_match (type, TREE_TYPE (@0)))
>>> +   (switch
>>> +(if (types_match (type, float_type_node))
>>> + (BUILT_IN_COPYSIGNF { build_one_cst (type); } (outn @0)))
>>> +(if (types_match (type, double_type_node))
>>> + (BUILT_IN_COPYSIGN { build_one_cst (type); } (outn @0)))
>>> +(if (types_match (type, long_double_type_node))
>>> + (BUILT_IN_COPYSIGNL { build_one_cst (type); } (outn @0)))
>>> +
>>> +/* Transform X * copysign (1.0, X) into abs(X). */
>>> +(simplify
>>> + (mult:c @0 (COPYSIGN real_onep @0))
>>> + (if (!HONOR_NANS (type) && !HONOR_SIGNED_ZEROS (type))
>>> +  (abs @0)))
>>>
>>> I would have expected it do to the right thing for signed zero and qNaN. Can
>>> you describe a case where it would give the wrong result, or are the
>>> conditions just conservative?
>>
>> I was just being conservative; maybe too conservative but I was a bit
>> worried I could get it incorrect.
>>
>>>
>>> +/* Transform X * copysign (1.0, -X) into -abs(X). */
>>> +(simplify
>>> + (mult:c @0 (COPYSIGN real_onep (negate @0)))
>>> + (if (!HONOR_NANS (type) && !HONOR_SIGNED_ZEROS (type))
>>> +  (negate (abs @0
>>> +
>>> +/* Transform copysign (-1.0, X) into copysign (1.0, X). */
>>> +(simplify
>>> + (COPYSIGN real_minus_onep @0)
>>> + (COPYSIGN { build_one_cst (type); } @0))
>>>
>>> (simplify
>>>  (COPYSIGN REAL_CST@0 @1)
>>>  (if (REAL_VALUE_NEGATIVE (TREE_REAL_CST (@0)))
>>>   (COPYSIGN (negate @0) @1)))
>>> ? Or does that create trouble with sNaN and only the 1.0 case is worth
>>> the trouble?
>>
>> No that is the correct way; I Noticed the other thread about copysign
>> had something similar as what should be done too.
>>
>> I will send out a new patch after testing soon.
>
> New patch.
> OK? Bootstrapped and tested on aarch64-linux-gnu with no regressions.
>
> Thanks,
> Andrew Pinski
>
> ChangeLog:
> * match.pd (X >/>=/ (X * copysign (1.0, X)): New pattern.
> (X * copysign (1.0, -X)): New pattern.
> (copysign (-1.0, CST)): New pattern.
>
> testsuite/ChangeLog:
> * gcc.dg/tree-ssa/copy-sign-1.c: New testcase.
> * gcc.dg/tree-ssa/copy-sign-2.c: New testcase.
> * gcc.dg/tree-ssa/mult-abs-2.c: New testcase.
>

This caused:

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81255

-- 
H.J.


Re: [PATCH] Fold (a > 0 ? 1.0 : -1.0) into copysign (1.0, a) and a * copysign (1.0, a) into abs(a)

2017-06-28 Thread Richard Biener
On Wed, Jun 28, 2017 at 10:50 AM, Christophe Lyon
 wrote:
> On 25 June 2017 at 23:28, Andrew Pinski  wrote:
>> On Sun, Jun 25, 2017 at 11:18 AM, Andrew Pinski  wrote:
>>> On Sun, Jun 25, 2017 at 1:28 AM, Marc Glisse  wrote:
 +(for cmp (gt ge lt le)
 + outp (convert convert negate negate)
 + outn (negate negate convert convert)
 + /* Transform (X > 0.0 ? 1.0 : -1.0) into copysign(1, X). */
 + /* Transform (X >= 0.0 ? 1.0 : -1.0) into copysign(1, X). */
 + /* Transform (X < 0.0 ? 1.0 : -1.0) into copysign(1,-X). */
 + /* Transform (X <= 0.0 ? 1.0 : -1.0) into copysign(1,-X). */
 + (simplify
 +  (cond (cmp @0 real_zerop) real_onep real_minus_onep)
 +  (if (!HONOR_NANS (type) && !HONOR_SIGNED_ZEROS (type)
 +   && types_match (type, TREE_TYPE (@0)))
 +   (switch
 +(if (types_match (type, float_type_node))
 + (BUILT_IN_COPYSIGNF { build_one_cst (type); } (outp @0)))
 +(if (types_match (type, double_type_node))
 + (BUILT_IN_COPYSIGN { build_one_cst (type); } (outp @0)))
 +(if (types_match (type, long_double_type_node))
 + (BUILT_IN_COPYSIGNL { build_one_cst (type); } (outp @0))

 There is already a 1.0 of the right type in the input, it would be easier 
 to
 reuse it in the output than build a new one.
>>>
>>> Right.  Fixed.
>>>

 Non-generic builtins like copysign are such a pain... We also end up 
 missing
 the 128-bit case that way (pre-existing problem, not your patch). We seem 
 to
 have a corresponding internal function, but apparently it is not used until
 expansion (well, maybe during vectorization).
>>>
>>> Yes I noticed that while working on a different patch related to
>>> copysign; The generic version of a*copysign(1.0, b) [see the other
>>> thread where the ARM folks started a patch for it; yes it was by pure
>>> accident that I was working on this and really did not notice that
>>> thread until yesterday].
>>> I was looking into a nice way of creating copysign without having to
>>> do the switch but I could not find one.  In the end I copied was done
>>> already in a different location in match.pd; this is also the reason
>>> why I had the build_one_cst there.
>>>

 + /* Transform (X > 0.0 ? -1.0 : 1.0) into copysign(1,-X). */
 + /* Transform (X >= 0.0 ? -1.0 : 1.0) into copysign(1,-X). */
 + /* Transform (X < 0.0 ? -1.0 : 1.0) into copysign(1,X). */
 + /* Transform (X <= 0.0 ? -1.0 : 1.0) into copysign(1,X). */
 + (simplify
 +  (cond (cmp @0 real_zerop) real_minus_onep real_onep)
 +  (if (!HONOR_NANS (type) && !HONOR_SIGNED_ZEROS (type)
 +   && types_match (type, TREE_TYPE (@0)))
 +   (switch
 +(if (types_match (type, float_type_node))
 + (BUILT_IN_COPYSIGNF { build_one_cst (type); } (outn @0)))
 +(if (types_match (type, double_type_node))
 + (BUILT_IN_COPYSIGN { build_one_cst (type); } (outn @0)))
 +(if (types_match (type, long_double_type_node))
 + (BUILT_IN_COPYSIGNL { build_one_cst (type); } (outn @0)))
 +
 +/* Transform X * copysign (1.0, X) into abs(X). */
 +(simplify
 + (mult:c @0 (COPYSIGN real_onep @0))
 + (if (!HONOR_NANS (type) && !HONOR_SIGNED_ZEROS (type))
 +  (abs @0)))

 I would have expected it do to the right thing for signed zero and qNaN. 
 Can
 you describe a case where it would give the wrong result, or are the
 conditions just conservative?
>>>
>>> I was just being conservative; maybe too conservative but I was a bit
>>> worried I could get it incorrect.
>>>

 +/* Transform X * copysign (1.0, -X) into -abs(X). */
 +(simplify
 + (mult:c @0 (COPYSIGN real_onep (negate @0)))
 + (if (!HONOR_NANS (type) && !HONOR_SIGNED_ZEROS (type))
 +  (negate (abs @0
 +
 +/* Transform copysign (-1.0, X) into copysign (1.0, X). */
 +(simplify
 + (COPYSIGN real_minus_onep @0)
 + (COPYSIGN { build_one_cst (type); } @0))

 (simplify
  (COPYSIGN REAL_CST@0 @1)
  (if (REAL_VALUE_NEGATIVE (TREE_REAL_CST (@0)))
   (COPYSIGN (negate @0) @1)))
 ? Or does that create trouble with sNaN and only the 1.0 case is worth
 the trouble?
>>>
>>> No that is the correct way; I Noticed the other thread about copysign
>>> had something similar as what should be done too.
>>>
>>> I will send out a new patch after testing soon.
>>
>> New patch.
>> OK? Bootstrapped and tested on aarch64-linux-gnu with no regressions.
>>
> Hi Andrew,
>
> 2 of the new testcases fail on aarch64*-elf:
> FAIL:gcc.dg/tree-ssa/copy-sign-1.c scan-tree-dump-times gimple "copysign" 
> 8
> FAIL:gcc.dg/tree-ssa/mult-abs-2.c scan-tree-dump-times gimple "ABS" 8
>
> The attached patch makes them unsupported by requiring c99_runtime
> effective-target.
>
> OK?

Ok.

>
>> Thanks,
>> Andrew 

Re: [PATCH] Fold (a > 0 ? 1.0 : -1.0) into copysign (1.0, a) and a * copysign (1.0, a) into abs(a)

2017-06-28 Thread Christophe Lyon
On 25 June 2017 at 23:28, Andrew Pinski  wrote:
> On Sun, Jun 25, 2017 at 11:18 AM, Andrew Pinski  wrote:
>> On Sun, Jun 25, 2017 at 1:28 AM, Marc Glisse  wrote:
>>> +(for cmp (gt ge lt le)
>>> + outp (convert convert negate negate)
>>> + outn (negate negate convert convert)
>>> + /* Transform (X > 0.0 ? 1.0 : -1.0) into copysign(1, X). */
>>> + /* Transform (X >= 0.0 ? 1.0 : -1.0) into copysign(1, X). */
>>> + /* Transform (X < 0.0 ? 1.0 : -1.0) into copysign(1,-X). */
>>> + /* Transform (X <= 0.0 ? 1.0 : -1.0) into copysign(1,-X). */
>>> + (simplify
>>> +  (cond (cmp @0 real_zerop) real_onep real_minus_onep)
>>> +  (if (!HONOR_NANS (type) && !HONOR_SIGNED_ZEROS (type)
>>> +   && types_match (type, TREE_TYPE (@0)))
>>> +   (switch
>>> +(if (types_match (type, float_type_node))
>>> + (BUILT_IN_COPYSIGNF { build_one_cst (type); } (outp @0)))
>>> +(if (types_match (type, double_type_node))
>>> + (BUILT_IN_COPYSIGN { build_one_cst (type); } (outp @0)))
>>> +(if (types_match (type, long_double_type_node))
>>> + (BUILT_IN_COPYSIGNL { build_one_cst (type); } (outp @0))
>>>
>>> There is already a 1.0 of the right type in the input, it would be easier to
>>> reuse it in the output than build a new one.
>>
>> Right.  Fixed.
>>
>>>
>>> Non-generic builtins like copysign are such a pain... We also end up missing
>>> the 128-bit case that way (pre-existing problem, not your patch). We seem to
>>> have a corresponding internal function, but apparently it is not used until
>>> expansion (well, maybe during vectorization).
>>
>> Yes I noticed that while working on a different patch related to
>> copysign; The generic version of a*copysign(1.0, b) [see the other
>> thread where the ARM folks started a patch for it; yes it was by pure
>> accident that I was working on this and really did not notice that
>> thread until yesterday].
>> I was looking into a nice way of creating copysign without having to
>> do the switch but I could not find one.  In the end I copied was done
>> already in a different location in match.pd; this is also the reason
>> why I had the build_one_cst there.
>>
>>>
>>> + /* Transform (X > 0.0 ? -1.0 : 1.0) into copysign(1,-X). */
>>> + /* Transform (X >= 0.0 ? -1.0 : 1.0) into copysign(1,-X). */
>>> + /* Transform (X < 0.0 ? -1.0 : 1.0) into copysign(1,X). */
>>> + /* Transform (X <= 0.0 ? -1.0 : 1.0) into copysign(1,X). */
>>> + (simplify
>>> +  (cond (cmp @0 real_zerop) real_minus_onep real_onep)
>>> +  (if (!HONOR_NANS (type) && !HONOR_SIGNED_ZEROS (type)
>>> +   && types_match (type, TREE_TYPE (@0)))
>>> +   (switch
>>> +(if (types_match (type, float_type_node))
>>> + (BUILT_IN_COPYSIGNF { build_one_cst (type); } (outn @0)))
>>> +(if (types_match (type, double_type_node))
>>> + (BUILT_IN_COPYSIGN { build_one_cst (type); } (outn @0)))
>>> +(if (types_match (type, long_double_type_node))
>>> + (BUILT_IN_COPYSIGNL { build_one_cst (type); } (outn @0)))
>>> +
>>> +/* Transform X * copysign (1.0, X) into abs(X). */
>>> +(simplify
>>> + (mult:c @0 (COPYSIGN real_onep @0))
>>> + (if (!HONOR_NANS (type) && !HONOR_SIGNED_ZEROS (type))
>>> +  (abs @0)))
>>>
>>> I would have expected it do to the right thing for signed zero and qNaN. Can
>>> you describe a case where it would give the wrong result, or are the
>>> conditions just conservative?
>>
>> I was just being conservative; maybe too conservative but I was a bit
>> worried I could get it incorrect.
>>
>>>
>>> +/* Transform X * copysign (1.0, -X) into -abs(X). */
>>> +(simplify
>>> + (mult:c @0 (COPYSIGN real_onep (negate @0)))
>>> + (if (!HONOR_NANS (type) && !HONOR_SIGNED_ZEROS (type))
>>> +  (negate (abs @0
>>> +
>>> +/* Transform copysign (-1.0, X) into copysign (1.0, X). */
>>> +(simplify
>>> + (COPYSIGN real_minus_onep @0)
>>> + (COPYSIGN { build_one_cst (type); } @0))
>>>
>>> (simplify
>>>  (COPYSIGN REAL_CST@0 @1)
>>>  (if (REAL_VALUE_NEGATIVE (TREE_REAL_CST (@0)))
>>>   (COPYSIGN (negate @0) @1)))
>>> ? Or does that create trouble with sNaN and only the 1.0 case is worth
>>> the trouble?
>>
>> No that is the correct way; I Noticed the other thread about copysign
>> had something similar as what should be done too.
>>
>> I will send out a new patch after testing soon.
>
> New patch.
> OK? Bootstrapped and tested on aarch64-linux-gnu with no regressions.
>
Hi Andrew,

2 of the new testcases fail on aarch64*-elf:
FAIL:gcc.dg/tree-ssa/copy-sign-1.c scan-tree-dump-times gimple "copysign" 8
FAIL:gcc.dg/tree-ssa/mult-abs-2.c scan-tree-dump-times gimple "ABS" 8

The attached patch makes them unsupported by requiring c99_runtime
effective-target.

OK?


> Thanks,
> Andrew Pinski
>
> ChangeLog:
> * match.pd (X >/>=/ (X * copysign (1.0, X)): New pattern.
> (X * copysign (1.0, -X)): New pattern.
> (copysign (-1.0, CST)): New pattern.
>
> testsuite/ChangeLog:
> * gcc.dg/tree-ssa/copy-sign-1.c: New testcase.
> * 

Re: [PATCH] Fold (a > 0 ? 1.0 : -1.0) into copysign (1.0, a) and a * copysign (1.0, a) into abs(a)

2017-06-28 Thread Uros Bizjak
On Wed, Jun 28, 2017 at 9:37 AM, Jakub Jelinek  wrote:
> On Tue, Jun 27, 2017 at 10:52:47AM -0700, Andrew Pinski wrote:
>> On Tue, Jun 27, 2017 at 7:56 AM, Richard Biener
>>  wrote:
>> > On June 27, 2017 4:52:28 PM GMT+02:00, Tamar Christina 
>> >  wrote:
>> >>> >> +(for cmp (gt ge lt le)
>> >>> >> + outp (convert convert negate negate)
>> >>> >> + outn (negate negate convert convert)
>> >>> >> + /* Transform (X > 0.0 ? 1.0 : -1.0) into copysign(1, X). */
>> >>> >> + /* Transform (X >= 0.0 ? 1.0 : -1.0) into copysign(1, X). */
>> >>> >> + /* Transform (X < 0.0 ? 1.0 : -1.0) into copysign(1,-X). */
>> >>> >> + /* Transform (X <= 0.0 ? 1.0 : -1.0) into copysign(1,-X). */
>> >>> >> +(simplify
>> >>> >> +  (cond (cmp @0 real_zerop) real_onep real_minus_onep)
>> >>> >> +  (if (!HONOR_NANS (type) && !HONOR_SIGNED_ZEROS (type)
>> >>> >> +   && types_match (type, TREE_TYPE (@0)))
>> >>> >> +   (switch
>> >>> >> +(if (types_match (type, float_type_node))
>> >>> >> + (BUILT_IN_COPYSIGNF { build_one_cst (type); } (outp @0)))
>> >>> >> +(if (types_match (type, double_type_node))
>> >>> >> + (BUILT_IN_COPYSIGN { build_one_cst (type); } (outp @0)))
>> >>> >> +(if (types_match (type, long_double_type_node))
>> >>> >> + (BUILT_IN_COPYSIGNL { build_one_cst (type); } (outp @0))
>
> The patch regressed the gcc.target/i386/cmov7.c testcase.
> From the description in the testcase it was testing the combiner, so I've
> transformed it into something that also tests the combiner the same way,
> ok for trunk?  That said, for copysign if we match it we don't emit a fcmov
> while it might be a good idea.
>
> 2017-06-28  Jakub Jelinek  
>
> * gcc.target/i386/cmov7.c (sgn): Renamed to ...
> (foo): ... this.  Change constants such that it isn't matched
> as __builtin_copysign, yet tests the combiner the same.

OK.

Thanks,
Uros.

> --- gcc/testsuite/gcc.target/i386/cmov7.c.jj2016-05-22 12:20:23.0 
> +0200
> +++ gcc/testsuite/gcc.target/i386/cmov7.c   2017-06-28 09:20:24.0 
> +0200
> @@ -10,7 +10,7 @@
> (set (reg:DF) (float_extend:DF (mem:SF (symbol_ref....  */
>
>  double
> -sgn (double __x)
> +foo (double __x)
>  {
> -  return __x >= 0.0 ? 1.0 : -1.0;
> +  return __x >= 1.0 ? 0.0 : -1.0;
>  }
>
>
> Jakub


Re: [PATCH] Fold (a > 0 ? 1.0 : -1.0) into copysign (1.0, a) and a * copysign (1.0, a) into abs(a)

2017-06-28 Thread Jakub Jelinek
On Tue, Jun 27, 2017 at 10:52:47AM -0700, Andrew Pinski wrote:
> On Tue, Jun 27, 2017 at 7:56 AM, Richard Biener
>  wrote:
> > On June 27, 2017 4:52:28 PM GMT+02:00, Tamar Christina 
> >  wrote:
> >>> >> +(for cmp (gt ge lt le)
> >>> >> + outp (convert convert negate negate)
> >>> >> + outn (negate negate convert convert)
> >>> >> + /* Transform (X > 0.0 ? 1.0 : -1.0) into copysign(1, X). */
> >>> >> + /* Transform (X >= 0.0 ? 1.0 : -1.0) into copysign(1, X). */
> >>> >> + /* Transform (X < 0.0 ? 1.0 : -1.0) into copysign(1,-X). */
> >>> >> + /* Transform (X <= 0.0 ? 1.0 : -1.0) into copysign(1,-X). */
> >>> >> +(simplify
> >>> >> +  (cond (cmp @0 real_zerop) real_onep real_minus_onep)
> >>> >> +  (if (!HONOR_NANS (type) && !HONOR_SIGNED_ZEROS (type)
> >>> >> +   && types_match (type, TREE_TYPE (@0)))
> >>> >> +   (switch
> >>> >> +(if (types_match (type, float_type_node))
> >>> >> + (BUILT_IN_COPYSIGNF { build_one_cst (type); } (outp @0)))
> >>> >> +(if (types_match (type, double_type_node))
> >>> >> + (BUILT_IN_COPYSIGN { build_one_cst (type); } (outp @0)))
> >>> >> +(if (types_match (type, long_double_type_node))
> >>> >> + (BUILT_IN_COPYSIGNL { build_one_cst (type); } (outp @0))

The patch regressed the gcc.target/i386/cmov7.c testcase.
>From the description in the testcase it was testing the combiner, so I've
transformed it into something that also tests the combiner the same way,
ok for trunk?  That said, for copysign if we match it we don't emit a fcmov
while it might be a good idea.

2017-06-28  Jakub Jelinek  

* gcc.target/i386/cmov7.c (sgn): Renamed to ...
(foo): ... this.  Change constants such that it isn't matched
as __builtin_copysign, yet tests the combiner the same.

--- gcc/testsuite/gcc.target/i386/cmov7.c.jj2016-05-22 12:20:23.0 
+0200
+++ gcc/testsuite/gcc.target/i386/cmov7.c   2017-06-28 09:20:24.0 
+0200
@@ -10,7 +10,7 @@
(set (reg:DF) (float_extend:DF (mem:SF (symbol_ref....  */
 
 double
-sgn (double __x)
+foo (double __x)
 {
-  return __x >= 0.0 ? 1.0 : -1.0;
+  return __x >= 1.0 ? 0.0 : -1.0;
 }


Jakub


Re: [PATCH] Fold (a > 0 ? 1.0 : -1.0) into copysign (1.0, a) and a * copysign (1.0, a) into abs(a)

2017-06-27 Thread Andrew Pinski
On Tue, Jun 27, 2017 at 7:56 AM, Richard Biener
 wrote:
> On June 27, 2017 4:52:28 PM GMT+02:00, Tamar Christina 
>  wrote:
>>> >> +(for cmp (gt ge lt le)
>>> >> + outp (convert convert negate negate)
>>> >> + outn (negate negate convert convert)
>>> >> + /* Transform (X > 0.0 ? 1.0 : -1.0) into copysign(1, X). */
>>> >> + /* Transform (X >= 0.0 ? 1.0 : -1.0) into copysign(1, X). */
>>> >> + /* Transform (X < 0.0 ? 1.0 : -1.0) into copysign(1,-X). */
>>> >> + /* Transform (X <= 0.0 ? 1.0 : -1.0) into copysign(1,-X). */
>>> >> +(simplify
>>> >> +  (cond (cmp @0 real_zerop) real_onep real_minus_onep)
>>> >> +  (if (!HONOR_NANS (type) && !HONOR_SIGNED_ZEROS (type)
>>> >> +   && types_match (type, TREE_TYPE (@0)))
>>> >> +   (switch
>>> >> +(if (types_match (type, float_type_node))
>>> >> + (BUILT_IN_COPYSIGNF { build_one_cst (type); } (outp @0)))
>>> >> +(if (types_match (type, double_type_node))
>>> >> + (BUILT_IN_COPYSIGN { build_one_cst (type); } (outp @0)))
>>> >> +(if (types_match (type, long_double_type_node))
>>> >> + (BUILT_IN_COPYSIGNL { build_one_cst (type); } (outp @0))
>>> >>
>>
>>Hi,
>>
>>Out of curiosity is there any reason why this transformation can't be
>>more general?
>>
>>e.g. Transform (X > 0.0 ? CST : -CST) into copysign(CST, X).
>
> That's also possible, yes.

I will be implementing that latter today.

Thanks,
Andrew Pinski

>
>>we would at the very least avoid a csel or a branch then.
>>
>>Regards,
>>Tamar
>


RE: [PATCH] Fold (a > 0 ? 1.0 : -1.0) into copysign (1.0, a) and a * copysign (1.0, a) into abs(a)

2017-06-27 Thread Richard Biener
On June 27, 2017 4:52:28 PM GMT+02:00, Tamar Christina 
 wrote:
>> >> +(for cmp (gt ge lt le)
>> >> + outp (convert convert negate negate)
>> >> + outn (negate negate convert convert)
>> >> + /* Transform (X > 0.0 ? 1.0 : -1.0) into copysign(1, X). */
>> >> + /* Transform (X >= 0.0 ? 1.0 : -1.0) into copysign(1, X). */
>> >> + /* Transform (X < 0.0 ? 1.0 : -1.0) into copysign(1,-X). */
>> >> + /* Transform (X <= 0.0 ? 1.0 : -1.0) into copysign(1,-X). */
>> >> +(simplify
>> >> +  (cond (cmp @0 real_zerop) real_onep real_minus_onep)
>> >> +  (if (!HONOR_NANS (type) && !HONOR_SIGNED_ZEROS (type)
>> >> +   && types_match (type, TREE_TYPE (@0)))
>> >> +   (switch
>> >> +(if (types_match (type, float_type_node))
>> >> + (BUILT_IN_COPYSIGNF { build_one_cst (type); } (outp @0)))
>> >> +(if (types_match (type, double_type_node))
>> >> + (BUILT_IN_COPYSIGN { build_one_cst (type); } (outp @0)))
>> >> +(if (types_match (type, long_double_type_node))
>> >> + (BUILT_IN_COPYSIGNL { build_one_cst (type); } (outp @0))
>> >>
>
>Hi,
>
>Out of curiosity is there any reason why this transformation can't be
>more general?
>
>e.g. Transform (X > 0.0 ? CST : -CST) into copysign(CST, X).

That's also possible, yes.

>we would at the very least avoid a csel or a branch then.
>
>Regards,
>Tamar



RE: [PATCH] Fold (a > 0 ? 1.0 : -1.0) into copysign (1.0, a) and a * copysign (1.0, a) into abs(a)

2017-06-27 Thread Tamar Christina
> >> +(for cmp (gt ge lt le)
> >> + outp (convert convert negate negate)
> >> + outn (negate negate convert convert)
> >> + /* Transform (X > 0.0 ? 1.0 : -1.0) into copysign(1, X). */
> >> + /* Transform (X >= 0.0 ? 1.0 : -1.0) into copysign(1, X). */
> >> + /* Transform (X < 0.0 ? 1.0 : -1.0) into copysign(1,-X). */
> >> + /* Transform (X <= 0.0 ? 1.0 : -1.0) into copysign(1,-X). */
> >> +(simplify
> >> +  (cond (cmp @0 real_zerop) real_onep real_minus_onep)
> >> +  (if (!HONOR_NANS (type) && !HONOR_SIGNED_ZEROS (type)
> >> +   && types_match (type, TREE_TYPE (@0)))
> >> +   (switch
> >> +(if (types_match (type, float_type_node))
> >> + (BUILT_IN_COPYSIGNF { build_one_cst (type); } (outp @0)))
> >> +(if (types_match (type, double_type_node))
> >> + (BUILT_IN_COPYSIGN { build_one_cst (type); } (outp @0)))
> >> +(if (types_match (type, long_double_type_node))
> >> + (BUILT_IN_COPYSIGNL { build_one_cst (type); } (outp @0))
> >>

Hi,

Out of curiosity is there any reason why this transformation can't be more 
general?

e.g. Transform (X > 0.0 ? CST : -CST) into copysign(CST, X).

we would at the very least avoid a csel or a branch then.

Regards,
Tamar


Re: [PATCH] Fold (a > 0 ? 1.0 : -1.0) into copysign (1.0, a) and a * copysign (1.0, a) into abs(a)

2017-06-27 Thread Richard Biener
On Sun, Jun 25, 2017 at 11:28 PM, Andrew Pinski  wrote:
> On Sun, Jun 25, 2017 at 11:18 AM, Andrew Pinski  wrote:
>> On Sun, Jun 25, 2017 at 1:28 AM, Marc Glisse  wrote:
>>> +(for cmp (gt ge lt le)
>>> + outp (convert convert negate negate)
>>> + outn (negate negate convert convert)
>>> + /* Transform (X > 0.0 ? 1.0 : -1.0) into copysign(1, X). */
>>> + /* Transform (X >= 0.0 ? 1.0 : -1.0) into copysign(1, X). */
>>> + /* Transform (X < 0.0 ? 1.0 : -1.0) into copysign(1,-X). */
>>> + /* Transform (X <= 0.0 ? 1.0 : -1.0) into copysign(1,-X). */
>>> + (simplify
>>> +  (cond (cmp @0 real_zerop) real_onep real_minus_onep)
>>> +  (if (!HONOR_NANS (type) && !HONOR_SIGNED_ZEROS (type)
>>> +   && types_match (type, TREE_TYPE (@0)))
>>> +   (switch
>>> +(if (types_match (type, float_type_node))
>>> + (BUILT_IN_COPYSIGNF { build_one_cst (type); } (outp @0)))
>>> +(if (types_match (type, double_type_node))
>>> + (BUILT_IN_COPYSIGN { build_one_cst (type); } (outp @0)))
>>> +(if (types_match (type, long_double_type_node))
>>> + (BUILT_IN_COPYSIGNL { build_one_cst (type); } (outp @0))
>>>
>>> There is already a 1.0 of the right type in the input, it would be easier to
>>> reuse it in the output than build a new one.
>>
>> Right.  Fixed.
>>
>>>
>>> Non-generic builtins like copysign are such a pain... We also end up missing
>>> the 128-bit case that way (pre-existing problem, not your patch). We seem to
>>> have a corresponding internal function, but apparently it is not used until
>>> expansion (well, maybe during vectorization).
>>
>> Yes I noticed that while working on a different patch related to
>> copysign; The generic version of a*copysign(1.0, b) [see the other
>> thread where the ARM folks started a patch for it; yes it was by pure
>> accident that I was working on this and really did not notice that
>> thread until yesterday].
>> I was looking into a nice way of creating copysign without having to
>> do the switch but I could not find one.  In the end I copied was done
>> already in a different location in match.pd; this is also the reason
>> why I had the build_one_cst there.
>>
>>>
>>> + /* Transform (X > 0.0 ? -1.0 : 1.0) into copysign(1,-X). */
>>> + /* Transform (X >= 0.0 ? -1.0 : 1.0) into copysign(1,-X). */
>>> + /* Transform (X < 0.0 ? -1.0 : 1.0) into copysign(1,X). */
>>> + /* Transform (X <= 0.0 ? -1.0 : 1.0) into copysign(1,X). */
>>> + (simplify
>>> +  (cond (cmp @0 real_zerop) real_minus_onep real_onep)
>>> +  (if (!HONOR_NANS (type) && !HONOR_SIGNED_ZEROS (type)
>>> +   && types_match (type, TREE_TYPE (@0)))
>>> +   (switch
>>> +(if (types_match (type, float_type_node))
>>> + (BUILT_IN_COPYSIGNF { build_one_cst (type); } (outn @0)))
>>> +(if (types_match (type, double_type_node))
>>> + (BUILT_IN_COPYSIGN { build_one_cst (type); } (outn @0)))
>>> +(if (types_match (type, long_double_type_node))
>>> + (BUILT_IN_COPYSIGNL { build_one_cst (type); } (outn @0)))
>>> +
>>> +/* Transform X * copysign (1.0, X) into abs(X). */
>>> +(simplify
>>> + (mult:c @0 (COPYSIGN real_onep @0))
>>> + (if (!HONOR_NANS (type) && !HONOR_SIGNED_ZEROS (type))
>>> +  (abs @0)))
>>>
>>> I would have expected it do to the right thing for signed zero and qNaN. Can
>>> you describe a case where it would give the wrong result, or are the
>>> conditions just conservative?
>>
>> I was just being conservative; maybe too conservative but I was a bit
>> worried I could get it incorrect.
>>
>>>
>>> +/* Transform X * copysign (1.0, -X) into -abs(X). */
>>> +(simplify
>>> + (mult:c @0 (COPYSIGN real_onep (negate @0)))
>>> + (if (!HONOR_NANS (type) && !HONOR_SIGNED_ZEROS (type))
>>> +  (negate (abs @0
>>> +
>>> +/* Transform copysign (-1.0, X) into copysign (1.0, X). */
>>> +(simplify
>>> + (COPYSIGN real_minus_onep @0)
>>> + (COPYSIGN { build_one_cst (type); } @0))
>>>
>>> (simplify
>>>  (COPYSIGN REAL_CST@0 @1)
>>>  (if (REAL_VALUE_NEGATIVE (TREE_REAL_CST (@0)))
>>>   (COPYSIGN (negate @0) @1)))
>>> ? Or does that create trouble with sNaN and only the 1.0 case is worth
>>> the trouble?
>>
>> No that is the correct way; I Noticed the other thread about copysign
>> had something similar as what should be done too.
>>
>> I will send out a new patch after testing soon.
>
> New patch.
> OK? Bootstrapped and tested on aarch64-linux-gnu with no regressions.

Ok.

We can see if the discussion around using internal functions can end up
improving things here later.  We've several cases in match.pd dealing
with generating of {,f,l} variants.

Richard.

> Thanks,
> Andrew Pinski
>
> ChangeLog:
> * match.pd (X >/>=/ (X * copysign (1.0, X)): New pattern.
> (X * copysign (1.0, -X)): New pattern.
> (copysign (-1.0, CST)): New pattern.
>
> testsuite/ChangeLog:
> * gcc.dg/tree-ssa/copy-sign-1.c: New testcase.
> * gcc.dg/tree-ssa/copy-sign-2.c: New testcase.
> * gcc.dg/tree-ssa/mult-abs-2.c: New testcase.
>
>>
>> 

Re: [PATCH] Fold (a > 0 ? 1.0 : -1.0) into copysign (1.0, a) and a * copysign (1.0, a) into abs(a)

2017-06-26 Thread Richard Sandiford
Joseph Myers  writes:
> On Mon, 26 Jun 2017, Richard Sandiford wrote:
>> > Non-generic builtins like copysign are such a pain... We also end up 
>> > missing the 128-bit case that way (pre-existing problem, not your patch). 
>> > We seem to have a corresponding internal function, but apparently it is 
>> > not used until expansion (well, maybe during vectorization).
>> 
>> It should be OK to introduce uses of the internal functions whenever
>> it's useful.  The match code will check that the internal function is
>> implemented before allowing the transformation.
>
> How well would internal functions work with some having built-in functions 
> only for float, double and long double, others (like copysign) having them 
> for all the _FloatN and _FloatNx types?

I don't think the internal functions themselves should be affected,
since they rely on optabs rather than external functions.  They can
support any mode that the target can support, even if there's no
equivalent standard function.

It might be a good idea to extend gencfn-macros.c and co. to handle
built-in functions that operate on _Float types though.  That wouldn't
be needed for correctness, but would be useful if we want to have folds
that operate on all built-in copysign functions as well as the internal
copysign function.

Thanks,
Richard


Re: [PATCH] Fold (a > 0 ? 1.0 : -1.0) into copysign (1.0, a) and a * copysign (1.0, a) into abs(a)

2017-06-26 Thread Joseph Myers
On Mon, 26 Jun 2017, Richard Sandiford wrote:

> > Non-generic builtins like copysign are such a pain... We also end up 
> > missing the 128-bit case that way (pre-existing problem, not your patch). 
> > We seem to have a corresponding internal function, but apparently it is 
> > not used until expansion (well, maybe during vectorization).
> 
> It should be OK to introduce uses of the internal functions whenever
> it's useful.  The match code will check that the internal function is
> implemented before allowing the transformation.

How well would internal functions work with some having built-in functions 
only for float, double and long double, others (like copysign) having them 
for all the _FloatN and _FloatNx types?

(Preferably of course the built-in functions for libm functions would 
generally exist for all the types.  I didn't include that in my patches 
adding _FloatN/_FloatNx support 
 
 and noted 
various issues to watch out for there, especially increasing the size of 
the enum of built-in functions and the startup cost of initializing them.  
There are other optimizations with similar issues of only covering float, 
double and long double.)

-- 
Joseph S. Myers
jos...@codesourcery.com


Re: [PATCH] Fold (a > 0 ? 1.0 : -1.0) into copysign (1.0, a) and a * copysign (1.0, a) into abs(a)

2017-06-26 Thread Richard Sandiford
Marc Glisse  writes:
> +(for cmp (gt ge lt le)
> + outp (convert convert negate negate)
> + outn (negate negate convert convert)
> + /* Transform (X > 0.0 ? 1.0 : -1.0) into copysign(1, X). */
> + /* Transform (X >= 0.0 ? 1.0 : -1.0) into copysign(1, X). */
> + /* Transform (X < 0.0 ? 1.0 : -1.0) into copysign(1,-X). */
> + /* Transform (X <= 0.0 ? 1.0 : -1.0) into copysign(1,-X). */
> + (simplify
> +  (cond (cmp @0 real_zerop) real_onep real_minus_onep)
> +  (if (!HONOR_NANS (type) && !HONOR_SIGNED_ZEROS (type)
> +   && types_match (type, TREE_TYPE (@0)))
> +   (switch
> +(if (types_match (type, float_type_node))
> + (BUILT_IN_COPYSIGNF { build_one_cst (type); } (outp @0)))
> +(if (types_match (type, double_type_node))
> + (BUILT_IN_COPYSIGN { build_one_cst (type); } (outp @0)))
> +(if (types_match (type, long_double_type_node))
> + (BUILT_IN_COPYSIGNL { build_one_cst (type); } (outp @0))
>
> There is already a 1.0 of the right type in the input, it would be easier 
> to reuse it in the output than build a new one.
>
> Non-generic builtins like copysign are such a pain... We also end up 
> missing the 128-bit case that way (pre-existing problem, not your patch). 
> We seem to have a corresponding internal function, but apparently it is 
> not used until expansion (well, maybe during vectorization).

It should be OK to introduce uses of the internal functions whenever
it's useful.  The match code will check that the internal function is
implemented before allowing the transformation.

The idea was more-or-less:

- Leave calls to libm functions alone until expand if there's no
  particular benefit to converting them earlier.  This avoids introducing
  a gratuitous difference between targets that can and can't open-code the
  function.

- Fold calls to libm functions to calls to libm functions where
  possible, because these transformations work regardless of whether the
  function can be open-coded.

- When introducing new calls, use internal functions if we need to be
  sure that the target has an appropriate optab.

- Also use internal functions to represent the non-errno setting forms
  of an internal function, in cases where the built-in functions are
  assumed to set errno.

But IFN_COPYSIGN might not be useful as-is, since the copysign built-ins
are usually expanded without the help of an optab.  It should be possible
to change things so that IFN_COPYSIGN is supported in the same situations
as the built-in though.

Thanks,
Richard


Re: [PATCH] Fold (a > 0 ? 1.0 : -1.0) into copysign (1.0, a) and a * copysign (1.0, a) into abs(a)

2017-06-25 Thread Andrew Pinski
On Sun, Jun 25, 2017 at 11:18 AM, Andrew Pinski  wrote:
> On Sun, Jun 25, 2017 at 1:28 AM, Marc Glisse  wrote:
>> +(for cmp (gt ge lt le)
>> + outp (convert convert negate negate)
>> + outn (negate negate convert convert)
>> + /* Transform (X > 0.0 ? 1.0 : -1.0) into copysign(1, X). */
>> + /* Transform (X >= 0.0 ? 1.0 : -1.0) into copysign(1, X). */
>> + /* Transform (X < 0.0 ? 1.0 : -1.0) into copysign(1,-X). */
>> + /* Transform (X <= 0.0 ? 1.0 : -1.0) into copysign(1,-X). */
>> + (simplify
>> +  (cond (cmp @0 real_zerop) real_onep real_minus_onep)
>> +  (if (!HONOR_NANS (type) && !HONOR_SIGNED_ZEROS (type)
>> +   && types_match (type, TREE_TYPE (@0)))
>> +   (switch
>> +(if (types_match (type, float_type_node))
>> + (BUILT_IN_COPYSIGNF { build_one_cst (type); } (outp @0)))
>> +(if (types_match (type, double_type_node))
>> + (BUILT_IN_COPYSIGN { build_one_cst (type); } (outp @0)))
>> +(if (types_match (type, long_double_type_node))
>> + (BUILT_IN_COPYSIGNL { build_one_cst (type); } (outp @0))
>>
>> There is already a 1.0 of the right type in the input, it would be easier to
>> reuse it in the output than build a new one.
>
> Right.  Fixed.
>
>>
>> Non-generic builtins like copysign are such a pain... We also end up missing
>> the 128-bit case that way (pre-existing problem, not your patch). We seem to
>> have a corresponding internal function, but apparently it is not used until
>> expansion (well, maybe during vectorization).
>
> Yes I noticed that while working on a different patch related to
> copysign; The generic version of a*copysign(1.0, b) [see the other
> thread where the ARM folks started a patch for it; yes it was by pure
> accident that I was working on this and really did not notice that
> thread until yesterday].
> I was looking into a nice way of creating copysign without having to
> do the switch but I could not find one.  In the end I copied was done
> already in a different location in match.pd; this is also the reason
> why I had the build_one_cst there.
>
>>
>> + /* Transform (X > 0.0 ? -1.0 : 1.0) into copysign(1,-X). */
>> + /* Transform (X >= 0.0 ? -1.0 : 1.0) into copysign(1,-X). */
>> + /* Transform (X < 0.0 ? -1.0 : 1.0) into copysign(1,X). */
>> + /* Transform (X <= 0.0 ? -1.0 : 1.0) into copysign(1,X). */
>> + (simplify
>> +  (cond (cmp @0 real_zerop) real_minus_onep real_onep)
>> +  (if (!HONOR_NANS (type) && !HONOR_SIGNED_ZEROS (type)
>> +   && types_match (type, TREE_TYPE (@0)))
>> +   (switch
>> +(if (types_match (type, float_type_node))
>> + (BUILT_IN_COPYSIGNF { build_one_cst (type); } (outn @0)))
>> +(if (types_match (type, double_type_node))
>> + (BUILT_IN_COPYSIGN { build_one_cst (type); } (outn @0)))
>> +(if (types_match (type, long_double_type_node))
>> + (BUILT_IN_COPYSIGNL { build_one_cst (type); } (outn @0)))
>> +
>> +/* Transform X * copysign (1.0, X) into abs(X). */
>> +(simplify
>> + (mult:c @0 (COPYSIGN real_onep @0))
>> + (if (!HONOR_NANS (type) && !HONOR_SIGNED_ZEROS (type))
>> +  (abs @0)))
>>
>> I would have expected it do to the right thing for signed zero and qNaN. Can
>> you describe a case where it would give the wrong result, or are the
>> conditions just conservative?
>
> I was just being conservative; maybe too conservative but I was a bit
> worried I could get it incorrect.
>
>>
>> +/* Transform X * copysign (1.0, -X) into -abs(X). */
>> +(simplify
>> + (mult:c @0 (COPYSIGN real_onep (negate @0)))
>> + (if (!HONOR_NANS (type) && !HONOR_SIGNED_ZEROS (type))
>> +  (negate (abs @0
>> +
>> +/* Transform copysign (-1.0, X) into copysign (1.0, X). */
>> +(simplify
>> + (COPYSIGN real_minus_onep @0)
>> + (COPYSIGN { build_one_cst (type); } @0))
>>
>> (simplify
>>  (COPYSIGN REAL_CST@0 @1)
>>  (if (REAL_VALUE_NEGATIVE (TREE_REAL_CST (@0)))
>>   (COPYSIGN (negate @0) @1)))
>> ? Or does that create trouble with sNaN and only the 1.0 case is worth
>> the trouble?
>
> No that is the correct way; I Noticed the other thread about copysign
> had something similar as what should be done too.
>
> I will send out a new patch after testing soon.

New patch.
OK? Bootstrapped and tested on aarch64-linux-gnu with no regressions.

Thanks,
Andrew Pinski

ChangeLog:
* match.pd (X >/>=/
> Thanks,
> Andrew
>
>>
>> --
>> Marc Glisse
Index: match.pd
===
--- match.pd(revision 249626)
+++ match.pd(working copy)
@@ -155,6 +155,58 @@
|| !COMPLEX_FLOAT_TYPE_P (type)))
(negate @0)))
 
+(for cmp (gt ge lt le)
+ outp (convert convert negate negate)
+ outn (negate negate convert convert)
+ /* Transform (X > 0.0 ? 1.0 : -1.0) into copysign(1, X). */
+ /* Transform (X >= 0.0 ? 1.0 : -1.0) into copysign(1, X). */
+ /* Transform (X < 0.0 ? 1.0 : -1.0) into copysign(1,-X). */
+ /* Transform (X <= 0.0 ? 1.0 : -1.0) into copysign(1,-X). */
+ (simplify
+  (cond (cmp @0 real_zerop) 

Re: [PATCH] Fold (a > 0 ? 1.0 : -1.0) into copysign (1.0, a) and a * copysign (1.0, a) into abs(a)

2017-06-25 Thread Andrew Pinski
On Sun, Jun 25, 2017 at 1:28 AM, Marc Glisse  wrote:
> +(for cmp (gt ge lt le)
> + outp (convert convert negate negate)
> + outn (negate negate convert convert)
> + /* Transform (X > 0.0 ? 1.0 : -1.0) into copysign(1, X). */
> + /* Transform (X >= 0.0 ? 1.0 : -1.0) into copysign(1, X). */
> + /* Transform (X < 0.0 ? 1.0 : -1.0) into copysign(1,-X). */
> + /* Transform (X <= 0.0 ? 1.0 : -1.0) into copysign(1,-X). */
> + (simplify
> +  (cond (cmp @0 real_zerop) real_onep real_minus_onep)
> +  (if (!HONOR_NANS (type) && !HONOR_SIGNED_ZEROS (type)
> +   && types_match (type, TREE_TYPE (@0)))
> +   (switch
> +(if (types_match (type, float_type_node))
> + (BUILT_IN_COPYSIGNF { build_one_cst (type); } (outp @0)))
> +(if (types_match (type, double_type_node))
> + (BUILT_IN_COPYSIGN { build_one_cst (type); } (outp @0)))
> +(if (types_match (type, long_double_type_node))
> + (BUILT_IN_COPYSIGNL { build_one_cst (type); } (outp @0))
>
> There is already a 1.0 of the right type in the input, it would be easier to
> reuse it in the output than build a new one.

Right.  Fixed.

>
> Non-generic builtins like copysign are such a pain... We also end up missing
> the 128-bit case that way (pre-existing problem, not your patch). We seem to
> have a corresponding internal function, but apparently it is not used until
> expansion (well, maybe during vectorization).

Yes I noticed that while working on a different patch related to
copysign; The generic version of a*copysign(1.0, b) [see the other
thread where the ARM folks started a patch for it; yes it was by pure
accident that I was working on this and really did not notice that
thread until yesterday].
I was looking into a nice way of creating copysign without having to
do the switch but I could not find one.  In the end I copied was done
already in a different location in match.pd; this is also the reason
why I had the build_one_cst there.

>
> + /* Transform (X > 0.0 ? -1.0 : 1.0) into copysign(1,-X). */
> + /* Transform (X >= 0.0 ? -1.0 : 1.0) into copysign(1,-X). */
> + /* Transform (X < 0.0 ? -1.0 : 1.0) into copysign(1,X). */
> + /* Transform (X <= 0.0 ? -1.0 : 1.0) into copysign(1,X). */
> + (simplify
> +  (cond (cmp @0 real_zerop) real_minus_onep real_onep)
> +  (if (!HONOR_NANS (type) && !HONOR_SIGNED_ZEROS (type)
> +   && types_match (type, TREE_TYPE (@0)))
> +   (switch
> +(if (types_match (type, float_type_node))
> + (BUILT_IN_COPYSIGNF { build_one_cst (type); } (outn @0)))
> +(if (types_match (type, double_type_node))
> + (BUILT_IN_COPYSIGN { build_one_cst (type); } (outn @0)))
> +(if (types_match (type, long_double_type_node))
> + (BUILT_IN_COPYSIGNL { build_one_cst (type); } (outn @0)))
> +
> +/* Transform X * copysign (1.0, X) into abs(X). */
> +(simplify
> + (mult:c @0 (COPYSIGN real_onep @0))
> + (if (!HONOR_NANS (type) && !HONOR_SIGNED_ZEROS (type))
> +  (abs @0)))
>
> I would have expected it do to the right thing for signed zero and qNaN. Can
> you describe a case where it would give the wrong result, or are the
> conditions just conservative?

I was just being conservative; maybe too conservative but I was a bit
worried I could get it incorrect.

>
> +/* Transform X * copysign (1.0, -X) into -abs(X). */
> +(simplify
> + (mult:c @0 (COPYSIGN real_onep (negate @0)))
> + (if (!HONOR_NANS (type) && !HONOR_SIGNED_ZEROS (type))
> +  (negate (abs @0
> +
> +/* Transform copysign (-1.0, X) into copysign (1.0, X). */
> +(simplify
> + (COPYSIGN real_minus_onep @0)
> + (COPYSIGN { build_one_cst (type); } @0))
>
> (simplify
>  (COPYSIGN REAL_CST@0 @1)
>  (if (REAL_VALUE_NEGATIVE (TREE_REAL_CST (@0)))
>   (COPYSIGN (negate @0) @1)))
> ? Or does that create trouble with sNaN and only the 1.0 case is worth
> the trouble?

No that is the correct way; I Noticed the other thread about copysign
had something similar as what should be done too.

I will send out a new patch after testing soon.

Thanks,
Andrew

>
> --
> Marc Glisse


Re: [PATCH] Fold (a > 0 ? 1.0 : -1.0) into copysign (1.0, a) and a * copysign (1.0, a) into abs(a)

2017-06-25 Thread Marc Glisse

+(for cmp (gt ge lt le)
+ outp (convert convert negate negate)
+ outn (negate negate convert convert)
+ /* Transform (X > 0.0 ? 1.0 : -1.0) into copysign(1, X). */
+ /* Transform (X >= 0.0 ? 1.0 : -1.0) into copysign(1, X). */
+ /* Transform (X < 0.0 ? 1.0 : -1.0) into copysign(1,-X). */
+ /* Transform (X <= 0.0 ? 1.0 : -1.0) into copysign(1,-X). */
+ (simplify
+  (cond (cmp @0 real_zerop) real_onep real_minus_onep)
+  (if (!HONOR_NANS (type) && !HONOR_SIGNED_ZEROS (type)
+   && types_match (type, TREE_TYPE (@0)))
+   (switch
+(if (types_match (type, float_type_node))
+ (BUILT_IN_COPYSIGNF { build_one_cst (type); } (outp @0)))
+(if (types_match (type, double_type_node))
+ (BUILT_IN_COPYSIGN { build_one_cst (type); } (outp @0)))
+(if (types_match (type, long_double_type_node))
+ (BUILT_IN_COPYSIGNL { build_one_cst (type); } (outp @0))

There is already a 1.0 of the right type in the input, it would be easier 
to reuse it in the output than build a new one.


Non-generic builtins like copysign are such a pain... We also end up 
missing the 128-bit case that way (pre-existing problem, not your patch). 
We seem to have a corresponding internal function, but apparently it is 
not used until expansion (well, maybe during vectorization).


+ /* Transform (X > 0.0 ? -1.0 : 1.0) into copysign(1,-X). */
+ /* Transform (X >= 0.0 ? -1.0 : 1.0) into copysign(1,-X). */
+ /* Transform (X < 0.0 ? -1.0 : 1.0) into copysign(1,X). */
+ /* Transform (X <= 0.0 ? -1.0 : 1.0) into copysign(1,X). */
+ (simplify
+  (cond (cmp @0 real_zerop) real_minus_onep real_onep)
+  (if (!HONOR_NANS (type) && !HONOR_SIGNED_ZEROS (type)
+   && types_match (type, TREE_TYPE (@0)))
+   (switch
+(if (types_match (type, float_type_node))
+ (BUILT_IN_COPYSIGNF { build_one_cst (type); } (outn @0)))
+(if (types_match (type, double_type_node))
+ (BUILT_IN_COPYSIGN { build_one_cst (type); } (outn @0)))
+(if (types_match (type, long_double_type_node))
+ (BUILT_IN_COPYSIGNL { build_one_cst (type); } (outn @0)))
+
+/* Transform X * copysign (1.0, X) into abs(X). */
+(simplify
+ (mult:c @0 (COPYSIGN real_onep @0))
+ (if (!HONOR_NANS (type) && !HONOR_SIGNED_ZEROS (type))
+  (abs @0)))

I would have expected it do to the right thing for signed zero and qNaN. 
Can you describe a case where it would give the wrong result, or are the 
conditions just conservative?


+/* Transform X * copysign (1.0, -X) into -abs(X). */
+(simplify
+ (mult:c @0 (COPYSIGN real_onep (negate @0)))
+ (if (!HONOR_NANS (type) && !HONOR_SIGNED_ZEROS (type))
+  (negate (abs @0
+
+/* Transform copysign (-1.0, X) into copysign (1.0, X). */
+(simplify
+ (COPYSIGN real_minus_onep @0)
+ (COPYSIGN { build_one_cst (type); } @0))

(simplify
 (COPYSIGN REAL_CST@0 @1)
 (if (REAL_VALUE_NEGATIVE (TREE_REAL_CST (@0)))
  (COPYSIGN (negate @0) @1)))
? Or does that create trouble with sNaN and only the 1.0 case is worth
the trouble?

--
Marc Glisse