diff options
author | Jeff Law <jlaw@ventanamicro.com> | 2024-06-17 17:24:03 -0600 |
---|---|---|
committer | Jeff Law <jlaw@ventanamicro.com> | 2024-06-17 17:28:30 -0600 |
commit | 67bc21af7ba35b773b5cf0e85107715f7c2240e4 (patch) | |
tree | db179839933abc0aa5e30bb29b4f879812a9c549 | |
parent | d78694c238ccb0b530afe3fe5a7afbe7cda8ad4b (diff) | |
download | gcc-67bc21af7ba35b773b5cf0e85107715f7c2240e4.zip gcc-67bc21af7ba35b773b5cf0e85107715f7c2240e4.tar.gz gcc-67bc21af7ba35b773b5cf0e85107715f7c2240e4.tar.bz2 |
[to-be-committed,RISC-V] Handle zero_extract destination for single bit insertions
Combine will use zero_extract destinations for certain bitfield
insertions. If the bitfield is a single bit constant, then we can use
bset/bclr.
In this case we are only dealing with word_mode objects, so we don't
have to worry about the SI->DI extension issues for TARGET_64BIT.
The testcase was derived from 502.gcc in spec from the RAU team.
An earlier version of this (TARGET_64BIT only) went through Ventana's CI
system. This version has gone though mine after generalizing it to
handle rv32 as well. I'll wait for pre-commit CI to render its verdict
before moving forward.
gcc/
* config/riscv/bitmanip.md (bsetclr_zero_extract): New pattern.
gcc/testsuite/
* gcc.target/riscv/zbs-zext-3.c: New test.
-rw-r--r-- | gcc/config/riscv/bitmanip.md | 17 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/riscv/zbs-zext-3.c | 27 |
2 files changed, 44 insertions, 0 deletions
diff --git a/gcc/config/riscv/bitmanip.md b/gcc/config/riscv/bitmanip.md index 311f0d3..094bc2a 100644 --- a/gcc/config/riscv/bitmanip.md +++ b/gcc/config/riscv/bitmanip.md @@ -654,6 +654,23 @@ (any_or:DI (ashift:DI (const_int 1) (match_dup 1)) (match_dup 3)))]) +;; Yet another form of a bset/bclr that can be created by combine. +(define_insn "*bsetclr_zero_extract" + [(set (zero_extract:X (match_operand:X 0 "register_operand" "+r") + (const_int 1) + (zero_extend:X + (match_operand:QI 1 "register_operand" "r"))) + (match_operand 2 "immediate_operand" "n"))] + "TARGET_ZBS + && (operands[2] == CONST0_RTX (<MODE>mode) + || operands[2] == CONST1_RTX (<MODE>mode))" + { + return (operands[2] == CONST0_RTX (<MODE>mode) + ? "bclr\t%0,%0,%1" + : "bset\t%0,%0,%1"); + } + [(set_attr "type" "bitmanip")]) + (define_insn "*bclr<mode>" [(set (match_operand:X 0 "register_operand" "=r") (and:X (rotate:X (const_int -2) diff --git a/gcc/testsuite/gcc.target/riscv/zbs-zext-3.c b/gcc/testsuite/gcc.target/riscv/zbs-zext-3.c new file mode 100644 index 0000000..0239014 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/zbs-zext-3.c @@ -0,0 +1,27 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv64gc_zba_zbb_zbs -mabi=lp64d" { target { rv64 } } } */ +/* { dg-options "-march=rv32gc_zba_zbb_zbs -mabi=ilp32" { target { rv32 } } } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" } } */ + +/* We need to adjust the constant so this works for rv32 and rv64. */ +#if __riscv_xlen == 32 +#define ONE 1U +#else +#define ONE 1ULL +#endif + +void add_to_hard_reg_set(long long *a, unsigned int count) { + int i = 0; + while(i++ < count) + *a |= (1U << i); +} + +void remove_from_hard_reg_set(long long *a, unsigned int count) { + int i = 0; + while(i++ < count) + *a &= ~(ONE << i); +} + + +/* { dg-final { scan-assembler-not "and\t" } } */ +/* { dg-final { scan-assembler-not "andn\t" } } */ |