Am Do., 28. Mai 2026 um 00:12 Uhr schrieb H.J. Lu <[email protected]>:
>
> On Thu, May 28, 2026 at 12:50 AM oltolm <[email protected]> wrote:
> >
> > On x86_64-w64-mingw32, PR target/54412 is triggered when GCC creates
> > under-aligned stack storage for AVX values that are passed, returned or
> > materialized indirectly.
> >
> > Add coverage for the original by-value cases, for isolated hidden sret
> > allocation, for callee-side by-reference parameter setup, for the reduced
> > real-world C++ temporary-slot reproducer, and for an aligned(64) AVX512
> > case.
> >
> > gcc/testsuite/ChangeLog:
> >
> >     PR target/54412
> >     * gcc.target/i386/pr54412-v4d-o0-aligned-locals.c: New test.
> >     * gcc.target/i386/pr54412-o2-by-value-cases.c: New test.
> >     * gcc.target/i386/pr54412-sret-no-args.c: New test.
> >     * gcc.target/i386/pr54412-callee-byref-param.c: New test.
> >     * gcc.target/i386/pr54412-avx512-aligned64.c: New test.
> >     * g++.target/i386/pr54412-setactivepreset.C: New test.
> >     * g++.target/i386/pr54412-setactivepreset-2.C: New test.
> >
> > Signed-off-by: oltolm <[email protected]>
> > ---
> >  .../i386/pr54412-setactivepreset-2.C          |  58 ++++++++++
> >  .../g++.target/i386/pr54412-setactivepreset.C |  45 ++++++++
> >  .../i386/pr54412-avx512-aligned64.c           |  29 +++++
> >  .../i386/pr54412-callee-byref-param.c         |  27 +++++
> >  .../i386/pr54412-o2-by-value-cases.c          | 104 ++++++++++++++++++
> >  .../gcc.target/i386/pr54412-sret-no-args.c    |  36 ++++++
> >  .../i386/pr54412-v4d-o0-aligned-locals.c      |  27 +++++
> >  7 files changed, 326 insertions(+)
> >  create mode 100644 
> > gcc/testsuite/g++.target/i386/pr54412-setactivepreset-2.C
> >  create mode 100644 gcc/testsuite/g++.target/i386/pr54412-setactivepreset.C
> >  create mode 100644 gcc/testsuite/gcc.target/i386/pr54412-avx512-aligned64.c
> >  create mode 100644 
> > gcc/testsuite/gcc.target/i386/pr54412-callee-byref-param.c
> >  create mode 100644 
> > gcc/testsuite/gcc.target/i386/pr54412-o2-by-value-cases.c
> >  create mode 100644 gcc/testsuite/gcc.target/i386/pr54412-sret-no-args.c
> >  create mode 100644 
> > gcc/testsuite/gcc.target/i386/pr54412-v4d-o0-aligned-locals.c
> >
> > diff --git a/gcc/testsuite/g++.target/i386/pr54412-setactivepreset-2.C 
> > b/gcc/testsuite/g++.target/i386/pr54412-setactivepreset-2.C
> > new file mode 100644
> > index 00000000000..4f0abec6ec0
> > --- /dev/null
> > +++ b/gcc/testsuite/g++.target/i386/pr54412-setactivepreset-2.C
> > @@ -0,0 +1,58 @@
> > +/* PR target/54412 */
> > +/* { dg-do compile { target x86_64-*-mingw* } } */
> > +/* { dg-options "-O2 -mavx2 -masm=intel -std=gnu++17 
> > -fno-omit-frame-pointer" } */
> > +/* { dg-final { scan-assembler-not {lea[ \t]+r8, 63\[rsp\]} } } */
> > +/* { dg-final { scan-assembler-not {and[ \t]+r8, -32} } } */
> > +/* { dg-final { scan-assembler-not {vmovdqa[ \t]+YMMWORD PTR \[r8\], ymm0} 
> > } } */
> > +
> > +template <typename _InputIterator, typename _Predicate>
> > +__attribute__ ((noinline, noclone))
> > +_InputIterator
> > +find_if_inner (_InputIterator first, _InputIterator last, _Predicate &pred)
> > +{
> > +  asm volatile ("" : : "g" (first), "g" (last), "g" (&pred) : "memory");
> > +  return first;
> > +}
> > +
> > +template <typename _InputIterator, typename _Predicate>
> > +__attribute__ ((noinline, noclone))
> > +_InputIterator
> > +find_if (_InputIterator first, _InputIterator last, _Predicate pred)
> > +{
> > +  return find_if_inner (first, last, pred);
> > +}
> > +
> > +struct basic_string_view
> > +{
> > +  int n;
> > +  void *_r;
> > +};
> > +
> > +struct dummy_iter
> > +{
> > +  int n;
> > +};
> > +
> > +dummy_iter first;
> > +dummy_iter last;
> > +basic_string_view cit_name;
> > +basic_string_view cit_category;
> > +
> > +struct ic_
> > +{
> > +  void
> > +  set_active_preset (basic_string_view category,
> > +                    basic_string_view name,
> > +                    bool)
> > +  {
> > +    find_if (first, last, [category, name] (dummy_iter) { return false; });
> > +  }
> > +};
> > +
> > +ic_ cit_pack;
> > +
> > +void
> > +it (bool update_visibility)
> > +{
> > +  cit_pack.set_active_preset (cit_category, cit_name, update_visibility);
> > +}
> > diff --git a/gcc/testsuite/g++.target/i386/pr54412-setactivepreset.C 
> > b/gcc/testsuite/g++.target/i386/pr54412-setactivepreset.C
> > new file mode 100644
> > index 00000000000..c0b989fdb2c
> > --- /dev/null
> > +++ b/gcc/testsuite/g++.target/i386/pr54412-setactivepreset.C
> > @@ -0,0 +1,45 @@
> > +/* PR target/54412 */
> > +/* { dg-do compile { target x86_64-*-mingw* } } */
> > +/* { dg-options "-O2 -mavx2 -masm=intel -std=gnu++17 
> > -fno-omit-frame-pointer" } */
> > +/* { dg-final { scan-assembler-not {vmovdqa[ \t]+YMMWORD PTR 
> > -[0-9]+\[rbp\], ymm[0-9]+} } } */
> > +
> > +template <typename _InputIterator, typename _Predicate>
> > +__attribute__ ((noinline, noclone))
> > +void
> > +find_if (_InputIterator first, _InputIterator last, _Predicate pred)
> > +{
> > +  asm volatile ("" : : "g" (first), "g" (last), "g" (&pred) : "memory");
> > +}
> > +
> > +struct basic_string_view
> > +{
> > +  int n;
> > +  void *_r;
> > +
> > +  int cbegin () const;
> > +  int cend () const;
> > +};
> > +
> > +basic_string_view presets;
> > +basic_string_view cit_name;
> > +basic_string_view cit_category;
> > +
> > +struct ic_
> > +{
> > +  void
> > +  set_active_preset (basic_string_view category,
> > +                    basic_string_view name,
> > +                    bool)
> > +  {
> > +    find_if (&basic_string_view::cbegin, &basic_string_view::cend,
> > +            [category, name] {});
> > +  }
> > +};
> > +
> > +ic_ cit_pack;
> > +
> > +void
> > +it (bool update_visibility)
> > +{
> > +  cit_pack.set_active_preset (cit_category, cit_name, update_visibility);
> > +}
> > diff --git a/gcc/testsuite/gcc.target/i386/pr54412-avx512-aligned64.c 
> > b/gcc/testsuite/gcc.target/i386/pr54412-avx512-aligned64.c
> > new file mode 100644
> > index 00000000000..c496f76e76e
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.target/i386/pr54412-avx512-aligned64.c
> > @@ -0,0 +1,29 @@
> > +/* PR target/54412 */
> > +/* { dg-do run { target { avx512f && { ! ia32 } } } } */
> > +/* { dg-skip-if "PR target/54412 exercises the Win64 ABI" { ! 
> > x86_64-*-mingw* } } */
>
> Drop this.   Execution test should work for all.
>
> > +/* { dg-options "-O0 -mavx512f" } */
> > +
> > +#include "avx512-check.h"
> > +
> > +typedef double v8d __attribute__ ((vector_size (64), aligned (64)));
> > +
> > +__attribute__ ((noinline)) static v8d
> > +roundtrip_v8d (v8d x)
> > +{
> > +  return x;
> > +}
> > +
> > +static void
> > +test_512 (void)
> > +{
> > +  v8d x __attribute__ ((aligned (64)))
> > +    = { 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0 };
> > +  v8d expected __attribute__ ((aligned (64)))
> > +    = { 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0 };
> > +  v8d r __attribute__ ((aligned (64)));
> > +
> > +  r = roundtrip_v8d (x);
> > +
> > +  if (__builtin_memcmp (&r, &expected, sizeof (r)) != 0)
> > +    __builtin_abort ();
> > +}
> > diff --git a/gcc/testsuite/gcc.target/i386/pr54412-callee-byref-param.c 
> > b/gcc/testsuite/gcc.target/i386/pr54412-callee-byref-param.c
> > new file mode 100644
> > index 00000000000..1eb1164ff9b
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.target/i386/pr54412-callee-byref-param.c
> > @@ -0,0 +1,27 @@
> > +/* PR target/54412 */
> > +/* { dg-do run { target { avx && { ! ia32 } } } } */
> > +/* { dg-skip-if "PR target/54412 exercises the Win64 ABI" { ! 
> > x86_64-*-mingw* } } */
>
> Drop this.   Execution test should work for all.
>
> > +/* { dg-options "-O0 -mavx" } */
> > +
> > +#include "avx-check.h"
> > +
> > +typedef float v8f __attribute__ ((vector_size (32), aligned (32)));
> > +
> > +static const v8f expected = { 1.0f, 2.0f, 3.0f, 4.0f,
> > +                              5.0f, 6.0f, 7.0f, 8.0f };
> > +
> > +__attribute__ ((noinline)) static int
> > +param_matches (v8f x)
> > +{
> > +  return __builtin_memcmp (&x, &expected, sizeof (x)) == 0;
> > +}
> > +
> > +static void
> > +avx_test (void)
> > +{
> > +  v8f x __attribute__ ((aligned (32)))
> > +    = { 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f };
> > +
> > +  if (!param_matches (x))
> > +    __builtin_abort ();
> > +}
> > diff --git a/gcc/testsuite/gcc.target/i386/pr54412-o2-by-value-cases.c 
> > b/gcc/testsuite/gcc.target/i386/pr54412-o2-by-value-cases.c
> > new file mode 100644
> > index 00000000000..cdcca7b31f4
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.target/i386/pr54412-o2-by-value-cases.c
> > @@ -0,0 +1,104 @@
> > +/* PR target/54412 */
> > +/* { dg-do run { target { avx && { ! ia32 } } } } */
> > +/* { dg-skip-if "PR target/54412 exercises the Win64 ABI" { ! 
> > x86_64-*-mingw* } } */
>
> Drop this.   Execution test should work for all.
>
> > +/* { dg-options "-O2 -mavx -std=gnu99" } */
> > +
> > +#include "avx-check.h"
> > +#include <immintrin.h>
> > +
> > +typedef double v4d __attribute__ ((vector_size (32), aligned (32)));
> > +typedef char byte_vec __attribute__ ((vector_size (32)));
> > +
> > +struct avx_wrapper
> > +{
> > +  __m256 value;
> > +};
> > +
> > +#define PERM_LEFT_BVEC \
> > +  (byte_vec) { 63, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, \
> > +               15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, \
> > +               29, 30 }
> > +
> > +__attribute__ ((noinline, noclone)) static v4d
> > +roundtrip_v4d (v4d x)
> > +{
> > +  return x;
> > +}
> > +
> > +__attribute__ ((noinline)) static __m256
> > +pass_m256 (__m256 x)
> > +{
> > +  return x;
> > +}
> > +
> > +__attribute__ ((noinline)) static struct avx_wrapper
> > +pass_wrapper (struct avx_wrapper x)
> > +{
> > +  return x;
> > +}
> > +
> > +__attribute__ ((noinline)) static byte_vec
> > +permute (byte_vec x, byte_vec y)
> > +{
> > +  return __builtin_shuffle (x, y, PERM_LEFT_BVEC);
> > +}
> > +
> > +static void
> > +test_v4d_roundtrip (void)
> > +{
> > +  v4d x = (v4d) { 1.0, 2.0, 3.0, 4.0 };
> > +  v4d r = roundtrip_v4d (x);
> > +  v4d expected = (v4d) { 1.0, 2.0, 3.0, 4.0 };
> > +
> > +  if (__builtin_memcmp (&r, &expected, sizeof (r)) != 0)
> > +    __builtin_abort ();
> > +}
> > +
> > +static void
> > +test_m256_and_wrapper_by_value (void)
> > +{
> > +  __m256 m = _mm256_set_ps (8.0f, 7.0f, 6.0f, 5.0f,
> > +                            4.0f, 3.0f, 2.0f, 1.0f);
> > +  __m256 r = pass_m256 (m);
> > +  struct avx_wrapper x;
> > +  struct avx_wrapper y;
> > +
> > +  x.value = _mm256_set_ps (16.0f, 15.0f, 14.0f, 13.0f,
> > +                           12.0f, 11.0f, 10.0f, 9.0f);
> > +  y = pass_wrapper (x);
> > +
> > +  if (__builtin_memcmp (&r, &m, sizeof (r)) != 0)
> > +    __builtin_abort ();
> > +
> > +  if (__builtin_memcmp (&y, &x, sizeof (y)) != 0)
> > +    __builtin_abort ();
> > +}
> > +
> > +static void
> > +test_two_arg_bytevec_shuffle (void)
> > +{
> > +  byte_vec x = { 1, 2, 3, 4, 5, 6, 7, 8,
> > +                 9, 10, 11, 12, 13, 14, 15, 16,
> > +                 17, 18, 19, 20, 21, 22, 23, 24,
> > +                 25, 26, 27, 28, 29, 30, 31, 32 };
> > +  byte_vec y = { 11, 12, 13, 14, 15, 16, 17, 18,
> > +                 19, 110, 111, 112, 113, 114, 115, 116,
> > +                 117, 118, 119, 120, 121, 122, 123, 124,
> > +                 125, 126, 127, 88, 89, 90, 91, 92 };
> > +  byte_vec expected = { 92, 1, 2, 3, 4, 5, 6, 7,
> > +                        8, 9, 10, 11, 12, 13, 14, 15,
> > +                        16, 17, 18, 19, 20, 21, 22, 23,
> > +                        24, 25, 26, 27, 28, 29, 30, 31 };
> > +  byte_vec z = permute (x, y);
> > +
> > +  if (__builtin_memcmp (&z, &expected, sizeof (z)) != 0)
> > +    __builtin_abort ();
> > +}
> > +
> > +static void
> > +avx_test (void)
> > +{
> > +  test_v4d_roundtrip ();
> > +  test_m256_and_wrapper_by_value ();
> > +  test_two_arg_bytevec_shuffle ();
> > +}
> > diff --git a/gcc/testsuite/gcc.target/i386/pr54412-sret-no-args.c 
> > b/gcc/testsuite/gcc.target/i386/pr54412-sret-no-args.c
> > new file mode 100644
> > index 00000000000..af23e6a99a0
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.target/i386/pr54412-sret-no-args.c
> > @@ -0,0 +1,36 @@
> > +/* PR target/54412 */
> > +/* { dg-do run { target { avx && { ! ia32 } } } } */
> > +/* { dg-skip-if "PR target/54412 exercises the Win64 ABI" { ! 
> > x86_64-*-mingw* } } */
>
> Drop this.   Execution test should work for all.
>
> > +/* { dg-options "-O2 -mavx -std=gnu99" } */
> > +
> > +#include "avx-check.h"
> > +#include <immintrin.h>
> > +
> > +struct avx_wrapper
> > +{
> > +  __m256 value;
> > +};
> > +
> > +__attribute__ ((noinline)) static struct avx_wrapper
> > +make_wrapper (void)
> > +{
> > +  struct avx_wrapper x;
> > +
> > +  x.value = _mm256_set_ps (8.0f, 7.0f, 6.0f, 5.0f,
> > +                           4.0f, 3.0f, 2.0f, 1.0f);
> > +  return x;
> > +}
> > +
> > +static void
> > +avx_test (void)
> > +{
> > +  struct avx_wrapper expected;
> > +  struct avx_wrapper r;
> > +
> > +  expected.value = _mm256_set_ps (8.0f, 7.0f, 6.0f, 5.0f,
> > +                                  4.0f, 3.0f, 2.0f, 1.0f);
> > +  r = make_wrapper ();
> > +
> > +  if (__builtin_memcmp (&r, &expected, sizeof (r)) != 0)
> > +    __builtin_abort ();
> > +}
> > diff --git a/gcc/testsuite/gcc.target/i386/pr54412-v4d-o0-aligned-locals.c 
> > b/gcc/testsuite/gcc.target/i386/pr54412-v4d-o0-aligned-locals.c
> > new file mode 100644
> > index 00000000000..74675f53bcb
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.target/i386/pr54412-v4d-o0-aligned-locals.c
> > @@ -0,0 +1,27 @@
> > +/* PR target/54412 */
> > +/* { dg-do run { target { avx && { ! ia32 } } } } */
>
> Why !ia32?  Why do these tests fail for ia32?

Thanks for the review.

It was just a mistake. I wanted to exclude 32-bit Windows and confused
ia32 with x64-32.

I removed all the "dg-skip-if" lines and sent a new patch to the mailing list.

Best regards
Oleg Tolmatcev

Reply via email to