On Thu, Nov 21, 2024 at 6:43 AM H.J. Lu <hjl.to...@gmail.com> wrote:
> On Wed, Nov 20, 2024 at 9:55 PM Richard Sandiford < > richard.sandif...@arm.com> wrote: > >> "H.J. Lu" <hjl.to...@gmail.com> writes: >> > On Wed, Nov 20, 2024 at 2:12 AM Richard Sandiford >> > <richard.sandif...@arm.com> wrote: >> >> >> >> "H.J. Lu" <hjl.to...@gmail.com> writes: >> >> > Adjust BLKmode argument size for parameter alignment for sibcall >> check. >> >> > >> >> > gcc/ >> >> > >> >> > PR middle-end/117098 >> >> > * calls.cc (store_one_arg): Adjust BLKmode argument size for >> >> > alignment padding for sibcall check. >> >> > >> >> > gcc/testsuite/ >> >> > >> >> > PR middle-end/117098 >> >> > * gcc.dg/sibcall-12.c: New test. >> >> > >> >> > OK for master? >> >> > >> >> > >> >> > H.J. >> >> > From 8b0518906cb23a9b5e77b04d6132c49047daebd2 Mon Sep 17 00:00:00 >> 2001 >> >> > From: "H.J. Lu" <hjl.to...@gmail.com> >> >> > Date: Sun, 13 Oct 2024 04:53:14 +0800 >> >> > Subject: [PATCH] sibcall: Adjust BLKmode argument size for alignment >> padding >> >> > >> >> > Adjust BLKmode argument size for parameter alignment for sibcall >> check. >> >> > >> >> > gcc/ >> >> > >> >> > PR middle-end/117098 >> >> > * calls.cc (store_one_arg): Adjust BLKmode argument size for >> >> > alignment padding for sibcall check. >> >> > >> >> > gcc/testsuite/ >> >> > >> >> > PR middle-end/117098 >> >> > * gcc.dg/sibcall-12.c: New test. >> >> > >> >> > Signed-off-by: H.J. Lu <hjl.to...@gmail.com> >> >> > --- >> >> > gcc/calls.cc | 4 +++- >> >> > gcc/testsuite/gcc.dg/sibcall-12.c | 13 +++++++++++++ >> >> > 2 files changed, 16 insertions(+), 1 deletion(-) >> >> > create mode 100644 gcc/testsuite/gcc.dg/sibcall-12.c >> >> > >> >> > diff --git a/gcc/calls.cc b/gcc/calls.cc >> >> > index c5c26f65280..163c7e509d9 100644 >> >> > --- a/gcc/calls.cc >> >> > +++ b/gcc/calls.cc >> >> > @@ -5236,7 +5236,9 @@ store_one_arg (struct arg_data *arg, rtx >> argblock, int flags, >> >> > /* expand_call should ensure this. */ >> >> > gcc_assert (!arg->locate.offset.var >> >> > && arg->locate.size.var == 0); >> >> > - poly_int64 size_val = rtx_to_poly_int64 (size_rtx); >> >> > + /* Adjust for argument alignment padding. */ >> >> > + poly_int64 size_val = ROUND_UP (UINTVAL (size_rtx), >> >> > + parm_align / >> BITS_PER_UNIT); >> >> >> >> This doesn't look right to me. For one thing, going from >> >> rtx_to_poly_int64 to UINTVAL drops support for non-constant parameters. >> >> But even ignoring that, I think padding size_val (the size of >> arg->value >> >> IIUC) will pessimise the later: >> >> >> >> else if (maybe_in_range_p (arg->locate.offset.constant, >> >> i, size_val)) >> >> sibcall_failure = true; >> >> >> >> and so cause sibcall failures elsewhere. I'm also not sure this >> >> accurately reproduces the padding that is added by locate_and_pad_parm >> >> for all cases (arguments that grow up vs down, padding below vs above >> >> the argument). >> >> >> >> AIUI, the point of the: >> >> >> >> if (known_eq (arg->locate.offset.constant, i)) >> >> { >> >> /* Even though they appear to be at the same >> location, >> >> if part of the outgoing argument is in registers, >> >> they aren't really at the same location. Check >> for >> >> this by making sure that the incoming size is the >> >> same as the outgoing size. */ >> >> if (maybe_ne (arg->locate.size.constant, size_val)) >> >> sibcall_failure_1 = true; >> >> } >> > >> > Does this >> > >> > diff --git a/gcc/calls.cc b/gcc/calls.cc >> > index 246abe34243..98429cc757f 100644 >> > --- a/gcc/calls.cc >> > +++ b/gcc/calls.cc >> > @@ -5327,7 +5327,13 @@ store_one_arg (struct arg_data *arg, rtx >> > argblock, int flags, >> > they aren't really at the same location. Check for >> > this by making sure that the incoming size is the >> > same as the outgoing size. */ >> > - if (maybe_ne (arg->locate.size.constant, size_val)) >> > + poly_int64 aligned_size; >> > + if (CONST_INT_P (size_rtx)) >> > + aligned_size = ROUND_UP (UINTVAL (size_rtx), >> > + parm_align / BITS_PER_UNIT); >> > + else >> > + aligned_size = size_val; >> > + if (maybe_ne (arg->locate.size.constant, aligned_size)) >> > sibcall_failure = true; >> > } >> > else if (maybe_in_range_p (arg->locate.offset.constant, >> > >> > look correct? >> >> Heh. Playing the reviewer here, I was kind-of hoping you'd explain >> why it was correct to me :) >> >> But conceptually, the call is copying from arg->value to arg->locate. >> And this code is trying to detect whether the copy is a nop, whether >> it overlaps, or whether the source and destination are distinct. >> >> It feels odd to grow the size of arg->value (the source of the copy), >> given that the extra bytes shouldn't be copied. >> >> Like I mentioned in the previous reply, it feels to me like testing >> partial != 0 would deal with the situation described in the comment, >> and the testcase in PR32602. Personally I think we should try that first. >> Maybe it's wrong (quite probable), but if so, it'd be good to know and >> > The outgoing stack slot size may be different from the BLKmode argument size due to parameter alignment. Check partial != 0 for BLKmode argument passed on stack. gcc/ PR middle-end/117098 * calls.cc (store_one_arg): Check artial != 0 for BLKmode argument passed on stack. gcc/testsuite/ PR middle-end/117098 * gcc.dg/sibcall-12.c: New test. OK for master? Thanks. -- H.J.
From 055310301cd17247b156b2b14fc19aaaa0eec4ae Mon Sep 17 00:00:00 2001 From: "H.J. Lu" <hjl.to...@gmail.com> Date: Sun, 13 Oct 2024 04:53:14 +0800 Subject: [PATCH v2] sibcall: Check partial != 0 for BLKmode argument The outgoing stack slot size may be different from the BLKmode argument size due to parameter alignment. Check partial != 0 for BLKmode argument passed on stack. gcc/ PR middle-end/117098 * calls.cc (store_one_arg): Check artial != 0 for BLKmode argument passed on stack. gcc/testsuite/ PR middle-end/117098 * gcc.dg/sibcall-12.c: New test. Signed-off-by: H.J. Lu <hjl.to...@gmail.com> --- gcc/calls.cc | 2 +- gcc/testsuite/gcc.dg/sibcall-12.c | 13 +++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/gcc.dg/sibcall-12.c diff --git a/gcc/calls.cc b/gcc/calls.cc index f67067acad4..01c4ef51545 100644 --- a/gcc/calls.cc +++ b/gcc/calls.cc @@ -5246,7 +5246,7 @@ store_one_arg (struct arg_data *arg, rtx argblock, int flags, they aren't really at the same location. Check for this by making sure that the incoming size is the same as the outgoing size. */ - if (maybe_ne (arg->locate.size.constant, size_val)) + if (partial != 0) sibcall_failure = true; } else if (maybe_in_range_p (arg->locate.offset.constant, diff --git a/gcc/testsuite/gcc.dg/sibcall-12.c b/gcc/testsuite/gcc.dg/sibcall-12.c new file mode 100644 index 00000000000..5773c9c1c4a --- /dev/null +++ b/gcc/testsuite/gcc.dg/sibcall-12.c @@ -0,0 +1,13 @@ +// Test for sibcall optimization with struct aligned on stack. +// { dg-options "-O2" } +// { dg-final { scan-assembler "jmp" { target i?86-*-* x86_64-*-* } } } + +struct A { char a[17]; }; + +int baz (int a, int b, int c, void *p, struct A s, struct A); + +int +foo (int a, int b, int c, void *p, struct A s, struct A s2) +{ + return baz (a, b, c, p, s, s2); +} -- 2.47.0