@@ -654,6 +654,18 @@ (define_split
(any_or:DI (ashift:DI (const_int 1) (match_dup 1))
(match_dup 3)))])
+;; Yet another form of a bset/bclr that can be created by combine.
+(define_insn "*bsetclr_zero_extract"
+ [(set (zero_extract:X (match_operand:X 0 "register_operand" "+r")
+ (const_int 1)
+ (zero_extend:X (match_operand:QI 1 "register_operand" "r")))
+ (match_operand 2 "immediate_operand" "n"))]
+ "TARGET_ZBS
+ && (operands[2] == CONST0_RTX (<MODE>mode)
+ || operands[2] == CONST1_RTX (<MODE>mode))"
+ { return operands[2] == CONST0_RTX (<MODE>mode) ? "bclr\t%0,%0,%1" : "bset\t%0,%0,%1"; }
+ [(set_attr "type" "bitmanip")])
+
(define_insn "*bclr<mode>"
[(set (match_operand:X 0 "register_operand" "=r")
(and:X (rotate:X (const_int -2)
new file mode 100644
@@ -0,0 +1,27 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gc_zba_zbb_zbs -mabi=lp64d" { target { rv64 } } } */
+/* { dg-options "-march=rv32gc_zba_zbb_zbs -mabi=ilp32" { target { rv32 } } } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" } } */
+
+/* We need to adjust the constant so this works for rv32 and rv64. */
+#if __riscv_xlen == 32
+#define ONE 1U
+#else
+#define ONE 1ULL
+#endif
+
+void add_to_hard_reg_set(long long *a, unsigned int count) {
+ int i = 0;
+ while(i++ < count)
+ *a |= (1U << i);
+}
+
+void remove_from_hard_reg_set(long long *a, unsigned int count) {
+ int i = 0;
+ while(i++ < count)
+ *a &= ~(ONE << i);
+}
+
+
+/* { dg-final { scan-assembler-not "and\t" } } */
+/* { dg-final { scan-assembler-not "andn\t" } } */