	2009-06-23  Kazu Hirata  <kazu@codesourcery.com>

	Issue #4613
	gcc/
	* config/arm/arm.c (arm_rtx_costs_1): Teach that the cost of MLS
	is the same as its underlying multiplication.
	* config/arm/arm.md (two splitters): New.
	* config/arm/predicates.md (binary_operator): New.

2010-07-26  Julian Brown  <julian@codesourcery.com>

	Merge from Sourcery G++ 4.4:

 	2008-09-08  Daniel Jacobowitz  <dan@codesourcery.com>
 
 	gcc/

=== modified file 'gcc/config/arm/arm.c'
--- old/gcc/config/arm/arm.c	2010-08-12 11:33:54 +0000
+++ new/gcc/config/arm/arm.c	2010-08-12 13:35:39 +0000
@@ -6604,6 +6604,19 @@
 	  return true;
 	}
 
+      /* MLS is just as expensive as its underlying multiplication.
+	 Exclude a shift by a constant, which is expressed as a
+	 multiplication.  */
+      if (TARGET_32BIT && arm_arch_thumb2
+	  && GET_CODE (XEXP (x, 1)) == MULT
+	  && ! (GET_CODE (XEXP (XEXP (x, 1), 1)) == CONST_INT
+		&& ((INTVAL (XEXP (XEXP (x, 1), 1)) &
+		     (INTVAL (XEXP (XEXP (x, 1), 1)) - 1)) == 0)))
+	{
+	  /* The cost comes from the cost of the multiply.  */
+	  return false;
+	}
+
       /* Fall through */
 
     case PLUS:

=== modified file 'gcc/config/arm/arm.md'
--- old/gcc/config/arm/arm.md	2010-08-12 11:33:54 +0000
+++ new/gcc/config/arm/arm.md	2010-08-12 13:35:39 +0000
@@ -1355,6 +1355,49 @@
    (set_attr "predicable" "yes")]
 )
 
+; The combiner cannot combine the first and last insns in the
+; following sequence because of the intervening insn, so help the
+; combiner with this splitter.  The combiner does attempt to split
+; this particular combination but does not know this exact split.
+; Note that the combiner puts the constant at the outermost operation
+; as a part of canonicalization.
+;
+; mul r3, r2, r1
+; <add/sub> r3, r3, <constant>
+; add r3, r3, r4
+
+(define_split
+  [(set (match_operand:SI 0 "s_register_operand" "")
+	(match_operator:SI 1 "plusminus_operator"
+	 [(plus:SI (mult:SI (match_operand:SI 2 "s_register_operand" "")
+			    (match_operand:SI 3 "s_register_operand" ""))
+		   (match_operand:SI 4 "s_register_operand" ""))
+	  (match_operand:SI 5 "arm_immediate_operand" "")]))]
+  "TARGET_32BIT"
+  [(set (match_dup 0)
+	(plus:SI (mult:SI (match_dup 2) (match_dup 3))
+		 (match_dup 4)))
+   (set (match_dup 0)
+	(match_op_dup:SI 1 [(match_dup 0) (match_dup 5)]))]
+  "")
+
+; Likewise for MLS.  MLS is available only on select architectures.
+
+(define_split
+  [(set (match_operand:SI 0 "s_register_operand" "")
+	(match_operator:SI 1 "plusminus_operator"
+	 [(minus:SI (match_operand:SI 2 "s_register_operand" "")
+		    (mult:SI (match_operand:SI 3 "s_register_operand" "")
+			     (match_operand:SI 4 "s_register_operand" "")))
+	  (match_operand:SI 5 "arm_immediate_operand" "")]))]
+  "TARGET_32BIT && arm_arch_thumb2"
+  [(set (match_dup 0)
+	(minus:SI (match_dup 2)
+		  (mult:SI (match_dup 3) (match_dup 4))))
+   (set (match_dup 0)
+	(match_op_dup:SI 1 [(match_dup 0) (match_dup 5)]))]
+  "")
+
 (define_insn "*mulsi3addsi_compare0"
   [(set (reg:CC_NOOV CC_REGNUM)
 	(compare:CC_NOOV

=== modified file 'gcc/config/arm/predicates.md'
--- old/gcc/config/arm/predicates.md	2010-08-10 13:31:21 +0000
+++ new/gcc/config/arm/predicates.md	2010-08-12 13:35:39 +0000
@@ -197,6 +197,11 @@
   (and (match_code "plus,minus,ior,xor,and")
        (match_test "mode == GET_MODE (op)")))
 
+;; True for plus/minus operators
+(define_special_predicate "plusminus_operator"
+  (and (match_code "plus,minus")
+       (match_test "mode == GET_MODE (op)")))
+
 ;; True for logical binary operators.
 (define_special_predicate "logical_binary_operator"
   (and (match_code "ior,xor,and")

