1 //===-- Elementary operations for native scalar types ---------------------===//
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 #ifndef LLVM_LIBC_SRC_STRING_MEMORY_UTILS_BACKEND_SCALAR_H
9 #define LLVM_LIBC_SRC_STRING_MEMORY_UTILS_BACKEND_SCALAR_H
10 
11 #include "src/__support/CPP/TypeTraits.h" // ConditionalType, EnableIfType
12 #include "src/__support/endian.h"
13 
14 namespace __llvm_libc {
15 
16 struct Scalar64BitBackend {
17   static constexpr bool IS_BACKEND_TYPE = true;
18 
19   template <typename T>
20   static constexpr bool IsScalarType =
21       cpp::IsSameV<T, uint8_t> || cpp::IsSameV<T, uint16_t> ||
22       cpp::IsSameV<T, uint32_t> || cpp::IsSameV<T, uint64_t>;
23 
24   template <typename T, Temporality TS, Aligned AS>
loadScalar64BitBackend25   static inline T load(const T *src) {
26     static_assert(IsScalarType<T>);
27     static_assert(TS == Temporality::TEMPORAL,
28                   "Scalar load does not support non-temporal access");
29     return *src;
30   }
31 
32   template <typename T, Temporality TS, Aligned AS>
storeScalar64BitBackend33   static inline void store(T *dst, T value) {
34     static_assert(IsScalarType<T>);
35     static_assert(TS == Temporality::TEMPORAL,
36                   "Scalar store does not support non-temporal access");
37     *dst = value;
38   }
39 
splatScalar64BitBackend40   template <typename T> static inline T splat(ubyte value) {
41     static_assert(IsScalarType<T>);
42     return (T(~0ULL) / T(0xFF)) * T(value);
43   }
44 
notEqualsScalar64BitBackend45   template <typename T> static inline uint64_t notEquals(T v1, T v2) {
46     static_assert(IsScalarType<T>);
47     return v1 ^ v2;
48   }
49 
threeWayCmpScalar64BitBackend50   template <typename T> static inline int32_t threeWayCmp(T v1, T v2) {
51     DeferredStaticAssert("not implemented");
52   }
53 
54   // Returns the type to use to consume Size bytes.
55   template <size_t Size>
56   using getNextType = cpp::ConditionalType<
57       Size >= 8, uint64_t,
58       cpp::ConditionalType<Size >= 4, uint32_t,
59                            cpp::ConditionalType<Size >= 2, uint16_t, uint8_t>>>;
60 };
61 
62 template <>
63 int32_t inline Scalar64BitBackend::threeWayCmp<uint8_t>(uint8_t a, uint8_t b) {
64   const int16_t la = Endian::to_big_endian(a);
65   const int16_t lb = Endian::to_big_endian(b);
66   return la - lb;
67 }
68 template <>
69 int32_t inline Scalar64BitBackend::threeWayCmp<uint16_t>(uint16_t a,
70                                                          uint16_t b) {
71   const int32_t la = Endian::to_big_endian(a);
72   const int32_t lb = Endian::to_big_endian(b);
73   return la - lb;
74 }
75 template <>
76 int32_t inline Scalar64BitBackend::threeWayCmp<uint32_t>(uint32_t a,
77                                                          uint32_t b) {
78   const uint32_t la = Endian::to_big_endian(a);
79   const uint32_t lb = Endian::to_big_endian(b);
80   return la > lb ? 1 : la < lb ? -1 : 0;
81 }
82 template <>
83 int32_t inline Scalar64BitBackend::threeWayCmp<uint64_t>(uint64_t a,
84                                                          uint64_t b) {
85   const uint64_t la = Endian::to_big_endian(a);
86   const uint64_t lb = Endian::to_big_endian(b);
87   return la > lb ? 1 : la < lb ? -1 : 0;
88 }
89 
90 namespace scalar {
91 using _1 = SizedOp<Scalar64BitBackend, 1>;
92 using _2 = SizedOp<Scalar64BitBackend, 2>;
93 using _3 = SizedOp<Scalar64BitBackend, 3>;
94 using _4 = SizedOp<Scalar64BitBackend, 4>;
95 using _8 = SizedOp<Scalar64BitBackend, 8>;
96 using _16 = SizedOp<Scalar64BitBackend, 16>;
97 using _32 = SizedOp<Scalar64BitBackend, 32>;
98 using _64 = SizedOp<Scalar64BitBackend, 64>;
99 using _128 = SizedOp<Scalar64BitBackend, 128>;
100 } // namespace scalar
101 
102 } // namespace __llvm_libc
103 
104 #endif // LLVM_LIBC_SRC_STRING_MEMORY_UTILS_BACKEND_SCALAR_H
105