]> git.ipfire.org Git - thirdparty/gcc.git/commit
LoongArch: Improve GAR store for va_list
authorXi Ruoyao <xry111@xry111.site>
Tue, 28 Mar 2023 17:36:09 +0000 (01:36 +0800)
committerXi Ruoyao <xry111@xry111.site>
Wed, 19 Apr 2023 09:59:23 +0000 (17:59 +0800)
commit81c6501445fcddad653363f815cd04ca6fdb488e
treeb648838c4314254e63e6786ea26b5115146177dd
parent01e79e21bbb2d10ecac784d383cefb88d2e20692
LoongArch: Improve GAR store for va_list

LoongArch backend used to save all GARs for a function with variable
arguments.  But sometimes a function only accepts variable arguments for
a purpose like C++ function overloading.  For example, POSIX defines
open() as:

    int open(const char *path, int oflag, ...);

But only two forms are actually used:

    int open(const char *pathname, int flags);
    int open(const char *pathname, int flags, mode_t mode);

So it's obviously a waste to save all 8 GARs in open().  We can use the
cfun->va_list_gpr_size field set by the stdarg pass to only save the
GARs necessary to be saved.

If the va_list escapes (for example, in fprintf() we pass it to
vfprintf()), stdarg would set cfun->va_list_gpr_size to 255 so we
don't need a special case.

With this patch, only one GAR ($a2/$r6) is saved in open().  Ideally
even this stack store should be omitted too, but doing so is not trivial
and AFAIK there are no compilers (for any target) performing the "ideal"
optimization here, see https://godbolt.org/z/n1YqWq9c9.

Bootstrapped and regtested on loongarch64-linux-gnu.  Ok for trunk
(GCC 14 or now)?

gcc/ChangeLog:

* config/loongarch/loongarch.cc
(loongarch_setup_incoming_varargs): Don't save more GARs than
cfun->va_list_gpr_size / UNITS_PER_WORD.

gcc/testsuite/ChangeLog:

* gcc.target/loongarch/va_arg.c: New test.
gcc/config/loongarch/loongarch.cc
gcc/testsuite/gcc.target/loongarch/va_arg.c [new file with mode: 0644]