Patchwork FMA RTL simplifications

login
register
mail settings
Submitter Richard Henderson
Date Oct. 18, 2010, 8:31 p.m.
Message ID <4CBCAE99.1010202@redhat.com>
Download mbox | patch
Permalink /patch/68238/
State New
Headers show

Comments

Richard Henderson - Oct. 18, 2010, 8:31 p.m.
Here I add two simplifications in order to support the
ia64 fnma = (fma (neg a) b c) instruction.

Briefly tested on ia64-linux; full build+test underway.


r~
* simplify-rtx.c (simplify_ternary_operation) [FMA]: Simplify
	(fma (neg a) (neg b) c) and (fma a (neg b) c).
Richard Henderson - Oct. 19, 2010, 2:22 a.m.
On 10/18/2010 01:31 PM, Richard Henderson wrote:
> Here I add two simplifications in order to support the
> ia64 fnma = (fma (neg a) b c) instruction.
> 
> Briefly tested on ia64-linux; full build+test underway.

Committed after testing on ia64 and x86_64 (with the
subsequent patch that implements fma patterns for fma4).


r~

Patch

Index: simplify-rtx.c
===================================================================
--- simplify-rtx.c	(revision 165650)
+++ simplify-rtx.c	(working copy)
@@ -4705,6 +4705,8 @@ 
 			    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 @@ 
 
   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: