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
>