This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[AVR] Fix target/11259
- From: Anatoly Sokolov <aesok at post dot ru>
- To: gcc-patches at gcc dot gnu dot org
- Cc: aesok at post dot ru, eweddington at cso dot atmel dot com
- Date: Sat, 23 Aug 2008 01:14:55 +0400
- Subject: [AVR] Fix target/11259
Hello.
This patch fix target/11259: [avr] gcc Double 'andi' missed optimization
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=11259
The ashlqi3 and lshrqi3 insn patterns is rewritten to use RTL expanders
and new splitters and peephole2 patterns is added.
Tested on avr port. Committed.
2008-08-22 Anatoly Sokolov <aesok@post.ru>
PR target/11259
* config/avr/avr.md (UNSPEC_SWAP): New constants.
(*swap): New insn pattern.
(*ashlqi3): Rename from ashlqi3 insn pattern.
(ashlqi3): New expanders.
(*lshrqi3): Rename from lshrqi3 insn pattern.
(lshrqi3): New expanders.
(ashlqi3_const4, ashlqi3_const5, ashlqi3_const6, lshrqi3_const4,
lshrqi3_const5, lshrqi3_const6): New splitters.
(andi, ashlqi3_l_const4, ashlqi3_l_const5, ashlqi3_l_const6,
lshrqi3_l_const4, lshrqi3_l_const5, lshrqi3_l_const6): Define
peephole2 patterns.
Index: gcc/config/avr/avr.md
===================================================================
--- gcc/config/avr/avr.md (revision 139245)
+++ gcc/config/avr/avr.md (working copy)
@@ -54,6 +54,7 @@
(UNSPEC_INDEX_JMP 1)
(UNSPEC_SEI 2)
(UNSPEC_CLI 3)
+ (UNSPEC_SWAP 4)
(UNSPECV_PROLOGUE_SAVES 0)
(UNSPECV_EPILOGUE_RESTORES 1)
@@ -1261,6 +1262,19 @@
[(set_attr "length" "4,4")
(set_attr "cc" "set_n,set_n")])
+(define_peephole2 ; andi
+ [(set (match_operand:QI 0 "d_register_operand" "")
+ (and:QI (match_dup 0)
+ (match_operand:QI 1 "const_int_operand" "")))
+ (set (match_dup 0)
+ (and:QI (match_dup 0)
+ (match_operand:QI 2 "const_int_operand" "")))]
+ ""
+ [(set (match_dup 0) (and:QI (match_dup 0) (match_dup 1)))]
+ {
+ operands[1] = GEN_INT (INTVAL (operands[1]) & INTVAL (operands[2]));
+ })
+
;;|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
;; ior
@@ -1389,10 +1403,57 @@
[(set_attr "length" "4")
(set_attr "cc" "set_n")])
+;; swap
+
+(define_insn "*swap"
+ [(set (match_operand:QI 0 "register_operand" "=r")
+ (unspec:QI [(match_operand:QI 1 "register_operand" "0")]
+ UNSPEC_SWAP))]
+ ""
+ "swap %0"
+ [(set_attr "length" "1")
+ (set_attr "cc" "none")])
+
;;<< << << << << << << << << << << << << << << << << << << << << << << << << <<
;; arithmetic shift left
-(define_insn "ashlqi3"
+(define_expand "ashlqi3"
+ [(set (match_operand:QI 0 "register_operand" "")
+ (ashift:QI (match_operand:QI 1 "register_operand" "")
+ (match_operand:QI 2 "general_operand" "")))]
+ ""
+ "")
+
+(define_split ; ashlqi3_const4
+ [(set (match_operand:QI 0 "d_register_operand" "")
+ (ashift:QI (match_dup 0)
+ (const_int 4)))]
+ ""
+ [(set (match_dup 0) (unspec:QI [(match_dup 0)] UNSPEC_SWAP))
+ (set (match_dup 0) (and:QI (match_dup 0) (const_int -16)))]
+ "")
+
+(define_split ; ashlqi3_const5
+ [(set (match_operand:QI 0 "d_register_operand" "")
+ (ashift:QI (match_dup 0)
+ (const_int 5)))]
+ ""
+ [(set (match_dup 0) (unspec:QI [(match_dup 0)] UNSPEC_SWAP))
+ (set (match_dup 0) (ashift:QI (match_dup 0) (const_int 1)))
+ (set (match_dup 0) (and:QI (match_dup 0) (const_int -32)))]
+ "")
+
+(define_split ; ashlqi3_const6
+ [(set (match_operand:QI 0 "d_register_operand" "")
+ (ashift:QI (match_dup 0)
+ (const_int 6)))]
+ ""
+ [(set (match_dup 0) (unspec:QI [(match_dup 0)] UNSPEC_SWAP))
+ (set (match_dup 0) (ashift:QI (match_dup 0) (const_int 2)))
+ (set (match_dup 0) (and:QI (match_dup 0) (const_int -64)))]
+ "")
+
+(define_insn "*ashlqi3"
[(set (match_operand:QI 0 "register_operand" "=r,r,r,r,!d,r,r")
(ashift:QI (match_operand:QI 1 "register_operand" "0,0,0,0,0,0,0")
(match_operand:QI 2 "general_operand" "r,L,P,K,n,n,Qm")))]
@@ -1421,6 +1482,41 @@
;; Optimize if a scratch register from LD_REGS happens to be available.
+(define_peephole2 ; ashlqi3_l_const4
+ [(set (match_operand:QI 0 "l_register_operand" "")
+ (ashift:QI (match_dup 0)
+ (const_int 4)))
+ (match_scratch:QI 1 "d")]
+ ""
+ [(set (match_dup 0) (unspec:QI [(match_dup 0)] UNSPEC_SWAP))
+ (set (match_dup 1) (const_int -16))
+ (set (match_dup 0) (and:QI (match_dup 0) (match_dup 1)))]
+ "")
+
+(define_peephole2 ; ashlqi3_l_const5
+ [(set (match_operand:QI 0 "l_register_operand" "")
+ (ashift:QI (match_dup 0)
+ (const_int 5)))
+ (match_scratch:QI 1 "d")]
+ ""
+ [(set (match_dup 0) (unspec:QI [(match_dup 0)] UNSPEC_SWAP))
+ (set (match_dup 0) (ashift:QI (match_dup 0) (const_int 1)))
+ (set (match_dup 1) (const_int -32))
+ (set (match_dup 0) (and:QI (match_dup 0) (match_dup 1)))]
+ "")
+
+(define_peephole2 ; ashlqi3_l_const6
+ [(set (match_operand:QI 0 "l_register_operand" "")
+ (ashift:QI (match_dup 0)
+ (const_int 6)))
+ (match_scratch:QI 1 "d")]
+ ""
+ [(set (match_dup 0) (unspec:QI [(match_dup 0)] UNSPEC_SWAP))
+ (set (match_dup 0) (ashift:QI (match_dup 0) (const_int 2)))
+ (set (match_dup 1) (const_int -64))
+ (set (match_dup 0) (and:QI (match_dup 0) (match_dup 1)))]
+ "")
+
(define_peephole2
[(match_scratch:QI 3 "d")
(set (match_operand:HI 0 "register_operand" "")
@@ -1536,7 +1632,43 @@
;; >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >>
;; logical shift right
-(define_insn "lshrqi3"
+(define_expand "lshrqi3"
+ [(set (match_operand:QI 0 "register_operand" "")
+ (lshiftrt:QI (match_operand:QI 1 "register_operand" "")
+ (match_operand:QI 2 "general_operand" "")))]
+ ""
+ "")
+
+(define_split ; lshrqi3_const4
+ [(set (match_operand:QI 0 "d_register_operand" "")
+ (lshiftrt:QI (match_dup 0)
+ (const_int 4)))]
+ ""
+ [(set (match_dup 0) (unspec:QI [(match_dup 0)] UNSPEC_SWAP))
+ (set (match_dup 0) (and:QI (match_dup 0) (const_int 15)))]
+ "")
+
+(define_split ; lshrqi3_const5
+ [(set (match_operand:QI 0 "d_register_operand" "")
+ (lshiftrt:QI (match_dup 0)
+ (const_int 5)))]
+ ""
+ [(set (match_dup 0) (unspec:QI [(match_dup 0)] UNSPEC_SWAP))
+ (set (match_dup 0) (lshiftrt:QI (match_dup 0) (const_int 1)))
+ (set (match_dup 0) (and:QI (match_dup 0) (const_int 7)))]
+ "")
+
+(define_split ; lshrqi3_const6
+ [(set (match_operand:QI 0 "d_register_operand" "")
+ (lshiftrt:QI (match_dup 0)
+ (const_int 6)))]
+ ""
+ [(set (match_dup 0) (unspec:QI [(match_dup 0)] UNSPEC_SWAP))
+ (set (match_dup 0) (lshiftrt:QI (match_dup 0) (const_int 2)))
+ (set (match_dup 0) (and:QI (match_dup 0) (const_int 3)))]
+ "")
+
+(define_insn "*lshrqi3"
[(set (match_operand:QI 0 "register_operand" "=r,r,r,r,!d,r,r")
(lshiftrt:QI (match_operand:QI 1 "register_operand" "0,0,0,0,0,0,0")
(match_operand:QI 2 "general_operand" "r,L,P,K,n,n,Qm")))]
@@ -1565,6 +1697,41 @@
;; Optimize if a scratch register from LD_REGS happens to be available.
+(define_peephole2 ; lshrqi3_l_const4
+ [(set (match_operand:QI 0 "l_register_operand" "")
+ (lshiftrt:QI (match_dup 0)
+ (const_int 4)))
+ (match_scratch:QI 1 "d")]
+ ""
+ [(set (match_dup 0) (unspec:QI [(match_dup 0)] UNSPEC_SWAP))
+ (set (match_dup 1) (const_int 15))
+ (set (match_dup 0) (and:QI (match_dup 0) (match_dup 1)))]
+ "")
+
+(define_peephole2 ; lshrqi3_l_const5
+ [(set (match_operand:QI 0 "l_register_operand" "")
+ (lshiftrt:QI (match_dup 0)
+ (const_int 5)))
+ (match_scratch:QI 1 "d")]
+ ""
+ [(set (match_dup 0) (unspec:QI [(match_dup 0)] UNSPEC_SWAP))
+ (set (match_dup 0) (lshiftrt:QI (match_dup 0) (const_int 1)))
+ (set (match_dup 1) (const_int 7))
+ (set (match_dup 0) (and:QI (match_dup 0) (match_dup 1)))]
+ "")
+
+(define_peephole2 ; lshrqi3_l_const6
+ [(set (match_operand:QI 0 "l_register_operand" "")
+ (lshiftrt:QI (match_dup 0)
+ (const_int 6)))
+ (match_scratch:QI 1 "d")]
+ ""
+ [(set (match_dup 0) (unspec:QI [(match_dup 0)] UNSPEC_SWAP))
+ (set (match_dup 0) (lshiftrt:QI (match_dup 0) (const_int 2)))
+ (set (match_dup 1) (const_int 3))
+ (set (match_dup 0) (and:QI (match_dup 0) (match_dup 1)))]
+ "")
+
(define_peephole2
[(match_scratch:QI 3 "d")
(set (match_operand:HI 0 "register_operand" "")
Anatoliy.