[3/4] Add some optimizations to gimple_expand_builtin_cabs
Checks
Context |
Check |
Description |
linaro-tcwg-bot/tcwg_gcc_build--master-aarch64 |
success
|
Build passed
|
linaro-tcwg-bot/tcwg_gcc_build--master-arm |
success
|
Build passed
|
linaro-tcwg-bot/tcwg_gcc_check--master-aarch64 |
success
|
Test passed
|
linaro-tcwg-bot/tcwg_gcc_check--master-arm |
success
|
Test passed
|
Commit Message
While looking into the original folding code for cabs
(moved to match in r6-4111-gabcc43f5323869), I noticed that
`cabs(x+0i)` was optimized even without the need of sqrt.
I also noticed that now the code generation in this case
will be worse if the target had a sqrt. So let's implement
this small optimizations in gimple_expand_builtin_cabs.
Note `cabs(x+0i)` is done without unsafe math optimizations.
This is because the definition of `cabs(x+0i)` is `hypot(x, 0)`
and the definition in the standard says that just returns `abs(x)`.
Bootstrapped and tested on x86_64-linux-gnu with no regressions.
gcc/ChangeLog:
* tree-complex.cc (gimple_expand_builtin_cabs): Add
`cabs(a+ai)`, `cabs(x+0i)` and `cabs(0+xi)` optimizations.
gcc/testsuite/ChangeLog:
* gcc.dg/tree-ssa/cabs-3.c: New test.
* gcc.dg/tree-ssa/cabs-4.c: New test.
* gcc.dg/tree-ssa/cabs-5.c: New test.
* gcc.dg/tree-ssa/cabs-6.c: New test.
Signed-off-by: Andrew Pinski <quic_apinski@quicinc.com>
Fix optimizations
Signed-off-by: Andrew Pinski <quic_apinski@quicinc.com>
---
gcc/testsuite/gcc.dg/tree-ssa/cabs-3.c | 24 +++++++++++
gcc/testsuite/gcc.dg/tree-ssa/cabs-4.c | 16 ++++++++
gcc/testsuite/gcc.dg/tree-ssa/cabs-5.c | 22 ++++++++++
gcc/testsuite/gcc.dg/tree-ssa/cabs-6.c | 16 ++++++++
gcc/tree-complex.cc | 56 +++++++++++++++++++++-----
5 files changed, 123 insertions(+), 11 deletions(-)
create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/cabs-3.c
create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/cabs-4.c
create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/cabs-5.c
create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/cabs-6.c
Comments
On Mon, Jul 1, 2024 at 11:48 PM Andrew Pinski <quic_apinski@quicinc.com> wrote:
>
> While looking into the original folding code for cabs
> (moved to match in r6-4111-gabcc43f5323869), I noticed that
> `cabs(x+0i)` was optimized even without the need of sqrt.
> I also noticed that now the code generation in this case
> will be worse if the target had a sqrt. So let's implement
> this small optimizations in gimple_expand_builtin_cabs.
> Note `cabs(x+0i)` is done without unsafe math optimizations.
> This is because the definition of `cabs(x+0i)` is `hypot(x, 0)`
> and the definition in the standard says that just returns `abs(x)`.
>
> Bootstrapped and tested on x86_64-linux-gnu with no regressions.
OK.
Btw, I was wondering if there's any concern about errno given
hypot documents some but cabs doesn't (and sqrt doesn't set
any)?
> gcc/ChangeLog:
>
> * tree-complex.cc (gimple_expand_builtin_cabs): Add
> `cabs(a+ai)`, `cabs(x+0i)` and `cabs(0+xi)` optimizations.
>
> gcc/testsuite/ChangeLog:
>
> * gcc.dg/tree-ssa/cabs-3.c: New test.
> * gcc.dg/tree-ssa/cabs-4.c: New test.
> * gcc.dg/tree-ssa/cabs-5.c: New test.
> * gcc.dg/tree-ssa/cabs-6.c: New test.
>
> Signed-off-by: Andrew Pinski <quic_apinski@quicinc.com>
>
> Fix optimizations
>
> Signed-off-by: Andrew Pinski <quic_apinski@quicinc.com>
> ---
> gcc/testsuite/gcc.dg/tree-ssa/cabs-3.c | 24 +++++++++++
> gcc/testsuite/gcc.dg/tree-ssa/cabs-4.c | 16 ++++++++
> gcc/testsuite/gcc.dg/tree-ssa/cabs-5.c | 22 ++++++++++
> gcc/testsuite/gcc.dg/tree-ssa/cabs-6.c | 16 ++++++++
> gcc/tree-complex.cc | 56 +++++++++++++++++++++-----
> 5 files changed, 123 insertions(+), 11 deletions(-)
> create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/cabs-3.c
> create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/cabs-4.c
> create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/cabs-5.c
> create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/cabs-6.c
>
> diff --git a/gcc/testsuite/gcc.dg/tree-ssa/cabs-3.c b/gcc/testsuite/gcc.dg/tree-ssa/cabs-3.c
> new file mode 100644
> index 00000000000..976c0169131
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/tree-ssa/cabs-3.c
> @@ -0,0 +1,24 @@
> +/* { dg-do compile { target sqrt_insn } } */
> +/* { dg-options "-Ofast -fdump-tree-cplxlower1" } */
> +/* { dg-add-options sqrt_insn } */
> +
> +
> +double f(double a, double c)
> +{
> + _Complex double b = a;
> + b+= c;
> + return __builtin_cabs(b);
> +}
> +
> +double f1(double a, double c)
> +{
> + _Complex double b = __builtin_complex(0.0, a);
> + b+= __builtin_complex(0.0, c);
> + return __builtin_cabs(b);
> +}
> +
> +/* Check that cabs is expanded during complex lowering. */
> +/* { dg-final { scan-tree-dump-not "__builtin_cabs " "cplxlower1" } } */
> +/* { dg-final { scan-tree-dump-not "__builtin_sqrt " "cplxlower1" } } */
> +/* { dg-final { scan-tree-dump-times "ABS_EXPR <" 2 "cplxlower1" } } */
> +
> diff --git a/gcc/testsuite/gcc.dg/tree-ssa/cabs-4.c b/gcc/testsuite/gcc.dg/tree-ssa/cabs-4.c
> new file mode 100644
> index 00000000000..00aa3c9d4e7
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/tree-ssa/cabs-4.c
> @@ -0,0 +1,16 @@
> +/* { dg-do compile } */
> +/* { dg-options "-Ofast -fdump-tree-cplxlower1" } */
> +
> +double f(double a, double c)
> +{
> + _Complex double d = __builtin_complex (a, a);
> + d+=__builtin_complex(1.0, 1.0);
> + return __builtin_cabs(d);
> +}
> +
> +/* Check that cabs is expanded during complex lowering and there is no sqrt (since it is a constant). */
> +/* { dg-final { scan-tree-dump-not "__builtin_cabs " "cplxlower1" } } */
> +/* { dg-final { scan-tree-dump-not "__builtin_sqrt " "cplxlower1" } } */
> +/* { dg-final { scan-tree-dump-times "ABS_EXPR <" 1 "cplxlower1" } } */
> +
> +
> diff --git a/gcc/testsuite/gcc.dg/tree-ssa/cabs-5.c b/gcc/testsuite/gcc.dg/tree-ssa/cabs-5.c
> new file mode 100644
> index 00000000000..dd794079921
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/tree-ssa/cabs-5.c
> @@ -0,0 +1,22 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O2 -fdump-tree-cplxlower1" } */
> +
> +double f(double a, double c)
> +{
> + _Complex double b = a;
> + b+= c;
> + return __builtin_cabs(b);
> +}
> +
> +double f1(double a, double c)
> +{
> + _Complex double b = __builtin_complex(0.0, a);
> + b+= __builtin_complex(0.0, c);
> + return __builtin_cabs(b);
> +}
> +
> +/* Check that cabs is expanded into ABS for both f and f1 during complex lowering. */
> +/* { dg-final { scan-tree-dump-not "__builtin_cabs " "cplxlower1" } } */
> +/* { dg-final { scan-tree-dump-not "__builtin_sqrt " "cplxlower1" } } */
> +/* { dg-final { scan-tree-dump-times "ABS_EXPR <" 2 "cplxlower1" } } */
> +
> diff --git a/gcc/testsuite/gcc.dg/tree-ssa/cabs-6.c b/gcc/testsuite/gcc.dg/tree-ssa/cabs-6.c
> new file mode 100644
> index 00000000000..bc88932449c
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/tree-ssa/cabs-6.c
> @@ -0,0 +1,16 @@
> +/* { dg-do compile } */
> +/* { dg-options "-Ofast -fdump-tree-cplxlower1" } */
> +
> +double f(double a, double c)
> +{
> + _Complex double d = __builtin_complex (a, 0.0);
> + d+=__builtin_complex(0.0, a);
> + return __builtin_cabs(d);
> +}
> +
> +/* Check that cabs is expanded during complex lowering and there is no sqrt (since it is a constant). */
> +/* { dg-final { scan-tree-dump-not "__builtin_cabs " "cplxlower1" } } */
> +/* { dg-final { scan-tree-dump-not "__builtin_sqrt " "cplxlower1" } } */
> +/* { dg-final { scan-tree-dump-times "ABS_EXPR <" 1 "cplxlower1" } } */
> +
> +
> diff --git a/gcc/tree-complex.cc b/gcc/tree-complex.cc
> index d1276dc1c2f..d2d9d76827d 100644
> --- a/gcc/tree-complex.cc
> +++ b/gcc/tree-complex.cc
> @@ -1701,10 +1701,10 @@ expand_complex_asm (gimple_stmt_iterator *gsi)
> }
>
>
> -/* ARG is the argument to a cabs builtin call in GSI with location info
> - LOC. Create a sequence of statements prior to GSI that calculates
> - sqrt(R*R + I*I), where R and I are the real and imaginary components
> - of ARG, respectively. */
> +/* ARG is the argument to a cabs builtin call in GSI from the
> + original OLD_STMT. Create a sequence of statements prior
> + to GSI that calculates sqrt(R*R + I*I), where R and
> + I are the real and imaginary components of ARG, respectively. */
>
> static void
> gimple_expand_builtin_cabs (gimple_stmt_iterator *gsi, gimple *old_stmt)
> @@ -1712,21 +1712,56 @@ gimple_expand_builtin_cabs (gimple_stmt_iterator *gsi, gimple *old_stmt)
> tree real_part, imag_part, addend1, addend2, sum;
> tree arg = gimple_call_arg (old_stmt, 0);
> tree type = TREE_TYPE (TREE_TYPE (arg));
> - tree sqrtfn = mathfn_built_in (type, BUILT_IN_SQRT);
> machine_mode mode = TYPE_MODE (type);
> gimple *new_stmt;
>
> - if (!flag_unsafe_math_optimizations
> - || !optimize_bb_for_speed_p (gimple_bb (old_stmt))
> - || !sqrtfn
> - || optab_handler (sqrt_optab, mode) == CODE_FOR_nothing)
> - return;
> + tree lhs = gimple_call_lhs (old_stmt);
>
> real_part = extract_component (gsi, arg, false, true);
> imag_part = extract_component (gsi, arg, true, true);
> location_t loc = gimple_location (old_stmt);
>
> gimple_seq stmts = NULL;
> +
> + /* cabs(x+0i) -> abs(x).
> + cabs(0+xi) -> abs(x).
> + These 2 can be done even without unsafe math optimizations. */
> + if (real_zerop (imag_part)
> + || real_zerop (real_part))
> + {
> + tree other = real_zerop (imag_part) ? real_part : imag_part;
> + sum = gimple_build (&stmts, loc, ABS_EXPR, type, other);
> + gsi_insert_seq_before (gsi, stmts, GSI_SAME_STMT);
> + new_stmt = gimple_build_assign (lhs, sum);
> + gimple_set_location (new_stmt, loc);
> + gsi_replace (gsi, new_stmt, true);
> + return;
> + }
> +
> + if (!flag_unsafe_math_optimizations)
> + return;
> +
> + /* cabs(x+xi) -> fabs(x)*sqrt(2). */
> + if (operand_equal_p (real_part, imag_part))
> + {
> + tree sqrt2 = build_real_truncate (type, dconst_sqrt2 ());
> + sum = gimple_build (&stmts, loc, ABS_EXPR, type, real_part);
> + sum = gimple_build (&stmts, loc, MULT_EXPR, type, sum, sqrt2);
> + gsi_insert_seq_before (gsi, stmts, GSI_SAME_STMT);
> + new_stmt = gimple_build_assign (lhs, sum);
> + gimple_set_location (new_stmt, loc);
> + gsi_replace (gsi, new_stmt, true);
> + return;
> + }
> +
> + /* cabs(a+bi) -> sqrt(a*a+b*b) if sqrt exists on the target
> + and optimizing for speed. */
> + tree sqrtfn = mathfn_built_in (type, BUILT_IN_SQRT);
> + if (!optimize_bb_for_speed_p (gimple_bb (old_stmt))
> + || !sqrtfn
> + || optab_handler (sqrt_optab, mode) == CODE_FOR_nothing)
> + return;
> +
> addend1 = gimple_build (&stmts, loc, MULT_EXPR, type, real_part, real_part);
> addend2 = gimple_build (&stmts, loc, MULT_EXPR, type, imag_part, imag_part);
> sum = gimple_build (&stmts, loc, PLUS_EXPR, type, addend1, addend2);
> @@ -1735,7 +1770,6 @@ gimple_expand_builtin_cabs (gimple_stmt_iterator *gsi, gimple *old_stmt)
> /* Build the sqrt call. */
> new_stmt = gimple_build_call (sqrtfn, 1, sum);
> gimple_set_location (new_stmt, loc);
> - tree lhs = gimple_call_lhs (old_stmt);
> gimple_call_set_lhs (new_stmt, lhs);
> gsi_replace (gsi, new_stmt, true);
> }
> --
> 2.43.0
>
On Tue, Jul 2, 2024 at 10:11 AM Richard Biener
<richard.guenther@gmail.com> wrote:
>
> On Mon, Jul 1, 2024 at 11:48 PM Andrew Pinski <quic_apinski@quicinc.com> wrote:
> >
> > While looking into the original folding code for cabs
> > (moved to match in r6-4111-gabcc43f5323869), I noticed that
> > `cabs(x+0i)` was optimized even without the need of sqrt.
> > I also noticed that now the code generation in this case
> > will be worse if the target had a sqrt. So let's implement
> > this small optimizations in gimple_expand_builtin_cabs.
> > Note `cabs(x+0i)` is done without unsafe math optimizations.
> > This is because the definition of `cabs(x+0i)` is `hypot(x, 0)`
> > and the definition in the standard says that just returns `abs(x)`.
> >
> > Bootstrapped and tested on x86_64-linux-gnu with no regressions.
>
> OK.
>
> Btw, I was wondering if there's any concern about errno given
> hypot documents some but cabs doesn't (and sqrt doesn't set
> any)?
Likewise sNaNs might fail to get to qNaNs with cabs(sNaN + 0i)
to abs (sNaN)?
> > gcc/ChangeLog:
> >
> > * tree-complex.cc (gimple_expand_builtin_cabs): Add
> > `cabs(a+ai)`, `cabs(x+0i)` and `cabs(0+xi)` optimizations.
> >
> > gcc/testsuite/ChangeLog:
> >
> > * gcc.dg/tree-ssa/cabs-3.c: New test.
> > * gcc.dg/tree-ssa/cabs-4.c: New test.
> > * gcc.dg/tree-ssa/cabs-5.c: New test.
> > * gcc.dg/tree-ssa/cabs-6.c: New test.
> >
> > Signed-off-by: Andrew Pinski <quic_apinski@quicinc.com>
> >
> > Fix optimizations
> >
> > Signed-off-by: Andrew Pinski <quic_apinski@quicinc.com>
> > ---
> > gcc/testsuite/gcc.dg/tree-ssa/cabs-3.c | 24 +++++++++++
> > gcc/testsuite/gcc.dg/tree-ssa/cabs-4.c | 16 ++++++++
> > gcc/testsuite/gcc.dg/tree-ssa/cabs-5.c | 22 ++++++++++
> > gcc/testsuite/gcc.dg/tree-ssa/cabs-6.c | 16 ++++++++
> > gcc/tree-complex.cc | 56 +++++++++++++++++++++-----
> > 5 files changed, 123 insertions(+), 11 deletions(-)
> > create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/cabs-3.c
> > create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/cabs-4.c
> > create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/cabs-5.c
> > create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/cabs-6.c
> >
> > diff --git a/gcc/testsuite/gcc.dg/tree-ssa/cabs-3.c b/gcc/testsuite/gcc.dg/tree-ssa/cabs-3.c
> > new file mode 100644
> > index 00000000000..976c0169131
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.dg/tree-ssa/cabs-3.c
> > @@ -0,0 +1,24 @@
> > +/* { dg-do compile { target sqrt_insn } } */
> > +/* { dg-options "-Ofast -fdump-tree-cplxlower1" } */
> > +/* { dg-add-options sqrt_insn } */
> > +
> > +
> > +double f(double a, double c)
> > +{
> > + _Complex double b = a;
> > + b+= c;
> > + return __builtin_cabs(b);
> > +}
> > +
> > +double f1(double a, double c)
> > +{
> > + _Complex double b = __builtin_complex(0.0, a);
> > + b+= __builtin_complex(0.0, c);
> > + return __builtin_cabs(b);
> > +}
> > +
> > +/* Check that cabs is expanded during complex lowering. */
> > +/* { dg-final { scan-tree-dump-not "__builtin_cabs " "cplxlower1" } } */
> > +/* { dg-final { scan-tree-dump-not "__builtin_sqrt " "cplxlower1" } } */
> > +/* { dg-final { scan-tree-dump-times "ABS_EXPR <" 2 "cplxlower1" } } */
> > +
> > diff --git a/gcc/testsuite/gcc.dg/tree-ssa/cabs-4.c b/gcc/testsuite/gcc.dg/tree-ssa/cabs-4.c
> > new file mode 100644
> > index 00000000000..00aa3c9d4e7
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.dg/tree-ssa/cabs-4.c
> > @@ -0,0 +1,16 @@
> > +/* { dg-do compile } */
> > +/* { dg-options "-Ofast -fdump-tree-cplxlower1" } */
> > +
> > +double f(double a, double c)
> > +{
> > + _Complex double d = __builtin_complex (a, a);
> > + d+=__builtin_complex(1.0, 1.0);
> > + return __builtin_cabs(d);
> > +}
> > +
> > +/* Check that cabs is expanded during complex lowering and there is no sqrt (since it is a constant). */
> > +/* { dg-final { scan-tree-dump-not "__builtin_cabs " "cplxlower1" } } */
> > +/* { dg-final { scan-tree-dump-not "__builtin_sqrt " "cplxlower1" } } */
> > +/* { dg-final { scan-tree-dump-times "ABS_EXPR <" 1 "cplxlower1" } } */
> > +
> > +
> > diff --git a/gcc/testsuite/gcc.dg/tree-ssa/cabs-5.c b/gcc/testsuite/gcc.dg/tree-ssa/cabs-5.c
> > new file mode 100644
> > index 00000000000..dd794079921
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.dg/tree-ssa/cabs-5.c
> > @@ -0,0 +1,22 @@
> > +/* { dg-do compile } */
> > +/* { dg-options "-O2 -fdump-tree-cplxlower1" } */
> > +
> > +double f(double a, double c)
> > +{
> > + _Complex double b = a;
> > + b+= c;
> > + return __builtin_cabs(b);
> > +}
> > +
> > +double f1(double a, double c)
> > +{
> > + _Complex double b = __builtin_complex(0.0, a);
> > + b+= __builtin_complex(0.0, c);
> > + return __builtin_cabs(b);
> > +}
> > +
> > +/* Check that cabs is expanded into ABS for both f and f1 during complex lowering. */
> > +/* { dg-final { scan-tree-dump-not "__builtin_cabs " "cplxlower1" } } */
> > +/* { dg-final { scan-tree-dump-not "__builtin_sqrt " "cplxlower1" } } */
> > +/* { dg-final { scan-tree-dump-times "ABS_EXPR <" 2 "cplxlower1" } } */
> > +
> > diff --git a/gcc/testsuite/gcc.dg/tree-ssa/cabs-6.c b/gcc/testsuite/gcc.dg/tree-ssa/cabs-6.c
> > new file mode 100644
> > index 00000000000..bc88932449c
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.dg/tree-ssa/cabs-6.c
> > @@ -0,0 +1,16 @@
> > +/* { dg-do compile } */
> > +/* { dg-options "-Ofast -fdump-tree-cplxlower1" } */
> > +
> > +double f(double a, double c)
> > +{
> > + _Complex double d = __builtin_complex (a, 0.0);
> > + d+=__builtin_complex(0.0, a);
> > + return __builtin_cabs(d);
> > +}
> > +
> > +/* Check that cabs is expanded during complex lowering and there is no sqrt (since it is a constant). */
> > +/* { dg-final { scan-tree-dump-not "__builtin_cabs " "cplxlower1" } } */
> > +/* { dg-final { scan-tree-dump-not "__builtin_sqrt " "cplxlower1" } } */
> > +/* { dg-final { scan-tree-dump-times "ABS_EXPR <" 1 "cplxlower1" } } */
> > +
> > +
> > diff --git a/gcc/tree-complex.cc b/gcc/tree-complex.cc
> > index d1276dc1c2f..d2d9d76827d 100644
> > --- a/gcc/tree-complex.cc
> > +++ b/gcc/tree-complex.cc
> > @@ -1701,10 +1701,10 @@ expand_complex_asm (gimple_stmt_iterator *gsi)
> > }
> >
> >
> > -/* ARG is the argument to a cabs builtin call in GSI with location info
> > - LOC. Create a sequence of statements prior to GSI that calculates
> > - sqrt(R*R + I*I), where R and I are the real and imaginary components
> > - of ARG, respectively. */
> > +/* ARG is the argument to a cabs builtin call in GSI from the
> > + original OLD_STMT. Create a sequence of statements prior
> > + to GSI that calculates sqrt(R*R + I*I), where R and
> > + I are the real and imaginary components of ARG, respectively. */
> >
> > static void
> > gimple_expand_builtin_cabs (gimple_stmt_iterator *gsi, gimple *old_stmt)
> > @@ -1712,21 +1712,56 @@ gimple_expand_builtin_cabs (gimple_stmt_iterator *gsi, gimple *old_stmt)
> > tree real_part, imag_part, addend1, addend2, sum;
> > tree arg = gimple_call_arg (old_stmt, 0);
> > tree type = TREE_TYPE (TREE_TYPE (arg));
> > - tree sqrtfn = mathfn_built_in (type, BUILT_IN_SQRT);
> > machine_mode mode = TYPE_MODE (type);
> > gimple *new_stmt;
> >
> > - if (!flag_unsafe_math_optimizations
> > - || !optimize_bb_for_speed_p (gimple_bb (old_stmt))
> > - || !sqrtfn
> > - || optab_handler (sqrt_optab, mode) == CODE_FOR_nothing)
> > - return;
> > + tree lhs = gimple_call_lhs (old_stmt);
> >
> > real_part = extract_component (gsi, arg, false, true);
> > imag_part = extract_component (gsi, arg, true, true);
> > location_t loc = gimple_location (old_stmt);
> >
> > gimple_seq stmts = NULL;
> > +
> > + /* cabs(x+0i) -> abs(x).
> > + cabs(0+xi) -> abs(x).
> > + These 2 can be done even without unsafe math optimizations. */
> > + if (real_zerop (imag_part)
> > + || real_zerop (real_part))
> > + {
> > + tree other = real_zerop (imag_part) ? real_part : imag_part;
> > + sum = gimple_build (&stmts, loc, ABS_EXPR, type, other);
> > + gsi_insert_seq_before (gsi, stmts, GSI_SAME_STMT);
> > + new_stmt = gimple_build_assign (lhs, sum);
> > + gimple_set_location (new_stmt, loc);
> > + gsi_replace (gsi, new_stmt, true);
> > + return;
> > + }
> > +
> > + if (!flag_unsafe_math_optimizations)
> > + return;
> > +
> > + /* cabs(x+xi) -> fabs(x)*sqrt(2). */
> > + if (operand_equal_p (real_part, imag_part))
> > + {
> > + tree sqrt2 = build_real_truncate (type, dconst_sqrt2 ());
> > + sum = gimple_build (&stmts, loc, ABS_EXPR, type, real_part);
> > + sum = gimple_build (&stmts, loc, MULT_EXPR, type, sum, sqrt2);
> > + gsi_insert_seq_before (gsi, stmts, GSI_SAME_STMT);
> > + new_stmt = gimple_build_assign (lhs, sum);
> > + gimple_set_location (new_stmt, loc);
> > + gsi_replace (gsi, new_stmt, true);
> > + return;
> > + }
> > +
> > + /* cabs(a+bi) -> sqrt(a*a+b*b) if sqrt exists on the target
> > + and optimizing for speed. */
> > + tree sqrtfn = mathfn_built_in (type, BUILT_IN_SQRT);
> > + if (!optimize_bb_for_speed_p (gimple_bb (old_stmt))
> > + || !sqrtfn
> > + || optab_handler (sqrt_optab, mode) == CODE_FOR_nothing)
> > + return;
> > +
> > addend1 = gimple_build (&stmts, loc, MULT_EXPR, type, real_part, real_part);
> > addend2 = gimple_build (&stmts, loc, MULT_EXPR, type, imag_part, imag_part);
> > sum = gimple_build (&stmts, loc, PLUS_EXPR, type, addend1, addend2);
> > @@ -1735,7 +1770,6 @@ gimple_expand_builtin_cabs (gimple_stmt_iterator *gsi, gimple *old_stmt)
> > /* Build the sqrt call. */
> > new_stmt = gimple_build_call (sqrtfn, 1, sum);
> > gimple_set_location (new_stmt, loc);
> > - tree lhs = gimple_call_lhs (old_stmt);
> > gimple_call_set_lhs (new_stmt, lhs);
> > gsi_replace (gsi, new_stmt, true);
> > }
> > --
> > 2.43.0
> >
new file mode 100644
@@ -0,0 +1,24 @@
+/* { dg-do compile { target sqrt_insn } } */
+/* { dg-options "-Ofast -fdump-tree-cplxlower1" } */
+/* { dg-add-options sqrt_insn } */
+
+
+double f(double a, double c)
+{
+ _Complex double b = a;
+ b+= c;
+ return __builtin_cabs(b);
+}
+
+double f1(double a, double c)
+{
+ _Complex double b = __builtin_complex(0.0, a);
+ b+= __builtin_complex(0.0, c);
+ return __builtin_cabs(b);
+}
+
+/* Check that cabs is expanded during complex lowering. */
+/* { dg-final { scan-tree-dump-not "__builtin_cabs " "cplxlower1" } } */
+/* { dg-final { scan-tree-dump-not "__builtin_sqrt " "cplxlower1" } } */
+/* { dg-final { scan-tree-dump-times "ABS_EXPR <" 2 "cplxlower1" } } */
+
new file mode 100644
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-options "-Ofast -fdump-tree-cplxlower1" } */
+
+double f(double a, double c)
+{
+ _Complex double d = __builtin_complex (a, a);
+ d+=__builtin_complex(1.0, 1.0);
+ return __builtin_cabs(d);
+}
+
+/* Check that cabs is expanded during complex lowering and there is no sqrt (since it is a constant). */
+/* { dg-final { scan-tree-dump-not "__builtin_cabs " "cplxlower1" } } */
+/* { dg-final { scan-tree-dump-not "__builtin_sqrt " "cplxlower1" } } */
+/* { dg-final { scan-tree-dump-times "ABS_EXPR <" 1 "cplxlower1" } } */
+
+
new file mode 100644
@@ -0,0 +1,22 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-cplxlower1" } */
+
+double f(double a, double c)
+{
+ _Complex double b = a;
+ b+= c;
+ return __builtin_cabs(b);
+}
+
+double f1(double a, double c)
+{
+ _Complex double b = __builtin_complex(0.0, a);
+ b+= __builtin_complex(0.0, c);
+ return __builtin_cabs(b);
+}
+
+/* Check that cabs is expanded into ABS for both f and f1 during complex lowering. */
+/* { dg-final { scan-tree-dump-not "__builtin_cabs " "cplxlower1" } } */
+/* { dg-final { scan-tree-dump-not "__builtin_sqrt " "cplxlower1" } } */
+/* { dg-final { scan-tree-dump-times "ABS_EXPR <" 2 "cplxlower1" } } */
+
new file mode 100644
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-options "-Ofast -fdump-tree-cplxlower1" } */
+
+double f(double a, double c)
+{
+ _Complex double d = __builtin_complex (a, 0.0);
+ d+=__builtin_complex(0.0, a);
+ return __builtin_cabs(d);
+}
+
+/* Check that cabs is expanded during complex lowering and there is no sqrt (since it is a constant). */
+/* { dg-final { scan-tree-dump-not "__builtin_cabs " "cplxlower1" } } */
+/* { dg-final { scan-tree-dump-not "__builtin_sqrt " "cplxlower1" } } */
+/* { dg-final { scan-tree-dump-times "ABS_EXPR <" 1 "cplxlower1" } } */
+
+
@@ -1701,10 +1701,10 @@ expand_complex_asm (gimple_stmt_iterator *gsi)
}
-/* ARG is the argument to a cabs builtin call in GSI with location info
- LOC. Create a sequence of statements prior to GSI that calculates
- sqrt(R*R + I*I), where R and I are the real and imaginary components
- of ARG, respectively. */
+/* ARG is the argument to a cabs builtin call in GSI from the
+ original OLD_STMT. Create a sequence of statements prior
+ to GSI that calculates sqrt(R*R + I*I), where R and
+ I are the real and imaginary components of ARG, respectively. */
static void
gimple_expand_builtin_cabs (gimple_stmt_iterator *gsi, gimple *old_stmt)
@@ -1712,21 +1712,56 @@ gimple_expand_builtin_cabs (gimple_stmt_iterator *gsi, gimple *old_stmt)
tree real_part, imag_part, addend1, addend2, sum;
tree arg = gimple_call_arg (old_stmt, 0);
tree type = TREE_TYPE (TREE_TYPE (arg));
- tree sqrtfn = mathfn_built_in (type, BUILT_IN_SQRT);
machine_mode mode = TYPE_MODE (type);
gimple *new_stmt;
- if (!flag_unsafe_math_optimizations
- || !optimize_bb_for_speed_p (gimple_bb (old_stmt))
- || !sqrtfn
- || optab_handler (sqrt_optab, mode) == CODE_FOR_nothing)
- return;
+ tree lhs = gimple_call_lhs (old_stmt);
real_part = extract_component (gsi, arg, false, true);
imag_part = extract_component (gsi, arg, true, true);
location_t loc = gimple_location (old_stmt);
gimple_seq stmts = NULL;
+
+ /* cabs(x+0i) -> abs(x).
+ cabs(0+xi) -> abs(x).
+ These 2 can be done even without unsafe math optimizations. */
+ if (real_zerop (imag_part)
+ || real_zerop (real_part))
+ {
+ tree other = real_zerop (imag_part) ? real_part : imag_part;
+ sum = gimple_build (&stmts, loc, ABS_EXPR, type, other);
+ gsi_insert_seq_before (gsi, stmts, GSI_SAME_STMT);
+ new_stmt = gimple_build_assign (lhs, sum);
+ gimple_set_location (new_stmt, loc);
+ gsi_replace (gsi, new_stmt, true);
+ return;
+ }
+
+ if (!flag_unsafe_math_optimizations)
+ return;
+
+ /* cabs(x+xi) -> fabs(x)*sqrt(2). */
+ if (operand_equal_p (real_part, imag_part))
+ {
+ tree sqrt2 = build_real_truncate (type, dconst_sqrt2 ());
+ sum = gimple_build (&stmts, loc, ABS_EXPR, type, real_part);
+ sum = gimple_build (&stmts, loc, MULT_EXPR, type, sum, sqrt2);
+ gsi_insert_seq_before (gsi, stmts, GSI_SAME_STMT);
+ new_stmt = gimple_build_assign (lhs, sum);
+ gimple_set_location (new_stmt, loc);
+ gsi_replace (gsi, new_stmt, true);
+ return;
+ }
+
+ /* cabs(a+bi) -> sqrt(a*a+b*b) if sqrt exists on the target
+ and optimizing for speed. */
+ tree sqrtfn = mathfn_built_in (type, BUILT_IN_SQRT);
+ if (!optimize_bb_for_speed_p (gimple_bb (old_stmt))
+ || !sqrtfn
+ || optab_handler (sqrt_optab, mode) == CODE_FOR_nothing)
+ return;
+
addend1 = gimple_build (&stmts, loc, MULT_EXPR, type, real_part, real_part);
addend2 = gimple_build (&stmts, loc, MULT_EXPR, type, imag_part, imag_part);
sum = gimple_build (&stmts, loc, PLUS_EXPR, type, addend1, addend2);
@@ -1735,7 +1770,6 @@ gimple_expand_builtin_cabs (gimple_stmt_iterator *gsi, gimple *old_stmt)
/* Build the sqrt call. */
new_stmt = gimple_build_call (sqrtfn, 1, sum);
gimple_set_location (new_stmt, loc);
- tree lhs = gimple_call_lhs (old_stmt);
gimple_call_set_lhs (new_stmt, lhs);
gsi_replace (gsi, new_stmt, true);
}