RISC-V: bitmanip: add splitter to use bexti for "(a & (1 << BIT_NO)) ? 0 : -1"
authorPhilipp Tomsich <philipp.tomsich@vrull.eu>
Tue, 9 Nov 2021 17:54:54 +0000 (18:54 +0100)
committerPhilipp Tomsich <philipp.tomsich@vrull.eu>
Thu, 17 Nov 2022 15:20:56 +0000 (16:20 +0100)
commit1957bedf29a1b2cc231972aba680fe80199d5498
tree144a389ad8f20ad201f6de9932a2fd0392565fca
parent705bae2351a870dc3ff59db47fa0de6baaf829c8
RISC-V: bitmanip: add splitter to use bexti for "(a & (1 << BIT_NO)) ? 0 : -1"

Consider creating a polarity-reversed mask from a set-bit (i.e., if
the bit is set, produce all-ones; otherwise: all-zeros).  Using Zbb,
this can be expressed as bexti, followed by an addi of minus-one.  To
enable the combiner to discover this opportunity, we need to split the
canonical expression for "(a & (1 << BIT_NO)) ? 0 : -1" into a form
combinable into bexti.

Consider the function:
    long f(long a)
    {
      return (a & (1 << BIT_NO)) ? 0 : -1;
    }
This produces the following sequence prior to this change:
andi a0,a0,16
seqz a0,a0
neg a0,a0
ret
Following this change, it results in:
bexti a0,a0,4
addi a0,a0,-1
ret

gcc/ChangeLog:

* config/riscv/bitmanip.md: Add a splitter to generate
  polarity-reversed masks from a set bit using bexti + addi.

gcc/testsuite/ChangeLog:

* gcc.target/riscv/zbs-bexti.c: New test.
gcc/config/riscv/bitmanip.md
gcc/testsuite/gcc.target/riscv/zbs-bexti.c