gcc/ * config/riscv/bitmanip.md (bextseqzdisi): New patterns. gcc/testsuite/ * gcc.target/riscv/zbs-bext-2.c: New test. * gcc.target/riscv/zbs-bext.c: Fix one of the possible expectes sequences. 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 "*bextseqz" + [(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..79f120b2286 --- /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" "-Og" } } */ + + +_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" 2 } } */ +/* { dg-final { scan-assembler-times "seqz\t|xori\t" 2 } } */ +/* { dg-final { scan-assembler-not "sraw\t" } } */ +/* { dg-final { scan-assembler-not "not\t" } } */ +/* { dg-final { scan-assembler-not "andi\t" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/zbs-bext.c b/gcc/testsuite/gcc.target/riscv/zbs-bext.c index ff75dad6528..0db97f5ab59 100644 --- a/gcc/testsuite/gcc.target/riscv/zbs-bext.c +++ b/gcc/testsuite/gcc.target/riscv/zbs-bext.c @@ -38,7 +38,7 @@ long bext64_4(long a, char bitno) /* { dg-final { scan-assembler-times "bexti\t" 1 } } */ /* { dg-final { scan-assembler-times "bext\t" 5 } } */ -/* { dg-final { scan-assembler-times "xori\t|snez\t" 1 } } */ +/* { dg-final { scan-assembler-times "xori\t|seqz\t" 1 } } */ /* { dg-final { scan-assembler-times "addi\t" 1 } } */ /* { dg-final { scan-assembler-times "neg\t" 1 } } */ /* { dg-final { scan-assembler-not {\mandi} } } */