https://gcc.gnu.org/g:67bc21af7ba35b773b5cf0e85107715f7c2240e4
commit r15-1386-g67bc21af7ba35b773b5cf0e85107715f7c2240e4 Author: Jeff Law <j...@ventanamicro.com> Date: Mon Jun 17 17:24:03 2024 -0600 [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. Diff: --- gcc/config/riscv/bitmanip.md | 17 +++++++++++++++++ gcc/testsuite/gcc.target/riscv/zbs-zext-3.c | 27 +++++++++++++++++++++++++++ 2 files changed, 44 insertions(+) diff --git a/gcc/config/riscv/bitmanip.md b/gcc/config/riscv/bitmanip.md index 311f0d373c00..094bc2acf1c7 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 000000000000..0239014e06bf --- /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" } } */