This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[Patch,AVR]: Implement PR50446
- From: Georg-Johann Lay <avr at gjlay dot de>
- To: gcc-patches at gcc dot gnu dot org
- Cc: Denis Chertykov <chertykov at gmail dot com>, Eric Weddington <eric dot weddington at atmel dot com>, Anatoly Sokolov <aesok at post dot ru>
- Date: Thu, 22 Sep 2011 14:00:15 +0200
- Subject: [Patch,AVR]: Implement PR50446
This adds rotate left/right by 1 for HI and SI and rotates by QI.
It's all straight forward. The test case in the PR leads to generation of the
new rotate patterns.
Passed without regressions.
Ok?
Johann
PR target/50446
* config/avr/avr.md (rotlqi3): Support all offsets 0..7.
(rotlqi3_4): Turn insn into expander.
(*rotlqi3): New insn.
(rotlhi3, rotlsi3): Support rotate left/right by 1.
(*rotlhi2.1, *rotlhi2.15): New insns.
(*rotlsi2.1, *rotlsi2.31): New insns.
* config/avr/constraints.md (C03, C05, C06, C07): New constraints.
Index: config/avr/avr.md
===================================================================
--- config/avr/avr.md (revision 179081)
+++ config/avr/avr.md (working copy)
@@ -2390,23 +2390,38 @@ (define_insn "xorsi3"
(define_expand "rotlqi3"
[(set (match_operand:QI 0 "register_operand" "")
- (rotate:QI (match_operand:QI 1 "register_operand" "")
- (match_operand:QI 2 "const_int_operand" "")))]
+ (rotate:QI (match_operand:QI 1 "register_operand" "")
+ (match_operand:QI 2 "const_0_to_7_operand" "")))]
""
- "
-{
- if (!CONST_INT_P (operands[2]) || (INTVAL (operands[2]) != 4))
- FAIL;
-}")
-
-(define_insn "rotlqi3_4"
- [(set (match_operand:QI 0 "register_operand" "=r")
- (rotate:QI (match_operand:QI 1 "register_operand" "0")
- (const_int 4)))]
- ""
- "swap %0"
- [(set_attr "length" "1")
- (set_attr "cc" "none")])
+ {
+ if (!CONST_INT_P (operands[2]))
+ FAIL;
+
+ operands[2] = gen_int_mode (INTVAL (operands[2]) & 7, QImode);
+ })
+
+;; Expander used by __builtin_avr_swap
+(define_expand "rotlqi3_4"
+ [(set (match_operand:QI 0 "register_operand" "")
+ (rotate:QI (match_operand:QI 1 "register_operand" "")
+ (const_int 4)))])
+
+(define_insn "*rotlqi3"
+ [(set (match_operand:QI 0 "register_operand" "=r,r,r ,r ,r ,r ,r ,r")
+ (rotate:QI (match_operand:QI 1 "register_operand" "0,0,0 ,0 ,0 ,0 ,0 ,0")
+ (match_operand:QI 2 "const_0_to_7_operand" "P,K,C03,C04,C05,C06,C07,L")))]
+ ""
+ "@
+ lsl %0\;adc %0,__zero_reg__
+ lsl %0\;adc %0,__zero_reg__\;lsl %0\;adc %0,__zero_reg__
+ swap %0\;bst %0,0\;ror %0\;bld %0,7
+ swap %0
+ swap %0\;lsl %0\;adc %0,__zero_reg__
+ swap %0\;lsl %0\;adc %0,__zero_reg__\;lsl %0\;adc %0,__zero_reg__
+ bst %0,0\;ror %0\;bld %0,7
+ "
+ [(set_attr "length" "2,4,4,1,3,5,3,0")
+ (set_attr "cc" "set_n,set_n,clobber,none,set_n,set_n,clobber,none")])
;; Split all rotates of HI,SI and DImode registers where rotation is by
;; a whole number of bytes. The split creates the appropriate moves and
@@ -2418,25 +2433,79 @@ (define_insn "rotlqi3_4"
(define_mode_attr rotx [(DI "&r,&r,X") (SI "&r,&r,X") (HI "X,X,X")])
(define_mode_attr rotsmode [(DI "QI") (SI "HI") (HI "QI")])
+;; "rotlhi3"
+;; "rotlsi3"
+;; "rotldi3"
(define_expand "rotl<mode>3"
[(parallel [(set (match_operand:HIDI 0 "register_operand" "")
- (rotate:HIDI (match_operand:HIDI 1 "register_operand" "")
- (match_operand:VOID 2 "const_int_operand" "")))
- (clobber (match_dup 3))])]
+ (rotate:HIDI (match_operand:HIDI 1 "register_operand" "")
+ (match_operand:VOID 2 "const_int_operand" "")))
+ (clobber (match_dup 3))])]
""
{
- if (CONST_INT_P (operands[2])
- && 0 == INTVAL (operands[2]) % 8)
+ int offset;
+
+ if (!CONST_INT_P (operands[2]))
+ FAIL;
+
+ offset = INTVAL (operands[2]);
+
+ if (0 == offset % 8)
{
- if (AVR_HAVE_MOVW && 0 == INTVAL (operands[2]) % 16)
+ if (AVR_HAVE_MOVW && 0 == offset % 16)
operands[3] = gen_rtx_SCRATCH (<rotsmode>mode);
else
operands[3] = gen_rtx_SCRATCH (QImode);
}
+ else if (<MODE>mode != DImode
+ && (offset == 1
+ || offset == GET_MODE_BITSIZE (<MODE>mode) -1))
+ {
+ /*; Support rotate left/right by 1 */
+
+ emit_move_insn (operands[0],
+ gen_rtx_ROTATE (<MODE>mode, operands[1], operands[2]));
+ DONE;
+ }
else
FAIL;
})
+(define_insn "*rotlhi2.1"
+ [(set (match_operand:HI 0 "register_operand" "=r")
+ (rotate:HI (match_operand:HI 1 "register_operand" "0")
+ (const_int 1)))]
+ ""
+ "lsl %A0\;rol %B0\;adc %A0,__zero_reg__"
+ [(set_attr "length" "3")
+ (set_attr "cc" "clobber")])
+
+(define_insn "*rotlhi2.15"
+ [(set (match_operand:HI 0 "register_operand" "=r")
+ (rotate:HI (match_operand:HI 1 "register_operand" "0")
+ (const_int 15)))]
+ ""
+ "bst %A0,0\;ror %B0\;ror %A0\;bld %B0,7"
+ [(set_attr "length" "3")
+ (set_attr "cc" "clobber")])
+
+(define_insn "*rotlsi2.1"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (rotate:SI (match_operand:SI 1 "register_operand" "0")
+ (const_int 1)))]
+ ""
+ "lsl %A0\;rol %B0\;rol %C0\;rol %D0\;adc %A0,__zero_reg__"
+ [(set_attr "length" "5")
+ (set_attr "cc" "clobber")])
+
+(define_insn "*rotlsi2.31"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (rotate:SI (match_operand:SI 1 "register_operand" "0")
+ (const_int 31)))]
+ ""
+ "bst %A0,0\;ror %D0\;ror %C0\;ror %B0\;ror %A0\;bld %D0,7"
+ [(set_attr "length" "6")
+ (set_attr "cc" "clobber")])
;; Overlapping non-HImode registers often (but not always) need a scratch.
;; The best we can do is use early clobber alternative "#&r" so that
@@ -2444,7 +2513,11 @@ (define_expand "rotl<mode>3"
;; allocation does not prefer non-overlapping.
-; Split word aligned rotates using scratch that is mode dependent.
+;; Split word aligned rotates using scratch that is mode dependent.
+
+;; "*rotwhi"
+;; "*rotwsi"
+;; "*rotwdi"
(define_insn_and_split "*rotw<mode>"
[(set (match_operand:HIDI 0 "register_operand" "=r,r,#&r")
(rotate:HIDI (match_operand:HIDI 1 "register_operand" "0,r,r")
@@ -2462,7 +2535,11 @@ (define_insn_and_split "*rotw<mode>"
})
-; Split byte aligned rotates using scratch that is always QI mode.
+;; Split byte aligned rotates using scratch that is always QI mode.
+
+;; "*rotbhi"
+;; "*rotbsi"
+;; "*rotbdi"
(define_insn_and_split "*rotb<mode>"
[(set (match_operand:HIDI 0 "register_operand" "=r,r,#&r")
(rotate:HIDI (match_operand:HIDI 1 "register_operand" "0,r,r")
Index: config/avr/constraints.md
===================================================================
--- config/avr/constraints.md (revision 179081)
+++ config/avr/constraints.md (working copy)
@@ -108,11 +108,31 @@ (define_memory_constraint "Q"
(and (match_code "mem")
(match_test "extra_constraint_Q (op)")))
+(define_constraint "C03"
+ "Constant integer 3."
+ (and (match_code "const_int")
+ (match_test "ival == 3")))
+
(define_constraint "C04"
"Constant integer 4."
(and (match_code "const_int")
(match_test "ival == 4")))
+(define_constraint "C05"
+ "Constant integer 5."
+ (and (match_code "const_int")
+ (match_test "ival == 5")))
+
+(define_constraint "C06"
+ "Constant integer 6."
+ (and (match_code "const_int")
+ (match_test "ival == 6")))
+
+(define_constraint "C07"
+ "Constant integer 7."
+ (and (match_code "const_int")
+ (match_test "ival == 7")))
+
(define_constraint "Ca2"
"Constant 2-byte integer that allows AND without clobber register."
(and (match_code "const_int")