From 5d94b9886327df3f4b977d4bc0d1d09c1b6d3220 Mon Sep 17 00:00:00 2001 From: Georg-Johann Lay Date: Fri, 23 Sep 2011 10:14:23 +0000 Subject: [PATCH] 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 --- gcc/ChangeLog | 11 ++++ gcc/config/avr/avr.md | 121 +++++++++++++++++++++++++++------- gcc/config/avr/constraints.md | 20 ++++++ 3 files changed, 130 insertions(+), 22 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 096dcabf112..5fcf03cfb82 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,14 @@ +2011-09-23 Georg-Johann Lay + + 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. + 2011-09-23 Bin Cheng * config/arm/bpabi.h (BE8_LINK_SPEC): Add cortex-m arch diff --git a/gcc/config/avr/avr.md b/gcc/config/avr/avr.md index ab17104453e..c7a28c74f0e 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 "rotl3" [(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 (mode); else operands[3] = gen_rtx_SCRATCH (QImode); } + else if (mode != DImode + && (offset == 1 + || offset == GET_MODE_BITSIZE (mode) -1)) + { + /*; Support rotate left/right by 1 */ + + emit_move_insn (operands[0], + gen_rtx_ROTATE (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" [(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" [(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 d6c172f86e2..f02c1978673 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")