On Thu, Apr 24, 2025 at 09:44:45AM +0200, Stefan Schulze Frielinghaus wrote: > Yes, every parameter is sign or zero extended if its type is smaller > than 64bit.
> Note, on s390 a parameter is either passed in a register (pair) or via > memory, but not partly in a register and memory. Ok, so like this then if it passes bootstrap/regtest? So far tested with make check-gcc RUNTESTFLAGS='--target_board=unix\{-m64,-m31\} s390.exp=pr119873*' in a cross-compiler. 2025-04-24 Jakub Jelinek <ja...@redhat.com> Stefan Schulze Frielinghaus <stefa...@gcc.gnu.org> PR target/119873 * config/s390/s390.cc (s390_call_saved_register_used): Don't return true if default definition of PARM_DECL SSA_NAME of the same register is passed in call saved register. (s390_function_ok_for_sibcall): Adjust comment. * gcc.target/s390/pr119873-1.c: New test. * gcc.target/s390/pr119873-2.c: New test. * gcc.target/s390/pr119873-3.c: New test. * gcc.target/s390/pr119873-4.c: New test. --- gcc/config/s390/s390.cc.jj 2025-04-22 09:45:29.907576749 +0200 +++ gcc/config/s390/s390.cc 2025-04-24 12:22:48.897695685 +0200 @@ -14496,7 +14496,21 @@ s390_call_saved_register_used (tree call for (reg = 0; reg < nregs; reg++) if (!call_used_or_fixed_reg_p (reg + REGNO (parm_rtx))) - return true; + { + rtx parm; + /* Allow passing through unmodified value from caller, + see PR119873. */ + if (TREE_CODE (parameter) == SSA_NAME + && SSA_NAME_IS_DEFAULT_DEF (parameter) + && SSA_NAME_VAR (parameter) + && TREE_CODE (SSA_NAME_VAR (parameter)) == PARM_DECL + && (parm = DECL_INCOMING_RTL (SSA_NAME_VAR (parameter))) + && REG_P (parm) + && REGNO (parm) == REGNO (parm_rtx) + && REG_NREGS (parm) == REG_NREGS (parm_rtx)) + break; + return true; + } } else if (GET_CODE (parm_rtx) == PARALLEL) { @@ -14543,8 +14557,9 @@ s390_function_ok_for_sibcall (tree decl, return false; /* Register 6 on s390 is available as an argument register but unfortunately - "caller saved". This makes functions needing this register for arguments - not suitable for sibcalls. */ + "caller saved". This makes functions needing this register for arguments + not suitable for sibcalls, unless the same value is passed from the + caller. */ return !s390_call_saved_register_used (exp); } --- gcc/testsuite/gcc.target/s390/pr119873-1.c.jj 2025-04-24 12:19:05.617685023 +0200 +++ gcc/testsuite/gcc.target/s390/pr119873-1.c 2025-04-24 12:19:05.617685023 +0200 @@ -0,0 +1,11 @@ +/* PR target/119873 */ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ + +const char *foo (void *, void *, void *, void *, unsigned long, unsigned long); + +const char * +bar (void *a, void *b, void *c, void *d, unsigned long e, unsigned long f) +{ + [[gnu::musttail]] return foo (a, b, c, d, e, f); +} --- gcc/testsuite/gcc.target/s390/pr119873-2.c.jj 2025-04-24 12:19:05.617685023 +0200 +++ gcc/testsuite/gcc.target/s390/pr119873-2.c 2025-04-24 12:19:05.617685023 +0200 @@ -0,0 +1,17 @@ +/* PR target/119873 */ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ + +const char *foo (void *, void *, void *, void *, unsigned long, unsigned long); + +const char * +bar (void *a, void *b, void *c, void *d, unsigned long e, unsigned long f) +{ + [[gnu::musttail]] return foo (a, b, c, d, e + 1, f); /* { dg-error "cannot tail-call: target is not able to optimize the call into a sibling call" } */ +} + +const char * +baz (void *a, void *b, void *c, void *d, unsigned long e, unsigned long f) +{ + [[gnu::musttail]] return foo (a, b, c, d, f, e); /* { dg-error "cannot tail-call: target is not able to optimize the call into a sibling call" } */ +} --- gcc/testsuite/gcc.target/s390/pr119873-3.c.jj 2025-04-24 12:32:13.550135958 +0200 +++ gcc/testsuite/gcc.target/s390/pr119873-3.c 2025-04-24 12:44:13.744520302 +0200 @@ -0,0 +1,27 @@ +/* PR target/119873 */ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ + +extern int foo (int, int, int, long long, int); + +int +bar (int u, int v, int w, long long x, int y) +{ + [[gnu::musttail]] return foo (u, v, w, x, y); +} + +extern int baz (int, int, int, int, int); + +int +qux (int u, int v, int w, int x, int y) +{ + [[gnu::musttail]] return baz (u, v, w, x, y); +} + +extern int corge (int, int, int, int, unsigned short); + +int +garply (int u, int v, int w, int x, unsigned short y) +{ + [[gnu::musttail]] return corge (u, v, w, x, y); +} --- gcc/testsuite/gcc.target/s390/pr119873-4.c.jj 2025-04-24 12:45:21.162620820 +0200 +++ gcc/testsuite/gcc.target/s390/pr119873-4.c 2025-04-24 12:46:02.169073715 +0200 @@ -0,0 +1,27 @@ +/* PR target/119873 */ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ + +extern int foo (int, int, int, long long, int); + +int +bar (int u, int v, int w, long long x, int y) +{ + [[gnu::musttail]] return foo (u, v, w, x + 1, y - 1); /* { dg-error "cannot tail-call: target is not able to optimize the call into a sibling call" } */ +} + +extern int baz (int, int, int, int, int); + +int +qux (int u, int v, int w, int x, int y) +{ + [[gnu::musttail]] return baz (u, v, w, x, y + 1); /* { dg-error "cannot tail-call: target is not able to optimize the call into a sibling call" } */ +} + +extern int corge (int, int, int, int, unsigned short); + +int +garply (int u, int v, int w, int x, unsigned short y) +{ + [[gnu::musttail]] return corge (u, v, w, x, y + 1); /* { dg-error "cannot tail-call: target is not able to optimize the call into a sibling call" } */ +} Jakub