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
