aboutsummaryrefslogtreecommitdiff
path: root/gcc/config/avr
diff options
context:
space:
mode:
authorGeorg-Johann Lay <avr@gjlay.de>2011-09-16 18:27:10 +0000
committerGeorg-Johann Lay <gjl@gcc.gnu.org>2011-09-16 18:27:10 +0000
commit1b65da7dfd8fca8ba99c6af6cdbc4b1a067b8620 (patch)
tree0700ffb1a342f14f27c505db50d258963e552953 /gcc/config/avr
parent71743a68ece25642e8f00467bc2e0ac58fb0b970 (diff)
downloadgcc-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.c40
-rw-r--r--gcc/config/avr/avr.md77
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"))