https://gcc.gnu.org/g:13a6b20e991ece33f4f016780549bb16a5a00796

commit 13a6b20e991ece33f4f016780549bb16a5a00796
Author: Jeff Law <j...@ventanamicro.com>
Date:   Sun Jun 16 08:36:27 2024 -0600

    [to-be-committed] [RISC-V] Improve (1 << N) | C for rv64
    
    Another improvement for generating Zbs instructions.
    
    In this case we're looking at stuff like (1 << N) | C where N varies and C 
is a
    single bit constant.
    
    In this pattern the (1 << N) happens in SImode, but is zero extended out to
    DImode before the bit manipulation.  The fact that we're modifying a DImode
    object in the logical op is important as it means we don't have to worry 
about
    whether or not the resulting value is sign extended from SI to DI.
    
    This has run through Ventana's CI system.  I'll wait for it to roll through
    pre-commit CI before moving forward.
    
    gcc/
            * config/riscv/bitmanip.md ((1 << N) | C): New splitter for IOR/XOR
            of a single bit an a DImode object.
    
    gcc/testsuite/
    
            * gcc.target/riscv/zbs-zext.c: New test.
    
    (cherry picked from commit 59dfce6d618ccf5865dec216603dbc25a4f7bf2d)

Diff:
---
 gcc/config/riscv/bitmanip.md              | 15 +++++++++++++++
 gcc/testsuite/gcc.target/riscv/zbs-zext.c | 31 +++++++++++++++++++++++++++++++
 2 files changed, 46 insertions(+)

diff --git a/gcc/config/riscv/bitmanip.md b/gcc/config/riscv/bitmanip.md
index 4ee413c143e..0d35fb786e1 100644
--- a/gcc/config/riscv/bitmanip.md
+++ b/gcc/config/riscv/bitmanip.md
@@ -627,6 +627,21 @@
   "bseti\t%0,%1,%S2"
   [(set_attr "type" "bitmanip")])
 
+;; We can easily handle zero extensions
+(define_split
+  [(set (match_operand:DI 0 "register_operand")
+    (any_or:DI (zero_extend:DI
+                (ashift:SI (const_int 1)
+                           (match_operand:QI 1 "register_operand")))
+              (match_operand:DI 2 "single_bit_mask_operand")))
+   (clobber (match_operand:DI 3 "register_operand"))]
+  "TARGET_64BIT && TARGET_ZBS"
+  [(set (match_dup 3)
+        (match_dup 2))
+   (set (match_dup 0)
+     (any_or:DI (ashift:DI (const_int 1) (match_dup 1))
+               (match_dup 3)))])
+
 (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.c 
b/gcc/testsuite/gcc.target/riscv/zbs-zext.c
new file mode 100644
index 00000000000..5773b15d298
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/zbs-zext.c
@@ -0,0 +1,31 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gc_zbs -mabi=lp64" } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-O1" } } */
+typedef unsigned long uint64_t;
+typedef unsigned int uint32_t;
+
+uint64_t bset (const uint32_t i)
+{
+  uint64_t checks = 8;
+  checks |= 1U << i;
+  return checks;
+}
+
+uint64_t binv (const uint32_t i)
+{
+  uint64_t checks = 8;
+  checks ^= 1U << i;
+  return checks;
+}
+
+uint64_t bclr (const uint32_t i)
+{
+  uint64_t checks = 10;
+  checks &= ~(1U << i);
+  return checks;
+}
+
+/* { dg-final { scan-assembler-times "bset\t" 1 } } */
+/* { dg-final { scan-assembler-times "binv\t" 1 } } */
+/* { dg-final { scan-assembler-times "bclr\t" 1 } } */
+/* { dg-final { scan-assembler-not "sllw\t"} } */

Reply via email to