OSDN Git Service

PR tree-optimization/23452
authorsayle <sayle@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 30 May 2006 21:34:04 +0000 (21:34 +0000)
committersayle <sayle@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 30 May 2006 21:34:04 +0000 (21:34 +0000)
* 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.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@114246 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/fold-const.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/fold-mulconj-1.c [new file with mode: 0644]

index 0385d8f..95c9bad 100644 (file)
@@ -1,3 +1,11 @@
+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.
index 7ef0fa1..19058b2 100644 (file)
@@ -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);
index 1cc2f13..3738afa 100644 (file)
@@ -1,3 +1,8 @@
+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
diff --git a/gcc/testsuite/gcc.dg/fold-mulconj-1.c b/gcc/testsuite/gcc.dg/fold-mulconj-1.c
new file mode 100644 (file)
index 0000000..0e04653
--- /dev/null
@@ -0,0 +1,16 @@
+/* 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" } } */