1 //===-- Unittests for memory_utils ----------------------------------------===//
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/Array.h"
10 #include "src/__support/CPP/ArrayRef.h"
11 #include "src/string/memory_utils/elements.h"
12 #include "utils/UnitTest/Test.h"
13 
14 namespace __llvm_libc {
15 
16 // Registering Types
17 using FixedSizeTypes = testing::TypeList<
18 #if defined(__SSE2__)
19     x86::Vector128, //
20 #endif              // __SSE2__
21 #if defined(__AVX2__)
22     x86::Vector256, //
23 #endif              // __AVX2__
24 #if defined(__AVX512F__) and defined(__AVX512BW__)
25     x86::Vector512, //
26 #endif              // defined(__AVX512F__) and defined(__AVX512BW__)
27     scalar::UINT8,  //
28     scalar::UINT16, //
29     scalar::UINT32, //
30     scalar::UINT64, //
31     Repeated<scalar::UINT64, 2>,                            //
32     Repeated<scalar::UINT64, 4>,                            //
33     Repeated<scalar::UINT64, 8>,                            //
34     Repeated<scalar::UINT64, 16>,                           //
35     Repeated<scalar::UINT64, 32>,                           //
36     Chained<scalar::UINT16, scalar::UINT8>,                 //
37     Chained<scalar::UINT32, scalar::UINT16, scalar::UINT8>, //
38     builtin::_1,                                            //
39     builtin::_2,                                            //
40     builtin::_3,                                            //
41     builtin::_4,                                            //
42     builtin::_8                                             //
43     >;
44 
GetRandomChar()45 char GetRandomChar() {
46   static constexpr const uint64_t a = 1103515245;
47   static constexpr const uint64_t c = 12345;
48   static constexpr const uint64_t m = 1ULL << 31;
49   static uint64_t seed = 123456789;
50   seed = (a * seed + c) % m;
51   return seed;
52 }
53 
Randomize(cpp::MutableArrayRef<char> buffer)54 void Randomize(cpp::MutableArrayRef<char> buffer) {
55   for (auto &current : buffer)
56     current = GetRandomChar();
57 }
58 
59 template <typename Element> using Buffer = cpp::Array<char, Element::SIZE>;
60 
GetRandomBuffer()61 template <typename Element> Buffer<Element> GetRandomBuffer() {
62   Buffer<Element> buffer;
63   Randomize(buffer);
64   return buffer;
65 }
66 
TYPED_TEST(LlvmLibcMemoryElements,copy,FixedSizeTypes)67 TYPED_TEST(LlvmLibcMemoryElements, copy, FixedSizeTypes) {
68   Buffer<ParamType> Dst;
69   const auto buffer = GetRandomBuffer<ParamType>();
70   copy<ParamType>(Dst.data(), buffer.data());
71   for (size_t i = 0; i < ParamType::SIZE; ++i)
72     EXPECT_EQ(Dst[i], buffer[i]);
73 }
74 
copy(const T & Input)75 template <typename T> T copy(const T &Input) {
76   T Output;
77   for (size_t I = 0; I < Input.size(); ++I)
78     Output[I] = Input[I];
79   return Output;
80 }
81 
TYPED_TEST(LlvmLibcMemoryElements,Move,FixedSizeTypes)82 TYPED_TEST(LlvmLibcMemoryElements, Move, FixedSizeTypes) {
83   constexpr size_t SIZE = ParamType::SIZE;
84   using LargeBuffer = cpp::Array<char, SIZE * 2>;
85   LargeBuffer GroundTruth;
86   Randomize(GroundTruth);
87   // Forward, we move the SIZE first bytes from offset 0 to SIZE.
88   for (size_t Offset = 0; Offset < SIZE; ++Offset) {
89     LargeBuffer Buffer = copy(GroundTruth);
90     move<ParamType>(&Buffer[Offset], &Buffer[0]);
91     for (size_t I = 0; I < SIZE; ++I)
92       EXPECT_EQ(Buffer[I + Offset], GroundTruth[I]);
93   }
94   // Backward, we move the SIZE last bytes from offset 0 to SIZE.
95   for (size_t Offset = 0; Offset < SIZE; ++Offset) {
96     LargeBuffer Buffer = copy(GroundTruth);
97     move<ParamType>(&Buffer[Offset], &Buffer[SIZE]);
98     for (size_t I = 0; I < SIZE; ++I)
99       EXPECT_EQ(Buffer[I + Offset], GroundTruth[SIZE + I]);
100   }
101 }
102 
TYPED_TEST(LlvmLibcMemoryElements,Equals,FixedSizeTypes)103 TYPED_TEST(LlvmLibcMemoryElements, Equals, FixedSizeTypes) {
104   const auto buffer = GetRandomBuffer<ParamType>();
105   EXPECT_TRUE(equals<ParamType>(buffer.data(), buffer.data()));
106 }
107 
TYPED_TEST(LlvmLibcMemoryElements,three_way_compare,FixedSizeTypes)108 TYPED_TEST(LlvmLibcMemoryElements, three_way_compare, FixedSizeTypes) {
109   Buffer<ParamType> initial;
110   for (auto &c : initial)
111     c = 5;
112 
113   // Testing equality
114   EXPECT_EQ(three_way_compare<ParamType>(initial.data(), initial.data()), 0);
115 
116   // Testing all mismatching positions
117   for (size_t i = 0; i < ParamType::SIZE; ++i) {
118     auto copy = initial;
119     ++copy[i]; // copy is now lexicographycally greated than initial
120     const auto *less = initial.data();
121     const auto *greater = copy.data();
122     EXPECT_LT(three_way_compare<ParamType>(less, greater), 0);
123     EXPECT_GT(three_way_compare<ParamType>(greater, less), 0);
124   }
125 }
126 
TYPED_TEST(LlvmLibcMemoryElements,Splat,FixedSizeTypes)127 TYPED_TEST(LlvmLibcMemoryElements, Splat, FixedSizeTypes) {
128   Buffer<ParamType> Dst;
129   const cpp::Array<char, 3> values = {char(0x00), char(0x7F), char(0xFF)};
130   for (char value : values) {
131     splat_set<ParamType>(Dst.data(), value);
132     for (size_t i = 0; i < ParamType::SIZE; ++i)
133       EXPECT_EQ(Dst[i], value);
134   }
135 }
136 
137 } // namespace __llvm_libc
138