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.

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