Commit 99b25753 by Roger Sayle Committed by Roger Sayle

re PR tree-optimization/23452 (Optimizing CONJG_EXPR (a) * a)


	PR tree-optimization/23452
	* fold-const.c (fold_mult_zconjz): New subroutine of fold_binary,
	to optimize z * conj(z) as realpart(z)^2 + imagpart(z)^2.
	(fold_binary) <MULT_EXPR>: Call fold_mult_zconjz for integral
	complex values and with -ffast-math for FP complex values.

	* gcc.dg/fold-mulconj-1.c: New test case.

From-SVN: r114246
parent 606791f6
2006-05-30 Roger Sayle <roger@eyesopen.com>
PR tree-optimization/23452
* fold-const.c (fold_mult_zconjz): New subroutine of fold_binary,
to optimize z * conj(z) as realpart(z)^2 + imagpart(z)^2.
(fold_binary) <MULT_EXPR>: Call fold_mult_zconjz for integral
complex values and with -ffast-math for FP complex values.
2006-05-30 Kazu Hirata <kazu@codesourcery.com>
* c-common.h: Remove the prototype for yyparse.
......
......@@ -8105,6 +8105,44 @@ fold_comparison (enum tree_code code, tree type, tree op0, tree op1)
return NULL_TREE;
}
/* Subroutine of fold_binary. Optimize complex multiplications of the
form z * conj(z), as pow(realpart(z),2) + pow(imagpart(z),2). The
argument EXPR represents the expression "z" of type TYPE. */
static tree
fold_mult_zconjz (tree type, tree expr)
{
tree itype = TREE_TYPE (type);
tree rpart, ipart, tem;
if (TREE_CODE (expr) == COMPLEX_EXPR)
{
rpart = TREE_OPERAND (expr, 0);
ipart = TREE_OPERAND (expr, 1);
}
else if (TREE_CODE (expr) == COMPLEX_CST)
{
rpart = TREE_REALPART (expr);
ipart = TREE_IMAGPART (expr);
}
else
{
expr = save_expr (expr);
rpart = fold_build1 (REALPART_EXPR, itype, expr);
ipart = fold_build1 (IMAGPART_EXPR, itype, expr);
}
rpart = save_expr (rpart);
ipart = save_expr (ipart);
tem = fold_build2 (PLUS_EXPR, itype,
fold_build2 (MULT_EXPR, itype, rpart, rpart),
fold_build2 (MULT_EXPR, itype, ipart, ipart));
return fold_build2 (COMPLEX_EXPR, type, tem,
fold_convert (itype, integer_zero_node));
}
/* Fold a binary expression of code CODE and type TYPE with operands
OP0 and OP1. Return the folded expression if folding is
successful. Otherwise, return NULL_TREE. */
......@@ -8768,6 +8806,13 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
code, NULL_TREE)))
return fold_convert (type, tem);
/* Optimize z * conj(z) for integer complex numbers. */
if (TREE_CODE (arg0) == CONJ_EXPR
&& operand_equal_p (TREE_OPERAND (arg0, 0), arg1, 0))
return fold_mult_zconjz (type, arg1);
if (TREE_CODE (arg1) == CONJ_EXPR
&& operand_equal_p (arg0, TREE_OPERAND (arg1, 0), 0))
return fold_mult_zconjz (type, arg0);
}
else
{
......@@ -8813,6 +8858,18 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
}
}
/* 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. */
if (flag_unsafe_math_optimizations
&& TREE_CODE (arg0) == CONJ_EXPR
&& operand_equal_p (TREE_OPERAND (arg0, 0), arg1, 0))
return fold_mult_zconjz (type, arg1);
if (flag_unsafe_math_optimizations
&& TREE_CODE (arg1) == CONJ_EXPR
&& operand_equal_p (arg0, TREE_OPERAND (arg1, 0), 0))
return fold_mult_zconjz (type, arg0);
if (flag_unsafe_math_optimizations)
{
enum built_in_function fcode0 = builtin_mathfn_code (arg0);
......
2006-05-30 Roger Sayle <roger@eyesopen.com>
PR tree-optimization/23452
* gcc.dg/fold-mulconj-1.c: New test case.
2006-05-30 Mark Mitchell <mark@codesourcery.com>
PR c++/27803
/* PR tree-optimization/23452 */
/* { dg-do compile } */
/* { dg-options "-O2 -ffast-math -fdump-tree-gimple" } */
_Complex double foo(_Complex double z)
{
return z * ~z;
}
_Complex int bar(_Complex int z)
{
return z * ~z;
}
/* { dg-final { scan-tree-dump-times "CONJ_EXPR" 0 "gimple" } } */
/* { dg-final { cleanup-tree-dump "gimple" } } */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment