On Mon, Jun 22, 2026 at 2:01 AM Richard Biener
<[email protected]> wrote:
>
> On Mon, Jun 22, 2026 at 7:29 AM Eikansh Gupta
> <[email protected]> wrote:
> >
> > Add a pattern for `(trunc)copysign ((extend)x, CST)`.  Only the sign of
> > CST matters, not its value, so it can be simplified to
> > `copysign (x, +-0.0)` depending on the sign of CST.  When signed zeros
> > are not honored their sign may be lost, so `copysign (x, +-1.0)` is used
> > instead.
>
> Is it worth that trouble?  Why not always use +-1.0?

Jeff asked him to change it to be that way but I think it is not so
useful. So yes using +-1.0 should be used. Though +1 will turn into
ABS_EXPR anyways.

>
> As a side-note (but existing pattern before looks the same), I wonder if
> there's any two FP formats X and Y with  TYPE_PRECISION (X) > TYPE_PRECISION 
> (Y)
> where "extending" from Y to X can involve rounding, thus not all values in Y
> are exactly representable in X?  What about normalization to NaNs or Infs or
> denormals?

Yes, that could be an issue.  infs should not be an issue.
Normalization for NaN and rounding might be an issue.
The other pattern which has a similar issue is the conversion to/from
even without copysign.
-frounding-math should disable both of those but don't.  I will file a
bug about these set of patterns in the morning for this.

Thanks,
Andrea

>
> >
> >         PR tree-optimization/112472
> >
> > gcc/ChangeLog:
> >
> >         * match.pd ((trunc)copysign ((extend)x, CST) --> copysign (x, 
> > +-0.0/1.0)):
> >         New pattern.
> >
> > gcc/testsuite/ChangeLog:
> >
> >         * gcc.dg/tree-ssa/pr112472.c: New test.
> >
> > Signed-off-by: Eikansh Gupta <[email protected]>
> > ---
> >  gcc/match.pd                             | 20 +++++++++++++++++++-
> >  gcc/testsuite/gcc.dg/tree-ssa/pr112472.c | 24 ++++++++++++++++++++++++
> >  2 files changed, 43 insertions(+), 1 deletion(-)
> >  create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr112472.c
> >
> > diff --git a/gcc/match.pd b/gcc/match.pd
> > index 8c410c2f3b3..e050ecdf6d6 100644
> > --- a/gcc/match.pd
> > +++ b/gcc/match.pd
> > @@ -9293,7 +9293,25 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
> >         && TYPE_PRECISION (type) < TYPE_PRECISION (TREE_TYPE (@2))
> >         && direct_internal_fn_supported_p (IFN_COPYSIGN,
> >                                           type, OPTIMIZE_FOR_BOTH))
> > -    (IFN_COPYSIGN @0 @1))))
> > +    (IFN_COPYSIGN @0 @1)))
> > + /* Simplify (trunc)copysign ((extend)x, CST) to copysign (x, +-0.0/1.0).  
> > */
> > + (simplify
> > +  (convert (copysigns (convert@2 @0) REAL_CST@1))
> > +   (if (optimize
> > +       && !HONOR_SNANS (@2)
> > +       && types_match (type, TREE_TYPE (@0))
> > +       && TYPE_PRECISION (type) < TYPE_PRECISION (TREE_TYPE (@2))
> > +       && direct_internal_fn_supported_p (IFN_COPYSIGN,
> > +                                         type, OPTIMIZE_FOR_BOTH))
> > +    (with { bool neg = REAL_VALUE_NEGATIVE (TREE_REAL_CST (@1));
> > +           /* Use +-0.0 if possible.  When signed zeros are not honored,
> > +              use +-1.0 instead.  */
> > +           tree cst = HONOR_SIGNED_ZEROS (type)
> > +                      ? (neg ? build_real (type, dconstm0)
> > +                             : build_zero_cst (type))
> > +                      : (neg ? build_minus_one_cst (type)
> > +                             : build_one_cst (type)); }
> > +     (IFN_COPYSIGN @0 { cst; })))))
> >
> >  (for froms (BUILT_IN_FMAF BUILT_IN_FMA BUILT_IN_FMAL)
> >       tos (IFN_FMA IFN_FMA IFN_FMA)
> > diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr112472.c 
> > b/gcc/testsuite/gcc.dg/tree-ssa/pr112472.c
> > new file mode 100644
> > index 00000000000..0112b4a2b61
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr112472.c
> > @@ -0,0 +1,24 @@
> > +/* PR tree-optimization/112472 */
> > +/* { dg-do compile } */
> > +/* { dg-options "-O1 -fdump-tree-optimized" } */
> > +
> > +/* (trunc)copysign ((extend)a, negative CST) is simplified to
> > +   .COPYSIGN (a, -0.0).  */
> > +float f(float a)
> > +{
> > +  return (float)__builtin_copysign(a, -3.0);
> > +}
> > +
> > +/* When signed zeros are not honored, .COPYSIGN (a, -1.0) is used
> > +   instead.  */
> > +__attribute__((optimize("no-signed-zeros")))
> > +float g(float a)
> > +{
> > +  return (float)__builtin_copysign(a, -3.0);
> > +}
> > +
> > +/* { dg-final { scan-tree-dump-not "= __builtin_copysign" "optimized" } } 
> > */
> > +/* { dg-final { scan-tree-dump-not " double " "optimized" { target 
> > ifn_copysign } } } */
> > +/* { dg-final { scan-tree-dump-times ".COPYSIGN" 2 "optimized" { target 
> > ifn_copysign } } } */
> > +/* { dg-final { scan-tree-dump-times "-0\\.0" 1 "optimized" { target 
> > ifn_copysign } } } */
> > +/* { dg-final { scan-tree-dump-times "-1\\.0e\\+0" 1 "optimized" { target 
> > ifn_copysign } } } */
> > --
> > 2.34.1
> >
> >
> > From 208e5c41a71f0900d37ba3d51a57911a32931de4 Mon Sep 17 00:00:00 2001
> > From: Eikansh Gupta <[email protected]>
> > Date: Mon, 15 Jun 2026 12:19:45 +0530
> > Subject: [PATCH v2 2/2] MATCH: Simplify `(trunc)abs ((extend)x)` to `abs 
> > (x)`
> >  [PR112472]
> >
> > When the second argument of copysign is a non-negative constant, the
> > inner copysign is canonicalized to abs before the copysign pattern can
> > match, leaving (trunc)abs ((extend)x) with a redundant extend/truncate.
> > Add a pattern so the non-negative-constant copysign case is fully optimized 
> > too.
> >
> >         PR tree-optimization/112472
> >
> > gcc/ChangeLog:
> >
> >         * match.pd ((trunc)abs (extend x) --> abs (x)): New pattern.
> >
> > gcc/testsuite/ChangeLog:
> >
> >         * gcc.dg/tree-ssa/pr112472.c: Add non-negative constant case.
> >
> > Signed-off-by: Eikansh Gupta <[email protected]>
> > ---
> >  gcc/match.pd                             | 9 +++++++++
> >  gcc/testsuite/gcc.dg/tree-ssa/pr112472.c | 9 +++++++++
> >  2 files changed, 18 insertions(+)
> >
> > diff --git a/gcc/match.pd b/gcc/match.pd
> > index e050ecdf6d6..7f540aa1c4e 100644
> > --- a/gcc/match.pd
> > +++ b/gcc/match.pd
> > @@ -9313,6 +9313,15 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
> >                               : build_one_cst (type)); }
> >       (IFN_COPYSIGN @0 { cst; })))))
> >
> > +/* (trunc)abs (extend x) --> abs (x)  */
> > +(simplify
> > + (convert (abs (convert@1 @0)))
> > +  (if (optimize
> > +      && !HONOR_SNANS (@1)
> > +      && types_match (type, TREE_TYPE (@0))
> > +      && TYPE_PRECISION (type) < TYPE_PRECISION (TREE_TYPE (@1)))
> > +   (abs @0)))
> > +
> >  (for froms (BUILT_IN_FMAF BUILT_IN_FMA BUILT_IN_FMAL)
> >       tos (IFN_FMA IFN_FMA IFN_FMA)
> >   (simplify
> > diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr112472.c 
> > b/gcc/testsuite/gcc.dg/tree-ssa/pr112472.c
> > index 0112b4a2b61..6aa905497bc 100644
> > --- a/gcc/testsuite/gcc.dg/tree-ssa/pr112472.c
> > +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr112472.c
> > @@ -17,8 +17,17 @@ float g(float a)
> >    return (float)__builtin_copysign(a, -3.0);
> >  }
> >
> > +/* With a non-negative CST, copysign is canonicalized to abs, so this
> > +   becomes (float)abs((double)a) and is then simplified to abs(a),
> > +   dropping the wider type.  */
> > +float f2(float a)
> > +{
> > +  return (float)__builtin_copysign(a, 5.0);
> > +}
> > +
> >  /* { dg-final { scan-tree-dump-not "= __builtin_copysign" "optimized" } } 
> > */
> >  /* { dg-final { scan-tree-dump-not " double " "optimized" { target 
> > ifn_copysign } } } */
> >  /* { dg-final { scan-tree-dump-times ".COPYSIGN" 2 "optimized" { target 
> > ifn_copysign } } } */
> >  /* { dg-final { scan-tree-dump-times "-0\\.0" 1 "optimized" { target 
> > ifn_copysign } } } */
> >  /* { dg-final { scan-tree-dump-times "-1\\.0e\\+0" 1 "optimized" { target 
> > ifn_copysign } } } */
> > +/* { dg-final { scan-tree-dump-times " ABS_EXPR " 1 "optimized" { target 
> > ifn_copysign } } } */
> > --
> > 2.34.1
> >

Reply via email to