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")