aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorXi Ruoyao <xry111@xry111.site>2024-12-02 10:53:27 +0800
committerXi Ruoyao <xry111@xry111.site>2024-12-18 16:43:37 +0800
commit13ea50fdac104b674eb484936023e20dec0b62cf (patch)
treed858e8f6045c6d5fb686e31cc3c34926f5a86048 /gcc
parent8e47615f24b9fdebf14e270e6131cea6a67f1b04 (diff)
downloadgcc-13ea50fdac104b674eb484936023e20dec0b62cf.zip
gcc-13ea50fdac104b674eb484936023e20dec0b62cf.tar.gz
gcc-13ea50fdac104b674eb484936023e20dec0b62cf.tar.bz2
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.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/config/loongarch/loongarch.md51
1 files changed, 51 insertions, 0 deletions
diff --git a/gcc/config/loongarch/loongarch.md b/gcc/config/loongarch/loongarch.md
index bf32224..fe1678c 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")