public inbox for libstdc++-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc r15-1500] libstdc++: Fix find_last_set(simd_mask) to ignore padding bits
@ 2024-06-20 10:57 Matthias Kretz
  0 siblings, 0 replies; only message in thread
From: Matthias Kretz @ 2024-06-20 10:57 UTC (permalink / raw)
  To: gcc-cvs, libstdc++-cvs

https://gcc.gnu.org/g:1340ddea0158de3f49aeb75b4013e5fc313ff6f4

commit r15-1500-g1340ddea0158de3f49aeb75b4013e5fc313ff6f4
Author: Matthias Kretz <m.kretz@gsi.de>
Date:   Fri Jun 14 15:11:25 2024 +0200

    libstdc++: Fix find_last_set(simd_mask) to ignore padding bits
    
    With the change to the AVX512 find_last_set implementation, the change
    to AVX512 operator!= is unnecessary. However, the latter was not
    producing optimal code and unnecessarily set the padding bits. In
    theory, the compiler could determine that with the new !=
    implementation, the bit operation for clearing the padding bits is a
    no-op and can be elided.
    
    Signed-off-by: Matthias Kretz <m.kretz@gsi.de>
    
    libstdc++-v3/ChangeLog:
    
            PR libstdc++/115454
            * include/experimental/bits/simd_x86.h (_S_not_equal_to): Use
            neq comparison instead of bitwise negation after eq.
            (_S_find_last_set): Clear unused high bits before computing
            bit_width.
            * testsuite/experimental/simd/pr115454_find_last_set.cc: New
            test.

Diff:
---
 libstdc++-v3/include/experimental/bits/simd_x86.h  | 26 ++++++------
 .../experimental/simd/pr115454_find_last_set.cc    | 49 ++++++++++++++++++++++
 2 files changed, 62 insertions(+), 13 deletions(-)

diff --git a/libstdc++-v3/include/experimental/bits/simd_x86.h b/libstdc++-v3/include/experimental/bits/simd_x86.h
index 4ab933b573c6..e498b1e4ee4d 100644
--- a/libstdc++-v3/include/experimental/bits/simd_x86.h
+++ b/libstdc++-v3/include/experimental/bits/simd_x86.h
@@ -2339,29 +2339,29 @@ template <typename _Abi, typename>
 		  __assert_unreachable<_Tp>();
 	      }
 	    else if constexpr (sizeof(__xi) == 64 && sizeof(_Tp) == 8)
-	      return ~_mm512_mask_cmpeq_epi64_mask(__k1, __xi, __yi);
+	      return _mm512_mask_cmpneq_epi64_mask(__k1, __xi, __yi);
 	    else if constexpr (sizeof(__xi) == 64 && sizeof(_Tp) == 4)
-	      return ~_mm512_mask_cmpeq_epi32_mask(__k1, __xi, __yi);
+	      return _mm512_mask_cmpneq_epi32_mask(__k1, __xi, __yi);
 	    else if constexpr (sizeof(__xi) == 64 && sizeof(_Tp) == 2)
-	      return ~_mm512_mask_cmpeq_epi16_mask(__k1, __xi, __yi);
+	      return _mm512_mask_cmpneq_epi16_mask(__k1, __xi, __yi);
 	    else if constexpr (sizeof(__xi) == 64 && sizeof(_Tp) == 1)
-	      return ~_mm512_mask_cmpeq_epi8_mask(__k1, __xi, __yi);
+	      return _mm512_mask_cmpneq_epi8_mask(__k1, __xi, __yi);
 	    else if constexpr (sizeof(__xi) == 32 && sizeof(_Tp) == 8)
-	      return ~_mm256_mask_cmpeq_epi64_mask(__k1, __xi, __yi);
+	      return _mm256_mask_cmpneq_epi64_mask(__k1, __xi, __yi);
 	    else if constexpr (sizeof(__xi) == 32 && sizeof(_Tp) == 4)
-	      return ~_mm256_mask_cmpeq_epi32_mask(__k1, __xi, __yi);
+	      return _mm256_mask_cmpneq_epi32_mask(__k1, __xi, __yi);
 	    else if constexpr (sizeof(__xi) == 32 && sizeof(_Tp) == 2)
-	      return ~_mm256_mask_cmpeq_epi16_mask(__k1, __xi, __yi);
+	      return _mm256_mask_cmpneq_epi16_mask(__k1, __xi, __yi);
 	    else if constexpr (sizeof(__xi) == 32 && sizeof(_Tp) == 1)
-	      return ~_mm256_mask_cmpeq_epi8_mask(__k1, __xi, __yi);
+	      return _mm256_mask_cmpneq_epi8_mask(__k1, __xi, __yi);
 	    else if constexpr (sizeof(__xi) == 16 && sizeof(_Tp) == 8)
-	      return ~_mm_mask_cmpeq_epi64_mask(__k1, __xi, __yi);
+	      return _mm_mask_cmpneq_epi64_mask(__k1, __xi, __yi);
 	    else if constexpr (sizeof(__xi) == 16 && sizeof(_Tp) == 4)
-	      return ~_mm_mask_cmpeq_epi32_mask(__k1, __xi, __yi);
+	      return _mm_mask_cmpneq_epi32_mask(__k1, __xi, __yi);
 	    else if constexpr (sizeof(__xi) == 16 && sizeof(_Tp) == 2)
-	      return ~_mm_mask_cmpeq_epi16_mask(__k1, __xi, __yi);
+	      return _mm_mask_cmpneq_epi16_mask(__k1, __xi, __yi);
 	    else if constexpr (sizeof(__xi) == 16 && sizeof(_Tp) == 1)
-	      return ~_mm_mask_cmpeq_epi8_mask(__k1, __xi, __yi);
+	      return _mm_mask_cmpneq_epi8_mask(__k1, __xi, __yi);
 	    else
 	      __assert_unreachable<_Tp>();
 	  }                                                   // }}}
@@ -5292,7 +5292,7 @@ template <typename _Abi, typename>
       _S_find_last_set(simd_mask<_Tp, _Abi> __k)
       {
 	if constexpr (__is_avx512_abi<_Abi>())
-	  return std::__bit_width(__k._M_data._M_data) - 1;
+	  return std::__bit_width(_Abi::_S_masked(__k._M_data)._M_data) - 1;
 	else
 	  return _Base::_S_find_last_set(__k);
       }
diff --git a/libstdc++-v3/testsuite/experimental/simd/pr115454_find_last_set.cc b/libstdc++-v3/testsuite/experimental/simd/pr115454_find_last_set.cc
new file mode 100644
index 000000000000..b47f19d30674
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/simd/pr115454_find_last_set.cc
@@ -0,0 +1,49 @@
+// { dg-options "-std=gnu++17" }
+// { dg-do run { target *-*-* } }
+// { dg-require-effective-target c++17 }
+// { dg-additional-options "-march=x86-64-v4" { target avx512f } }
+// { dg-require-cmath "" }
+
+#include <experimental/simd>
+
+namespace stdx = std::experimental;
+
+using T = std::uint64_t;
+
+template <typename U, int N>
+using V = stdx::simd<U, stdx::simd_abi::deduce_t<U, N>>;
+
+[[gnu::noinline, gnu::noipa]]
+int reduce(V<T, 4> x)
+{
+  static_assert(stdx::find_last_set(V<T, 4>([](unsigned i) { return i; }) != V<T, 4>(0)) == 3);
+  return stdx::find_last_set(x != -1);
+}
+
+[[gnu::noinline, gnu::noipa]]
+int reduce2()
+{
+  using M8 = typename V<short, 8>::mask_type;
+  using M4 = typename V<int, 4>::mask_type;
+  if constexpr (sizeof(M8) == sizeof(M4))
+    {
+      M4 k;
+      __builtin_memcpy(&__data(k), &__data(M8(true)), sizeof(M4));
+      return stdx::find_last_set(k);
+    }
+  return 3;
+}
+
+
+int main()
+{
+  const V<T, 4> x {};
+
+  const int r = reduce(x);
+  if (r != 3)
+      __builtin_abort();
+
+  const int r2 = reduce2();
+  if (r2 != 3)
+      __builtin_abort();
+}

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2024-06-20 10:57 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-06-20 10:57 [gcc r15-1500] libstdc++: Fix find_last_set(simd_mask) to ignore padding bits Matthias Kretz

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).