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
32namespace ngen {
33namespace utils {
34
35template <typename T, typename U>
36struct 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
46template <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
63template <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
80template <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
95template <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
103template <typename T> static inline constexpr14 T rounddown_pow2(T x)
104{
105 return (x <= 1) ? x : (1 << bsr(x));
106}
107
108template <typename T> static inline constexpr bool is_zero_or_pow2(T x)
109{
110 return !(x & (x - 1));
111}
112
113template <typename T> static inline constexpr14 int log2(T x)
114{
115 return bsr(x);
116}
117
118template <typename T> static inline constexpr T alignup_pow2(T x, int align)
119{
120 return (x + align - 1) & -align;
121}
122
123template <typename Container>
124static 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
137template <typename Container>
138static 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