aboutsummaryrefslogtreecommitdiff
path: root/gcc/fold-const.c
diff options
context:
space:
mode:
authorRoger Sayle <roger@eyesopen.com>2006-05-30 21:34:04 +0000
committerRoger Sayle <sayle@gcc.gnu.org>2006-05-30 21:34:04 +0000
commit99b25753bb82141b1f9b9a8eb62e14d6237c7a23 (patch)
treee8c7d9474db25736fdee60d42de43372bd6ae36e /gcc/fold-const.c
parent606791f69894426ecd59d7baf18664fb77138324 (diff)
downloadgcc-99b25753bb82141b1f9b9a8eb62e14d6237c7a23.zip
gcc-99b25753bb82141b1f9b9a8eb62e14d6237c7a23.tar.gz
gcc-99b25753bb82141b1f9b9a8eb62e14d6237c7a23.tar.bz2
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
Diffstat (limited to 'gcc/fold-const.c')
-rw-r--r--gcc/fold-const.c57
1 files changed, 57 insertions, 0 deletions
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index 7ef0fa1..19058b2 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -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);