[gcc r17-2823] MATCH: fold signbit comparison and conditional negate to copysign [PR109843]
Eikansh Gupta via Gcc-cvs <[email protected]> Thu, 30 Jul 2026 10:39:41 +0000 (GMT)
| Newsgroups | gmane.comp.gcc.cvs |
|---|---|
| Message-ID | <[email protected]> |
https://gcc.gnu.org/g:1c8ca0108746d3a7452134f9d1c2e5d89857fed7 commit r17-2823-g1c8ca0108746d3a7452134f9d1c2e5d89857fed7 Author: Eikansh Gupta <[email protected]> Date: Wed Jun 17 09:58:16 2026 +0530 MATCH: fold signbit comparison and conditional negate to copysign [PR109843] 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]> Diff: --- gcc/match.pd | 20 +++++++++ gcc/testsuite/gcc.dg/tree-ssa/pr109843.c | 76 ++++++++++++++++++++++++++++++++ 2 files changed, 96 insertions(+) diff --git a/gcc/match.pd b/gcc/match.pd index 782cfe7dc557..6c9bb0da7cf0 100644 --- a/gcc/match.pd +++ b/gcc/match.pd @@ -9846,6 +9846,26 @@ 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)) + (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 000000000000..a7138ee58178 --- /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 } } } */