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