brintos

brintos / llvm-project-archived public Read only

0
0
Text · 4.5 KiB · 8bead84 Raw
151 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8 9#include "src/__support/CPP/simd.h"10#include "src/__support/CPP/utility.h"11 12#include "test/UnitTest/Test.h"13 14static_assert(LIBC_HAS_VECTOR_TYPE, "compiler needs ext_vector_type support");15 16using namespace LIBC_NAMESPACE;17 18TEST(LlvmLibcSIMDTest, Basic) {}19TEST(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 27TEST(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 39TEST(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 52TEST(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 62TEST(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_FALSE(cpp::none_of(mask));68  EXPECT_TRUE(cpp::some_of(mask));69  EXPECT_EQ(cpp::find_first_set(mask), 0);70  EXPECT_EQ(cpp::find_last_set(mask), 2);71  EXPECT_EQ(cpp::popcount(mask), 2);72}73 74TEST(LlvmLibcSIMDTest, SplitConcat) {75  cpp::simd<char, 8> v{1, 1, 2, 2, 3, 3, 4, 4};76  auto [v1, v2, v3, v4] = cpp::split<2, 2, 2, 2>(v);77  EXPECT_TRUE(cpp::all_of(v1 == 1));78  EXPECT_TRUE(cpp::all_of(v2 == 2));79  EXPECT_TRUE(cpp::all_of(v3 == 3));80  EXPECT_TRUE(cpp::all_of(v4 == 4));81 82  cpp::simd<char, 8> m = cpp::concat(v1, v2, v3, v4);83  EXPECT_TRUE(cpp::all_of(m == v));84 85  cpp::simd<char, 1> c(~0);86  cpp::simd<char, 8> n = cpp::concat(c, c, c, c, c, c, c, c);87  EXPECT_TRUE(cpp::all_of(n == ~0));88}89 90TEST(LlvmLibcSIMDTest, LoadStore) {91  constexpr size_t SIZE = cpp::simd_size_v<cpp::simd<int>>;92  alignas(alignof(cpp::simd<int>)) int buf[SIZE];93 94  cpp::simd<int> v1 = cpp::splat(1);95  cpp::store(v1, buf);96  cpp::simd<int> v2 = cpp::load<cpp::simd<int>>(buf);97 98  EXPECT_TRUE(cpp::all_of(v1 == 1));99  EXPECT_TRUE(cpp::all_of(v2 == 1));100 101  cpp::simd<int> v3 = cpp::splat(2);102  cpp::store(v3, buf, /*aligned=*/true);103  cpp::simd<int> v4 = cpp::load<cpp::simd<int>>(buf, /*aligned=*/true);104 105  EXPECT_TRUE(cpp::all_of(v3 == 2));106  EXPECT_TRUE(cpp::all_of(v4 == 2));107}108 109TEST(LlvmLibcSIMDTest, MaskedLoadStore) {110  constexpr size_t SIZE = cpp::simd_size_v<cpp::simd<int>>;111  alignas(alignof(cpp::simd<int>)) int buf[SIZE] = {0};112 113  cpp::simd<int> mask = cpp::iota(0) % 2 == 0;114  cpp::simd<int> v1 = cpp::splat(1);115 116  cpp::store_masked<cpp::simd<int>>(mask, v1, buf);117  cpp::simd<int> v2 = cpp::load_masked<cpp::simd<int>>(mask, buf);118 119  EXPECT_TRUE(cpp::all_of((v2 == 1) == mask));120}121 122TEST(LlvmLibcSIMDTest, GatherScatter) {123  constexpr int SIZE = cpp::simd_size_v<cpp::simd<int>>;124  alignas(alignof(cpp::simd<int>)) int buf[SIZE];125 126  cpp::simd<int> mask = cpp::iota(1);127  cpp::simd<int> idx = cpp::iota(0);128  cpp::simd<int> v1 = cpp::splat(1);129 130  cpp::scatter<cpp::simd<int>>(mask, idx, v1, buf);131  cpp::simd<int> v2 = cpp::gather<cpp::simd<int>>(mask, idx, buf);132 133  EXPECT_TRUE(cpp::all_of(v1 == 1));134  EXPECT_TRUE(cpp::all_of(v2 == 1));135}136 137TEST(LlvmLibcSIMDTest, MaskedCompressExpand) {138  constexpr size_t SIZE = cpp::simd_size_v<cpp::simd<int>>;139  alignas(alignof(cpp::simd<int>)) int buf[SIZE] = {0};140 141  cpp::simd<int> mask_expand = cpp::iota(0) % 2 == 0;142  cpp::simd<int> mask_compress = 1;143 144  cpp::simd<int> v1 = cpp::iota(0);145 146  cpp::compress<cpp::simd<int>>(mask_compress, v1, buf);147  cpp::simd<int> v2 = cpp::expand<cpp::simd<int>>(mask_expand, buf);148 149  EXPECT_TRUE(cpp::all_of(!mask_expand || v2 <= SIZE / 2));150}151