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

Reply via email to