From 28f4586bf8676b0c6a44d239e366432d5e1fbe1b Mon Sep 17 00:00:00 2001 From: Richard Guenther Date: Thu, 14 Dec 2006 13:14:23 +0000 Subject: [PATCH] re PR middle-end/30197 (cexp ( __complex__ ( 0, x ) ) can be folded to cexpi (x)) 2006-12-14 Richard Guenther PR tree-optimization/30197 * builtins.c (fold_builtin_cexp): New function to fold cexp to cexpi and exp parts. * tree-ssa-pre.c (try_combine_conversion): Also handle REALPART_EXPR and IMAGPART_EXPR. * gcc.c-torture/execute/complex-1.c: Fix function name. * gcc.dg/builtins-61.c: New testcase. From-SVN: r119860 --- gcc/ChangeLog | 8 +++ gcc/builtins.c | 64 +++++++++++++++++++ gcc/testsuite/ChangeLog | 6 ++ .../gcc.c-torture/execute/complex-1.c | 4 +- gcc/testsuite/gcc.dg/builtins-61.c | 31 +++++++++ gcc/tree-ssa-pre.c | 4 +- 6 files changed, 114 insertions(+), 3 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/builtins-61.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index c81598c1d43..82a3641ea28 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2006-12-14 Richard Guenther + + PR tree-optimization/30197 + * builtins.c (fold_builtin_cexp): New function to fold cexp + to cexpi and exp parts. + * tree-ssa-pre.c (try_combine_conversion): Also handle + REALPART_EXPR and IMAGPART_EXPR. + 2006-12-14 Richard Guenther PR middle-end/30172 diff --git a/gcc/builtins.c b/gcc/builtins.c index d0271bc2308..f5798e78947 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -7367,6 +7367,67 @@ fold_builtin_sincos (tree arglist) build1 (REALPART_EXPR, type, call))); } +/* Fold function call to builtin cexp, cexpf, or cexpl. Return + NULL_TREE if no simplification can be made. */ + +static tree +fold_builtin_cexp (tree arglist, tree type) +{ + tree arg0, rtype; + tree realp, imagp, ifn; + + if (!validate_arglist (arglist, COMPLEX_TYPE, VOID_TYPE)) + return NULL_TREE; + + arg0 = TREE_VALUE (arglist); + rtype = TREE_TYPE (TREE_TYPE (arg0)); + + /* In case we can figure out the real part of arg0 and it is constant zero + fold to cexpi. */ + ifn = mathfn_built_in (rtype, BUILT_IN_CEXPI); + if (!ifn) + return NULL_TREE; + + if ((realp = fold_unary (REALPART_EXPR, rtype, arg0)) + && real_zerop (realp)) + { + tree narg = fold_build1 (IMAGPART_EXPR, rtype, arg0); + return build_function_call_expr (ifn, build_tree_list (NULL_TREE, narg)); + } + + /* In case we can easily decompose real and imaginary parts split cexp + to exp (r) * cexpi (i). */ + if (flag_unsafe_math_optimizations + && realp) + { + tree rfn, rcall, icall; + + rfn = mathfn_built_in (rtype, BUILT_IN_EXP); + if (!rfn) + return NULL_TREE; + + imagp = fold_unary (IMAGPART_EXPR, rtype, arg0); + if (!imagp) + return NULL_TREE; + + icall = build_function_call_expr (ifn, + build_tree_list (NULL_TREE, imagp)); + icall = builtin_save_expr (icall); + rcall = build_function_call_expr (rfn, + build_tree_list (NULL_TREE, realp)); + rcall = builtin_save_expr (rcall); + return build2 (COMPLEX_EXPR, type, + build2 (MULT_EXPR, rtype, + rcall, + build1 (REALPART_EXPR, rtype, icall)), + build2 (MULT_EXPR, rtype, + rcall, + build1 (IMAGPART_EXPR, rtype, icall))); + } + + return NULL_TREE; +} + /* Fold function call to builtin trunc, truncf or truncl. Return NULL_TREE if no simplification can be made. */ @@ -9312,6 +9373,9 @@ fold_builtin_1 (tree fndecl, tree arglist, bool ignore) CASE_FLT_FN (BUILT_IN_SINCOS): return fold_builtin_sincos (arglist); + CASE_FLT_FN (BUILT_IN_CEXP): + return fold_builtin_cexp (arglist, type); + CASE_FLT_FN (BUILT_IN_CEXPI): if (validate_arglist (arglist, REAL_TYPE, VOID_TYPE)) return do_mpfr_sincos (TREE_VALUE (arglist), NULL_TREE, NULL_TREE); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 296a34ca7c3..ee65e74c581 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2006-12-14 Richard Guenther + + PR tree-optimization/30197 + * gcc.c-torture/execute/complex-1.c: Fix function name. + * gcc.dg/builtins-61.c: New testcase. + 2006-12-14 Richard Guenther PR middle-end/30172 diff --git a/gcc/testsuite/gcc.c-torture/execute/complex-1.c b/gcc/testsuite/gcc.c-torture/execute/complex-1.c index 424fa65b150..59101796475 100644 --- a/gcc/testsuite/gcc.c-torture/execute/complex-1.c +++ b/gcc/testsuite/gcc.c-torture/execute/complex-1.c @@ -17,7 +17,7 @@ g2 (double x) } __complex__ double -cexp (__complex__ double x) +xcexp (__complex__ double x) { double r; @@ -31,7 +31,7 @@ main () { __complex__ double x; - x = cexp (1.0i); + x = xcexp (1.0i); if (__real__ x != -1.0) abort (); if (__imag__ x != 0.0) diff --git a/gcc/testsuite/gcc.dg/builtins-61.c b/gcc/testsuite/gcc.dg/builtins-61.c new file mode 100644 index 00000000000..9f0c99065da --- /dev/null +++ b/gcc/testsuite/gcc.dg/builtins-61.c @@ -0,0 +1,31 @@ +/* { dg-do compile } */ +/* { dg-options "-O -ffast-math -fdump-tree-optimized" } */ + +double test1 (double x) +{ + return __real __builtin_cexp(x * (__extension__ 1.0iF)); +} + +double test2(double x) +{ + return __imag __builtin_cexp((__extension__ 1.0iF) * x); +} + +double test3(double x) +{ + _Complex c = __builtin_cexp(x * (__extension__ 1.0iF)); + return __imag c + __real c; +} + +double test4(double x, double y) +{ + _Complex c = __builtin_cexp(x); + x = __builtin_exp (x); + return x - __real c; +} + +/* { dg-final { scan-tree-dump "cexpi" "optimized" } } */ +/* { dg-final { scan-tree-dump "sin" "optimized" } } */ +/* { dg-final { scan-tree-dump "cos" "optimized" } } */ +/* { dg-final { scan-tree-dump "return 0.0" "optimized" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/tree-ssa-pre.c b/gcc/tree-ssa-pre.c index 871006dc232..72af16d2caa 100644 --- a/gcc/tree-ssa-pre.c +++ b/gcc/tree-ssa-pre.c @@ -3613,7 +3613,9 @@ try_combine_conversion (tree *expr_p) unsigned int firstbit; if (!((TREE_CODE (expr) == NOP_EXPR - || TREE_CODE (expr) == CONVERT_EXPR) + || TREE_CODE (expr) == CONVERT_EXPR + || TREE_CODE (expr) == REALPART_EXPR + || TREE_CODE (expr) == IMAGPART_EXPR) && TREE_CODE (TREE_OPERAND (expr, 0)) == VALUE_HANDLE && !VALUE_HANDLE_VUSES (TREE_OPERAND (expr, 0)))) return false; -- 2.30.2