We shouldn't try to make use of the multiplication result twice in
FMA_EXPR building.  The following ensures that if the uses go
through a negate.

Bootstrap and regtest processing on x86_64-unknown-linux-gnu.

Richard.

2011-03-11  Richard Guenther  <rguent...@suse.de>

        PR tree-optimization/48067
        * tree-ssa-math-opts.c (convert_mult_to_fma): Verify the
        multiplication result will be only used once on the target
        stmt.

        * gcc.dg/pr48067.c: New testcase.

Index: gcc/tree-ssa-math-opts.c
===================================================================
*** gcc/tree-ssa-math-opts.c    (revision 170873)
--- gcc/tree-ssa-math-opts.c    (working copy)
*************** convert_mult_to_fma (gimple mul_stmt, tr
*** 1557,1562 ****
--- 1557,1565 ----
        /* A negate on the multiplication leads to FNMA.  */
        if (use_code == NEGATE_EXPR)
        {
+         ssa_op_iter iter;
+         tree use;
+ 
          result = gimple_assign_lhs (use_stmt);
  
          /* Make sure the negate statement becomes dead with this
*************** convert_mult_to_fma (gimple mul_stmt, tr
*** 1565,1570 ****
--- 1568,1578 ----
                               &use_p, &neguse_stmt))
            return false;
  
+         /* Make sure the multiplication isn't also used on that stmt.  */
+         FOR_EACH_SSA_TREE_OPERAND (use, neguse_stmt, iter, SSA_OP_USE)
+           if (use == mul_result)
+             return false;
+ 
          /* Re-validate.  */
          use_stmt = neguse_stmt;
          if (gimple_bb (use_stmt) != gimple_bb (mul_stmt))
Index: gcc/testsuite/gcc.dg/pr48067.c
===================================================================
*** gcc/testsuite/gcc.dg/pr48067.c      (revision 0)
--- gcc/testsuite/gcc.dg/pr48067.c      (revision 0)
***************
*** 0 ****
--- 1,11 ----
+ /* { dg-do compile } */
+ /* { dg-options "-O2 -ffast-math -fno-tree-forwprop -fno-tree-reassoc" } */
+ /* { dg-options "-O2 -ffast-math -fno-tree-forwprop -fno-tree-reassoc -mfma4" 
{ target x86_64-*-* i?86-*-* } } */
+ 
+ float
+ foo (float x, float cim)
+ {
+   float c = x * cim;
+   float d = -c;
+   return c - d;
+ }

Reply via email to