re PR middle-end/30172 (Operations with partly constant complex values not folded)

2006-12-14  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.

From-SVN: r119859
This commit is contained in:
Richard Guenther 2006-12-14 13:12:11 +00:00 committed by Richard Biener
parent 85aef79f75
commit 9f5396713d
4 changed files with 84 additions and 0 deletions

View file

@ -1,3 +1,10 @@
2006-12-14 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).
2006-12-14 Richard Guenther <rguenther@suse.de>
PR tree-optimization/30198

View file

@ -8755,6 +8755,41 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
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)
@ -9207,6 +9242,28 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
}
}
/* 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. */

View file

@ -1,3 +1,8 @@
2006-12-14 Richard Guenther <rguenther@suse.de>
PR middle-end/30172
* gcc.dg/pr30172-1.c: New testcase.
2006-12-14 Richard Guenther <rguenther@suse.de>
PR tree-optimization/30198

View file

@ -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" } } */