https://gcc.gnu.org/g:13ea50fdac104b674eb484936023e20dec0b62cf

commit r15-6320-g13ea50fdac104b674eb484936023e20dec0b62cf
Author: Xi Ruoyao <xry...@xry111.site>
Date:   Mon Dec 2 10:53:27 2024 +0800

    LoongArch: Add bit reverse operations
    
    LoongArch supports native bit reverse operation for QI, SI, DI, and for
    HI we can expand it into a shift and a bit reverse in word_mode.
    
    I was reluctant to add them because until PR50481 is fixed these
    operations will be just useless.  But now it turns out we can use them
    to optimize the bit reversing CRC calculation if recognized by the
    generic CRC pass.  So add them in prepare for the next patch adding CRC
    expanders.
    
    gcc/ChangeLog:
    
            * config/loongarch/loongarch.md (@rbit<mode:GPR>): New
            define_insn template.
            (rbitsi_extended): New define_insn.
            (rbitqi): New define_insn.
            (rbithi): New define_expand.

Diff:
---
 gcc/config/loongarch/loongarch.md | 51 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 51 insertions(+)

diff --git a/gcc/config/loongarch/loongarch.md 
b/gcc/config/loongarch/loongarch.md
index bf322240271c..fe1678c5891b 100644
--- a/gcc/config/loongarch/loongarch.md
+++ b/gcc/config/loongarch/loongarch.md
@@ -4239,6 +4239,57 @@
   [(set_attr "type" "unknown")
    (set_attr "mode" "DI")])
 
+(define_insn "@rbit<mode>"
+  [(set (match_operand:GPR 0 "register_operand" "=r")
+       (bitreverse:GPR (match_operand:GPR 1 "register_operand" "r")))]
+  ""
+  "bitrev.<size>\t%0,%1"
+  [(set_attr "type" "unknown")
+   (set_attr "mode" "<MODE>")])
+
+(define_insn "rbitsi_extended"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+       (sign_extend:DI
+         (bitreverse:SI (match_operand:SI 1 "register_operand" "r"))))]
+  "TARGET_64BIT"
+  "bitrev.w\t%0,%1"
+  [(set_attr "type" "unknown")
+   (set_attr "mode" "SI")])
+
+;; If we don't care high bits, bitrev.4b can reverse bits of values in
+;; QImode.
+(define_insn "rbitqi"
+  [(set (match_operand:QI 0 "register_operand" "=r")
+       (bitreverse:QI (match_operand:QI 1 "register_operand" "r")))]
+  ""
+  "bitrev.4b\t%0,%1"
+  [(set_attr "type" "unknown")
+   (set_attr "mode" "SI")])
+
+;; For HImode it's a little complicated...
+(define_expand "rbithi"
+  [(match_operand:HI 0 "register_operand")
+   (match_operand:HI 1 "register_operand")]
+  ""
+  {
+    rtx t = gen_reg_rtx (word_mode);
+
+    /* Oh, using paradoxical subreg.  I learnt the trick from RISC-V,
+       hoping we won't be blown up altogether one day.  */
+    emit_insn (gen_rbit(word_mode, t,
+                       gen_lowpart (word_mode, operands[1])));
+    t = expand_simple_binop (word_mode, LSHIFTRT, t,
+                            GEN_INT (GET_MODE_BITSIZE (word_mode) - 16),
+                            NULL_RTX, false, OPTAB_DIRECT);
+
+    t = gen_lowpart (HImode, t);
+    SUBREG_PROMOTED_VAR_P (t) = 1;
+    SUBREG_PROMOTED_SET (t, SRP_UNSIGNED);
+    emit_move_insn (operands[0], t);
+
+    DONE;
+  })
+
 (define_insn "@stack_tie<mode>"
   [(set (mem:BLK (scratch))
        (unspec:BLK [(match_operand:X 0 "register_operand" "r")

Reply via email to