https://gcc.gnu.org/g:bd78d15abf96a90bb4e2a2f3b2cc6dc638c5ed4b

commit bd78d15abf96a90bb4e2a2f3b2cc6dc638c5ed4b
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.
    
    (cherry picked from commit 67bc21af7ba35b773b5cf0e85107715f7c2240e4)

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 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>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 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" } } */

Reply via email to