Skip to content

Commit 44d1404

Browse files
authored
[libc] Add check for support and a test for libc SIMD helpers (llvm#157746)
Summary: This adds a few basic tests for the SIMD helpers and adds a CMake variable we can use to detect support.
1 parent 2581354 commit 44d1404

File tree

5 files changed

+93
-1
lines changed

5 files changed

+93
-1
lines changed

libc/cmake/modules/CheckCompilerFeatures.cmake

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ set(
1515
"fixed_point"
1616
"cfloat16"
1717
"cfloat128"
18+
"ext_vector_type"
1819
)
1920

2021
# Making sure ALL_COMPILER_FEATURES is sorted.
@@ -126,6 +127,8 @@ foreach(feature IN LISTS ALL_COMPILER_FEATURES)
126127
set(LIBC_COMPILER_HAS_BUILTIN_ROUND TRUE)
127128
elseif(${feature} STREQUAL "builtin_roundeven")
128129
set(LIBC_COMPILER_HAS_BUILTIN_ROUNDEVEN TRUE)
130+
elseif(${feature} STREQUAL "ext_vector_type")
131+
set(LIBC_COMPILER_HAS_EXT_VECTOR_TYPE TRUE)
129132
endif()
130133
endif()
131134
endforeach()
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#include "src/__support/macros/attributes.h"
2+
3+
#if !LIBC_HAS_VECTOR_TYPE
4+
#error unsupported
5+
#endif
6+
7+
bool [[clang::ext_vector_type(1)]] v;

libc/src/__support/CPP/simd.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ LIBC_INLINE constexpr static int find_first_set(simd<bool, N> m) {
117117
template <size_t N>
118118
LIBC_INLINE constexpr static int find_last_set(simd<bool, N> m) {
119119
constexpr size_t size = simd_size_v<simd<bool, N>>;
120-
return size - __builtin_clzg(m);
120+
return size - 1 - __builtin_clzg(m);
121121
}
122122

123123
// Elementwise operations.

libc/test/src/__support/CPP/CMakeLists.txt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,3 +170,15 @@ add_libc_test(
170170
DEPENDS
171171
libc.src.__support.CPP.type_traits
172172
)
173+
174+
if(LIBC_COMPILER_HAS_EXT_VECTOR_TYPE)
175+
add_libc_test(
176+
simd_test
177+
SUITE
178+
libc-cpp-utils-tests
179+
SRCS
180+
simd_test.cpp
181+
DEPENDS
182+
libc.src.__support.CPP.simd
183+
)
184+
endif()
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
//===-- Unittests for cpp::simd -------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "src/__support/CPP/simd.h"
10+
#include "src/__support/CPP/utility.h"
11+
12+
#include "test/UnitTest/Test.h"
13+
14+
static_assert(LIBC_HAS_VECTOR_TYPE, "compiler needs ext_vector_type support");
15+
16+
using namespace LIBC_NAMESPACE;
17+
18+
TEST(LlvmLibcSIMDTest, Basic) {}
19+
TEST(LlvmLibcSIMDTest, VectorCreation) {
20+
cpp::simd<int> v1 = cpp::splat(5);
21+
cpp::simd<int> v2 = cpp::iota<int>();
22+
23+
EXPECT_EQ(v1[0], 5);
24+
EXPECT_EQ(v2[0], 0);
25+
}
26+
27+
TEST(LlvmLibcSIMDTest, TypeTraits) {
28+
cpp::simd<int> v1 = cpp::splat(0);
29+
30+
static_assert(cpp::is_simd_v<decltype(v1)>, "v1 should be a SIMD type");
31+
static_assert(!cpp::is_simd_v<int>, "int is not a SIMD type");
32+
static_assert(cpp::is_simd_mask_v<cpp::simd<bool, 4>>,
33+
"should be a SIMD mask");
34+
35+
using Elem = cpp::simd_element_type_t<decltype(v1)>;
36+
static_assert(cpp::is_same_v<Elem, int>, "element type should be int");
37+
}
38+
39+
TEST(LlvmLibcSIMDTest, ElementwiseOperations) {
40+
cpp::simd<int> vi1 = cpp::splat(1);
41+
cpp::simd<int> vi2 = cpp::splat(-1);
42+
43+
cpp::simd<int> v_abs = cpp::abs(vi2);
44+
cpp::simd<int> v_min = cpp::min(vi1, vi2);
45+
cpp::simd<int> v_max = cpp::max(vi1, vi2);
46+
47+
EXPECT_EQ(v_abs[0], 1);
48+
EXPECT_EQ(v_min[0], -1);
49+
EXPECT_EQ(v_max[0], 1);
50+
}
51+
52+
TEST(LlvmLibcSIMDTest, ReductionOperations) {
53+
cpp::simd<int> v = cpp::splat(1);
54+
55+
int sum = cpp::reduce(v);
56+
int prod = cpp::reduce(v, cpp::multiplies<>{});
57+
58+
EXPECT_EQ(sum, static_cast<int>(cpp::simd_size_v<decltype(v)>));
59+
EXPECT_EQ(prod, 1);
60+
}
61+
62+
TEST(LlvmLibcSIMDTest, MaskOperations) {
63+
cpp::simd<bool, 8> mask{true, false, true, false, false, false, false, false};
64+
65+
EXPECT_TRUE(cpp::any_of(mask));
66+
EXPECT_FALSE(cpp::all_of(mask));
67+
EXPECT_TRUE(cpp::some_of(mask));
68+
EXPECT_EQ(cpp::find_first_set(mask), 0);
69+
EXPECT_EQ(cpp::find_last_set(mask), 2);
70+
}

0 commit comments

Comments
 (0)