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 <[email protected]>
Stefan Schulze Frielinghaus <[email protected]>
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