aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorGeorg-Johann Lay <avr@gjlay.de>2011-08-11 07:50:37 +0000
committerGeorg-Johann Lay <gjl@gcc.gnu.org>2011-08-11 07:50:37 +0000
commit7ece388150bbbfb0c946b28efa43ad1eeb2f0bf8 (patch)
tree336df3258cbf4c19f353f45981a4f0518f40ea77 /gcc
parentfb2c2b167238f82d9103b7fb78ad24918548c245 (diff)
downloadgcc-7ece388150bbbfb0c946b28efa43ad1eeb2f0bf8.zip
gcc-7ece388150bbbfb0c946b28efa43ad1eeb2f0bf8.tar.gz
gcc-7ece388150bbbfb0c946b28efa43ad1eeb2f0bf8.tar.bz2
re PR target/49687 ([avr] Missed optimization for widening MUL)
PR target/49687 * config/avr/avr.md (smulqi3_highpart): New insn. (umulqi3_highpart): New insn. (*subqi3.ashiftrt7): New insn. (smulhi3_highpart): New expander. (umulhi3_highpart): Nex expander. (*smulhi3_highpart_call): New insn. (*umulhi3_highpart_call): New insn. (extend_u): New code attribute. (extend_prefix): Rename code attribute to extend_su. * config/avr/avr.c (avr_rtx_costs): Report costs of highpart of widening QI/HI multiply. From-SVN: r177648
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog15
-rw-r--r--gcc/config/avr/avr.c14
-rw-r--r--gcc/config/avr/avr.md131
3 files changed, 118 insertions, 42 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index f85d349..0220752 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,18 @@
+2011-08-11 Georg-Johann Lay <avr@gjlay.de>
+
+ PR target/49687
+ * config/avr/avr.md (smulqi3_highpart): New insn.
+ (umulqi3_highpart): New insn.
+ (*subqi3.ashiftrt7): New insn.
+ (smulhi3_highpart): New expander.
+ (umulhi3_highpart): Nex expander.
+ (*smulhi3_highpart_call): New insn.
+ (*umulhi3_highpart_call): New insn.
+ (extend_u): New code attribute.
+ (extend_prefix): Rename code attribute to extend_su.
+ * config/avr/avr.c (avr_rtx_costs): Report costs of highpart of
+ widening QI/HI multiply.
+
2011-08-11 Ira Rosen <ira.rosen@linaro.org>
PR tree-optimization/50039
diff --git a/gcc/config/avr/avr.c b/gcc/config/avr/avr.c
index d9ed224..76542a8 100644
--- a/gcc/config/avr/avr.c
+++ b/gcc/config/avr/avr.c
@@ -5954,6 +5954,20 @@ avr_rtx_costs (rtx x, int codearg, int outer_code ATTRIBUTE_UNUSED, int *total,
*total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, speed);
return true;
+ case TRUNCATE:
+ if (AVR_HAVE_MUL
+ && LSHIFTRT == GET_CODE (XEXP (x, 0))
+ && MULT == GET_CODE (XEXP (XEXP (x, 0), 0))
+ && CONST_INT_P (XEXP (XEXP (x, 0), 1)))
+ {
+ if (QImode == mode || HImode == mode)
+ {
+ *total = COSTS_N_INSNS (2);
+ return true;
+ }
+ }
+ break;
+
default:
break;
}
diff --git a/gcc/config/avr/avr.md b/gcc/config/avr/avr.md
index 8293ba7..356b509 100644
--- a/gcc/config/avr/avr.md
+++ b/gcc/config/avr/avr.md
@@ -141,10 +141,14 @@
(define_code_iterator any_extend2 [sign_extend zero_extend])
;; Define code attributes
-(define_code_attr extend_prefix
+(define_code_attr extend_su
[(sign_extend "s")
(zero_extend "u")])
+(define_code_attr extend_u
+ [(sign_extend "")
+ (zero_extend "u")])
+
;;========================================================================
;; The following is used by nonlocal_goto and setjmp.
@@ -1015,6 +1019,43 @@
[(set_attr "type" "xcall")
(set_attr "cc" "clobber")])
+(define_insn "smulqi3_highpart"
+ [(set (match_operand:QI 0 "register_operand" "=r")
+ (truncate:QI
+ (lshiftrt:HI (mult:HI (sign_extend:HI (match_operand:QI 1 "register_operand" "d"))
+ (sign_extend:HI (match_operand:QI 2 "register_operand" "d")))
+ (const_int 8))))]
+ "AVR_HAVE_MUL"
+ "muls %1,%2
+ mov %0,r1
+ clr __zero_reg__"
+ [(set_attr "length" "3")
+ (set_attr "cc" "clobber")])
+
+(define_insn "umulqi3_highpart"
+ [(set (match_operand:QI 0 "register_operand" "=r")
+ (truncate:QI
+ (lshiftrt:HI (mult:HI (zero_extend:HI (match_operand:QI 1 "register_operand" "r"))
+ (zero_extend:HI (match_operand:QI 2 "register_operand" "r")))
+ (const_int 8))))]
+ "AVR_HAVE_MUL"
+ "mul %1,%2
+ mov %0,r1
+ clr __zero_reg__"
+ [(set_attr "length" "3")
+ (set_attr "cc" "clobber")])
+
+;; Used when expanding div or mod inline for some special values
+(define_insn "*subqi3.ashiftrt7"
+ [(set (match_operand:QI 0 "register_operand" "=r")
+ (minus:QI (match_operand:QI 1 "register_operand" "0")
+ (ashiftrt:QI (match_operand:QI 2 "register_operand" "r")
+ (const_int 7))))]
+ ""
+ "sbrc %2,7\;inc %0"
+ [(set_attr "length" "2")
+ (set_attr "cc" "clobber")])
+
(define_insn "mulqihi3"
[(set (match_operand:HI 0 "register_operand" "=r")
(mult:HI (sign_extend:HI (match_operand:QI 1 "register_operand" "d"))
@@ -1367,9 +1408,7 @@
[(set_attr "type" "xcall")
(set_attr "cc" "clobber")])
-;; Operand 2 (reg:SI 18) not clobbered on the enhanced core.
-;; All call-used registers clobbered otherwise - normal library call.
-;; To support widening multiplicatioon with constant we postpone
+;; To support widening multiplicatioon with constant we postpone
;; expanding to the implicit library call until post combine and
;; prior to register allocation. Clobber all hard registers that
;; might be used by the (widening) multiply until it is split and
@@ -1535,19 +1574,12 @@
(reg:SI 22))]
"")
-(define_expand "mulhisi3"
+;; "mulhisi3"
+;; "umulhisi3"
+(define_expand "<extend_u>mulhisi3"
[(parallel [(set (match_operand:SI 0 "register_operand" "")
- (mult:SI (sign_extend:SI (match_operand:HI 1 "register_operand" ""))
- (sign_extend:SI (match_operand:HI 2 "register_operand" ""))))
- (clobber (reg:HI 26))
- (clobber (reg:DI 18))])]
- "AVR_HAVE_MUL"
- "")
-
-(define_expand "umulhisi3"
- [(parallel [(set (match_operand:SI 0 "register_operand" "")
- (mult:SI (zero_extend:SI (match_operand:HI 1 "register_operand" ""))
- (zero_extend:SI (match_operand:HI 2 "register_operand" ""))))
+ (mult:SI (any_extend:SI (match_operand:HI 1 "register_operand" ""))
+ (any_extend:SI (match_operand:HI 2 "register_operand" ""))))
(clobber (reg:HI 26))
(clobber (reg:DI 18))])]
"AVR_HAVE_MUL"
@@ -1567,7 +1599,7 @@
;; "*sumulqihisi3" "*sumulhiqisi3" "*sumulhihisi3" "*sumulqiqisi3"
;; "*ssmulqihisi3" "*ssmulhiqisi3" "*ssmulhihisi3" "*ssmulqiqisi3"
(define_insn_and_split
- "*<any_extend:extend_prefix><any_extend2:extend_prefix>mul<QIHI:mode><QIHI2:mode>si3"
+ "*<any_extend:extend_su><any_extend2:extend_su>mul<QIHI:mode><QIHI2:mode>si3"
[(set (match_operand:SI 0 "pseudo_register_operand" "=r")
(mult:SI (any_extend:SI (match_operand:QIHI 1 "pseudo_register_operand" "r"))
(any_extend2:SI (match_operand:QIHI2 2 "pseudo_register_operand" "r"))))
@@ -1618,6 +1650,24 @@
}
})
+;; "smulhi3_highpart"
+;; "umulhi3_highpart"
+(define_expand "<extend_su>mulhi3_highpart"
+ [(set (reg:HI 18)
+ (match_operand:HI 1 "nonmemory_operand" ""))
+ (set (reg:HI 26)
+ (match_operand:HI 2 "nonmemory_operand" ""))
+ (parallel [(set (reg:HI 24)
+ (truncate:HI (lshiftrt:SI (mult:SI (any_extend:SI (reg:HI 18))
+ (any_extend:SI (reg:HI 26)))
+ (const_int 16))))
+ (clobber (reg:HI 22))])
+ (set (match_operand:HI 0 "register_operand" "")
+ (reg:HI 24))]
+ "AVR_HAVE_MUL"
+ "")
+
+
(define_insn "*mulsi3_call"
[(set (reg:SI 22)
(mult:SI (reg:SI 22)
@@ -1628,21 +1678,27 @@
[(set_attr "type" "xcall")
(set_attr "cc" "clobber")])
-(define_insn "*mulhisi3_call"
+;; "*mulhisi3_call"
+;; "*umulhisi3_call"
+(define_insn "*<extend_u>mulhisi3_call"
[(set (reg:SI 22)
- (mult:SI (sign_extend:SI (reg:HI 18))
- (sign_extend:SI (reg:HI 26))))]
+ (mult:SI (any_extend:SI (reg:HI 18))
+ (any_extend:SI (reg:HI 26))))]
"AVR_HAVE_MUL"
- "%~call __mulhisi3"
+ "%~call __<extend_u>mulhisi3"
[(set_attr "type" "xcall")
(set_attr "cc" "clobber")])
-(define_insn "*umulhisi3_call"
- [(set (reg:SI 22)
- (mult:SI (zero_extend:SI (reg:HI 18))
- (zero_extend:SI (reg:HI 26))))]
+;; "*umulhi3_highpart_call"
+;; "*smulhi3_highpart_call"
+(define_insn "*<extend_su>mulhi3_highpart_call"
+ [(set (reg:HI 24)
+ (truncate:HI (lshiftrt:SI (mult:SI (any_extend:SI (reg:HI 18))
+ (any_extend:SI (reg:HI 26)))
+ (const_int 16))))
+ (clobber (reg:HI 22))]
"AVR_HAVE_MUL"
- "%~call __umulhisi3"
+ "%~call __<extend_u>mulhisi3"
[(set_attr "type" "xcall")
(set_attr "cc" "clobber")])
@@ -1655,21 +1711,12 @@
[(set_attr "type" "xcall")
(set_attr "cc" "clobber")])
-(define_insn "*muluhisi3_call"
- [(set (reg:SI 22)
- (mult:SI (zero_extend:SI (reg:HI 26))
- (reg:SI 18)))]
- "AVR_HAVE_MUL"
- "%~call __muluhisi3"
- [(set_attr "type" "xcall")
- (set_attr "cc" "clobber")])
-
-(define_insn "*mulshisi3_call"
+(define_insn "*mul<extend_su>hisi3_call"
[(set (reg:SI 22)
- (mult:SI (sign_extend:SI (reg:HI 26))
+ (mult:SI (any_extend:SI (reg:HI 26))
(reg:SI 18)))]
"AVR_HAVE_MUL"
- "%~call __mulshisi3"
+ "%~call __mul<extend_su>hisi3"
[(set_attr "type" "xcall")
(set_attr "cc" "clobber")])
@@ -2269,7 +2316,7 @@
;; "*ashluqihiqi3"
;; "*ashlsqihiqi3"
-(define_insn_and_split "*ashl<extend_prefix>qihiqi3"
+(define_insn_and_split "*ashl<extend_su>qihiqi3"
[(set (match_operand:QI 0 "register_operand" "=r")
(subreg:QI (ashift:HI (any_extend:HI (match_operand:QI 1 "register_operand" "0"))
(match_operand:QI 2 "register_operand" "r"))
@@ -2287,7 +2334,7 @@
;; "*ashluqihiqi3.mem"
;; "*ashlsqihiqi3.mem"
-(define_insn_and_split "*ashl<extend_prefix>qihiqi3.mem"
+(define_insn_and_split "*ashl<extend_su>qihiqi3.mem"
[(set (match_operand:QI 0 "memory_operand" "=m")
(subreg:QI (ashift:HI (any_extend:HI (match_operand:QI 1 "register_operand" "r"))
(match_operand:QI 2 "register_operand" "r"))
@@ -2301,7 +2348,7 @@
(set (match_dup 0)
(match_dup 3))]
{
- operands[3] = force_reg (QImode, operands[0]);
+ operands[3] = gen_reg_rtx (QImode);
})
;; Similar.
@@ -2320,7 +2367,7 @@
(match_dup 4))]
{
operands[3] = simplify_gen_subreg (QImode, operands[1], HImode, 0);
- operands[4] = force_reg (QImode, operands[0]);
+ operands[4] = gen_reg_rtx (QImode);
})
;; High part of 16-bit shift is unused after the instruction: