This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[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")

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]