This patch adds insns for 16-bit and 32-bit __builtin_bitreverse.
With the patch, the generated code has a better size / speed ratio.

The patch uses hard-reg constraints, which is possible since the
code generation doesn't rely on insn combine.

Passes without new regressions. Ok for trunk?

Johann

--

AVR: Add insns and libgcc functions for __builtin_bitreverse16/32.

gcc/
        * config/avr/avr.md (bitreversehi2, bitreversesi2): New insn_and_split.
        (*bitreversehi2.libgcc, *bitreversesi2.libgcc): New insns.
libgcc/
        * config/avr/t-avr (LIB1ASMFUNCS): Add _bitreverse8, _bitreverse16,
        _bitreverse24, _bitreverse32.
        * config/avr/lib1funcs.S (__bitreverse8, __bitreverse16)
        (__bitreverse24, __bitreverse32): New functions.
diff --git a/gcc/config/avr/avr.md b/gcc/config/avr/avr.md
index 17b614a6d70..7d5c70b961d 100644
--- a/gcc/config/avr/avr.md
+++ b/gcc/config/avr/avr.md
@@ -9036,6 +9036,44 @@ (define_insn_and_split "*popcountqihi2.libgcc"
    (set (reg:QI 25)
         (const_int 0))])
 
+
+;; Bit Reverse
+
+(define_insn_and_split "bitreversehi2"
+  [(set (match_operand:HI 0 "register_operand"               "={r24}")
+        (bitreverse:HI (match_operand:HI 1 "register_operand" "{r24}")))]
+  ""
+  "#"
+  "&& reload_completed"
+  [(scratch)]
+  { DONE_ADD_CCC })
+
+(define_insn "*bitreversehi2.libgcc"
+  [(set (reg:HI 24)
+        (bitreverse:HI (reg:HI 24)))
+   (clobber (reg:CC REG_CC))]
+  "reload_completed"
+  "%~call __bitreverse16"
+  [(set_attr "type" "xcall")])
+
+(define_insn_and_split "bitreversesi2"
+  [(set (match_operand:SI 0 "register_operand"               "={r22}")
+        (bitreverse:SI (match_operand:SI 1 "register_operand" "{r22}")))]
+  ""
+  "#"
+  "&& reload_completed"
+  [(scratch)]
+  { DONE_ADD_CCC })
+
+(define_insn "*bitreversesi2.libgcc"
+  [(set (reg:SI 22)
+        (bitreverse:SI (reg:SI 22)))
+   (clobber (reg:CC REG_CC))]
+  "reload_completed"
+  "%~call __bitreverse32"
+  [(set_attr "type" "xcall")])
+
+
 ;; Count Leading Zeros
 
 (define_expand "clzhi2"
diff --git a/libgcc/config/avr/lib1funcs.S b/libgcc/config/avr/lib1funcs.S
index 1cb2decbb51..93071da8b1a 100644
--- a/libgcc/config/avr/lib1funcs.S
+++ b/libgcc/config/avr/lib1funcs.S
@@ -3205,6 +3205,64 @@ DEFUN __bswapdi2
 ENDF __bswapdi2
 #endif /* defined (L_bswapdi2) */
 
+
+/*****************************************
+ * Reverse bitorder (__builtin_bitreverse)
+ ****************************************/
+
+#if defined (L_bitreverse8)
+DEFUN __bitreverse8
+    ;; 76543210
+    lsl r24
+    adc r24, __zero_reg__
+    ;; ...3...7
+    mov __tmp_reg__, r24
+    bst __tmp_reg__, 1 $ bld r24, 7
+    ;; 0..3...7
+    bst __tmp_reg__, 2 $ bld r24, 6
+    ;; 01.3...7
+    bst __tmp_reg__, 3 $ bld r24, 5
+    ;; 0123...7
+    bst __tmp_reg__, 5 $ bld r24, 3
+    ;; 01234..7
+    bst __tmp_reg__, 6 $ bld r24, 2
+    ;; 012345.7
+    bst __tmp_reg__, 7 $ bld r24, 1
+    ;; 01234567
+    ret
+ENDF __bitreverse8
+#endif /* L_bitreverse8 */
+
+#if defined (L_bitreverse16)
+DEFUN __bitreverse16
+    XCALL __bitreverse8
+    bswap   r24, r25
+    XJMP __bitreverse8
+ENDF __bitreverse16
+#endif /* L_bitreverse16 */
+
+#if defined (L_bitreverse24)
+DEFUN __bitreverse24
+    XCALL __bitreverse8
+    push    r24
+    mov     r24, r23
+    XCALL __bitreverse8
+    mov     r23, r24
+    mov     r24, r22
+    pop     r22
+    XJMP __bitreverse8
+ENDF __bitreverse24
+#endif /* L_bitreverse24 */
+
+#if defined (L_bitreverse32)
+DEFUN __bitreverse32
+    XCALL __bitreverse16
+    bswap   r22, r24
+    bswap   r23, r25
+    XJMP __bitreverse16
+ENDF __bitreverse32
+#endif /* L_bitreverse32 */
+
 
 /**********************************
  * 64-bit shifts
diff --git a/libgcc/config/avr/t-avr b/libgcc/config/avr/t-avr
index d181784e0e7..9b05c8575b6 100644
--- a/libgcc/config/avr/t-avr
+++ b/libgcc/config/avr/t-avr
@@ -34,6 +34,7 @@ LIB1ASMFUNCS = \
 	_popcountsi2 \
 	_popcountqi2 \
 	_bswapsi2 \
+	_bitreverse8 _bitreverse16 _bitreverse24 _bitreverse32 \
 	_fmul _fmuls _fmulsu \
 	_mulqq3 \
 	_mulhq3 _muluhq3 \

Reply via email to