This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[Patch,AVR]: Fix PR29560 (map 16-bit shift to 8-bit)
- From: Georg-Johann Lay <avr at gjlay dot de>
- To: gcc-patches at gcc dot gnu dot org
- Cc: Anatoly Sokolov <aesok at post dot ru>, Denis Chertykov <chertykov at gmail dot com>, Eric Weddington <eric dot weddington at atmel dot com>, Richard Henderson <rth at redhat dot com>
- Date: Mon, 25 Jul 2011 19:30:35 +0200
- Subject: [Patch,AVR]: Fix PR29560 (map 16-bit shift to 8-bit)
This is an optimization for 8-bit shifts if the high part is unused.
Variable shift offset shifts are tedious on AVR because these devices
can just shift by 1.
If the high part of a shift is unused, the high part need not to be
computed, i.e. the 16-bit shift can be mapped to a 8-bit shift.
Most of such shifts come from implicit 8->16 bit (word_mode) conversions
when dealing with 8-bit variables as in the example code:
unsigned char shift1 (unsigned char x, unsigned char s)
{
return x << s;
}
unsigned char y;
void shift2 (unsigned char x, unsigned char s)
{
y = x << s;
}
Note that the result will still be correct for shift offsets
8..15, i.e. the result will be 0.
Ok to commit?
Johann
PR target/29560
* config/avr/avr.md: Add peephole2 to map ashlhi3 to ashlqi3 if
high part of shift target is unused.
Index: config/avr/avr.md
===================================================================
--- config/avr/avr.md (revision 176624)
+++ config/avr/avr.md (working copy)
@@ -1993,6 +1993,29 @@ (define_insn "ashlhi3"
[(set_attr "length" "6,0,2,2,4,10,10")
(set_attr "cc" "clobber,none,set_n,clobber,set_n,clobber,clobber")])
+
+;; High part of 16-bit shift is unused after the instruction:
+;; No need to compute it, map to 8-bit shift.
+
+(define_peephole2
+ [(set (match_operand:HI 0 "register_operand" "")
+ (ashift:HI (match_dup 0)
+ (match_operand:QI 1 "register_operand" "")))]
+ ""
+ [(set (match_dup 2)
+ (ashift:QI (match_dup 2)
+ (match_dup 1)))
+ (clobber (match_dup 3))]
+ {
+ operands[3] = simplify_gen_subreg (QImode, operands[0], HImode, 1);
+
+ if (!peep2_reg_dead_p (1, operands[3]))
+ FAIL;
+
+ operands[2] = simplify_gen_subreg (QImode, operands[0], HImode, 0);
+ })
+
+
(define_insn "ashlsi3"
[(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r,r")
(ashift:SI (match_operand:SI 1 "register_operand" "0,0,0,r,0,0,0")