riscv: Add support for strlen inline expansion
commitdf48285b2484eb4f8e0570c566677114eb0e553a
authorChristoph Müllner <christoph.muellner@vrull.eu>
Wed, 28 Sep 2022 09:19:06 +0000 (28 11:19 +0200)
committerPhilipp Tomsich <philipp.tomsich@vrull.eu>
Tue, 12 Sep 2023 09:36:16 +0000 (12 11:36 +0200)
tree18c042643132e1cc1774217eaf062698256ce20d
parentfb5d27be272b71fb9026224535fc73f125ce3be7
riscv: Add support for strlen inline expansion

This patch implements the expansion of the strlen builtin for RV32/RV64
for xlen-aligned aligned strings if Zbb or XTheadBb instructions are available.
The inserted sequences are:

rv32gc_zbb (RV64 is similar):
      add     a3,a0,4
      li      a4,-1
.L1:  lw      a5,0(a0)
      add     a0,a0,4
      orc.b   a5,a5
      beq     a5,a4,.L1
      not     a5,a5
      ctz     a5,a5
      srl     a5,a5,0x3
      add     a0,a0,a5
      sub     a0,a0,a3

rv64gc_xtheadbb (RV32 is similar):
      add       a4,a0,8
.L2:  ld        a5,0(a0)
      add       a0,a0,8
      th.tstnbz a5,a5
      beqz      a5,.L2
      th.rev    a5,a5
      th.ff1    a5,a5
      srl       a5,a5,0x3
      add       a0,a0,a5
      sub       a0,a0,a4

This allows to inline calls to strlen(), with optimized code for
xlen-aligned strings, resulting in the following benefits over
a call to libc:
* no call/ret instructions
* no stack frame allocation
* no register saving/restoring
* no alignment test

The inlining mechanism is gated by a new switch ('-minline-strlen')
and by the variable 'optimize_size'.

Tested using the glibc string tests.

Signed-off-by: Christoph Müllner <christoph.muellner@vrull.eu>
gcc/ChangeLog:

* config.gcc: Add new object riscv-string.o.
riscv-string.cc.
* config/riscv/riscv-protos.h (riscv_expand_strlen):
New function.
* config/riscv/riscv.md (strlen<mode>): New expand INSN.
* config/riscv/riscv.opt: New flag 'minline-strlen'.
* config/riscv/t-riscv: Add new object riscv-string.o.
* config/riscv/thead.md (th_rev<mode>2): Export INSN name.
(th_rev<mode>2): Likewise.
(th_tstnbz<mode>2): New INSN.
* doc/invoke.texi: Document '-minline-strlen'.
* emit-rtl.cc (emit_likely_jump_insn): New helper function.
(emit_unlikely_jump_insn): Likewise.
* rtl.h (emit_likely_jump_insn): New prototype.
(emit_unlikely_jump_insn): Likewise.
* config/riscv/riscv-string.cc: New file.

gcc/testsuite/ChangeLog:

* gcc.target/riscv/xtheadbb-strlen-unaligned.c: New test.
* gcc.target/riscv/xtheadbb-strlen.c: New test.
* gcc.target/riscv/zbb-strlen-disabled-2.c: New test.
* gcc.target/riscv/zbb-strlen-disabled.c: New test.
* gcc.target/riscv/zbb-strlen-unaligned.c: New test.
* gcc.target/riscv/zbb-strlen.c: New test.
16 files changed:
gcc/config.gcc
gcc/config/riscv/riscv-protos.h
gcc/config/riscv/riscv-string.cc [new file with mode: 0644]
gcc/config/riscv/riscv.md
gcc/config/riscv/riscv.opt
gcc/config/riscv/t-riscv
gcc/config/riscv/thead.md
gcc/doc/invoke.texi
gcc/emit-rtl.cc
gcc/rtl.h
gcc/testsuite/gcc.target/riscv/xtheadbb-strlen-unaligned.c [new file with mode: 0644]
gcc/testsuite/gcc.target/riscv/xtheadbb-strlen.c [new file with mode: 0644]
gcc/testsuite/gcc.target/riscv/zbb-strlen-disabled-2.c [new file with mode: 0644]
gcc/testsuite/gcc.target/riscv/zbb-strlen-disabled.c [new file with mode: 0644]
gcc/testsuite/gcc.target/riscv/zbb-strlen-unaligned.c [new file with mode: 0644]
gcc/testsuite/gcc.target/riscv/zbb-strlen.c [new file with mode: 0644]