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 \