From 4f31c7ec654d1b4523288f8cc6d4e21f43afd845 Mon Sep 17 00:00:00 2001
From: Roger Sayle <roger@eyesopen.com>
Date: Wed, 31 May 2006 17:44:56 +0000
Subject: [PATCH] builtins.c (fold_builtin_cabs): Delete prototype.

	* builtins.c (fold_builtin_cabs): Delete prototype.  Require an
	additional FNDECL argument.  Optimize cabs(-z) and cabs(~z) as
	cabs(z).
	(fold_builtin_decl) <BUILT_IN_CABS>: Update fold_builtin_cabs call.

	* gcc.dg/builtins-54.c: New test case.

From-SVN: r114276
---
 gcc/ChangeLog                      |  7 +++++
 gcc/builtins.c                     | 18 ++++++++----
 gcc/testsuite/ChangeLog            |  4 +++
 gcc/testsuite/gcc.dg/builtins-54.c | 44 ++++++++++++++++++++++++++++++
 4 files changed, 68 insertions(+), 5 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/builtins-54.c

diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 6268ad04e09f..4dcbbf12802c 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,10 @@
+2006-05-31  Roger Sayle  <roger@eyesopen.com>
+
+	* builtins.c (fold_builtin_cabs): Delete prototype.  Require an
+	additional FNDECL argument.  Optimize cabs(-z) and cabs(~z) as
+	cabs(z).
+	(fold_builtin_decl) <BUILT_IN_CABS>: Update fold_builtin_cabs call.
+
 2006-05-31  Jie Zhang  <jie.zhang@analog.com>
 
 	* config/bfin/bfin-protos.h (bfin_hardware_loop): Declare.
diff --git a/gcc/builtins.c b/gcc/builtins.c
index b9d94ebcda97..7113681ad352 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -146,7 +146,6 @@ static tree fold_trunc_transparent_mathfn (tree, tree);
 static bool readonly_data_expr (tree);
 static rtx expand_builtin_fabs (tree, rtx, rtx);
 static rtx expand_builtin_signbit (tree, rtx);
-static tree fold_builtin_cabs (tree, tree);
 static tree fold_builtin_sqrt (tree, tree);
 static tree fold_builtin_cbrt (tree, tree);
 static tree fold_builtin_pow (tree, tree, tree);
@@ -6772,11 +6771,12 @@ fold_fixed_mathfn (tree fndecl, tree arglist)
 }
 
 /* Fold function call to builtin cabs, cabsf or cabsl.  ARGLIST
-   is the argument list and TYPE is the return type.  Return
-   NULL_TREE if no if no simplification can be made.  */
+   is the argument list, TYPE is the return type and FNDECL is the
+   original function DECL.  Return NULL_TREE if no if no simplification
+   can be made.  */
 
 static tree
-fold_builtin_cabs (tree arglist, tree type)
+fold_builtin_cabs (tree arglist, tree type, tree fndecl)
 {
   tree arg;
 
@@ -6817,6 +6817,14 @@ fold_builtin_cabs (tree arglist, tree type)
       && real_zerop (TREE_OPERAND (arg, 1)))
     return fold_build1 (ABS_EXPR, type, TREE_OPERAND (arg, 0));
 
+  /* Optimize cabs(-z) and cabs(conj(z)) as cabs(z).  */
+  if (TREE_CODE (arg) == NEGATE_EXPR
+      || TREE_CODE (arg) == CONJ_EXPR)
+    {
+      tree arglist = build_tree_list (NULL_TREE, TREE_OPERAND (arg, 0));
+      return build_function_call_expr (fndecl, arglist);
+    }
+
   /* Don't do this when optimizing for size.  */
   if (flag_unsafe_math_optimizations
       && optimize && !optimize_size)
@@ -8648,7 +8656,7 @@ fold_builtin_1 (tree fndecl, tree arglist, bool ignore)
       break;
 
     CASE_FLT_FN (BUILT_IN_CABS):
-      return fold_builtin_cabs (arglist, type);
+      return fold_builtin_cabs (arglist, type, fndecl);
 
     CASE_FLT_FN (BUILT_IN_SQRT):
       return fold_builtin_sqrt (arglist, type);
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index ddd2fdaa286e..c0b7c04597d6 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,7 @@
+2006-05-31  Roger Sayle  <roger@eyesopen.com>
+
+	* gcc.dg/builtins-54.c: New test case.
+
 2006-05-30  Mark Mitchell  <mark@codesourcery.com>
 
 	PR c++/26433
diff --git a/gcc/testsuite/gcc.dg/builtins-54.c b/gcc/testsuite/gcc.dg/builtins-54.c
new file mode 100644
index 000000000000..29cdf20663de
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/builtins-54.c
@@ -0,0 +1,44 @@
+/* { dg-do link } */
+/* { dg-options "-O2 -ffast-math" } */
+
+double cabs(__complex__ double);
+float cabsf(__complex__ float);
+long double cabsl(__complex__ long double);
+
+void link_error (void);
+
+void test(__complex__ double x)
+{
+  if (cabs(x) != cabs(-x))
+    link_error();
+
+  if (cabs(x) != cabs(~x))
+    link_error();
+}
+
+void testf(__complex__ float x)
+{
+  if (cabsf(x) != cabsf(-x))
+    link_error();
+
+  if (cabsf(x) != cabsf(~x))
+    link_error();
+}
+
+void testl(__complex__ long double x)
+{
+  if (cabsl(x) != cabsl(-x))
+    link_error();
+
+  if (cabsl(x) != cabsl(~x))
+    link_error();
+}
+
+int main()
+{
+  test(0.0);
+  testf(0.0);
+  testl(0.0);
+  return 0;
+}
+
-- 
GitLab