Re: [PATCH] libstdc++: arm: convert vpadd_* operands to intrinsic types [PR122981]

Matthias Kretz <[email protected]>
Newsgroups gmane.comp.gcc.patches,gmane.comp.gcc.libstdc++.devel
Organization GSI Helmholtz Center for Heavy Ion Research
Message-ID <[email protected]>
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
──────────────────────────────────────────────────────────────────────────
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.