[PATCH] Fix PR30172, some folding of complex expressions

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


This adds the capability to fold z * +-I and z1 + z2 in case the real/imag
parts of z1/z2 are zero.  This helps constructing complex constants such
as _Complex c = 5.0 + x*1.i but unfortunately only in cases we can ignore
(signalling) NaNs and signed zeros.

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

Will apply to mainline later.

Richard.

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

	PR middle-end/30172
	* fold-const.c (fold_binary): Fold __complex__ ( x, 0 )
	+ __complex__ ( 0, y ) to __complex__ ( x, y ).
	Fold __complex__ (x, y) * +-I to __complex__ (-+y, +-x).

	* gcc.dg/pr30172-1.c: New testcase.

Index: fold-const.c
===================================================================
*** fold-const.c	(revision 119828)
--- fold-const.c	(working copy)
*************** fold_binary (enum tree_code code, tree t
*** 8729,8734 ****
--- 8823,8863 ----
  				    fold_convert (type, tem));
  	    }
  
+ 	  /* Fold __complex__ ( x, 0 ) + __complex__ ( 0, y )
+ 	     to __complex__ ( x, y ).  This is not the same for SNaNs or
+ 	     if singed zeros are involved.  */
+ 	  if (!HONOR_SNANS (TYPE_MODE (TREE_TYPE (arg0)))
+               && !HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (arg0)))
+ 	      && COMPLEX_FLOAT_TYPE_P (TREE_TYPE (arg0)))
+ 	    {
+ 	      tree rtype = TREE_TYPE (TREE_TYPE (arg0));
+ 	      tree arg0r = fold_unary (REALPART_EXPR, rtype, arg0);
+ 	      tree arg0i = fold_unary (IMAGPART_EXPR, rtype, arg0);
+ 	      bool arg0rz = false, arg0iz = false;
+ 	      if ((arg0r && (arg0rz = real_zerop (arg0r)))
+ 		  || (arg0i && (arg0iz = real_zerop (arg0i))))
+ 		{
+ 		  tree arg1r = fold_unary (REALPART_EXPR, rtype, arg1);
+ 		  tree arg1i = fold_unary (IMAGPART_EXPR, rtype, arg1);
+ 		  if (arg0rz && arg1i && real_zerop (arg1i))
+ 		    {
+ 		      tree rp = arg1r ? arg1r
+ 				  : build1 (REALPART_EXPR, rtype, arg1);
+ 		      tree ip = arg0i ? arg0i
+ 				  : build1 (IMAGPART_EXPR, rtype, arg0);
+ 		      return fold_build2 (COMPLEX_EXPR, type, rp, ip);
+ 		    }
+ 		  else if (arg0iz && arg1r && real_zerop (arg1r))
+ 		    {
+ 		      tree rp = arg0r ? arg0r
+ 				  : build1 (REALPART_EXPR, rtype, arg0);
+ 		      tree ip = arg1i ? arg1i
+ 				  : build1 (IMAGPART_EXPR, rtype, arg1);
+ 		      return fold_build2 (COMPLEX_EXPR, type, rp, ip);
+ 		    }
+ 		}
+ 	    }
+ 
            if (flag_unsafe_math_optimizations
  	      && (TREE_CODE (arg0) == RDIV_EXPR || TREE_CODE (arg0) == MULT_EXPR)
  	      && (TREE_CODE (arg1) == RDIV_EXPR || TREE_CODE (arg1) == MULT_EXPR)
*************** fold_binary (enum tree_code code, tree t
*** 9181,9186 ****
--- 9310,9337 ----
  		}
  	    }
  
+ 	  /* Fold z * +-I to __complex__ (-+__imag z, +-__real z).
+ 	     This is not the same for NaNs or if singed zeros are
+ 	     involved.  */
+ 	  if (!HONOR_NANS (TYPE_MODE (TREE_TYPE (arg0)))
+               && !HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (arg0)))
+ 	      && COMPLEX_FLOAT_TYPE_P (TREE_TYPE (arg0))
+ 	      && TREE_CODE (arg1) == COMPLEX_CST
+ 	      && real_zerop (TREE_REALPART (arg1)))
+ 	    {
+ 	      tree rtype = TREE_TYPE (TREE_TYPE (arg0));
+ 	      if (real_onep (TREE_IMAGPART (arg1)))
+ 		return fold_build2 (COMPLEX_EXPR, type,
+ 				    negate_expr (fold_build1 (IMAGPART_EXPR,
+ 							      rtype, arg0)),
+ 				    fold_build1 (REALPART_EXPR, rtype, arg0));
+ 	      else if (real_minus_onep (TREE_IMAGPART (arg1)))
+ 		return fold_build2 (COMPLEX_EXPR, type,
+ 				    fold_build1 (IMAGPART_EXPR, rtype, arg0),
+ 				    negate_expr (fold_build1 (REALPART_EXPR,
+ 							      rtype, arg0)));
+ 	    }
+ 
  	  /* Optimize z * conj(z) for floating point complex numbers.
  	     Guarded by flag_unsafe_math_optimizations as non-finite
  	     imaginary components don't produce scalar results.  */
Index: testsuite/gcc.dg/pr30172-1.c
===================================================================
*** testsuite/gcc.dg/pr30172-1.c	(revision 0)
--- testsuite/gcc.dg/pr30172-1.c	(revision 0)
***************
*** 0 ****
--- 1,15 ----
+ /* { dg-do compile } */
+ /* { dg-options "-funsafe-math-optimizations -ffinite-math-only -fdump-tree-gimple" } */
+ 
+ _Complex double test1 (double x) { return x + 1.i; }
+ _Complex double test2 (double x) { return 1 + x * 1.i; }
+ _Complex double test3 (double x, double y) { return x + y * 1.i; }
+ _Complex double test4 (double x, double y) { return (x + y * 1.i) * 1.i; }
+ _Complex double test5 (double x, double y) { return (x + y * 1.i) * -1.i; }
+ 
+ /* { dg-final { scan-tree-dump "COMPLEX_EXPR <x, 1.0e\\+0>" "gimple" } } */
+ /* { dg-final { scan-tree-dump "COMPLEX_EXPR <1.0e\\+0, x>" "gimple" } } */
+ /* { dg-final { scan-tree-dump "COMPLEX_EXPR <x, y>" "gimple" } } */
+ /* { dg-final { scan-tree-dump "D.* = -y;\n.*COMPLEX_EXPR <D.*, x>" "gimple" } } */
+ /* { dg-final { scan-tree-dump "D.* = -x;\n.*COMPLEX_EXPR <y, D.*>" "gimple" } } */
+ /* { dg-final { cleanup-tree-dump "original" } } */



More information about the Gcc-patches mailing list