* simplify-rtx.c (simplify_ternary_operation) [FMA]: Simplify
authorrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 19 Oct 2010 02:12:07 +0000 (02:12 +0000)
committerrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 19 Oct 2010 02:12:07 +0000 (02:12 +0000)
(fma (neg a) (neg b) c) and (fma a (neg b) c).

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

gcc/ChangeLog
gcc/simplify-rtx.c

index 8f1595d..d044941 100644 (file)
@@ -1,5 +1,10 @@
 2010-10-18  Richard Henderson  <rth@redhat.com>
 
+        * simplify-rtx.c (simplify_ternary_operation) [FMA]: Simplify
+       (fma (neg a) (neg b) c) and (fma a (neg b) c).
+
+2010-10-18  Richard Henderson  <rth@redhat.com>
+
        * config/i386/i386.c (IX86_BUILTIN_VFMSUBSS, IX86_BUILTIN_VFMSUBSD,
        IX86_BUILTIN_VFMSUBPS, IX86_BUILTIN_VFMSUBPD,
        IX86_BUILTIN_VFMSUBADDPS, IX86_BUILTIN_VFMSUBADDPD,
index f700958..e45917f 100644 (file)
@@ -4705,6 +4705,8 @@ simplify_ternary_operation (enum rtx_code code, enum machine_mode mode,
                            rtx op2)
 {
   unsigned int width = GET_MODE_BITSIZE (mode);
+  bool any_change = false;
+  rtx tem;
 
   /* VOIDmode means "infinite" precision.  */
   if (width == 0)
@@ -4712,10 +4714,29 @@ simplify_ternary_operation (enum rtx_code code, enum machine_mode mode,
 
   switch (code)
     {
-      /* At present, don't simplify fused multiply and add ops, because we need
-        to make sure there are no intermediate rounding steps used, and that
-        we get the right sign if negative 0 would be returned.  */
     case FMA:
+      /* Simplify negations around the multiplication.  */
+      /* -a * -b + c  =>  a * b + c.  */
+      if (GET_CODE (op0) == NEG)
+       {
+         tem = simplify_unary_operation (NEG, mode, op1, mode);
+         if (tem)
+           op1 = tem, op0 = XEXP (op0, 0), any_change = true;
+       }
+      else if (GET_CODE (op1) == NEG)
+       {
+         tem = simplify_unary_operation (NEG, mode, op0, mode);
+         if (tem)
+           op0 = tem, op1 = XEXP (op1, 0), any_change = true;
+       }
+
+      /* Canonicalize the two multiplication operands.  */
+      /* a * -b + c  =>  -b * a + c.  */
+      if (swap_commutative_operands_p (op0, op1))
+       tem = op0, op0 = op1, op1 = tem, any_change = true;
+
+      if (any_change)
+       return gen_rtx_FMA (mode, op0, op1, op2);
       return NULL_RTX;
 
     case SIGN_EXTRACT: