From: Jeff Law Date: Mon, 17 Jun 2024 23:24:03 +0000 (-0600) Subject: [to-be-committed,RISC-V] Handle zero_extract destination for single bit insertions X-Git-Tag: basepoints/gcc-16~8167 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=67bc21af7ba35b773b5cf0e85107715f7c2240e4;p=thirdparty%2Fgcc.git [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 --git a/gcc/config/riscv/bitmanip.md b/gcc/config/riscv/bitmanip.md index 311f0d373c0..094bc2acf1c 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) + || operands[2] == CONST1_RTX (mode))" + { + return (operands[2] == CONST0_RTX (mode) + ? "bclr\t%0,%0,%1" + : "bset\t%0,%0,%1"); + } + [(set_attr "type" "bitmanip")]) + (define_insn "*bclr" [(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 00000000000..0239014e06b --- /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" } } */