* config/riscv/riscv.cc (riscv_build_integer_1): Recognize cases where we can use shNadd to improve constant synthesis. (riscv_move_integer): Handle code generation for shNadd. gcc/testsuite * gcc.target/riscv/synthesis-1.c: Also count shNadd instructions. * gcc.target/riscv/synthesis-3.c: New test. diff --git a/gcc/config/riscv/bitmanip.md b/gcc/config/riscv/bitmanip.md index d76a72d30e0..cf2fa04d4c4 100644 --- a/gcc/config/riscv/bitmanip.md +++ b/gcc/config/riscv/bitmanip.md @@ -711,6 +711,30 @@ (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) (and:DI (subreg:DI + (lshiftrt:SI (match_dup 1) + (match_dup 2)) 0) + (const_int 1))) + (set (match_dup 0) (eq:DI (match_dup 0) (const_int 0)))] + "" + [(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..53f47dc3afe --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/zbs-bext-2.c @@ -0,0 +1,15 @@ +/* { 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); +} + + +/* { 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" } } */