2010-05-06  Andrew Church  <achurch@achurch.org>

	* expr.c: Allow a PLUS_EXPR with a MULT_EXPR operand to be
	optimized to a multiply-add instruction regardless of whether the
	MULT_EXPR is the first or the second operand.

--- gcc-4.4.3-orig/gcc/expr.c	2010-01-16 18:44:57 +0900
+++ gcc-4.4.3/gcc/expr.c	2010-05-06 04:32:32 +0900
@@ -8363,51 +8363,62 @@
 						  TREE_OPERAND (exp, 1))));
     case PLUS_EXPR:
 
-      /* Check if this is a case for multiplication and addition.  */
-      if ((TREE_CODE (type) == INTEGER_TYPE
-	   || TREE_CODE (type) == FIXED_POINT_TYPE)
-	  && TREE_CODE (TREE_OPERAND (exp, 0)) == MULT_EXPR)
+      /* Check if this is a case for multiplication and addition.
+	 Addition is commutative, so the multiplication expression
+	 could be either operand 0 or operand 1.  */
+      if (TREE_CODE (type) == INTEGER_TYPE
+	  || TREE_CODE (type) == FIXED_POINT_TYPE)
 	{
-	  tree subsubexp0, subsubexp1;
-	  enum tree_code code0, code1, this_code;
-
-	  subexp0 = TREE_OPERAND (exp, 0);
-	  subsubexp0 = TREE_OPERAND (subexp0, 0);
-	  subsubexp1 = TREE_OPERAND (subexp0, 1);
-	  code0 = TREE_CODE (subsubexp0);
-	  code1 = TREE_CODE (subsubexp1);
-	  this_code = TREE_CODE (type) == INTEGER_TYPE ? NOP_EXPR
-						       : FIXED_CONVERT_EXPR;
-	  if (code0 == this_code && code1 == this_code
-	      && (TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (subsubexp0, 0)))
-		  < TYPE_PRECISION (TREE_TYPE (subsubexp0)))
-	      && (TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (subsubexp0, 0)))
-		  == TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (subsubexp1, 0))))
-	      && (TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (subsubexp0, 0)))
-		  == TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (subsubexp1, 0)))))
+	  int mult_operand, add_operand;
+	  if (TREE_CODE (TREE_OPERAND (exp, 0)) == MULT_EXPR)
+	    mult_operand = 0, add_operand = 1;
+	  else if (TREE_CODE (TREE_OPERAND (exp, 1)) == MULT_EXPR)
+	    mult_operand = 1, add_operand = 0;
+	  else
+	    mult_operand = add_operand = -1;
+	  if (mult_operand >= 0)
 	    {
-	      tree op0type = TREE_TYPE (TREE_OPERAND (subsubexp0, 0));
-	      enum machine_mode innermode = TYPE_MODE (op0type);
-	      bool zextend_p = TYPE_UNSIGNED (op0type);
-	      bool sat_p = TYPE_SATURATING (TREE_TYPE (subsubexp0));
-	      if (sat_p == 0)
-		this_optab = zextend_p ? umadd_widen_optab : smadd_widen_optab;
-	      else
-		this_optab = zextend_p ? usmadd_widen_optab
-				       : ssmadd_widen_optab;
-	      if (mode == GET_MODE_2XWIDER_MODE (innermode)
-		  && (optab_handler (this_optab, mode)->insn_code
-		      != CODE_FOR_nothing))
+	      tree subsubexp0, subsubexp1;
+	      enum tree_code code0, code1, this_code;
+
+	      subexp0 = TREE_OPERAND (exp, mult_operand);
+	      subsubexp0 = TREE_OPERAND (subexp0, 0);
+	      subsubexp1 = TREE_OPERAND (subexp0, 1);
+	      code0 = TREE_CODE (subsubexp0);
+	      code1 = TREE_CODE (subsubexp1);
+	      this_code = TREE_CODE (type) == INTEGER_TYPE ? NOP_EXPR
+							   : FIXED_CONVERT_EXPR;
+	      if (code0 == this_code && code1 == this_code
+		  && (TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (subsubexp0, 0)))
+		      < TYPE_PRECISION (TREE_TYPE (subsubexp0)))
+		  && (TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (subsubexp0, 0)))
+		      == TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (subsubexp1, 0))))
+		  && (TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (subsubexp0, 0)))
+		      == TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (subsubexp1, 0)))))
 		{
-		  expand_operands (TREE_OPERAND (subsubexp0, 0),
-				   TREE_OPERAND (subsubexp1, 0),
-				   NULL_RTX, &op0, &op1, EXPAND_NORMAL);
-		  op2 = expand_expr (TREE_OPERAND (exp, 1), subtarget,
-				     VOIDmode, EXPAND_NORMAL);
-		  temp = expand_ternary_op (mode, this_optab, op0, op1, op2,
-					    target, unsignedp);
-		  gcc_assert (temp);
-		  return REDUCE_BIT_FIELD (temp);
+		  tree op0type = TREE_TYPE (TREE_OPERAND (subsubexp0, 0));
+		  enum machine_mode innermode = TYPE_MODE (op0type);
+		  bool zextend_p = TYPE_UNSIGNED (op0type);
+		  bool sat_p = TYPE_SATURATING (TREE_TYPE (subsubexp0));
+		  if (sat_p == 0)
+		    this_optab = zextend_p ? umadd_widen_optab : smadd_widen_optab;
+		  else
+		    this_optab = zextend_p ? usmadd_widen_optab
+					   : ssmadd_widen_optab;
+		  if (mode == GET_MODE_2XWIDER_MODE (innermode)
+		      && (optab_handler (this_optab, mode)->insn_code
+			  != CODE_FOR_nothing))
+		    {
+		      expand_operands (TREE_OPERAND (subsubexp0, 0),
+				       TREE_OPERAND (subsubexp1, 0),
+				       NULL_RTX, &op0, &op1, EXPAND_NORMAL);
+		      op2 = expand_expr (TREE_OPERAND (exp, add_operand),
+					 subtarget, VOIDmode, EXPAND_NORMAL);
+		      temp = expand_ternary_op (mode, this_optab, op0, op1,
+						op2, target, unsignedp);
+		      gcc_assert (temp);
+		      return REDUCE_BIT_FIELD (temp);
+		    }
 		}
 	    }
 	}
