Hi,
On 22/09/26 11:27 pm, Piotr Kubaj wrote:
> The big-endian vbpermq permute constant in _mm_movemask_ps lists the
> four sign-bit indices as 0x00 0x20 0x40 0x60, which puts element 0 in
> the most significant of the four result bits, while x86 (and the
> little-endian branch) put element 0 in bit 0.  Reverse the order so
> big-endian returns the same mask as x86.  _mm_movemask_pd and
> _mm_movemask_epi8 are already correct on both endians.
> 
> The existing sse-movmskps-1.c test cannot catch this: its input has
> negative values in elements 0 and 3 only, and that mask reads the same
> in either bit order.  Add a variant with an asymmetric input.
> 
> Tested with GCC 14 on powerpc64-unknown-freebsd15.1 (POWER9,
> -mcpu=power8): {-1, 2, -3, 4} returned 10 instead of 5 before the fix.
> 

Yeah, this finding is correct for _mm_movemask_ps on Power8 and Power9.
Power10 uses a different implementation.

The new testcase passes with a Power8/9 configuration after this fix. With
Power10 configuration, however, '_mm_movemask_ps' uses 'vec_extractm' instead
of the 'vec_vbpermq' sequence. The 'vec_extractm' path has the issue described
in PR127274, which causes this testcase to fail on Power10 BE.

-Jeevitha.

> Assisted-by: Claude Fable 5.1
> 
> gcc/ChangeLog:
> 
>       * config/rs6000/xmmintrin.h (_mm_movemask_ps): Fix big-endian
>       permute constant.
> 
> gcc/testsuite/ChangeLog:
> 
>       * gcc.target/powerpc/sse-movmskps-2.c: New test.
> 
> Signed-off-by: Piotr Kubaj <[email protected]>
> ---
>  gcc/config/rs6000/xmmintrin.h                 |  2 +-
>  .../gcc.target/powerpc/sse-movmskps-2.c       | 45 +++++++++++++++++++
>  2 files changed, 46 insertions(+), 1 deletion(-)
>  create mode 100644 gcc/testsuite/gcc.target/powerpc/sse-movmskps-2.c
> 
> diff --git a/gcc/config/rs6000/xmmintrin.h b/gcc/config/rs6000/xmmintrin.h
> index bd5be19..79a2a4a 100644
> --- a/gcc/config/rs6000/xmmintrin.h
> +++ b/gcc/config/rs6000/xmmintrin.h
> @@ -1361,7 +1361,7 @@ _mm_movemask_ps (__m128  __A)
>  #ifdef __LITTLE_ENDIAN__
>       0x00204060, 0x80808080, 0x80808080, 0x80808080
>  #else
> -      0x80808080, 0x80808080, 0x80808080, 0x00204060
> +      0x80808080, 0x80808080, 0x80808080, 0x60402000
>  #endif
>      };
>  
> diff --git a/gcc/testsuite/gcc.target/powerpc/sse-movmskps-2.c 
> b/gcc/testsuite/gcc.target/powerpc/sse-movmskps-2.c
> new file mode 100644
> index 0000000..77a4d96
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/powerpc/sse-movmskps-2.c
> @@ -0,0 +1,45 @@
> +/* { dg-do run } */
> +/* { dg-options "-O3 -mvsx" } */
> +/* { dg-additional-options "-mdejagnu-cpu=power8" { target { ! has_arch_pwr8 
> } } } */
> +/* { dg-require-effective-target p8vector_hw } */
> +
> +#define NO_WARN_X86_INTRINSICS 1
> +
> +#ifndef CHECK_H
> +#define CHECK_H "sse-check.h"
> +#endif
> +
> +#include CHECK_H
> +
> +#ifndef TEST
> +#define TEST sse_test_movmskps_2
> +#endif
> +
> +#include <xmmintrin.h>
> +
> +static int
> +__attribute__((noinline, unused))
> +test (__m128 a)
> +{
> +  return _mm_movemask_ps (a);
> +}
> +
> +static void
> +TEST (void)
> +{
> +  union128 u;
> +  float s[4] = {-1.0, 2.0, -3.0, 4.0};
> +  int d;
> +  int e = 0;
> +  int i;
> +
> +  u.x = _mm_loadu_ps (s);
> +  d = test (u.x);
> +
> +  for (i = 0; i < 4; i++)
> +    if (s[i] < 0)
> +      e |= (1 << i);
> +
> +  if (checkVi (&d, &e, 1))
> +    abort ();
> +}
> -- 2.55.0
> 

Reply via email to