This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH v4] Add sinh(atanh(x)) and cosh(atanh(x)) optimizations
- From: Giuliano Augusto Faulin Belinassi <giuliano dot belinassi at usp dot br>
- To: GCC Patches <gcc-patches at gcc dot gnu dot org>, Wilco dot Dijkstra at arm dot com, Richard Biener <richard dot guenther at gmail dot com>
- Date: Tue, 27 Nov 2018 17:38:04 -0200
- Subject: [PATCH v4] Add sinh(atanh(x)) and cosh(atanh(x)) optimizations
Only do this optimization if funsafe-math and -fno-math-errno are
enabled, as pointed in the previous iteration.
Also added one more test case to ensure that fno-math-errno is
required for the optimization.
Special thanks for Wilco Dijsktra for all his help :-)
gcc/ChangeLog
2018-11-27 Giuliano Belinassi <giuliano.belinassi@usp.br>
* match.pd (sinh (atanh (x))): New simplification rules.
(cosh (atanh (x))): Likewise.
gcc/testsuite/ChangeLog
2018-11-27 Giuliano Belinassi <giuliano.belinassi@usp.br>
* gcc.dg/sinhatanh-1.c: New test.
* gcc.dg/sinhatanh-2.c: New test.
* gcc.dg/sinhatanh-3.c: New test.
Index: gcc/match.pd
===================================================================
--- gcc/match.pd (revision 266469)
+++ gcc/match.pd (working copy)
@@ -4342,6 +4342,25 @@
(rdiv { t_one; } (sqrts (plus (mult @0 @0) { t_one; })))
(copysigns { t_zero; } @0))))))
+ (if (!flag_errno_math)
+ /* Simplify sinh(atanh(x)) -> x / sqrt((1 - x)*(1 + x)). */
+ (for sinhs (SINH)
+ atanhs (ATANH)
+ sqrts (SQRT)
+ (simplify
+ (sinhs (atanhs:s @0))
+ (with { tree t_one = build_one_cst (type); }
+ (rdiv @0 (sqrts (mult (minus { t_one; } @0) (plus { t_one; } @0)))))))
+
+ /* Simplify cosh(atanh(x)) -> 1 / sqrt((1 - x)*(1 + x)) */
+ (for coshs (COSH)
+ atanhs (ATANH)
+ sqrts (SQRT)
+ (simplify
+ (coshs (atanhs:s @0))
+ (with { tree t_one = build_one_cst (type); }
+ (rdiv { t_one; } (sqrts (mult (minus { t_one; } @0) (plus { t_one; } @0))))))))
+
/* cabs(x+0i) or cabs(0+xi) -> abs(x). */
(simplify
(CABS (complex:C @0 real_zerop@1))
Index: gcc/testsuite/gcc.dg/sinhatanh-1.c
===================================================================
--- gcc/testsuite/gcc.dg/sinhatanh-1.c (nonexistent)
+++ gcc/testsuite/gcc.dg/sinhatanh-1.c (working copy)
@@ -0,0 +1,62 @@
+/* { dg-do compile } */
+/* { dg-options "-Ofast -fdump-tree-optimized" } */
+
+extern float sinhf (float);
+extern float coshf (float);
+extern float atanhf (float);
+extern float sqrtf (float);
+extern double sinh (double);
+extern double cosh (double);
+extern double atanh (double);
+extern double sqrt (double);
+extern long double sinhl (long double);
+extern long double coshl (long double);
+extern long double atanhl (long double);
+extern long double sqrtl (long double);
+
+double __attribute__ ((noinline))
+sinhatanh_ (double x)
+{
+ return sinh (atanh (x));
+}
+
+double __attribute__ ((noinline))
+coshatanh_ (double x)
+{
+ return cosh (atanh (x));
+}
+
+float __attribute__ ((noinline))
+sinhatanhf_(float x)
+{
+ return sinhf (atanhf (x));
+}
+
+float __attribute__ ((noinline))
+coshatanhf_(float x)
+{
+ return coshf (atanhf (x));
+}
+
+long double __attribute__ ((noinline))
+sinhatanhl_ (long double x)
+{
+ return sinhl (atanhl (x));
+}
+
+long double __attribute__ ((noinline))
+coshatanhl_ (long double x)
+{
+ return coshl (atanhl (x));
+}
+
+/* There must be no calls to sinh, cosh, or atanh */
+/* {dg-final { scan-tree-dump-not "sinh " "optimized" } } */
+/* {dg-final { scan-tree-dump-not "cosh " "optimized" } } */
+/* {dg-final { scan-tree-dump-not "atanh " "optimized" }} */
+/* {dg-final { scan-tree-dump-not "sinfh " "optimized" } } */
+/* {dg-final { scan-tree-dump-not "cosfh " "optimized" } } */
+/* {dg-final { scan-tree-dump-not "atanfh " "optimized" }} */
+/* {dg-final { scan-tree-dump-not "sinlh " "optimized" } } */
+/* {dg-final { scan-tree-dump-not "coslh " "optimized" } } */
+/* {dg-final { scan-tree-dump-not "atanlh " "optimized" }} */
Index: gcc/testsuite/gcc.dg/sinhatanh-2.c
===================================================================
--- gcc/testsuite/gcc.dg/sinhatanh-2.c (nonexistent)
+++ gcc/testsuite/gcc.dg/sinhatanh-2.c (working copy)
@@ -0,0 +1,68 @@
+/* { dg-do compile } */
+/* { dg-options "-Ofast -fdump-tree-optimized" } */
+
+extern float sinhf (float);
+extern float coshf (float);
+extern float atanhf (float);
+extern float sqrtf (float);
+extern double sinh (double);
+extern double cosh (double);
+extern double atanh (double);
+extern double sqrt (double);
+extern long double sinhl (long double);
+extern long double coshl (long double);
+extern long double atanhl (long double);
+extern long double sqrtl (long double);
+
+float __attribute__ ((noinline))
+coshatanhf_(float x)
+{
+ float atg = atanhf(x);
+ return coshf(atg) + atg;
+}
+
+double __attribute__ ((noinline))
+cosatan_(double x)
+{
+ double atg = atanh(x);
+ return cosh(atg) + atg;
+}
+
+long double __attribute__ ((noinline))
+cosatanl_(long double x)
+{
+ long double atg = atanhl(x);
+ return coshl(atg) + atg;
+}
+
+float __attribute__ ((noinline))
+sinatanf_(float x)
+{
+ float atg = atanhf(x);
+ return sinhf(atg) + atg;
+}
+
+double __attribute__ ((noinline))
+sinatan_(double x)
+{
+ double atg = atanh(x);
+ return sinh(atg) + atg;
+}
+
+long double __attribute__ ((noinline))
+sinatanl_(long double x)
+{
+ long double atg = atanhl(x);
+ return sinhl(atg) + atg;
+}
+
+/* There should be calls to sinh, cosh and atanh */
+/* { dg-final { scan-tree-dump "cosh " "optimized" } } */
+/* { dg-final { scan-tree-dump "sinh " "optimized" } } */
+/* { dg-final { scan-tree-dump "atanh " "optimized" } } */
+/* { dg-final { scan-tree-dump "coshf " "optimized" } } */
+/* { dg-final { scan-tree-dump "sinhf " "optimized" } } */
+/* { dg-final { scan-tree-dump "atanhf " "optimized" } } */
+/* { dg-final { scan-tree-dump "coshl " "optimized" } } */
+/* { dg-final { scan-tree-dump "sinhl " "optimized" } } */
+/* { dg-final { scan-tree-dump "atanhl " "optimized" } } */
Index: gcc/testsuite/gcc.dg/sinhatanh-3.c
===================================================================
--- gcc/testsuite/gcc.dg/sinhatanh-3.c (nonexistent)
+++ gcc/testsuite/gcc.dg/sinhatanh-3.c (working copy)
@@ -0,0 +1,62 @@
+/* { dg-do compile } */
+/* { dg-options "-Ofast -fmath-errno -fdump-tree-optimized" } */
+
+extern float sinhf (float);
+extern float coshf (float);
+extern float atanhf (float);
+extern float sqrtf (float);
+extern double sinh (double);
+extern double cosh (double);
+extern double atanh (double);
+extern double sqrt (double);
+extern long double sinhl (long double);
+extern long double coshl (long double);
+extern long double atanhl (long double);
+extern long double sqrtl (long double);
+
+double __attribute__ ((noinline))
+sinhatanh_ (double x)
+{
+ return sinh (atanh (x));
+}
+
+double __attribute__ ((noinline))
+coshatanh_ (double x)
+{
+ return cosh (atanh (x));
+}
+
+float __attribute__ ((noinline))
+sinhatanhf_(float x)
+{
+ return sinhf (atanhf (x));
+}
+
+float __attribute__ ((noinline))
+coshatanhf_(float x)
+{
+ return coshf (atanhf (x));
+}
+
+long double __attribute__ ((noinline))
+sinhatanhl_ (long double x)
+{
+ return sinhl (atanhl (x));
+}
+
+long double __attribute__ ((noinline))
+coshatanhl_ (long double x)
+{
+ return coshl (atanhl (x));
+}
+
+/* There should be calls to sinh, cosh and atanh */
+/* { dg-final { scan-tree-dump "cosh " "optimized" } } */
+/* { dg-final { scan-tree-dump "sinh " "optimized" } } */
+/* { dg-final { scan-tree-dump "atanh " "optimized" } } */
+/* { dg-final { scan-tree-dump "coshf " "optimized" } } */
+/* { dg-final { scan-tree-dump "sinhf " "optimized" } } */
+/* { dg-final { scan-tree-dump "atanhf " "optimized" } } */
+/* { dg-final { scan-tree-dump "coshl " "optimized" } } */
+/* { dg-final { scan-tree-dump "sinhl " "optimized" } } */
+/* { dg-final { scan-tree-dump "atanhl " "optimized" } } */