diff mbox series

[to-be-committed,RISC-V] Generate bclr more often for rv64

Message ID a1e723ca-80f0-47d7-a9ae-32ea7da7854c@gmail.com
State New
Headers show
Series [to-be-committed,RISC-V] Generate bclr more often for rv64 | expand

Commit Message

Jeff Law June 10, 2024, 1:44 p.m. UTC
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 mbox series

Patch

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