[PATCH] Fix PR30197, folding of cexp ()

Richard Guenther rguenther@suse.de
Wed Dec 13 17:16:00 GMT 2006


This adds folding of cexp ( __complex__ (x, y) ) to exp (x) * cexpi (y)
for unsafe_math if x != 0 and always in case x == 0.  I don't have a
strong opinion on guarding the exp (x) * cexpi (y) transformation with
unsafe_math as all library implementations also suffer from this
extra rounding (they all decompose cexpi to exp() and sincos()).

The tree-ssa-pre.c part is to allow FRE combine and simplify

  c = COMPLEX_EXPR <D.1979, D.1982>;
  D.1984 = REALPART_EXPR <c>;

which no other pass does at the moment :/

(I can leave this part out and XFAIL the test4 check)

Bootstrapped and tested on x86_64-unknown-linux-gnu.

Will apply to mainline later.

Richard.


2006-12-06  Richard Guenther  <rguenther@suse.de>

	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.

Index: builtins.c
===================================================================
*** builtins.c	(revision 119828)
--- builtins.c	(working copy)
*************** fold_builtin_sincos (tree arglist)
*** 7367,7372 ****
--- 7367,7433 ----
  			 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.  */
  
*************** fold_builtin_1 (tree fndecl, tree arglis
*** 9312,9317 ****
--- 9373,9381 ----
      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);
Index: testsuite/gcc.dg/builtins-61.c
===================================================================
*** testsuite/gcc.dg/builtins-61.c	(revision 0)
--- testsuite/gcc.dg/builtins-61.c	(revision 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" } } */
Index: testsuite/gcc.c-torture/execute/complex-1.c
===================================================================
*** testsuite/gcc.c-torture/execute/complex-1.c	(revision 119650)
--- testsuite/gcc.c-torture/execute/complex-1.c	(working copy)
*************** g2 (double x)
*** 17,23 ****
  }
  
  __complex__ double
! cexp (__complex__ double x)
  {
    double r;
  
--- 17,23 ----
  }
  
  __complex__ double
! xcexp (__complex__ double x)
  {
    double r;
  
*************** main ()
*** 31,37 ****
  {
    __complex__ double x;
  
!   x = cexp (1.0i);
    if (__real__ x != -1.0)
      abort ();
    if (__imag__ x != 0.0)
--- 31,37 ----
  {
    __complex__ double x;
  
!   x = xcexp (1.0i);
    if (__real__ x != -1.0)
      abort ();
    if (__imag__ x != 0.0)


Index: tree-ssa-pre.c
===================================================================
*** tree-ssa-pre.c	(revision 119828)
--- tree-ssa-pre.c	(working copy)
*************** try_combine_conversion (tree *expr_p)
*** 3613,3619 ****
    unsigned int firstbit;
  
    if (!((TREE_CODE (expr) == NOP_EXPR
! 	 || TREE_CODE (expr) == CONVERT_EXPR)
  	&& TREE_CODE (TREE_OPERAND (expr, 0)) == VALUE_HANDLE
  	&& !VALUE_HANDLE_VUSES (TREE_OPERAND (expr, 0))))
      return false;
--- 3613,3621 ----
    unsigned int firstbit;
  
    if (!((TREE_CODE (expr) == NOP_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;



More information about the Gcc-patches mailing list