re PR target/50358 (AVR: Implement [u]maddqihi4 [u]msubqihi4 patterns on the enhanced core)

PR target/50358
	* config/avr/predicates.md (const_1_to_6_operand): New predicate.
	* config/avr/avr.md: (extend_s): New code attribute.
	(mul_r_d): New code attribute.
	(*maddqihi4, *umaddqihi4): New insns.
	(*msubqihi4, *umsubqihi4): New insns.
	(*usmaddqihi4, *sumaddqihi4): New insns.
	(*usmsubqihi4, *susubdqihi4): New insns.
	(*umaddqihi4.uconst, *maddqihi4.sconst): New insn-and-splits.
	(*umsubqihi4.uconst, *msubqihi4.sconst): New insn-and-splits.
	(*umsubqihi4.uconst.ashift): New insn-and-split.
	(*msubqihi4.sconst.ashift): New insn-and-split.
	(*sumaddqihi4.uconst): New insn-and-split.
	(*sumsubqihi4.uconst): New insn-and-split.
	* config/avr/avr.c (avr_rtx_costs): Report costs of above in case
	PLUS:HI and MINUS:HI.

From-SVN: r178806
This commit is contained in:
Georg-Johann Lay 2011-09-13 09:23:36 +00:00 committed by Georg-Johann Lay
parent a9fb4f13b1
commit 3e0cef6ddd
4 changed files with 315 additions and 0 deletions

View File

@ -1,3 +1,22 @@
2011-09-13 Georg-Johann Lay <avr@gjlay.de>
PR target/50358
* config/avr/predicates.md (const_1_to_6_operand): New predicate.
* config/avr/avr.md: (extend_s): New code attribute.
(mul_r_d): New code attribute.
(*maddqihi4, *umaddqihi4): New insns.
(*msubqihi4, *umsubqihi4): New insns.
(*usmaddqihi4, *sumaddqihi4): New insns.
(*usmsubqihi4, *susubdqihi4): New insns.
(*umaddqihi4.uconst, *maddqihi4.sconst): New insn-and-splits.
(*umsubqihi4.uconst, *msubqihi4.sconst): New insn-and-splits.
(*umsubqihi4.uconst.ashift): New insn-and-split.
(*msubqihi4.sconst.ashift): New insn-and-split.
(*sumaddqihi4.uconst): New insn-and-split.
(*sumsubqihi4.uconst): New insn-and-split.
* config/avr/avr.c (avr_rtx_costs): Report costs of above in case
PLUS:HI and MINUS:HI.
2011-09-13 Revital Eres <revital.eres@linaro.org>
modulo-sched.c (remove_node_from_ps): Return void instead of bool.

View File

@ -5576,6 +5576,16 @@ avr_rtx_costs (rtx x, int codearg, int outer_code ATTRIBUTE_UNUSED,
break;
case HImode:
if (AVR_HAVE_MUL
&& (MULT == GET_CODE (XEXP (x, 0))
|| ASHIFT == GET_CODE (XEXP (x, 0)))
&& register_operand (XEXP (x, 1), HImode)
&& (ZERO_EXTEND == GET_CODE (XEXP (XEXP (x, 0), 0))
|| SIGN_EXTEND == GET_CODE (XEXP (XEXP (x, 0), 0))))
{
*total = COSTS_N_INSNS (speed ? 5 : 4);
return true;
}
if (GET_CODE (XEXP (x, 1)) != CONST_INT)
{
*total = COSTS_N_INSNS (2);
@ -5608,6 +5618,17 @@ avr_rtx_costs (rtx x, int codearg, int outer_code ATTRIBUTE_UNUSED,
return true;
case MINUS:
if (AVR_HAVE_MUL
&& HImode == mode
&& register_operand (XEXP (x, 0), HImode)
&& (MULT == GET_CODE (XEXP (x, 1))
|| ASHIFT == GET_CODE (XEXP (x, 1)))
&& (ZERO_EXTEND == GET_CODE (XEXP (XEXP (x, 1), 0))
|| SIGN_EXTEND == GET_CODE (XEXP (XEXP (x, 1), 0))))
{
*total = COSTS_N_INSNS (speed ? 5 : 4);
return true;
}
case AND:
case IOR:
*total = COSTS_N_INSNS (GET_MODE_SIZE (mode));

View File

@ -150,6 +150,15 @@
[(sign_extend "")
(zero_extend "u")])
(define_code_attr extend_s
[(sign_extend "s")
(zero_extend "")])
;; Constrain input operand of widening multiply, i.e. MUL resp. MULS.
(define_code_attr mul_r_d
[(zero_extend "r")
(sign_extend "d")])
;;========================================================================
;; The following is used by nonlocal_goto and setjmp.
@ -1128,6 +1137,267 @@
[(set_attr "length" "4")
(set_attr "cc" "clobber")])
;******************************************************************************
; multiply-add/sub HI: $0 = $3 +/- $1*$2 with 8-bit values $1, $2
;******************************************************************************
;; We don't use standard insns/expanders as they lead to cumbersome code for,
;; e.g,
;;
;; int foo (unsigned char z)
;; {
;; extern int aInt[];
;; return aInt[3*z+2];
;; }
;;
;; because the constant +4 then is added explicitely instead of consuming it
;; with the aInt symbol. Therefore, we rely on insn combine which takes costs
;; into account more accurately and doesn't do burte-force multiply-add/sub.
;; The implementational effort is the same so we are fine with that approach.
;; "*maddqihi4"
;; "*umaddqihi4"
(define_insn "*<extend_u>maddqihi4"
[(set (match_operand:HI 0 "register_operand" "=r")
(plus:HI (mult:HI (any_extend:HI (match_operand:QI 1 "register_operand" "<mul_r_d>"))
(any_extend:HI (match_operand:QI 2 "register_operand" "<mul_r_d>")))
(match_operand:HI 3 "register_operand" "0")))]
"AVR_HAVE_MUL"
"mul<extend_s> %1,%2
add %A0,r0
adc %B0,r1
clr __zero_reg__"
[(set_attr "length" "4")
(set_attr "cc" "clobber")])
;; "*msubqihi4"
;; "*umsubqihi4"
(define_insn "*<extend_u>msubqihi4"
[(set (match_operand:HI 0 "register_operand" "=r")
(minus:HI (match_operand:HI 3 "register_operand" "0")
(mult:HI (any_extend:HI (match_operand:QI 1 "register_operand" "<mul_r_d>"))
(any_extend:HI (match_operand:QI 2 "register_operand" "<mul_r_d>")))))]
"AVR_HAVE_MUL"
"mul<extend_s> %1,%2
sub %A0,r0
sbc %B0,r1
clr __zero_reg__"
[(set_attr "length" "4")
(set_attr "cc" "clobber")])
;; "*usmaddqihi4"
;; "*sumaddqihi4"
(define_insn "*<any_extend:extend_su><any_extend2:extend_su>msubqihi4"
[(set (match_operand:HI 0 "register_operand" "=r")
(plus:HI (mult:HI (any_extend:HI (match_operand:QI 1 "register_operand" "a"))
(any_extend2:HI (match_operand:QI 2 "register_operand" "a")))
(match_operand:HI 3 "register_operand" "0")))]
"AVR_HAVE_MUL
&& reload_completed
&& <any_extend:CODE> != <any_extend2:CODE>"
{
output_asm_insn (<any_extend:CODE> == SIGN_EXTEND
? "mulsu %1,%2" : "mulsu %2,%1", operands);
return "add %A0,r0\;adc %B0,r1\;clr __zero_reg__";
}
[(set_attr "length" "4")
(set_attr "cc" "clobber")])
;; "*usmsubqihi4"
;; "*sumsubqihi4"
(define_insn "*<any_extend:extend_su><any_extend2:extend_su>msubqihi4"
[(set (match_operand:HI 0 "register_operand" "=r")
(minus:HI (match_operand:HI 3 "register_operand" "0")
(mult:HI (any_extend:HI (match_operand:QI 1 "register_operand" "a"))
(any_extend2:HI (match_operand:QI 2 "register_operand" "a")))))]
"AVR_HAVE_MUL
&& reload_completed
&& <any_extend:CODE> != <any_extend2:CODE>"
{
output_asm_insn (<any_extend:CODE> == SIGN_EXTEND
? "mulsu %1,%2" : "mulsu %2,%1", operands);
return "sub %A0,r0\;sbc %B0,r1\;clr __zero_reg__";
}
[(set_attr "length" "4")
(set_attr "cc" "clobber")])
;; Handle small constants
(define_insn_and_split "*umaddqihi4.uconst"
[(set (match_operand:HI 0 "register_operand" "=r")
(plus:HI (mult:HI (zero_extend:HI (match_operand:QI 1 "register_operand" "r"))
(match_operand:HI 2 "u8_operand" "M"))
(match_operand:HI 3 "register_operand" "0")))
(clobber (match_scratch:QI 4 "=&d"))]
"AVR_HAVE_MUL"
"#"
"&& reload_completed"
[(set (match_dup 4)
(match_dup 2))
; *umaddqihi4
(set (match_dup 0)
(plus:HI (mult:HI (zero_extend:HI (match_dup 1))
(zero_extend:HI (match_dup 4)))
(match_dup 3)))]
{
operands[2] = gen_int_mode (INTVAL (operands[2]), QImode);
})
(define_insn_and_split "*umsubqihi4.uconst"
[(set (match_operand:HI 0 "register_operand" "=r")
(minus:HI (match_operand:HI 3 "register_operand" "0")
(mult:HI (zero_extend:HI (match_operand:QI 1 "register_operand" "r"))
(match_operand:HI 2 "u8_operand" "M"))))
(clobber (match_scratch:QI 4 "=&d"))]
"AVR_HAVE_MUL"
"#"
"&& reload_completed"
[(set (match_dup 4)
(match_dup 2))
; *umsubqihi4
(set (match_dup 0)
(minus:HI (match_dup 3)
(mult:HI (zero_extend:HI (match_dup 1))
(zero_extend:HI (match_dup 4)))))]
{
operands[2] = gen_int_mode (INTVAL (operands[2]), QImode);
})
;; Same as the insn above, but combiner tries versions canonicalized to ASHIFT
;; for MULT with power of 2 and skips trying MULT insn above.
(define_insn_and_split "*umsubqihi4.uconst.ashift"
[(set (match_operand:HI 0 "register_operand" "=r")
(minus:HI (match_operand:HI 3 "register_operand" "0")
(ashift:HI (zero_extend:HI (match_operand:QI 1 "register_operand" "r"))
(match_operand:HI 2 "const_2_to_7_operand" "n"))))
(clobber (match_scratch:QI 4 "=&d"))]
"AVR_HAVE_MUL"
"#"
"&& reload_completed"
[(set (match_dup 4)
(match_dup 2))
; *umsubqihi4
(set (match_dup 0)
(minus:HI (match_dup 3)
(mult:HI (zero_extend:HI (match_dup 1))
(zero_extend:HI (match_dup 4)))))]
{
operands[2] = gen_int_mode (1 << INTVAL (operands[2]), QImode);
})
(define_insn_and_split "*maddqihi4.sconst"
[(set (match_operand:HI 0 "register_operand" "=r")
(plus:HI (mult:HI (sign_extend:HI (match_operand:QI 1 "register_operand" "d"))
(match_operand:HI 2 "s8_operand" "n"))
(match_operand:HI 3 "register_operand" "0")))
(clobber (match_scratch:QI 4 "=&d"))]
"AVR_HAVE_MUL"
"#"
"&& reload_completed"
[(set (match_dup 4)
(match_dup 2))
; *maddqihi4
(set (match_dup 0)
(plus:HI (mult:HI (sign_extend:HI (match_dup 1))
(sign_extend:HI (match_dup 4)))
(match_dup 3)))]
{
operands[2] = gen_int_mode (INTVAL (operands[2]), QImode);
})
(define_insn_and_split "*msubqihi4.sconst"
[(set (match_operand:HI 0 "register_operand" "=r")
(minus:HI (match_operand:HI 3 "register_operand" "0")
(mult:HI (sign_extend:HI (match_operand:QI 1 "register_operand" "d"))
(match_operand:HI 2 "s8_operand" "M"))))
(clobber (match_scratch:QI 4 "=&d"))]
"AVR_HAVE_MUL"
"#"
"&& reload_completed"
[(set (match_dup 4)
(match_dup 2))
; *smsubqihi4
(set (match_dup 0)
(minus:HI (match_dup 3)
(mult:HI (sign_extend:HI (match_dup 1))
(sign_extend:HI (match_dup 4)))))]
{
operands[2] = gen_int_mode (INTVAL (operands[2]), QImode);
})
;; Same as the insn above, but combiner tries versions canonicalized to ASHIFT
;; for MULT with power of 2 and skips trying MULT insn above. We omit 128
;; because this would require an extra pattern for just one value.
(define_insn_and_split "*msubqihi4.sconst.ashift"
[(set (match_operand:HI 0 "register_operand" "=r")
(minus:HI (match_operand:HI 3 "register_operand" "0")
(ashift:HI (sign_extend:HI (match_operand:QI 1 "register_operand" "d"))
(match_operand:HI 2 "const_1_to_6_operand" "M"))))
(clobber (match_scratch:QI 4 "=&d"))]
"AVR_HAVE_MUL"
"#"
"&& reload_completed"
[(set (match_dup 4)
(match_dup 2))
; *smsubqihi4
(set (match_dup 0)
(minus:HI (match_dup 3)
(mult:HI (sign_extend:HI (match_dup 1))
(sign_extend:HI (match_dup 4)))))]
{
operands[2] = gen_int_mode (1 << INTVAL (operands[2]), QImode);
})
;; For signed/unsigned combinations that require narrow constraint "a"
;; just provide a pattern if signed/unsigned combination is actually needed.
(define_insn_and_split "*sumaddqihi4.uconst"
[(set (match_operand:HI 0 "register_operand" "=r")
(plus:HI (mult:HI (sign_extend:HI (match_operand:QI 1 "register_operand" "a"))
(match_operand:HI 2 "u8_operand" "M"))
(match_operand:HI 3 "register_operand" "0")))
(clobber (match_scratch:QI 4 "=&a"))]
"AVR_HAVE_MUL
&& !s8_operand (operands[2], VOIDmode)"
"#"
"&& reload_completed"
[(set (match_dup 4)
(match_dup 2))
; *sumaddqihi4
(set (match_dup 0)
(plus:HI (mult:HI (sign_extend:HI (match_dup 1))
(zero_extend:HI (match_dup 4)))
(match_dup 3)))]
{
operands[2] = gen_int_mode (INTVAL (operands[2]), QImode);
})
(define_insn_and_split "*sumsubqihi4.uconst"
[(set (match_operand:HI 0 "register_operand" "=r")
(minus:HI (match_operand:HI 3 "register_operand" "0")
(mult:HI (sign_extend:HI (match_operand:QI 1 "register_operand" "a"))
(match_operand:HI 2 "u8_operand" "M"))))
(clobber (match_scratch:QI 4 "=&a"))]
"AVR_HAVE_MUL
&& !s8_operand (operands[2], VOIDmode)"
"#"
"&& reload_completed"
[(set (match_dup 4)
(match_dup 2))
; *sumsubqihi4
(set (match_dup 0)
(minus:HI (match_dup 3)
(mult:HI (sign_extend:HI (match_dup 1))
(zero_extend:HI (match_dup 4)))))]
{
operands[2] = gen_int_mode (INTVAL (operands[2]), QImode);
})
;******************************************************************************
; mul HI: $1 = sign/zero-extend, $2 = small constant

View File

@ -78,6 +78,11 @@
(and (match_code "const_int")
(match_test "IN_RANGE (INTVAL (op), 2, 7)")))
;; Return 1 if OP is constant integer 1..6 for MODE.
(define_predicate "const_1_to_6_operand"
(and (match_code "const_int")
(match_test "IN_RANGE (INTVAL (op), 1, 6)")))
;; Return 1 if OP is constant integer 2..6 for MODE.
(define_predicate "const_2_to_6_operand"
(and (match_code "const_int")