Thanks Torbjorn, and sorry for not looking earlier (yes, vacation and the madness that comes after).
I'm fairly certain that the code worked at some point. Actually, a quick test on Compiler Explorer and I can't reproduce the issue. But I must admit that I'm lost to all the variants of ARM, and I'm probably not testing the one that fails for you. Can you show me how to compile https://compiler-explorer.com/z/jWPEPTo8a so that it requires the cast to intrinsic type? Also, if you know of a better way to turn a vector-mask into a bit-mask, I'd be happy to replace that code altogether. - Matthias Torbjorn SVENSSON [Thursday, 6 August 2026, 17:55:25 CEST]: > On 2026-07-24 18:34, Jonathan Wakely wrote: > > On Sun, 12 Jul 2026 at 19:42 +0200, Torbjörn SVENSSON wrote: > >> I hope this is the right fix for the issue. > >> I've regtested for arm-none-eabi on top of r15-11320-g7909a9f85f30b6 and > >> it applies cleanly on trunk. The new test is derived from > >> libstdc++-v3/testsuite/experimental/simd/pr115454_find_last_set.cc. > >> > >> Ok for trunk, releases/gcc-16 and releases/gcc-15? > > > > OK for trunk but for the backports I'd prefer to wait for Matthias to > > confirm this is the correct fix. > > I've been holding of to push this since I do not want to push something that > might not be correct. Do you have any idea when Matthias is back (assuming > vacation period right now)? > > Kind regards, > Torbjörn > > >> When testing r15-10798-gae573c9d0e7f1c, I noticed that the > >> experimental/simd/pr115454_find_last_set.cc was failing due to that the > >> GNU vector type was used instead of the NEON intrinsic type. > >> > >> PR libstdc++/122981 > >> > >> libstdc++-v3/ChangeLog: > >> > >> * include/experimental/bits/simd_neon.h: Convert AArch32 NEON > >> vpadd_* operands to intrinsic types. > >> * testsuite/experimental/simd/pr122981_find_last_set_neon.cc: New > >> test. > >> > >> Signed-off-by: Torbjörn SVENSSON <[email protected]> > >> --- > >> .../include/experimental/bits/simd_neon.h | 31 +++++++----- > >> .../simd/pr122981_find_last_set_neon.cc | 50 +++++++++++++++++++ > >> 2 files changed, 69 insertions(+), 12 deletions(-) > >> create mode 100644 > >> libstdc++-v3/testsuite/experimental/simd/pr122981_find_last_set_neon.cc > >> > >> diff --git a/libstdc++-v3/include/experimental/bits/simd_neon.h > >> b/libstdc++-v3/include/experimental/bits/simd_neon.h index > >> d3785db2bfd..23c205f3dc9 100644 > >> --- a/libstdc++-v3/include/experimental/bits/simd_neon.h > >> +++ b/libstdc++-v3/include/experimental/bits/simd_neon.h > >> @@ -297,9 +297,10 @@ struct _MaskImplNeonMixin > >> __zero))[0]; > >> #else > >> return __vector_bitcast<_UShort>( > >> - vpadd_s8(vpadd_s8(vpadd_s8(__lo64(__asint), __hi64(__asint)), > >> - __zero), > >> - __zero))[0]; > >> + vpadd_s8(vpadd_s8(vpadd_s8(__to_intrin(__lo64(__asint)), > >> + __to_intrin(__hi64(__asint))), > >> + __to_intrin(__zero)), > >> + __to_intrin(__zero)))[0]; > >> #endif > >> } > >> else if constexpr (sizeof(_Tp) == 2) > >> @@ -313,9 +314,10 @@ struct _MaskImplNeonMixin > >> #ifdef __aarch64__ > >> return vaddvq_s16(__asint); > >> #else > >> - return vpadd_s16( > >> - vpadd_s16(vpadd_s16(__lo64(__asint), __hi64(__asint)), __zero), > >> - __zero)[0]; > >> + return > >> vpadd_s16(vpadd_s16(vpadd_s16(__to_intrin(__lo64(__asint)), > >> + __to_intrin(__hi64(__asint))), > >> + __to_intrin(__zero)), > >> + __to_intrin(__zero))[0]; > >> #endif > >> } > >> else if constexpr (sizeof(_Tp) == 4) > >> @@ -329,8 +331,9 @@ struct _MaskImplNeonMixin > >> #ifdef __aarch64__ > >> return vaddvq_s32(__asint); > >> #else > >> - return vpadd_s32(vpadd_s32(__lo64(__asint), __hi64(__asint)), > >> - __zero)[0]; > >> + return vpadd_s32(vpadd_s32(__to_intrin(__lo64(__asint)), > >> + __to_intrin(__hi64(__asint))), > >> + __to_intrin(__zero))[0]; > >> #endif > >> } > >> else if constexpr (sizeof(_Tp) == 8) > >> @@ -353,8 +356,10 @@ struct _MaskImplNeonMixin > >> #ifdef __aarch64__ > >> return vaddv_s8(__asint); > >> #else > >> - return vpadd_s8(vpadd_s8(vpadd_s8(__asint, __zero), __zero), > >> - __zero)[0]; > >> + return vpadd_s8(vpadd_s8(vpadd_s8(__to_intrin(__asint), > >> + __to_intrin(__zero)), > >> + __to_intrin(__zero)), > >> + __to_intrin(__zero))[0]; > >> #endif > >> } > >> else if constexpr (sizeof(_Tp) == 2) > >> @@ -368,7 +373,9 @@ struct _MaskImplNeonMixin > >> #ifdef __aarch64__ > >> return vaddv_s16(__asint); > >> #else > >> - return vpadd_s16(vpadd_s16(__asint, __zero), __zero)[0]; > >> + return vpadd_s16(vpadd_s16(__to_intrin(__asint), > >> + __to_intrin(__zero)), > >> + __to_intrin(__zero))[0]; > >> #endif > >> } > >> else if constexpr (sizeof(_Tp) == 4) > >> @@ -377,7 +384,7 @@ struct _MaskImplNeonMixin > >> #ifdef __aarch64__ > >> return vaddv_s32(__asint); > >> #else > >> - return vpadd_s32(__asint, __zero)[0]; > >> + return vpadd_s32(__to_intrin(__asint), > >> __to_intrin(__zero))[0]; > >> #endif > >> } > >> else > >> diff --git > >> a/libstdc++-v3/testsuite/experimental/simd/pr122981_find_last_set_neon.c > >> c > >> b/libstdc++-v3/testsuite/experimental/simd/pr122981_find_last_set_neon.c > >> c new file mode 100644 > >> index 00000000000..f7f79166ae6 > >> --- /dev/null > >> +++ > >> b/libstdc++-v3/testsuite/experimental/simd/pr122981_find_last_set_neon.c > >> c @@ -0,0 +1,50 @@ > >> +// { dg-options "-std=gnu++17" } > >> +// { dg-do compile { target c++17 } } > >> +// { dg-require-effective-target arm_neon_ok } > >> +// { dg-add-options arm_neon } > >> +// { dg-require-cmath "" } > >> + > >> +#include <experimental/simd> > >> + > >> +namespace stdx = std::experimental; > >> + > >> +template <typename U, int N> > >> +using V = stdx::simd<U, stdx::simd_abi::deduce_t<U, N>>; > >> + > >> +template <typename U, int N> > >> +[[gnu::noinline, gnu::noipa]] > >> +int reduce(typename V<U, N>::mask_type x) > >> +{ > >> + using M = typename V<U, N>::mask_type; > >> + static_assert(stdx::find_last_set(M(true)) == N - 1); > >> + return stdx::find_last_set(x); > >> +} > >> + > >> +int main() > >> +{ > >> + // 16 bytes: 16 int8_t lanes, 8 int16_t lanes, 4 int32_t lanes. > >> + const int r_int8_16 = reduce<std::int8_t, 16>(typename V<std::int8_t, > >> 16>::mask_type(true)); + if (r_int8_16 != 15) > >> + __builtin_abort(); > >> + > >> + const int r_int16_8 = reduce<std::int16_t, 8>(typename V<std::int16_t, > >> 8>::mask_type(true)); + if (r_int16_8 != 7) > >> + __builtin_abort(); > >> + > >> + const int r_int32_4 = reduce<std::int32_t, 4>(typename V<std::int32_t, > >> 4>::mask_type(true)); + if (r_int32_4 != 3) > >> + __builtin_abort(); > >> + > >> + // 8 bytes: 8 int8_t lanes, 4 int16_t lanes, 2 int32_t lanes. > >> + const int r_int8_8 = reduce<std::int8_t, 8>(typename V<std::int8_t, > >> 8>::mask_type(true)); + if (r_int8_8 != 7) > >> + __builtin_abort(); > >> + > >> + const int r_int16_4 = reduce<std::int16_t, 4>(typename V<std::int16_t, > >> 4>::mask_type(true)); + if (r_int16_4 != 3) > >> + __builtin_abort(); > >> + > >> + const int r_int32_2 = reduce<std::int32_t, 2>(typename V<std::int32_t, > >> 2>::mask_type(true)); + if (r_int32_2 != 1) > >> + __builtin_abort(); > >> +} -- ────────────────────────────────────────────────────────────────────────── Dr. Matthias Kretz https://mattkretz.github.io GSI Helmholtz Center for Heavy Ion Research https://gsi.de std::simd ──────────────────────────────────────────────────────────────────────────
