17fff39d9SGuillaume Chatelet //===-- Unittests for memory_utils ----------------------------------------===//
27fff39d9SGuillaume Chatelet //
37fff39d9SGuillaume Chatelet // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
47fff39d9SGuillaume Chatelet // See https://llvm.org/LICENSE.txt for license information.
57fff39d9SGuillaume Chatelet // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
67fff39d9SGuillaume Chatelet //
77fff39d9SGuillaume Chatelet //===----------------------------------------------------------------------===//
87fff39d9SGuillaume Chatelet 
9f362aea4SSiva Chandra Reddy #include "src/__support/CPP/Array.h"
101b927b68SGuillaume Chatelet #include "src/__support/CPP/ArrayRef.h"
117fff39d9SGuillaume Chatelet #include "src/string/memory_utils/elements.h"
127fff39d9SGuillaume Chatelet #include "utils/UnitTest/Test.h"
137fff39d9SGuillaume Chatelet 
147fff39d9SGuillaume Chatelet namespace __llvm_libc {
157fff39d9SGuillaume Chatelet 
167fff39d9SGuillaume Chatelet // Registering Types
177fff39d9SGuillaume Chatelet using FixedSizeTypes = testing::TypeList<
18649d9537SGuillaume Chatelet #if defined(__SSE2__)
197fff39d9SGuillaume Chatelet     x86::Vector128, //
207fff39d9SGuillaume Chatelet #endif              // __SSE2__
21649d9537SGuillaume Chatelet #if defined(__AVX2__)
227fff39d9SGuillaume Chatelet     x86::Vector256, //
237fff39d9SGuillaume Chatelet #endif              // __AVX2__
247fff39d9SGuillaume Chatelet #if defined(__AVX512F__) and defined(__AVX512BW__)
257fff39d9SGuillaume Chatelet     x86::Vector512, //
267fff39d9SGuillaume Chatelet #endif              // defined(__AVX512F__) and defined(__AVX512BW__)
277fff39d9SGuillaume Chatelet     scalar::UINT8,  //
287fff39d9SGuillaume Chatelet     scalar::UINT16, //
297fff39d9SGuillaume Chatelet     scalar::UINT32, //
307fff39d9SGuillaume Chatelet     scalar::UINT64, //
317fff39d9SGuillaume Chatelet     Repeated<scalar::UINT64, 2>,                            //
327fff39d9SGuillaume Chatelet     Repeated<scalar::UINT64, 4>,                            //
337fff39d9SGuillaume Chatelet     Repeated<scalar::UINT64, 8>,                            //
347fff39d9SGuillaume Chatelet     Repeated<scalar::UINT64, 16>,                           //
357fff39d9SGuillaume Chatelet     Repeated<scalar::UINT64, 32>,                           //
367fff39d9SGuillaume Chatelet     Chained<scalar::UINT16, scalar::UINT8>,                 //
377fff39d9SGuillaume Chatelet     Chained<scalar::UINT32, scalar::UINT16, scalar::UINT8>, //
387fff39d9SGuillaume Chatelet     builtin::_1,                                            //
397fff39d9SGuillaume Chatelet     builtin::_2,                                            //
407fff39d9SGuillaume Chatelet     builtin::_3,                                            //
417fff39d9SGuillaume Chatelet     builtin::_4,                                            //
427fff39d9SGuillaume Chatelet     builtin::_8                                             //
437fff39d9SGuillaume Chatelet     >;
447fff39d9SGuillaume Chatelet 
GetRandomChar()457fff39d9SGuillaume Chatelet char GetRandomChar() {
467fff39d9SGuillaume Chatelet   static constexpr const uint64_t a = 1103515245;
477fff39d9SGuillaume Chatelet   static constexpr const uint64_t c = 12345;
487fff39d9SGuillaume Chatelet   static constexpr const uint64_t m = 1ULL << 31;
497fff39d9SGuillaume Chatelet   static uint64_t seed = 123456789;
507fff39d9SGuillaume Chatelet   seed = (a * seed + c) % m;
517fff39d9SGuillaume Chatelet   return seed;
527fff39d9SGuillaume Chatelet }
537fff39d9SGuillaume Chatelet 
Randomize(cpp::MutableArrayRef<char> buffer)541b927b68SGuillaume Chatelet void Randomize(cpp::MutableArrayRef<char> buffer) {
557fff39d9SGuillaume Chatelet   for (auto &current : buffer)
567fff39d9SGuillaume Chatelet     current = GetRandomChar();
571b927b68SGuillaume Chatelet }
581b927b68SGuillaume Chatelet 
59*1c92911eSMichael Jones template <typename Element> using Buffer = cpp::Array<char, Element::SIZE>;
601b927b68SGuillaume Chatelet 
GetRandomBuffer()611b927b68SGuillaume Chatelet template <typename Element> Buffer<Element> GetRandomBuffer() {
621b927b68SGuillaume Chatelet   Buffer<Element> buffer;
631b927b68SGuillaume Chatelet   Randomize(buffer);
647fff39d9SGuillaume Chatelet   return buffer;
657fff39d9SGuillaume Chatelet }
667fff39d9SGuillaume Chatelet 
TYPED_TEST(LlvmLibcMemoryElements,copy,FixedSizeTypes)67*1c92911eSMichael Jones TYPED_TEST(LlvmLibcMemoryElements, copy, FixedSizeTypes) {
687fff39d9SGuillaume Chatelet   Buffer<ParamType> Dst;
697fff39d9SGuillaume Chatelet   const auto buffer = GetRandomBuffer<ParamType>();
70*1c92911eSMichael Jones   copy<ParamType>(Dst.data(), buffer.data());
71*1c92911eSMichael Jones   for (size_t i = 0; i < ParamType::SIZE; ++i)
727fff39d9SGuillaume Chatelet     EXPECT_EQ(Dst[i], buffer[i]);
737fff39d9SGuillaume Chatelet }
747fff39d9SGuillaume Chatelet 
copy(const T & Input)75*1c92911eSMichael Jones template <typename T> T copy(const T &Input) {
761b927b68SGuillaume Chatelet   T Output;
771b927b68SGuillaume Chatelet   for (size_t I = 0; I < Input.size(); ++I)
781b927b68SGuillaume Chatelet     Output[I] = Input[I];
791b927b68SGuillaume Chatelet   return Output;
801b927b68SGuillaume Chatelet }
811b927b68SGuillaume Chatelet 
TYPED_TEST(LlvmLibcMemoryElements,Move,FixedSizeTypes)821b927b68SGuillaume Chatelet TYPED_TEST(LlvmLibcMemoryElements, Move, FixedSizeTypes) {
83*1c92911eSMichael Jones   constexpr size_t SIZE = ParamType::SIZE;
84*1c92911eSMichael Jones   using LargeBuffer = cpp::Array<char, SIZE * 2>;
851b927b68SGuillaume Chatelet   LargeBuffer GroundTruth;
861b927b68SGuillaume Chatelet   Randomize(GroundTruth);
87*1c92911eSMichael Jones   // Forward, we move the SIZE first bytes from offset 0 to SIZE.
88*1c92911eSMichael Jones   for (size_t Offset = 0; Offset < SIZE; ++Offset) {
89*1c92911eSMichael Jones     LargeBuffer Buffer = copy(GroundTruth);
90*1c92911eSMichael Jones     move<ParamType>(&Buffer[Offset], &Buffer[0]);
91*1c92911eSMichael Jones     for (size_t I = 0; I < SIZE; ++I)
921b927b68SGuillaume Chatelet       EXPECT_EQ(Buffer[I + Offset], GroundTruth[I]);
931b927b68SGuillaume Chatelet   }
94*1c92911eSMichael Jones   // Backward, we move the SIZE last bytes from offset 0 to SIZE.
95*1c92911eSMichael Jones   for (size_t Offset = 0; Offset < SIZE; ++Offset) {
96*1c92911eSMichael Jones     LargeBuffer Buffer = copy(GroundTruth);
97*1c92911eSMichael Jones     move<ParamType>(&Buffer[Offset], &Buffer[SIZE]);
98*1c92911eSMichael Jones     for (size_t I = 0; I < SIZE; ++I)
99*1c92911eSMichael Jones       EXPECT_EQ(Buffer[I + Offset], GroundTruth[SIZE + I]);
1001b927b68SGuillaume Chatelet   }
1011b927b68SGuillaume Chatelet }
1021b927b68SGuillaume Chatelet 
TYPED_TEST(LlvmLibcMemoryElements,Equals,FixedSizeTypes)1037fff39d9SGuillaume Chatelet TYPED_TEST(LlvmLibcMemoryElements, Equals, FixedSizeTypes) {
1047fff39d9SGuillaume Chatelet   const auto buffer = GetRandomBuffer<ParamType>();
105*1c92911eSMichael Jones   EXPECT_TRUE(equals<ParamType>(buffer.data(), buffer.data()));
1067fff39d9SGuillaume Chatelet }
1077fff39d9SGuillaume Chatelet 
TYPED_TEST(LlvmLibcMemoryElements,three_way_compare,FixedSizeTypes)108*1c92911eSMichael Jones TYPED_TEST(LlvmLibcMemoryElements, three_way_compare, FixedSizeTypes) {
1097fff39d9SGuillaume Chatelet   Buffer<ParamType> initial;
1107fff39d9SGuillaume Chatelet   for (auto &c : initial)
1117fff39d9SGuillaume Chatelet     c = 5;
1127fff39d9SGuillaume Chatelet 
1137fff39d9SGuillaume Chatelet   // Testing equality
114*1c92911eSMichael Jones   EXPECT_EQ(three_way_compare<ParamType>(initial.data(), initial.data()), 0);
1157fff39d9SGuillaume Chatelet 
1167fff39d9SGuillaume Chatelet   // Testing all mismatching positions
117*1c92911eSMichael Jones   for (size_t i = 0; i < ParamType::SIZE; ++i) {
1187fff39d9SGuillaume Chatelet     auto copy = initial;
119*1c92911eSMichael Jones     ++copy[i]; // copy is now lexicographycally greated than initial
1207fff39d9SGuillaume Chatelet     const auto *less = initial.data();
1217fff39d9SGuillaume Chatelet     const auto *greater = copy.data();
122*1c92911eSMichael Jones     EXPECT_LT(three_way_compare<ParamType>(less, greater), 0);
123*1c92911eSMichael Jones     EXPECT_GT(three_way_compare<ParamType>(greater, less), 0);
1247fff39d9SGuillaume Chatelet   }
1257fff39d9SGuillaume Chatelet }
1267fff39d9SGuillaume Chatelet 
TYPED_TEST(LlvmLibcMemoryElements,Splat,FixedSizeTypes)1277fff39d9SGuillaume Chatelet TYPED_TEST(LlvmLibcMemoryElements, Splat, FixedSizeTypes) {
1287fff39d9SGuillaume Chatelet   Buffer<ParamType> Dst;
1297fff39d9SGuillaume Chatelet   const cpp::Array<char, 3> values = {char(0x00), char(0x7F), char(0xFF)};
1307fff39d9SGuillaume Chatelet   for (char value : values) {
131*1c92911eSMichael Jones     splat_set<ParamType>(Dst.data(), value);
132*1c92911eSMichael Jones     for (size_t i = 0; i < ParamType::SIZE; ++i)
1337fff39d9SGuillaume Chatelet       EXPECT_EQ(Dst[i], value);
1347fff39d9SGuillaume Chatelet   }
1357fff39d9SGuillaume Chatelet }
1367fff39d9SGuillaume Chatelet 
1377fff39d9SGuillaume Chatelet } // namespace __llvm_libc
138