[PATCH]: enhance and use fold_strip_sign_ops more often

Kaveh R. GHAZI ghazi@caip.rutgers.edu
Sat Nov 11 01:38:00 GMT 2006


This patch enhances fold_strip_sign_ops and uses it in more places where
we were previously manually transforming things.

The extra uses are in builtins cos and hypot which previously hand checked
for ABS_EXPR and/or NEGATE_EXPR.  Now these (and more) cases are handled
by using the existing fold_strip_sign_ops function.

The enhancement to fold_strip_sign_ops is to strip sign ops from the
argument of "odd" builtin math functions.  This allows simplifications as
seen in the testcase additions, e.g.:

	cos(-fabs(tan(x/-y))) -> cos(tan(x/y)

(Note in addition to removing the "-fabs", the "-y" became just "y".)

Tested on sparc-sun-solaris2.10, no regressions and the new cases all
pass.  Okay for mainline?

		Thanks,
		--Kaveh


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

	* builtins.c (fold_builtin_cos): Use fold_strip_sign_ops().
	(fold_builtin_hypot): Likewise.
	* fold-const.c (fold_strip_sign_ops): Handle "odd" builtins.

testsuite:
	* gcc.dg/builtins-20.c: Add more cases for stripping sign ops.

diff -rup orig/egcc-SVN20061110/gcc/builtins.c egcc-SVN20061110/gcc/builtins.c
--- orig/egcc-SVN20061110/gcc/builtins.c	2006-11-10 09:46:49.000000000 -0500
+++ egcc-SVN20061110/gcc/builtins.c	2006-11-10 11:19:24.370761614 -0500
@@ -7242,7 +7242,7 @@ static tree
 fold_builtin_cos (tree arglist, tree type, tree fndecl)
 {
   tree arg = TREE_VALUE (arglist);
-  tree res;
+  tree res, narg;

   if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
     return NULL_TREE;
@@ -7252,12 +7252,9 @@ fold_builtin_cos (tree arglist, tree typ
     return res;

   /* Optimize cos(-x) into cos (x).  */
-  if (TREE_CODE (arg) == NEGATE_EXPR)
-    {
-      tree args = build_tree_list (NULL_TREE,
-				   TREE_OPERAND (arg, 0));
-      return build_function_call_expr (fndecl, args);
-    }
+  if ((narg = fold_strip_sign_ops (arg)))
+    return build_function_call_expr (fndecl,
+				     build_tree_list (NULL_TREE, narg));

   return NULL_TREE;
 }
@@ -7765,7 +7762,7 @@ fold_builtin_hypot (tree fndecl, tree ar
 {
   tree arg0 = TREE_VALUE (arglist);
   tree arg1 = TREE_VALUE (TREE_CHAIN (arglist));
-  tree res;
+  tree res, narg0, narg1;

   if (!validate_arglist (arglist, REAL_TYPE, REAL_TYPE, VOID_TYPE))
     return NULL_TREE;
@@ -7776,17 +7773,13 @@ fold_builtin_hypot (tree fndecl, tree ar

   /* If either argument to hypot has a negate or abs, strip that off.
      E.g. hypot(-x,fabs(y)) -> hypot(x,y).  */
-  if (TREE_CODE (arg0) == NEGATE_EXPR || TREE_CODE (arg1) == NEGATE_EXPR
-      || TREE_CODE (arg0) == ABS_EXPR || TREE_CODE (arg1) == ABS_EXPR)
-    {
-      tree narg0 = (TREE_CODE (arg0) == NEGATE_EXPR
-		    || TREE_CODE (arg0) == ABS_EXPR)
-	? TREE_OPERAND (arg0, 0) : arg0;
-      tree narg1 = (TREE_CODE (arg1) == NEGATE_EXPR
-		    || TREE_CODE (arg1) == ABS_EXPR)
-	? TREE_OPERAND (arg1, 0) : arg1;
-      tree narglist = tree_cons (NULL_TREE, narg0,
-				 build_tree_list (NULL_TREE, narg1));
+  narg0 = fold_strip_sign_ops (arg0);
+  narg1 = fold_strip_sign_ops (arg1);
+  if (narg0 || narg1)
+    {
+      tree narglist = tree_cons (NULL_TREE, narg0 ? narg0 : arg0,
+				 build_tree_list (NULL_TREE,
+						  narg1 ? narg1 : arg1));
       return build_function_call_expr (fndecl, narglist);
     }

diff -rup orig/egcc-SVN20061110/gcc/fold-const.c egcc-SVN20061110/gcc/fold-const.c
--- orig/egcc-SVN20061110/gcc/fold-const.c	2006-11-10 09:46:51.000000000 -0500
+++ egcc-SVN20061110/gcc/fold-const.c	2006-11-10 10:51:12.440784902 -0500
@@ -13295,6 +13295,17 @@ fold_strip_sign_ops (tree exp)
 			    arg1 ? arg1 : TREE_OPERAND (exp, 1));
       break;

+    case CALL_EXPR:
+      /* Strip sign ops from the argument of "odd" math functions.  */
+      if (negate_mathfn_p (builtin_mathfn_code (exp)))
+        {
+	  arg0 = fold_strip_sign_ops (TREE_VALUE (TREE_OPERAND (exp, 1)));
+	  if (arg0)
+	    return build_function_call_expr (get_callee_fndecl (exp),
+					     build_tree_list (NULL_TREE, arg0));
+	}
+      break;
+
     default:
       break;
     }
diff -rup orig/egcc-SVN20061110/gcc/testsuite/gcc.dg/builtins-20.c egcc-SVN20061110/gcc/testsuite/gcc.dg/builtins-20.c
--- orig/egcc-SVN20061110/gcc/testsuite/gcc.dg/builtins-20.c	2006-11-10 09:46:06.000000000 -0500
+++ egcc-SVN20061110/gcc/testsuite/gcc.dg/builtins-20.c	2006-11-10 10:45:59.315614774 -0500
@@ -38,6 +38,15 @@ void test1(double x)
   if (cos(x) != cos(-x))
     link_error ();

+  if (cos(x) != cos(fabs(x)))
+    link_error ();
+
+  if (cos(x) != cos(-fabs(x)))
+    link_error ();
+
+  if (cos(tan(x)) != cos(tan(-fabs(x))))
+    link_error ();
+
   if (sin(x)/cos(x) != tan(x))
     link_error ();

@@ -65,6 +74,21 @@ void test2(double x, double y)
   if (-sin(x-y) != sin(y-x))
     link_error ();

+  if (cos(-x*y) != cos(x*y))
+    link_error ();
+
+  if (cos(x*-y) != cos(x*y))
+    link_error ();
+
+  if (cos(-x/y) != cos(x/y))
+    link_error ();
+
+  if (cos(x/-y) != cos(x/y))
+    link_error ();
+
+  if (cos(-fabs(tan(x/-y))) != cos(tan(x/y)))
+    link_error ();
+
   if (hypot (x, 0) != fabs(x))
     link_error ();

@@ -103,6 +127,9 @@ void test2(double x, double y)

   if (hypot (pure(x), -pure(x)) != fabs(pure(x)) * __builtin_sqrt(2))
     link_error ();
+
+  if (hypot (tan(-x), tan(-fabs(y))) != hypot (tan(x), tan(y)))
+    link_error ();
 }

 void test1f(float x)
@@ -110,6 +137,15 @@ void test1f(float x)
   if (cosf(x) != cosf(-x))
     link_error ();

+  if (cosf(x) != cosf(fabsf(x)))
+    link_error ();
+
+  if (cosf(x) != cosf(-fabsf(x)))
+    link_error ();
+
+  if (cosf(tanf(x)) != cosf(tanf(-fabsf(x))))
+    link_error ();
+
 #ifdef HAVE_C99_RUNTIME
   if (sinf(x)/cosf(x) != tanf(x))
     link_error ();
@@ -139,6 +175,21 @@ void test2f(float x, float y)
   if (-sinf(x-y) != sinf(y-x))
     link_error ();

+  if (cosf(-x*y) != cosf(x*y))
+    link_error ();
+
+  if (cosf(x*-y) != cosf(x*y))
+    link_error ();
+
+  if (cosf(-x/y) != cosf(x/y))
+    link_error ();
+
+  if (cosf(x/-y) != cosf(x/y))
+    link_error ();
+
+  if (cosf(-fabsf(tanf(x/-y))) != cosf(tanf(x/y)))
+    link_error ();
+
   if (hypotf (x, 0) != fabsf(x))
     link_error ();

@@ -177,6 +228,9 @@ void test2f(float x, float y)

   if (hypotf (puref(x), -puref(x)) != fabsf(puref(x)) * __builtin_sqrtf(2))
     link_error ();
+
+  if (hypotf (tanf(-x), tanf(-fabsf(y))) != hypotf (tanf(x), tanf(y)))
+    link_error ();
 }


@@ -185,6 +239,15 @@ void test1l(long double x)
   if (cosl(x) != cosl(-x))
     link_error ();

+  if (cosl(x) != cosl(fabsl(x)))
+    link_error ();
+
+  if (cosl(x) != cosl(-fabsl(x)))
+    link_error ();
+
+  if (cosl(tanl(x)) != cosl(tanl(-fabsl(x))))
+    link_error ();
+
 #ifdef HAVE_C99_RUNTIME
   if (sinl(x)/cosl(x) != tanl(x))
     link_error ();
@@ -214,6 +277,21 @@ void test2l(long double x, long double y
   if (-sinl(x-y) != sinl(y-x))
     link_error ();

+  if (cosl(-x*y) != cosl(x*y))
+    link_error ();
+
+  if (cosl(x*-y) != cosl(x*y))
+    link_error ();
+
+  if (cosl(-x/y) != cosl(x/y))
+    link_error ();
+
+  if (cosl(x/-y) != cosl(x/y))
+    link_error ();
+
+  if (cosl(-fabsl(tanl(x/-y))) != cosl(tanl(x/y)))
+    link_error ();
+
   if (hypotl (x, 0) != fabsl(x))
     link_error ();

@@ -252,6 +330,9 @@ void test2l(long double x, long double y

   if (hypotl (purel(x), -purel(x)) != fabsl(purel(x)) * __builtin_sqrtl(2))
     link_error ();
+
+  if (hypotl (tanl(-x), tanl(-fabsl(y))) != hypotl (tanl(x), tanl(y)))
+    link_error ();
 }

 int main()



More information about the Gcc-patches mailing list