On Mon, Jul 1, 2024 at 11:48 PM Andrew Pinski <quic_apin...@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_apin...@quicinc.com>
>
> Fix optimizations
>
> Signed-off-by: Andrew Pinski <quic_apin...@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
>

Reply via email to