On Mon, Jul 13, 2026 at 11:48 PM Eikansh Gupta
<[email protected]> wrote:
>
> Fold (signbit (x) cmp1 0) cmp (signbit (y) cmp2 0) ? y : -y
> to copysign (y, +-x).  The result keeps the magnitude of Y and takes its
> sign from X (or -X).  Emitted as IFN_COPYSIGN when the target supports it.
>
>         PR tree-optimization/109843
>
> gcc/ChangeLog:
>
>         * match.pd ((signbit (x) cmp 0) cmp (signbit (y) cmp 0) ? y : -y):
>         New simplification to copysign (y, +-x).
>
> gcc/testsuite/ChangeLog:
>
>         * gcc.dg/tree-ssa/pr109843.c: New test.
>
> Signed-off-by: Eikansh Gupta <[email protected]>
> ---
>  gcc/match.pd                             | 21 +++++++
>  gcc/testsuite/gcc.dg/tree-ssa/pr109843.c | 76 ++++++++++++++++++++++++
>  2 files changed, 97 insertions(+)
>  create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr109843.c
>
> diff --git a/gcc/match.pd b/gcc/match.pd
> index d1a12c35ed3..eb2687976d3 100644
> --- a/gcc/match.pd
> +++ b/gcc/match.pd
> @@ -9864,6 +9864,27 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
>       (abs @0)
>       (negate (abs @0))))))
>
> +/* (signbit (x) cmp1 0) cmp (signbit (y) cmp2 0) ? y : -y
> +   -> copysign (y, +-x).  */
> +#if GIMPLE
> +(for cmp (eq ne)
> + (for icmp1 (eq ne)
> +  (for icmp2 (eq ne)
> +   (for sign (SIGNBIT)
> +    (simplify
> +     (cond (cmp:c (icmp1 (sign @0) integer_zerop)
> +                 (icmp2 (sign @1) integer_zerop))
> +          @1 (negate @1))
> +     (if (SCALAR_FLOAT_TYPE_P (type)
> +         && types_match (type, TREE_TYPE (@0))
> +         && direct_internal_fn_supported_p (IFN_COPYSIGN, type,
> +                                            OPTIMIZE_FOR_BOTH))
> +      (if ((cmp == EQ_EXPR && icmp1 == icmp2)
> +          || (cmp == NE_EXPR && icmp1 != icmp2))

This condition can be reduced down to just:
if ((cmp == EQ_EXPR) == (icmp1 == icmp2))

Otherwise it looks good to me.

> +       (IFN_COPYSIGN @1 @0)
> +       (IFN_COPYSIGN @1 (negate @0)))))))))
> +#endif
> +
>  (simplify
>   /* signbit(x) -> 0 if x is nonnegative.  */
>   (SIGNBIT tree_expr_nonnegative_p@0)
> diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr109843.c 
> b/gcc/testsuite/gcc.dg/tree-ssa/pr109843.c
> new file mode 100644
> index 00000000000..a7138ee5817
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr109843.c
> @@ -0,0 +1,76 @@
> +/* PR tree-optimization/109843 */
> +/* { dg-do compile } */
> +/* { dg-options "-O2 -fdump-tree-optimized" } */
> +
> +#include <stdbool.h>
> +
> +/* Transforms to copysign (y, x)  */
> +
> +float copysign1 (float x, float y)
> +{
> +  bool t = __builtin_signbit (x) == 0;
> +  bool t1 = __builtin_signbit (y) == 0;
> +  return (t == t1) ? y : -y;
> +}
> +
> +float copysign2 (float x, float y)
> +{
> +  bool t = __builtin_signbit (x) != 0;
> +  bool t1 = __builtin_signbit (y) != 0;
> +  return (t == t1) ? y : -y;
> +}
> +
> +float copysign3 (float x, float y)
> +{
> +  bool t = __builtin_signbit (x) != 0;
> +  bool t1 = __builtin_signbit (y) == 0;
> +  return (t != t1) ? y : -y;
> +}
> +
> +float copysign4 (float x, float y)
> +{
> +  bool t = __builtin_signbit (x) == 0;
> +  bool t1 = __builtin_signbit (y) != 0;
> +  return (t != t1) ? y : -y;
> +}
> +
> +float copysign5 (float x, float y)
> +{
> +  bool t = __builtin_signbit (y) == 0;
> +  bool t1 = __builtin_signbit (x) == 0;
> +  return (t == t1) ? y : -y;
> +}
> +
> +/* Transforms to copysign (y, -x)  */
> +
> +float copysign6 (float x, float y)
> +{
> +  bool t = __builtin_signbit (x) == 0;
> +  bool t1 = __builtin_signbit (y) == 0;
> +  return (t != t1) ? y : -y;
> +}
> +
> +float copysign7 (float x, float y)
> +{
> +  bool t = __builtin_signbit (x) != 0;
> +  bool t1 = __builtin_signbit (y) == 0;
> +  return (t == t1) ? y : -y;
> +}
> +
> +float copysign8 (float x, float y)
> +{
> +  bool t = __builtin_signbit (x) == 0;
> +  bool t1 = __builtin_signbit (y) != 0;
> +  return (t == t1) ? y : -y;
> +}
> +
> +float copysign9 (float x, float y)
> +{
> +  bool t = __builtin_signbit (x) != 0;
> +  bool t1 = __builtin_signbit (y) != 0;
> +  return (t != t1) ? y : -y;
> +}
> +
> +/* { dg-final { scan-tree-dump-not "signbit" "optimized" { target 
> ifn_copysign } } } */
> +/* { dg-final { scan-tree-dump-times "= \\.COPYSIGN" 9 "optimized" { target 
> ifn_copysign } } } */
> +/* { dg-final { scan-tree-dump-times " = -" 4 "optimized" { target 
> ifn_copysign } } } */
> --
> 2.34.1
>

Reply via email to