aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGeorg-Johann Lay <avr@gjlay.de>2011-08-10 08:58:03 +0000
committerGeorg-Johann Lay <gjl@gcc.gnu.org>2011-08-10 08:58:03 +0000
commit4ada410ba1cf7440e3cc4b57a55c53da63ae341c (patch)
tree8455f2447914d9dcc0fa653e32875377b768e3ed
parentd1f4e15f16e037c3f57aa0636d0cc7eddcaff10e (diff)
downloadgcc-4ada410ba1cf7440e3cc4b57a55c53da63ae341c.zip
gcc-4ada410ba1cf7440e3cc4b57a55c53da63ae341c.tar.gz
gcc-4ada410ba1cf7440e3cc4b57a55c53da63ae341c.tar.bz2
re PR target/29560 ([avr] Poor optimization for byte shifts)
PR target/29560 * config/avr/avr.md (*ashlhiqi3): New insn-and-split. (*ashl<extend_prefix>qihiqi3): New insn-and-splits. (*ashl<extend_prefix>qihiqi3.mem): New insn-and-splits. Add peephole2 to map ashlhi3 to ashlqi3 if high part of shift target is unused. From-SVN: r177616
-rw-r--r--gcc/ChangeLog9
-rw-r--r--gcc/config/avr/avr.md82
2 files changed, 91 insertions, 0 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 2c50a1d..9fd1ab7 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,12 @@
+2011-08-10 Georg-Johann Lay <avr@gjlay.de>
+
+ PR target/29560
+ * config/avr/avr.md (*ashlhiqi3): New insn-and-split.
+ (*ashl<extend_prefix>qihiqi3): New insn-and-splits.
+ (*ashl<extend_prefix>qihiqi3.mem): New insn-and-splits.
+ Add peephole2 to map ashlhi3 to ashlqi3 if high part of
+ shift target is unused.
+
2011-08-10 Richard Guenther <rguenther@suse.de>
PR tree-optimization/49937
diff --git a/gcc/config/avr/avr.md b/gcc/config/avr/avr.md
index b5aa73c..8293ba7 100644
--- a/gcc/config/avr/avr.md
+++ b/gcc/config/avr/avr.md
@@ -2263,6 +2263,88 @@
[(set_attr "length" "6,0,2,2,4,10,10")
(set_attr "cc" "clobber,none,set_n,clobber,set_n,clobber,clobber")])
+
+;; Insns like the following are generated when (implicitly) extending 8-bit shifts
+;; like char1 = char2 << char3. Only the low-byte is needed in that situation.
+
+;; "*ashluqihiqi3"
+;; "*ashlsqihiqi3"
+(define_insn_and_split "*ashl<extend_prefix>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"))
+ 0))]
+ ""
+ "#"
+ ""
+ [(set (match_dup 0)
+ (ashift:QI (match_dup 1)
+ (match_dup 2)))]
+ "")
+
+;; ??? Combiner does not recognize that it could split the following insn;
+;; presumably because he has no register handy?
+
+;; "*ashluqihiqi3.mem"
+;; "*ashlsqihiqi3.mem"
+(define_insn_and_split "*ashl<extend_prefix>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"))
+ 0))]
+ "!reload_completed"
+ { gcc_unreachable(); }
+ "&& 1"
+ [(set (match_dup 3)
+ (ashift:QI (match_dup 1)
+ (match_dup 2)))
+ (set (match_dup 0)
+ (match_dup 3))]
+ {
+ operands[3] = force_reg (QImode, operands[0]);
+ })
+
+;; Similar.
+
+(define_insn_and_split "*ashlhiqi3"
+ [(set (match_operand:QI 0 "nonimmediate_operand" "=r")
+ (subreg:QI (ashift:HI (match_operand:HI 1 "register_operand" "0")
+ (match_operand:QI 2 "register_operand" "r")) 0))]
+ "!reload_completed"
+ { gcc_unreachable(); }
+ "&& 1"
+ [(set (match_dup 4)
+ (ashift:QI (match_dup 3)
+ (match_dup 2)))
+ (set (match_dup 0)
+ (match_dup 4))]
+ {
+ operands[3] = simplify_gen_subreg (QImode, operands[1], HImode, 0);
+ operands[4] = force_reg (QImode, operands[0]);
+ })
+
+;; 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")