So the first version failed CI and after looking at the patch again, I think it can be improved.

First, the output pattern might as well go ahead and use the zero_extract form.

Second, we should be able to handle cases where all the ops are in word_mode as well as when the shift is in a narrow made.

Third, the testcase should cover additional modes.

Fourth, fix some lint issues with tabs vs spaces.

This has only been lightly tested, so it should be interesting to see what CI shows.

Jeff
diff --git a/gcc/config/riscv/bitmanip.md b/gcc/config/riscv/bitmanip.md
index d76a72d30e0..724511b6df3 100644
--- a/gcc/config/riscv/bitmanip.md
+++ b/gcc/config/riscv/bitmanip.md
@@ -711,6 +711,49 @@ (define_insn "*bext<mode>"
   "bext\t%0,%1,%2"
   [(set_attr "type" "bitmanip")])
 
+;; This is a bext followed by a seqz.  Normally this would be a 3->2 split
+;; But the and-not pattern with a constant operand is a define_insn_and_split,
+;; so this looks like a 2->2 split, which combine rejects.  So implement it
+;; as a define_insn_and_split as well.
+(define_insn_and_split "*bextseqzdisi"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+       (and:DI
+         (not:DI
+           (subreg:DI
+             (lshiftrt:SI
+               (match_operand:SI 1 "register_operand" "r")
+               (match_operand:QI 2 "register_operand" "r")) 0))
+         (const_int 1)))]
+  "TARGET_64BIT && TARGET_ZBS"
+  "#"
+  "&& 1"
+  [(set (match_dup 0)
+       (zero_extract:DI (match_dup 1)
+                        (const_int 1)
+                        (zero_extend:DI (match_dup 2))))
+   (set (match_dup 0) (eq:DI (match_dup 0) (const_int 0)))]
+  "operands[1] = gen_lowpart (word_mode, operands[1]);"
+  [(set_attr "type" "bitmanip")])
+
+(define_insn_and_split "*bextseqzdisi"
+  [(set (match_operand:X 0 "register_operand" "=r")
+       (and:X
+         (not:X
+           (lshiftrt:X
+             (match_operand:X 1 "register_operand" "r")
+             (match_operand:QI 2 "register_operand" "r")))
+         (const_int 1)))]
+  "TARGET_ZBS"
+  "#"
+  "&& 1"
+  [(set (match_dup 0)
+       (zero_extract:X (match_dup 1)
+                       (const_int 1)
+                       (zero_extend:X (match_dup 2))))
+   (set (match_dup 0) (eq:X (match_dup 0) (const_int 0)))]
+  "operands[1] = gen_lowpart (word_mode, operands[1]);"
+  [(set_attr "type" "bitmanip")])
+
 ;; When performing `(a & (1UL << bitno)) ? 0 : -1` the combiner
 ;; usually has the `bitno` typed as X-mode (i.e. no further
 ;; zero-extension is performed around the bitno).
diff --git a/gcc/testsuite/gcc.target/riscv/zbs-bext-2.c 
b/gcc/testsuite/gcc.target/riscv/zbs-bext-2.c
new file mode 100644
index 00000000000..719df442fed
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/zbs-bext-2.c
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gc_zbs -mabi=lp64" } */
+/* { dg-skip-if "" { *-*-* } { "-O0" } } */
+
+
+_Bool match(const int ch, int fMap) {
+    return ((fMap & (1<<(ch))) == 0);
+}
+
+_Bool match2(const int ch, int fMap) {
+    return ((fMap & (1UL<<(ch))) == 0);
+}
+
+
+/* { dg-final { scan-assembler-times "bext\t" 1 } } */
+/* { dg-final { scan-assembler-times "seqz\t" 1 } } */
+/* { dg-final { scan-assembler-not "sraw\t" } } */
+/* { dg-final { scan-assembler-not "not\t" } } */
+/* { dg-final { scan-assembler-not "andi\t" } } */

Reply via email to