gcc/riscv: Add a mechanism to remove some calls to _riscv_save_0
authorAndrew Burgess <andrew.burgess@embecosm.com>
Mon, 28 Oct 2019 16:26:19 +0000 (16:26 +0000)
committerAndrew Burgess <aburgess@gcc.gnu.org>
Mon, 28 Oct 2019 16:26:19 +0000 (16:26 +0000)
commite18a6d1441cfb5d43d3193a2643207fc3f95fd5a
tree317e4993f74123551321eccf1c21bdb9b15ab169
parent4b0ab0d9588f6c63f7102e70de52684cdda49de8
gcc/riscv: Add a mechanism to remove some calls to _riscv_save_0

When using the -msave-restore flag we end up with calls to
_riscv_save_0 and _riscv_restore_0.  These functions adjust the stack
and save or restore the return address.  Due to grouping multiple
save/restore stub functions together the save/restore 0 calls actually
save s0, s1, s2, and the return address, but only the return address
actually matters.  Leaf functions don't call the save/restore stubs,
so whenever we do see a call to the save/restore stubs, the store of
the return address is required.

If we look in gcc/config/riscv/riscv.c at the function
riscv_expand_prologue and riscv_expand_epilogue we can see that it
would be reasonably easy to adjust these functions to avoid the calls
to the save/restore stubs for those cases where we are about to call
_riscv_save_0 and _riscv_restore_0, however, the actual code size
saving this would give is debatable, with linker relaxation, the calls
to save/restore are often just 4-bytes, and can sometimes even be
2-bytes, while leaving the stack adjust and return address save inline
is always going to be 4-bytes.

The interesting case is when we call _riscv_save_0 and
_riscv_restore_0, and also have a frame that would (without
save/restore) have resulted in a tail call.  In this case if we could
remove the save/restore calls, and restore the tail call then we would
get a real size saving.

The problem is that the choice of generating a tail call or not is
done during the gimple expand pass, at which point we don't know how
many registers we need to save (or restore).

The solution presented in this patch offers a partial solution to this
problem.  By using the TARGET_MACHINE_DEPENDENT_REORG pass to
implement a very limited pattern matching we identify functions that
call _riscv_save_0 and _riscv_restore_0, and which could be converted
to make use of a tail call.  These functions are then converted to the
non save/restore tail call form.

This should result in a code size reduction when compiling with -Os
and with the -msave-restore flag.

gcc/ChangeLog:

        * config.gcc: Add riscv-sr.o to extra_objs for riscv.
        * config/riscv/riscv-sr.c: New file.
        * config/riscv/riscv.c (riscv_reorg): New function.
        (TARGET_MACHINE_DEPENDENT_REORG): Define.
        * config/riscv/riscv.h (SIBCALL_REG_P): Define.
        (riscv_remove_unneeded_save_restore_calls): Declare.
        * config/riscv/t-riscv (riscv-sr.o): New build rule.

gcc/testsuite/ChangeLog:

        * gcc.target/riscv/save-restore-2.c: New file.
        * gcc.target/riscv/save-restore-3.c: New file.
        * gcc.target/riscv/save-restore-4.c: New file.
        * gcc.target/riscv/save-restore-5.c: New file.
        * gcc.target/riscv/save-restore-6.c: New file.
        * gcc.target/riscv/save-restore-7.c: New file.
        * gcc.target/riscv/save-restore-8.c: New file.

From-SVN: r277527
14 files changed:
gcc/ChangeLog
gcc/config.gcc
gcc/config/riscv/riscv-sr.c [new file with mode: 0644]
gcc/config/riscv/riscv.c
gcc/config/riscv/riscv.h
gcc/config/riscv/t-riscv
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/riscv/save-restore-2.c [new file with mode: 0644]
gcc/testsuite/gcc.target/riscv/save-restore-3.c [new file with mode: 0644]
gcc/testsuite/gcc.target/riscv/save-restore-4.c [new file with mode: 0644]
gcc/testsuite/gcc.target/riscv/save-restore-5.c [new file with mode: 0644]
gcc/testsuite/gcc.target/riscv/save-restore-6.c [new file with mode: 0644]
gcc/testsuite/gcc.target/riscv/save-restore-7.c [new file with mode: 0644]
gcc/testsuite/gcc.target/riscv/save-restore-8.c [new file with mode: 0644]