diff options
author | Georg-Johann Lay <avr@gjlay.de> | 2011-09-16 18:27:10 +0000 |
---|---|---|
committer | Georg-Johann Lay <gjl@gcc.gnu.org> | 2011-09-16 18:27:10 +0000 |
commit | 1b65da7dfd8fca8ba99c6af6cdbc4b1a067b8620 (patch) | |
tree | 0700ffb1a342f14f27c505db50d258963e552953 /gcc/config/avr | |
parent | 71743a68ece25642e8f00467bc2e0ac58fb0b970 (diff) | |
download | gcc-1b65da7dfd8fca8ba99c6af6cdbc4b1a067b8620.zip gcc-1b65da7dfd8fca8ba99c6af6cdbc4b1a067b8620.tar.gz gcc-1b65da7dfd8fca8ba99c6af6cdbc4b1a067b8620.tar.bz2 |
re PR target/50358 (AVR: Implement [u]maddqihi4 [u]msubqihi4 patterns on the enhanced core)
PR target/50358
* config/avr/avr.md (*ashiftqihi2.signx.1): New insn.
(*maddqi4, *maddqi4.const): New insns.
(*msubqi4, *msubqi4.const): New insns.
* config/avr/avr.c (avr_rtx_costs): Record costs of above in cases
PLUS:QI and MINUS:QI. Increase costs of multiply-add/-sub for
HImode by 1 in the case of multiplying with a CONST_INT.
Record cost of *ashiftqihi2.signx.1 in case ASHIFT:QI.
From-SVN: r178912
Diffstat (limited to 'gcc/config/avr')
-rw-r--r-- | gcc/config/avr/avr.c | 40 | ||||
-rw-r--r-- | gcc/config/avr/avr.md | 77 |
2 files changed, 116 insertions, 1 deletions
diff --git a/gcc/config/avr/avr.c b/gcc/config/avr/avr.c index 773aec2..b69efa9 100644 --- a/gcc/config/avr/avr.c +++ b/gcc/config/avr/avr.c @@ -1528,7 +1528,7 @@ notice_update_cc (rtx body ATTRIBUTE_UNUSED, rtx insn) /* Insn doesn't leave CC in a usable state. */ CC_STATUS_INIT; - /* Correct CC for the ashrqi3 with the shift count as CONST_INT != 6 */ + /* Correct CC for the ashrqi3 with the shift count as CONST_INT < 6 */ set = single_set (insn); if (set) { @@ -5570,6 +5570,17 @@ avr_rtx_costs (rtx x, int codearg, int outer_code ATTRIBUTE_UNUSED, switch (mode) { case QImode: + if (AVR_HAVE_MUL + && MULT == GET_CODE (XEXP (x, 0)) + && register_operand (XEXP (x, 1), QImode)) + { + /* multiply-add */ + *total = COSTS_N_INSNS (speed ? 4 : 3); + /* multiply-add with constant: will be split and load constant. */ + if (CONST_INT_P (XEXP (XEXP (x, 0), 1))) + *total = COSTS_N_INSNS (1) + *total; + return true; + } *total = COSTS_N_INSNS (1); if (GET_CODE (XEXP (x, 1)) != CONST_INT) *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1, speed); @@ -5583,7 +5594,11 @@ avr_rtx_costs (rtx x, int codearg, int outer_code ATTRIBUTE_UNUSED, && (ZERO_EXTEND == GET_CODE (XEXP (XEXP (x, 0), 0)) || SIGN_EXTEND == GET_CODE (XEXP (XEXP (x, 0), 0)))) { + /* multiply-add */ *total = COSTS_N_INSNS (speed ? 5 : 4); + /* multiply-add with constant: will be split and load constant. */ + if (CONST_INT_P (XEXP (XEXP (x, 0), 1))) + *total = COSTS_N_INSNS (1) + *total; return true; } if (GET_CODE (XEXP (x, 1)) != CONST_INT) @@ -5619,6 +5634,18 @@ avr_rtx_costs (rtx x, int codearg, int outer_code ATTRIBUTE_UNUSED, case MINUS: if (AVR_HAVE_MUL + && QImode == mode + && register_operand (XEXP (x, 0), QImode) + && MULT == GET_CODE (XEXP (x, 1))) + { + /* multiply-sub */ + *total = COSTS_N_INSNS (speed ? 4 : 3); + /* multiply-sub with constant: will be split and load constant. */ + if (CONST_INT_P (XEXP (XEXP (x, 1), 1))) + *total = COSTS_N_INSNS (1) + *total; + return true; + } + if (AVR_HAVE_MUL && HImode == mode && register_operand (XEXP (x, 0), HImode) && (MULT == GET_CODE (XEXP (x, 1)) @@ -5626,7 +5653,11 @@ avr_rtx_costs (rtx x, int codearg, int outer_code ATTRIBUTE_UNUSED, && (ZERO_EXTEND == GET_CODE (XEXP (XEXP (x, 1), 0)) || SIGN_EXTEND == GET_CODE (XEXP (XEXP (x, 1), 0)))) { + /* multiply-sub */ *total = COSTS_N_INSNS (speed ? 5 : 4); + /* multiply-sub with constant: will be split and load constant. */ + if (CONST_INT_P (XEXP (XEXP (x, 1), 1))) + *total = COSTS_N_INSNS (1) + *total; return true; } case AND: @@ -5815,6 +5846,13 @@ avr_rtx_costs (rtx x, int codearg, int outer_code ATTRIBUTE_UNUSED, } } + if (const1_rtx == (XEXP (x, 1)) + && SIGN_EXTEND == GET_CODE (XEXP (x, 0))) + { + *total = COSTS_N_INSNS (2); + return true; + } + if (GET_CODE (XEXP (x, 1)) != CONST_INT) { *total = COSTS_N_INSNS (!speed ? 5 : 41); diff --git a/gcc/config/avr/avr.md b/gcc/config/avr/avr.md index 8721314..c161504 100644 --- a/gcc/config/avr/avr.md +++ b/gcc/config/avr/avr.md @@ -1138,6 +1138,72 @@ (set_attr "cc" "clobber")]) ;****************************************************************************** +; multiply-add/sub QI: $0 = $3 +/- $1*$2 +;****************************************************************************** + +(define_insn "*maddqi4" + [(set (match_operand:QI 0 "register_operand" "=r") + (plus:QI (mult:QI (match_operand:QI 1 "register_operand" "r") + (match_operand:QI 2 "register_operand" "r")) + (match_operand:QI 3 "register_operand" "0")))] + + "AVR_HAVE_MUL" + "mul %1,%2 + add %A0,r0 + clr __zero_reg__" + [(set_attr "length" "4") + (set_attr "cc" "clobber")]) + +(define_insn "*msubqi4" + [(set (match_operand:QI 0 "register_operand" "=r") + (minus:QI (match_operand:QI 3 "register_operand" "0") + (mult:QI (match_operand:QI 1 "register_operand" "r") + (match_operand:QI 2 "register_operand" "r"))))] + "AVR_HAVE_MUL" + "mul %1,%2 + sub %A0,r0 + clr __zero_reg__" + [(set_attr "length" "4") + (set_attr "cc" "clobber")]) + +(define_insn_and_split "*maddqi4.const" + [(set (match_operand:QI 0 "register_operand" "=r") + (plus:QI (mult:QI (match_operand:QI 1 "register_operand" "r") + (match_operand:QI 2 "const_int_operand" "n")) + (match_operand:QI 3 "register_operand" "0"))) + (clobber (match_scratch:QI 4 "=&d"))] + "AVR_HAVE_MUL" + "#" + "&& reload_completed" + [(set (match_dup 4) + (match_dup 2)) + ; *maddqi4 + (set (match_dup 0) + (plus:QI (mult:QI (match_dup 1) + (match_dup 4)) + (match_dup 3)))] + "") + +(define_insn_and_split "*msubqi4.const" + [(set (match_operand:QI 0 "register_operand" "=r") + (minus:QI (match_operand:QI 3 "register_operand" "0") + (mult:QI (match_operand:QI 1 "register_operand" "r") + (match_operand:QI 2 "const_int_operand" "n")))) + (clobber (match_scratch:QI 4 "=&d"))] + "AVR_HAVE_MUL" + "#" + "&& reload_completed" + [(set (match_dup 4) + (match_dup 2)) + ; *msubqi4 + (set (match_dup 0) + (minus:QI (match_dup 3) + (mult:QI (match_dup 1) + (match_dup 4))))] + "") + + +;****************************************************************************** ; multiply-add/sub HI: $0 = $3 +/- $1*$2 with 8-bit values $1, $2 ;****************************************************************************** @@ -1497,6 +1563,17 @@ ;; expand decides to use ASHIFT instead of MUL because ASHIFT costs are cheaper ;; at that time. Fix that. +(define_insn "*ashiftqihi2.signx.1" + [(set (match_operand:HI 0 "register_operand" "=r,*r") + (ashift:HI (sign_extend:HI (match_operand:QI 1 "register_operand" "0,r")) + (const_int 1)))] + "" + "@ + lsl %A0\;sbc %B0,%B0 + mov %A0,%1\;lsl %A0\;sbc %B0,%B0" + [(set_attr "length" "2,3") + (set_attr "cc" "clobber")]) + (define_insn_and_split "*ashifthi3.signx.const" [(set (match_operand:HI 0 "register_operand" "=r") (ashift:HI (sign_extend:HI (match_operand:QI 1 "register_operand" "d")) |