This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH]: cosh is "even", integer rounding functions are "odd"


This patch updates cosh to act as an "even" symmetric math function
and always strip sign ops from the argument just like cos.

As was pointed out, the various abs functions are also "even", however
these cases are already handled by the ABS_EXPR tree code.  Nevertheless,
I added testcases for those as well to ensure they work.

Finally, several of the integer rounding functions are "odd".  The *round
and trunc functions always round away from or towards zero respectively
regardless of rounding mode or the sign of the argument, so they are
symmetric.  The *rint and nearbyint functions also do this when
-fno-rounding-math is set (and we therefore can assume the default mode).
Testcases for those added as well.

(The *floor and *ceil functions round towards positive or negative
infinity, so obviously they are not symmetric.)

Tested on sparc-sun-solaris2.10, no regressions and the new tests pass.

Okay for mainline?

		Thanks,
		--Kaveh


2006-11-11  Kaveh R. Ghazi  <ghazi@caip.rutgers.edu>

	* builtins.c (fold_builtin_cosh): New.
	(fold_builtin_1): Use it.
	* fold-const.c (negate_mathfn_p): Add llround, lround, round,
	trunc to the list of "odd" functions.  Also add llrint, lrint,
	rint and nearbyint when flag_rounding_math is false.

testsuite:
	* gcc.dg/torture/builtin-symmetric-1.c: Add more cases.

diff -rup orig/egcc-SVN20061111/gcc/builtins.c egcc-SVN20061111/gcc/builtins.c
--- orig/egcc-SVN20061111/gcc/builtins.c	2006-11-11 12:20:28.000000000 -0500
+++ egcc-SVN20061111/gcc/builtins.c	2006-11-11 21:44:52.769964556 -0500
@@ -151,6 +151,7 @@ static tree fold_builtin_cbrt (tree, tre
 static tree fold_builtin_pow (tree, tree, tree);
 static tree fold_builtin_powi (tree, tree, tree);
 static tree fold_builtin_cos (tree, tree, tree);
+static tree fold_builtin_cosh (tree, tree, tree);
 static tree fold_builtin_tan (tree, tree);
 static tree fold_builtin_trunc (tree, tree);
 static tree fold_builtin_floor (tree, tree);
@@ -7121,6 +7122,29 @@ fold_builtin_cos (tree arglist, tree typ
   return NULL_TREE;
 }

+/* Fold function call to builtin cosh, coshf, or coshl.  Return
+   NULL_TREE if no simplification can be made.  */
+static tree
+fold_builtin_cosh (tree arglist, tree type, tree fndecl)
+{
+  if (validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
+    {
+      tree arg = TREE_VALUE (arglist);
+      tree res, narg;
+
+      /* Calculate the result when the argument is a constant.  */
+      if ((res = do_mpfr_arg1 (arg, type, mpfr_cosh, NULL, NULL, 0)))
+	return res;
+
+      /* Optimize cosh(-x) into cosh (x).  */
+      if ((narg = fold_strip_sign_ops (arg)))
+	return build_function_call_expr (fndecl,
+					 build_tree_list (NULL_TREE, narg));
+    }
+
+  return NULL_TREE;
+}
+
 /* Fold function call to builtin tan, tanf, or tanl.  Return
    NULL_TREE if no simplification can be made.  */
 static tree
@@ -9046,10 +9070,7 @@ fold_builtin_1 (tree fndecl, tree arglis
     break;

     CASE_FLT_FN (BUILT_IN_COSH):
-      if (validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
-	return do_mpfr_arg1 (TREE_VALUE (arglist), type, mpfr_cosh,
-			     NULL, NULL, 0);
-    break;
+      return fold_builtin_cosh (arglist, type, fndecl);

     CASE_FLT_FN (BUILT_IN_TANH):
       if (validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
diff -rup orig/egcc-SVN20061111/gcc/fold-const.c egcc-SVN20061111/gcc/fold-const.c
--- orig/egcc-SVN20061111/gcc/fold-const.c	2006-11-11 12:20:28.000000000 -0500
+++ egcc-SVN20061111/gcc/fold-const.c	2006-11-11 22:58:34.064224878 -0500
@@ -890,13 +890,23 @@ negate_mathfn_p (enum built_in_function
     CASE_FLT_FN (BUILT_IN_ATAN):
     CASE_FLT_FN (BUILT_IN_ATANH):
     CASE_FLT_FN (BUILT_IN_CBRT):
+    CASE_FLT_FN (BUILT_IN_ERF):
+    CASE_FLT_FN (BUILT_IN_LLROUND):
+    CASE_FLT_FN (BUILT_IN_LROUND):
+    CASE_FLT_FN (BUILT_IN_ROUND):
     CASE_FLT_FN (BUILT_IN_SIN):
     CASE_FLT_FN (BUILT_IN_SINH):
     CASE_FLT_FN (BUILT_IN_TAN):
     CASE_FLT_FN (BUILT_IN_TANH):
-    CASE_FLT_FN (BUILT_IN_ERF):
+    CASE_FLT_FN (BUILT_IN_TRUNC):
       return true;

+    CASE_FLT_FN (BUILT_IN_LLRINT):
+    CASE_FLT_FN (BUILT_IN_LRINT):
+    CASE_FLT_FN (BUILT_IN_NEARBYINT):
+    CASE_FLT_FN (BUILT_IN_RINT):
+      return !flag_rounding_math;
+
     default:
       break;
     }
diff -rup orig/egcc-SVN20061111/gcc/testsuite/gcc.dg/torture/builtin-symmetric-1.c egcc-SVN20061111/gcc/testsuite/gcc.dg/torture/builtin-symmetric-1.c
--- orig/egcc-SVN20061111/gcc/testsuite/gcc.dg/torture/builtin-symmetric-1.c	2006-11-10 23:20:04.000000000 -0500
+++ egcc-SVN20061111/gcc/testsuite/gcc.dg/torture/builtin-symmetric-1.c	2006-11-11 22:59:42.413265321 -0500
@@ -21,6 +21,12 @@ extern void link_error(int);
     link_error(__LINE__); \
   } while (0)

+/* Test that FUNC(-VAR) == FUNC(VAR), where VAR has an int type.  */
+#define TESTIT_EVEN_I(FUNC,VAR) do { \
+  if (__builtin_##FUNC(-VAR) != __builtin_##FUNC(VAR)) \
+    link_error(__LINE__); \
+  } while (0)
+
 /* Test that -FUNC(ARG) == FUNC(-ARG).  */
 #define TESTIT_ODD(FUNC) do { \
   if (-__builtin_##FUNC##f(-xf) != __builtin_##FUNC##f(xf)) \
@@ -31,24 +37,40 @@ extern void link_error(int);
     link_error(__LINE__); \
   } while (0)

-void foo (float xf, double x, long double xl)
+void foo (float xf, double x, long double xl,
+	  int i, long l, long long ll, __INTMAX_TYPE__ im)
 {
   TESTIT_EVEN(cos);
+  TESTIT_EVEN(cosh);
+  TESTIT_EVEN(fabs);
+
+  TESTIT_EVEN_I(abs, i);
+  TESTIT_EVEN_I(imaxabs, im);
+  TESTIT_EVEN_I(labs, l);
+  TESTIT_EVEN_I(llabs, ll);

   TESTIT_ODD(asin);
   TESTIT_ODD(asinh);
   TESTIT_ODD(atan);
   TESTIT_ODD(atanh);
   TESTIT_ODD(cbrt);
+  TESTIT_ODD(erf);
+  TESTIT_ODD(llrint);
+  TESTIT_ODD(llround);
+  TESTIT_ODD(lrint);
+  TESTIT_ODD(lround);
+  TESTIT_ODD(nearbyint);
+  TESTIT_ODD(rint);
+  TESTIT_ODD(round);
   TESTIT_ODD(sin);
   TESTIT_ODD(sinh);
   TESTIT_ODD(tan);
   TESTIT_ODD(tanh);
-  TESTIT_ODD(erf);
+  TESTIT_ODD(trunc);
 }

 int main()
 {
-  foo (1,1,1);
+  foo (1,1,1,1,1,1,1);
   return 0;
 }


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]