Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mesa
Path: blob/21.2-virgl/src/amd/compiler/aco_util.h
4550 views
1
/*
2
* Copyright Michael Schellenberger Costa
3
* Copyright © 2020 Valve Corporation
4
*
5
* Permission is hereby granted, free of charge, to any person obtaining a
6
* copy of this software and associated documentation files (the "Software"),
7
* to deal in the Software without restriction, including without limitation
8
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
9
* and/or sell copies of the Software, and to permit persons to whom the
10
* Software is furnished to do so, subject to the following conditions:
11
*
12
* The above copyright notice and this permission notice (including the next
13
* paragraph) shall be included in all copies or substantial portions of the
14
* Software.
15
*
16
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22
* IN THE SOFTWARE.
23
*
24
*/
25
26
#ifndef ACO_UTIL_H
27
#define ACO_UTIL_H
28
29
#include "util/bitscan.h"
30
31
#include <cassert>
32
#include <cstddef>
33
#include <iterator>
34
#include <vector>
35
36
namespace aco {
37
38
/*! \brief Definition of a span object
39
*
40
* \details A "span" is an "array view" type for holding a view of contiguous
41
* data. The "span" object does not own the data itself.
42
*/
43
template <typename T> class span {
44
public:
45
using value_type = T;
46
using pointer = value_type*;
47
using const_pointer = const value_type*;
48
using reference = value_type&;
49
using const_reference = const value_type&;
50
using iterator = pointer;
51
using const_iterator = const_pointer;
52
using reverse_iterator = std::reverse_iterator<iterator>;
53
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
54
using size_type = uint16_t;
55
using difference_type = std::ptrdiff_t;
56
57
/*! \brief Compiler generated default constructor
58
*/
59
constexpr span() = default;
60
61
/*! \brief Constructor taking a pointer and the length of the span
62
* \param[in] data Pointer to the underlying data array
63
* \param[in] length The size of the span
64
*/
65
constexpr span(uint16_t offset_, const size_type length_) : offset{offset_}, length{length_} {}
66
67
/*! \brief Returns an iterator to the begin of the span
68
* \return data
69
*/
70
constexpr iterator begin() noexcept { return (pointer)((uintptr_t)this + offset); }
71
72
/*! \brief Returns a const_iterator to the begin of the span
73
* \return data
74
*/
75
constexpr const_iterator begin() const noexcept
76
{
77
return (const_pointer)((uintptr_t)this + offset);
78
}
79
80
/*! \brief Returns an iterator to the end of the span
81
* \return data + length
82
*/
83
constexpr iterator end() noexcept { return std::next(begin(), length); }
84
85
/*! \brief Returns a const_iterator to the end of the span
86
* \return data + length
87
*/
88
constexpr const_iterator end() const noexcept { return std::next(begin(), length); }
89
90
/*! \brief Returns a const_iterator to the begin of the span
91
* \return data
92
*/
93
constexpr const_iterator cbegin() const noexcept { return begin(); }
94
95
/*! \brief Returns a const_iterator to the end of the span
96
* \return data + length
97
*/
98
constexpr const_iterator cend() const noexcept { return std::next(begin(), length); }
99
100
/*! \brief Returns a reverse_iterator to the end of the span
101
* \return reverse_iterator(end())
102
*/
103
constexpr reverse_iterator rbegin() noexcept { return reverse_iterator(end()); }
104
105
/*! \brief Returns a const_reverse_iterator to the end of the span
106
* \return reverse_iterator(end())
107
*/
108
constexpr const_reverse_iterator rbegin() const noexcept
109
{
110
return const_reverse_iterator(end());
111
}
112
113
/*! \brief Returns a reverse_iterator to the begin of the span
114
* \return reverse_iterator(begin())
115
*/
116
constexpr reverse_iterator rend() noexcept { return reverse_iterator(begin()); }
117
118
/*! \brief Returns a const_reverse_iterator to the begin of the span
119
* \return reverse_iterator(begin())
120
*/
121
constexpr const_reverse_iterator rend() const noexcept
122
{
123
return const_reverse_iterator(begin());
124
}
125
126
/*! \brief Returns a const_reverse_iterator to the end of the span
127
* \return rbegin()
128
*/
129
constexpr const_reverse_iterator crbegin() const noexcept
130
{
131
return const_reverse_iterator(cend());
132
}
133
134
/*! \brief Returns a const_reverse_iterator to the begin of the span
135
* \return rend()
136
*/
137
constexpr const_reverse_iterator crend() const noexcept
138
{
139
return const_reverse_iterator(cbegin());
140
}
141
142
/*! \brief Unchecked access operator
143
* \param[in] index Index of the element we want to access
144
* \return *(std::next(data, index))
145
*/
146
constexpr reference operator[](const size_type index) noexcept
147
{
148
assert(length > index);
149
return *(std::next(begin(), index));
150
}
151
152
/*! \brief Unchecked const access operator
153
* \param[in] index Index of the element we want to access
154
* \return *(std::next(data, index))
155
*/
156
constexpr const_reference operator[](const size_type index) const noexcept
157
{
158
assert(length > index);
159
return *(std::next(begin(), index));
160
}
161
162
/*! \brief Returns a reference to the last element of the span
163
* \return *(std::next(data, length - 1))
164
*/
165
constexpr reference back() noexcept
166
{
167
assert(length > 0);
168
return *(std::next(begin(), length - 1));
169
}
170
171
/*! \brief Returns a const_reference to the last element of the span
172
* \return *(std::next(data, length - 1))
173
*/
174
constexpr const_reference back() const noexcept
175
{
176
assert(length > 0);
177
return *(std::next(begin(), length - 1));
178
}
179
180
/*! \brief Returns a reference to the first element of the span
181
* \return *begin()
182
*/
183
constexpr reference front() noexcept
184
{
185
assert(length > 0);
186
return *begin();
187
}
188
189
/*! \brief Returns a const_reference to the first element of the span
190
* \return *cbegin()
191
*/
192
constexpr const_reference front() const noexcept
193
{
194
assert(length > 0);
195
return *cbegin();
196
}
197
198
/*! \brief Returns true if the span is empty
199
* \return length == 0
200
*/
201
constexpr bool empty() const noexcept { return length == 0; }
202
203
/*! \brief Returns the size of the span
204
* \return length == 0
205
*/
206
constexpr size_type size() const noexcept { return length; }
207
208
/*! \brief Decreases the size of the span by 1
209
*/
210
constexpr void pop_back() noexcept
211
{
212
assert(length > 0);
213
--length;
214
}
215
216
/*! \brief Adds an element to the end of the span
217
*/
218
constexpr void push_back(const_reference val) noexcept { *std::next(begin(), length++) = val; }
219
220
/*! \brief Clears the span
221
*/
222
constexpr void clear() noexcept
223
{
224
offset = 0;
225
length = 0;
226
}
227
228
private:
229
uint16_t offset{0}; //!> Byte offset from span to data
230
size_type length{0}; //!> Size of the span
231
};
232
233
/*
234
* Cache-friendly set of 32-bit IDs with O(1) insert/erase/lookup and
235
* the ability to efficiently iterate over contained elements.
236
*
237
* Internally implemented as a bit vector: If the set contains an ID, the
238
* corresponding bit is set. It doesn't use std::vector<bool> since we then
239
* couldn't efficiently iterate over the elements.
240
*
241
* The interface resembles a subset of std::set/std::unordered_set.
242
*/
243
struct IDSet {
244
struct Iterator {
245
const IDSet* set;
246
union {
247
struct {
248
uint32_t bit : 6;
249
uint32_t word : 26;
250
};
251
uint32_t id;
252
};
253
254
Iterator& operator++();
255
256
bool operator!=(const Iterator& other) const;
257
258
uint32_t operator*() const;
259
};
260
261
size_t count(uint32_t id) const
262
{
263
if (id >= words.size() * 64)
264
return 0;
265
266
return words[id / 64u] & (1ull << (id % 64u)) ? 1 : 0;
267
}
268
269
Iterator find(uint32_t id) const
270
{
271
if (!count(id))
272
return end();
273
274
Iterator it;
275
it.set = this;
276
it.bit = id % 64u;
277
it.word = id / 64u;
278
return it;
279
}
280
281
std::pair<Iterator, bool> insert(uint32_t id)
282
{
283
if (words.size() * 64u <= id)
284
words.resize(id / 64u + 1);
285
286
Iterator it;
287
it.set = this;
288
it.bit = id % 64u;
289
it.word = id / 64u;
290
291
uint64_t mask = 1ull << it.bit;
292
if (words[it.word] & mask)
293
return std::make_pair(it, false);
294
295
words[it.word] |= mask;
296
bits_set++;
297
return std::make_pair(it, true);
298
}
299
300
size_t erase(uint32_t id)
301
{
302
if (!count(id))
303
return 0;
304
305
words[id / 64u] ^= 1ull << (id % 64u);
306
bits_set--;
307
return 1;
308
}
309
310
Iterator cbegin() const
311
{
312
Iterator it;
313
it.set = this;
314
for (size_t i = 0; i < words.size(); i++) {
315
if (words[i]) {
316
it.word = i;
317
it.bit = ffsll(words[i]) - 1;
318
return it;
319
}
320
}
321
return end();
322
}
323
324
Iterator cend() const
325
{
326
Iterator it;
327
it.set = this;
328
it.word = words.size();
329
it.bit = 0;
330
return it;
331
}
332
333
Iterator begin() const { return cbegin(); }
334
335
Iterator end() const { return cend(); }
336
337
bool empty() const { return bits_set == 0; }
338
339
size_t size() const { return bits_set; }
340
341
std::vector<uint64_t> words;
342
uint32_t bits_set = 0;
343
};
344
345
inline IDSet::Iterator&
346
IDSet::Iterator::operator++()
347
{
348
uint64_t m = set->words[word];
349
m &= ~((2ull << bit) - 1ull);
350
if (!m) {
351
/* don't continue past the end */
352
if (word == set->words.size())
353
return *this;
354
355
word++;
356
for (; word < set->words.size(); word++) {
357
if (set->words[word]) {
358
bit = ffsll(set->words[word]) - 1;
359
return *this;
360
}
361
}
362
bit = 0;
363
} else {
364
bit = ffsll(m) - 1;
365
}
366
return *this;
367
}
368
369
inline bool
370
IDSet::Iterator::operator!=(const IDSet::Iterator& other) const
371
{
372
assert(set == other.set);
373
return id != other.id;
374
}
375
376
inline uint32_t
377
IDSet::Iterator::operator*() const
378
{
379
return (word << 6) | bit;
380
}
381
382
} // namespace aco
383
384
#endif // ACO_UTIL_H
385
386