This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[Committed] Fold cabs(-z) and cabs(~z) as cabs(z)
- From: Roger Sayle <roger at eyesopen dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Wed, 31 May 2006 11:34:02 -0600 (MDT)
- Subject: [Committed] Fold cabs(-z) and cabs(~z) as cabs(z)
The following simple "missed optimization" bug-fix (though I admit
it's stretching the definition) was spotted whilst investigating and
developing my recent fix for PR 23452. Mathematically, z*~z is
cabs(z)**2, which lead to the observation that cabs(~z) and cabs(-z)
weren't being optimized by GCC as well as they should.
The following patch was tested on x86_64-unknown-linux-gnu with a
full "make bootstrap", all default languages, and regression tested
with a top-level "make -k check" with no new failures.
Committed to mainline as revision 114276.
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.
* gcc.dg/builtins-54.c: New test case.
Index: builtins.c
===================================================================
*** builtins.c (revision 114166)
--- builtins.c (working copy)
*************** static tree fold_trunc_transparent_mathf
*** 146,152 ****
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);
--- 146,151 ----
*************** fold_fixed_mathfn (tree fndecl, tree arg
*** 6772,6782 ****
}
/* 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. */
static tree
! fold_builtin_cabs (tree arglist, tree type)
{
tree arg;
--- 6771,6782 ----
}
/* Fold function call to builtin cabs, cabsf or cabsl. ARGLIST
! 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, tree fndecl)
{
tree arg;
*************** fold_builtin_cabs (tree arglist, tree ty
*** 6817,6822 ****
--- 6817,6830 ----
&& 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)
*************** fold_builtin_1 (tree fndecl, tree arglis
*** 8648,8654 ****
break;
CASE_FLT_FN (BUILT_IN_CABS):
! return fold_builtin_cabs (arglist, type);
CASE_FLT_FN (BUILT_IN_SQRT):
return fold_builtin_sqrt (arglist, type);
--- 8656,8662 ----
break;
CASE_FLT_FN (BUILT_IN_CABS):
! return fold_builtin_cabs (arglist, type, fndecl);
CASE_FLT_FN (BUILT_IN_SQRT):
return fold_builtin_sqrt (arglist, type);
/* { 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;
}
Roger
--