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