Another of Raphael's patches to improve our ability to safely generate a Zbs instruction, bclr in this instance.

In this case we have something like ~(1 << N) & C where N is variable, but C is a constant. If C has 33 or more leading zeros, then no matter what bit we clear via bclr, the result will always have at least bits 31..63 clear. So we don't have to worry about any of the extension issues with SI objects in rv64.

Odds are this was seen in spec at some point by the RAU team, thus leading to Raphael's pattern.

Anyway, this has been through Ventana's CI system in the past. I'll wait for it to work through upstream pre-commit CI before taking further action, but the plan is to commit after successful CI run.

Jeff



gcc/

        * config/riscv/bitmanip.md ((~1 << N) & C): New splitter.

gcc/testsuite/

        * gcc.target/riscv/zbs-ext.c: New test.


diff --git a/gcc/config/riscv/bitmanip.md b/gcc/config/riscv/bitmanip.md
index 6559d4d6950..4361be1c265 100644
--- a/gcc/config/riscv/bitmanip.md
+++ b/gcc/config/riscv/bitmanip.md
@@ -784,6 +784,23 @@ (define_insn_and_split "*bclridisi_nottwobits"
 }
 [(set_attr "type" "bitmanip")])
 
+;; An outer AND with a constant where bits 31..63 are 0 can be seen as
+;; a virtual zero extension from 31 to 64 bits.
+(define_split
+  [(set (match_operand:DI 0 "register_operand")
+    (and:DI (not:DI (subreg:DI
+                     (ashift:SI (const_int 1)
+                                (match_operand:QI 1 "register_operand")) 0))
+            (match_operand:DI 2 "arith_operand")))
+   (clobber (match_operand:DI 3 "register_operand"))]
+  "TARGET_64BIT && TARGET_ZBS
+   && clz_hwi (INTVAL (operands[2])) >= 33"
+  [(set (match_dup 3)
+        (match_dup 2))
+   (set (match_dup 0)
+         (and:DI (rotate:DI (const_int -2) (match_dup 1))
+                 (match_dup 3)))])
+
 (define_insn "*binv<mode>"
   [(set (match_operand:X 0 "register_operand" "=r")
        (xor:X (ashift:X (const_int 1)
diff --git a/gcc/testsuite/gcc.target/riscv/zbs-ext.c 
b/gcc/testsuite/gcc.target/riscv/zbs-ext.c
new file mode 100644
index 00000000000..65f42545b5f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/zbs-ext.c
@@ -0,0 +1,15 @@
+/* { 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 bclr (const uint32_t i)
+{
+  uint64_t checks = 10;
+  checks &= ~(1U << i);
+  return checks;
+}
+
+/* { dg-final { scan-assembler-times "bclr\t" 1 } } */
+/* { dg-final { scan-assembler-not "sllw\t"} } */

Reply via email to