[RISC-V][PR 127813] Add more czero patterns/splitters for RISC-V

So the first new pattern here is very straightforward.  It's essentially the
same pattern the VRULL guys did initially and I suggested they move towards the
if-then-else form.  This bug clearly shows that pattern useful.

The two other patterns are more interesting.

We'd really like to match the (and (neg (reg1)) (reg2)) when reg1 has a 0/1
value as a czero, similarly for the inverse which uses (plus (reg1) (const_int
-1)).   My first implementation checked nonzero_bits and matched that form
directly generating the czero.  Review via an LLM flagged that problem.

For this testcase (and I think reasonably generally) we'll often see these
wrapped by an IOR as part of a more general conditional move sequence
constructed from logicals with the IOR doing final selection.  So that's a 3->2
split that we can recognize in combine (using nonzero_bits), then immediately
rewrite into a form that doesn't require that test.  It's not ideal, but should
be enough to capture the most common cases.

Tested on riscv32-elf and riscv64-elf and bootstrapped and regression tested on
the k3.  c920 is being flaky so that'll have to spin overnight.  k1 is queued
and will pick this up on its next run which starts in an hour or two.

Anyway, pushing this to the trunk.  I'll keep the BZ open as Andrea wants to
tackle some stuff up in match.pd in a generic way.

	PR tree-optimization/127813
gcc/
	* config/riscv/zicond.md: Add new define_insn for czero expressed via
	logical ops.  Add define_splits when related patterns are used by an
	IOR to select across two values.

gcc/testsuite
	* gcc.target/riscv/pr127813.c: New test.
diff --git a/gcc/config/riscv/zicond.md b/gcc/config/riscv/zicond.md
index 99a8a4a..272bee5 100644
--- a/gcc/config/riscv/zicond.md
+++ b/gcc/config/riscv/zicond.md
@@ -490,3 +490,48 @@
 {
   operands[4] = gen_reg_rtx (<X:MODE>mode);
 })
+
+(define_insn ""
+  [(set (match_operand:X 0 "register_operand" "=r")
+	(and:X (neg:X (eq_or_ne (match_operand:X 1 "register_operand" "r")
+				(const_int 0)))
+	       (match_operand:X 2 "register_operand" "r")))]
+  "TARGET_ZICOND"
+  "czero.<eqz>\t%0,%2,%1"
+  [(set_attr "type" "zicond")])
+
+;; This is not ideal.  The (and ...) subexpression is just a czero, but
+;; we can't match it without knowing the register we're testing has a 0/1
+;; value, which we can't test in an insn condition.  We really want to
+;; match and rewrite the RTL form within combine.  We could do that with
+;; simplify-rtx.cc, but that's likely to not be generically a good thing.
+;;
+;; That low level primitive is often going to flow into an IOR which
+;; gives us the opportunity to do a 3->2 split, so we can rewrite
+;; immediately in combine and avoid testing pass specific state in an
+;; insn condition that lives beyond that single pass
+(define_split
+  [(set (match_operand:X 0 "register_operand")
+	(ior:X (and:X (neg:X (match_operand:X 1 "register_operand"))
+		      (match_operand:X 2 "register_operand"))
+	       (match_operand:X 3 "register_operand")))
+   (clobber (match_operand:X 4 "register_operand"))]
+  "TARGET_ZICOND && nonzero_bits (operands[1], word_mode) == 1"
+  [(set (match_dup 4) (if_then_else:X (ne:X (match_dup 1) (const_int 0))
+				      (match_dup 2)
+				      (const_int 0)))
+   (set (match_dup 0) (ior:X (match_dup 4) (match_dup 3)))])
+
+(define_split
+  [(set (match_operand:X 0 "register_operand")
+	(ior:X (and:X (plus:X (match_operand:X 1 "register_operand")
+			      (const_int -1))
+		      (match_operand:X 2 "register_operand"))
+	       (match_operand:X 3 "register_operand")))
+   (clobber (match_operand:X 4 "register_operand"))]
+  "TARGET_ZICOND && nonzero_bits (operands[1], word_mode) == 1"
+  [(set (match_dup 4) (if_then_else:X (eq:X (match_dup 1) (const_int 0))
+				      (match_dup 2)
+				      (const_int 0)))
+   (set (match_dup 0) (ior:X (match_dup 4) (match_dup 3)))])
+
diff --git a/gcc/testsuite/gcc.target/riscv/pr127813.c b/gcc/testsuite/gcc.target/riscv/pr127813.c
new file mode 100644
index 0000000..d9578ee
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/pr127813.c
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=rv64gcb_zicond -mabi=lp64d" { target { rv64 } } } */
+/* { dg-options "-O2 -march=rv32gcb_zicond -mabi=ilp32d" { target { rv32 } } } */
+
+typedef unsigned int uint32_t;
+uint32_t ct_select(uint32_t bit, uint32_t a, uint32_t b) {
+    uint32_t mask = -(bit & 1);
+    return (a & mask) | (b & ~mask);
+}
+
+/* { dg-final { scan-assembler-times {\mczero} 2 } } */
+
+