[libc-commits] [libc] [libc] Add check for support and a test for libc SIMD helpers (PR #157746)

Joseph Huber via libc-commits libc-commits at lists.llvm.org
Tue Sep 9 13:58:25 PDT 2025


https://github.com/jhuber6 updated https://github.com/llvm/llvm-project/pull/157746

>From 9d41d6fd5d6968b5b1aed7b1dac0e43e2b783b96 Mon Sep 17 00:00:00 2001
From: Joseph Huber <huberjn at outlook.com>
Date: Tue, 9 Sep 2025 15:41:22 -0500
Subject: [PATCH] [libc] Add check for support and a test for libc SIMD helpers

Summary:
This adds a few basic tests for the SIMD helpers and adds a CMake
variable we can use to detect support.
---
 .../cmake/modules/CheckCompilerFeatures.cmake |  3 +
 .../check_ext_vector_type.cpp                 |  7 ++
 libc/src/__support/CPP/simd.h                 |  2 +-
 libc/test/src/__support/CPP/CMakeLists.txt    | 12 ++++
 libc/test/src/__support/CPP/simd_test.cpp     | 70 +++++++++++++++++++
 5 files changed, 93 insertions(+), 1 deletion(-)
 create mode 100644 libc/cmake/modules/compiler_features/check_ext_vector_type.cpp
 create mode 100644 libc/test/src/__support/CPP/simd_test.cpp

diff --git a/libc/cmake/modules/CheckCompilerFeatures.cmake b/libc/cmake/modules/CheckCompilerFeatures.cmake
index a5ea66a5935b7..4d50d81e0ce45 100644
--- a/libc/cmake/modules/CheckCompilerFeatures.cmake
+++ b/libc/cmake/modules/CheckCompilerFeatures.cmake
@@ -15,6 +15,7 @@ set(
     "fixed_point"
     "cfloat16"
     "cfloat128"
+    "ext_vector_type"
 )
 
 # Making sure ALL_COMPILER_FEATURES is sorted.
@@ -126,6 +127,8 @@ foreach(feature IN LISTS ALL_COMPILER_FEATURES)
       set(LIBC_COMPILER_HAS_BUILTIN_ROUND TRUE)
     elseif(${feature} STREQUAL "builtin_roundeven")
       set(LIBC_COMPILER_HAS_BUILTIN_ROUNDEVEN TRUE)
+    elseif(${feature} STREQUAL "ext_vector_type")
+      set(LIBC_COMPILER_HAS_EXT_VECTOR_TYPE TRUE)
     endif()
   endif()
 endforeach()
diff --git a/libc/cmake/modules/compiler_features/check_ext_vector_type.cpp b/libc/cmake/modules/compiler_features/check_ext_vector_type.cpp
new file mode 100644
index 0000000000000..f268a8ff540f2
--- /dev/null
+++ b/libc/cmake/modules/compiler_features/check_ext_vector_type.cpp
@@ -0,0 +1,7 @@
+#include "src/__support/macros/attributes.h"
+
+#if !LIBC_HAS_VECTOR_TYPE
+#error unsupported
+#endif
+
+bool [[clang::ext_vector_type(1)]] v;
diff --git a/libc/src/__support/CPP/simd.h b/libc/src/__support/CPP/simd.h
index 449455c5c0390..12a493f6c7138 100644
--- a/libc/src/__support/CPP/simd.h
+++ b/libc/src/__support/CPP/simd.h
@@ -115,7 +115,7 @@ template <size_t N> LIBC_INLINE constexpr int find_first_set(simd<bool, N> m) {
 }
 template <size_t N> LIBC_INLINE constexpr int find_last_set(simd<bool, N> m) {
   constexpr size_t size = simd_size_v<simd<bool, N>>;
-  return size - __builtin_clzg(m);
+  return size - 1 - __builtin_clzg(m);
 }
 
 // Elementwise operations.
diff --git a/libc/test/src/__support/CPP/CMakeLists.txt b/libc/test/src/__support/CPP/CMakeLists.txt
index 3e1379d812c37..70965d6055bbe 100644
--- a/libc/test/src/__support/CPP/CMakeLists.txt
+++ b/libc/test/src/__support/CPP/CMakeLists.txt
@@ -160,3 +160,15 @@ add_libc_test(
   DEPENDS
   libc.src.__support.CPP.type_traits
 )
+
+if(LIBC_COMPILER_HAS_EXT_VECTOR_TYPE)
+  add_libc_test(
+    simd_test
+    SUITE
+      libc-cpp-utils-tests
+    SRCS
+      simd_test.cpp
+    DEPENDS
+      libc.src.__support.CPP.simd
+  )
+endif()
diff --git a/libc/test/src/__support/CPP/simd_test.cpp b/libc/test/src/__support/CPP/simd_test.cpp
new file mode 100644
index 0000000000000..09ec23fef3b61
--- /dev/null
+++ b/libc/test/src/__support/CPP/simd_test.cpp
@@ -0,0 +1,70 @@
+//===-- Unittests for cpp::simd -------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/__support/CPP/simd.h"
+#include "src/__support/CPP/utility.h"
+
+#include "test/UnitTest/FPMatcher.h"
+#include "test/UnitTest/Test.h"
+
+static_assert(LIBC_HAS_VECTOR_TYPE, "compiler needs ext_vector_type support");
+
+using namespace LIBC_NAMESPACE::cpp;
+
+TEST(LlvmLibcSIMDTest, Basic) {}
+TEST(LlvmLibcSIMDTest, VectorCreation) {
+  simd<int> v1 = splat(5);
+  simd<int> v2 = iota<int>();
+
+  EXPECT_EQ(v1[0], 5);
+  EXPECT_EQ(v2[0], 0);
+}
+
+TEST(LlvmLibcSIMDTest, TypeTraits) {
+  simd<int> v1 = splat(0);
+
+  static_assert(is_simd_v<decltype(v1)>, "v1 should be a SIMD type");
+  static_assert(!is_simd_v<int>, "int is not a SIMD type");
+  static_assert(is_simd_mask_v<simd<bool, 4>>, "should be a SIMD mask");
+
+  using Elem = simd_element_type_t<decltype(v1)>;
+  static_assert(is_same_v<Elem, int>, "element type should be int");
+}
+
+TEST(LlvmLibcSIMDTest, ElementwiseOperations) {
+  simd<int> v1 = splat(1);
+  simd<int> v2 = splat(-1);
+
+  simd<int> v_abs = abs(v2);
+  simd<int> v_min = min(v1, v2);
+  simd<int> v_max = max(v1, v2);
+
+  EXPECT_EQ(v_min[0], -1);
+  EXPECT_EQ(v_max[0], 1);
+  EXPECT_EQ(v_abs[0], 1);
+}
+
+TEST(LlvmLibcSIMDTest, ReductionOperations) {
+  simd<int> v = splat(1);
+
+  int sum = reduce(v);
+  int prod = reduce(v, multiplies<>{});
+
+  EXPECT_EQ(sum, static_cast<int>(simd_size_v<decltype(v)>));
+  EXPECT_EQ(prod, 1); // 1*3*5*7
+}
+
+TEST(LlvmLibcSIMDTest, MaskOperations) {
+  simd<bool, 8> mask{true, false, true, false, false, false, false, false};
+
+  EXPECT_TRUE(any_of(mask));
+  EXPECT_FALSE(all_of(mask));
+  EXPECT_TRUE(some_of(mask));
+  EXPECT_EQ(find_first_set(mask), 0);
+  EXPECT_EQ(find_last_set(mask), 2);
+}



More information about the libc-commits mailing list