diff options
author | Georg-Johann Lay <avr@gjlay.de> | 2011-09-23 10:14:23 +0000 |
---|---|---|
committer | Georg-Johann Lay <gjl@gcc.gnu.org> | 2011-09-23 10:14:23 +0000 |
commit | 5d94b9886327df3f4b977d4bc0d1d09c1b6d3220 (patch) | |
tree | f91cb94b7c6d3afa66fa6743fe352b3a8b63d84e /gcc/config/avr | |
parent | 9acebb8a99e519c40f0f3fb419c9adbb1c2c8209 (diff) | |
download | gcc-5d94b9886327df3f4b977d4bc0d1d09c1b6d3220.zip gcc-5d94b9886327df3f4b977d4bc0d1d09c1b6d3220.tar.gz gcc-5d94b9886327df3f4b977d4bc0d1d09c1b6d3220.tar.bz2 |
re PR target/50446 ([avr] Implement rotate patterns with offset 1)
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.
From-SVN: r179116
Diffstat (limited to 'gcc/config/avr')
-rw-r--r-- | gcc/config/avr/avr.md | 121 | ||||
-rw-r--r-- | gcc/config/avr/constraints.md | 20 |
2 files changed, 119 insertions, 22 deletions
diff --git a/gcc/config/avr/avr.md b/gcc/config/avr/avr.md index ab17104..c7a28c7 100644 --- a/gcc/config/avr/avr.md +++ b/gcc/config/avr/avr.md @@ -2390,23 +2390,38 @@ (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; -}") + { + if (!CONST_INT_P (operands[2])) + 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)))] + 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")))] "" - "swap %0" - [(set_attr "length" "1") - (set_attr "cc" "none")]) + "@ + 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_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 @@ ;; 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 @@ }) -; 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") diff --git a/gcc/config/avr/constraints.md b/gcc/config/avr/constraints.md index d6c172f..f02c197 100644 --- a/gcc/config/avr/constraints.md +++ b/gcc/config/avr/constraints.md @@ -108,11 +108,31 @@ (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") |