1 | /******************************************************************************* |
2 | * Copyright 2019-2022 Intel Corporation |
3 | * |
4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
5 | * you may not use this file except in compliance with the License. |
6 | * You may obtain a copy of the License at |
7 | * |
8 | * http://www.apache.org/licenses/LICENSE-2.0 |
9 | * |
10 | * Unless required by applicable law or agreed to in writing, software |
11 | * distributed under the License is distributed on an "AS IS" BASIS, |
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
13 | * See the License for the specific language governing permissions and |
14 | * limitations under the License. |
15 | *******************************************************************************/ |
16 | |
17 | #ifndef NGEN_UTILS_HPP |
18 | #define NGEN_UTILS_HPP |
19 | |
20 | #include <cstdint> |
21 | |
22 | #ifdef _MSC_VER |
23 | #include <intrin.h> |
24 | #endif |
25 | |
26 | #ifdef NGEN_CPP11 |
27 | #define constexpr14 |
28 | #else |
29 | #define constexpr14 constexpr |
30 | #endif |
31 | |
32 | namespace ngen { |
33 | namespace utils { |
34 | |
35 | template <typename T, typename U> |
36 | struct bitcast { |
37 | union { |
38 | T from; |
39 | U to; |
40 | }; |
41 | |
42 | explicit constexpr bitcast(T t) : from{t} {} |
43 | constexpr operator U() const { return to; } |
44 | }; |
45 | |
46 | template <typename T> static inline constexpr14 int bsf(T x) |
47 | { |
48 | #if defined(_MSC_VER) && !defined(__clang__) |
49 | unsigned long index; |
50 | if (sizeof(T) > 4) |
51 | (void) _BitScanForward64(&index, x); |
52 | else |
53 | (void) _BitScanForward(&index, x); |
54 | return index; |
55 | #else |
56 | if (sizeof(T) > 4) |
57 | return __builtin_ctzll(x); |
58 | else |
59 | return __builtin_ctz(x); |
60 | #endif |
61 | } |
62 | |
63 | template <typename T> static inline constexpr14 int bsr(T x) |
64 | { |
65 | #if defined(_MSC_VER) && !defined(__clang__) |
66 | unsigned long index; |
67 | if (sizeof(T) > 4) |
68 | (void) _BitScanReverse64(&index, x); |
69 | else |
70 | (void) _BitScanReverse(&index, x); |
71 | return index; |
72 | #else |
73 | if (sizeof(T) > 4) |
74 | return (sizeof(unsigned long long) * 8 - 1) - __builtin_clzll(x); |
75 | else |
76 | return (sizeof(int) * 8 - 1) - __builtin_clz(x); |
77 | #endif |
78 | } |
79 | |
80 | template <typename T> static inline constexpr14 int popcnt(T x) |
81 | { |
82 | #if defined(_MSC_VER) && !defined(__clang__) |
83 | if (sizeof(T) > 4) |
84 | return __popcnt64(x); |
85 | else |
86 | return __popcnt(x); |
87 | #else |
88 | if (sizeof(T) > 4) |
89 | return __builtin_popcountll(x); |
90 | else |
91 | return __builtin_popcount(x); |
92 | #endif |
93 | } |
94 | |
95 | template <typename T> static inline constexpr14 T roundup_pow2(T x) |
96 | { |
97 | if (x <= 1) |
98 | return 1; |
99 | else |
100 | return 1 << (1 + bsr(x - 1)); |
101 | } |
102 | |
103 | template <typename T> static inline constexpr14 T rounddown_pow2(T x) |
104 | { |
105 | return (x <= 1) ? x : (1 << bsr(x)); |
106 | } |
107 | |
108 | template <typename T> static inline constexpr bool is_zero_or_pow2(T x) |
109 | { |
110 | return !(x & (x - 1)); |
111 | } |
112 | |
113 | template <typename T> static inline constexpr14 int log2(T x) |
114 | { |
115 | return bsr(x); |
116 | } |
117 | |
118 | template <typename T> static inline constexpr T alignup_pow2(T x, int align) |
119 | { |
120 | return (x + align - 1) & -align; |
121 | } |
122 | |
123 | template <typename Container> |
124 | static inline void copy_into(std::vector<uint8_t> &dst, size_t dst_offset, |
125 | const Container &src, size_t src_offset, |
126 | size_t bytes) |
127 | { |
128 | if (src_offset >= src.size()) return; |
129 | if (dst_offset >= dst.size()) return; |
130 | |
131 | bytes = std::min({bytes, src.size() - src_offset, dst.size() - dst_offset}); |
132 | |
133 | for (size_t i = 0; i < bytes; i++) |
134 | dst[i + dst_offset] = src[i + src_offset]; |
135 | } |
136 | |
137 | template <typename Container> |
138 | static inline void copy_into(std::vector<uint8_t> &dst, size_t dst_offset, |
139 | const Container &src) |
140 | { |
141 | copy_into(dst, dst_offset, src, 0, src.size()); |
142 | } |
143 | |
144 | } /* namespace utils */ |
145 | } /* namespace ngen */ |
146 | |
147 | #endif |
148 | |