Message ID | 20240701214657.3163066-4-quic_apinski@quicinc.com |
---|---|
State | New |
Headers | show |
Series | Some improvements to complex lowering (cabs related) | expand |
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 > >
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); }