-
Notifications
You must be signed in to change notification settings - Fork 15.2k
[libc] Add check for support and a test for libc SIMD helpers #157746
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
@llvm/pr-subscribers-libc Author: Joseph Huber (jhuber6) ChangesSummary: Full diff: https://github.com/llvm/llvm-project/pull/157746.diff 4 Files Affected:
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/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..69324cc913986
--- /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, 4> mask{true, false, true, 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);
+}
|
Summary: This adds a few basic tests for the SIMD helpers and adds a CMake variable we can use to detect support.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM after fixes.
libc.src.__support.CPP.type_traits | ||
) | ||
|
||
if(LIBC_COMPILER_HAS_EXT_VECTOR_TYPE) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
would it make sense to wrap the header library target for simd.h
in this check as well?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What would I do for bazel with that?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's a good point, for the bazel we don't want the check. The cmake doesn't have to exactly match but leaving it out of the cmake is fine. When I get a chance I'll try to get the simd tests working in bazel, but that can be a separate patch.
|
||
simd<int> v_abs = abs(v2); | ||
simd<int> v_min = min(v1, v2); | ||
simd<int> v_max = max(v1, v2); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
could you add tests for all of the elementwise operations?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I figured just showing they work was enough, since they're pretty much all just wrappers around the clang builtins which are expected to work.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It'd be useful to check that they all work even if they're not fully exercised. That way if we end up with a second implementation, like if GCC implements similar intrinsics, we can be confident they behave the same.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, thanks for getting these tested!
Undoing those new tests, they make the bots unhappy because of some math conflicts when run through the unit testing version. I want to merge this stuff and I don't think it really tests much anyway. |
Summary:
This adds a few basic tests for the SIMD helpers and adds a CMake
variable we can use to detect support.