]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
Add some optimizations to gimple_expand_builtin_cabs
authorAndrew Pinski <quic_apinski@quicinc.com>
Mon, 1 Jul 2024 01:21:15 +0000 (18:21 -0700)
committerAndrew Pinski <quic_apinski@quicinc.com>
Tue, 2 Jul 2024 21:38:13 +0000 (14:38 -0700)
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>
gcc/testsuite/gcc.dg/tree-ssa/cabs-3.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tree-ssa/cabs-4.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tree-ssa/cabs-5.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tree-ssa/cabs-6.c [new file with mode: 0644]
gcc/tree-complex.cc

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 (file)
index 0000000..976c016
--- /dev/null
@@ -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 (file)
index 0000000..00aa3c9
--- /dev/null
@@ -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 (file)
index 0000000..dd79407
--- /dev/null
@@ -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 (file)
index 0000000..bc88932
--- /dev/null
@@ -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" } } */
+
+
index d1276dc1c2ff7a964ab63700d39aeb382d2a4ff4..d2d9d76827db5ccfd8022a8b2effeec0e8c679f1 100644 (file)
@@ -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);
 }