2009-06-23 Kazu Hirata 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 Merge from Sourcery G++ 4.4: 2008-09-08 Daniel Jacobowitz 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 +; r3, r3, +; 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")