Path: blob/21.2-virgl/src/amd/compiler/aco_util.h
4550 views
/*1* Copyright Michael Schellenberger Costa2* Copyright © 2020 Valve Corporation3*4* Permission is hereby granted, free of charge, to any person obtaining a5* copy of this software and associated documentation files (the "Software"),6* to deal in the Software without restriction, including without limitation7* the rights to use, copy, modify, merge, publish, distribute, sublicense,8* and/or sell copies of the Software, and to permit persons to whom the9* Software is furnished to do so, subject to the following conditions:10*11* The above copyright notice and this permission notice (including the next12* paragraph) shall be included in all copies or substantial portions of the13* Software.14*15* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR16* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,17* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL18* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER19* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING20* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS21* IN THE SOFTWARE.22*23*/2425#ifndef ACO_UTIL_H26#define ACO_UTIL_H2728#include "util/bitscan.h"2930#include <cassert>31#include <cstddef>32#include <iterator>33#include <vector>3435namespace aco {3637/*! \brief Definition of a span object38*39* \details A "span" is an "array view" type for holding a view of contiguous40* data. The "span" object does not own the data itself.41*/42template <typename T> class span {43public:44using value_type = T;45using pointer = value_type*;46using const_pointer = const value_type*;47using reference = value_type&;48using const_reference = const value_type&;49using iterator = pointer;50using const_iterator = const_pointer;51using reverse_iterator = std::reverse_iterator<iterator>;52using const_reverse_iterator = std::reverse_iterator<const_iterator>;53using size_type = uint16_t;54using difference_type = std::ptrdiff_t;5556/*! \brief Compiler generated default constructor57*/58constexpr span() = default;5960/*! \brief Constructor taking a pointer and the length of the span61* \param[in] data Pointer to the underlying data array62* \param[in] length The size of the span63*/64constexpr span(uint16_t offset_, const size_type length_) : offset{offset_}, length{length_} {}6566/*! \brief Returns an iterator to the begin of the span67* \return data68*/69constexpr iterator begin() noexcept { return (pointer)((uintptr_t)this + offset); }7071/*! \brief Returns a const_iterator to the begin of the span72* \return data73*/74constexpr const_iterator begin() const noexcept75{76return (const_pointer)((uintptr_t)this + offset);77}7879/*! \brief Returns an iterator to the end of the span80* \return data + length81*/82constexpr iterator end() noexcept { return std::next(begin(), length); }8384/*! \brief Returns a const_iterator to the end of the span85* \return data + length86*/87constexpr const_iterator end() const noexcept { return std::next(begin(), length); }8889/*! \brief Returns a const_iterator to the begin of the span90* \return data91*/92constexpr const_iterator cbegin() const noexcept { return begin(); }9394/*! \brief Returns a const_iterator to the end of the span95* \return data + length96*/97constexpr const_iterator cend() const noexcept { return std::next(begin(), length); }9899/*! \brief Returns a reverse_iterator to the end of the span100* \return reverse_iterator(end())101*/102constexpr reverse_iterator rbegin() noexcept { return reverse_iterator(end()); }103104/*! \brief Returns a const_reverse_iterator to the end of the span105* \return reverse_iterator(end())106*/107constexpr const_reverse_iterator rbegin() const noexcept108{109return const_reverse_iterator(end());110}111112/*! \brief Returns a reverse_iterator to the begin of the span113* \return reverse_iterator(begin())114*/115constexpr reverse_iterator rend() noexcept { return reverse_iterator(begin()); }116117/*! \brief Returns a const_reverse_iterator to the begin of the span118* \return reverse_iterator(begin())119*/120constexpr const_reverse_iterator rend() const noexcept121{122return const_reverse_iterator(begin());123}124125/*! \brief Returns a const_reverse_iterator to the end of the span126* \return rbegin()127*/128constexpr const_reverse_iterator crbegin() const noexcept129{130return const_reverse_iterator(cend());131}132133/*! \brief Returns a const_reverse_iterator to the begin of the span134* \return rend()135*/136constexpr const_reverse_iterator crend() const noexcept137{138return const_reverse_iterator(cbegin());139}140141/*! \brief Unchecked access operator142* \param[in] index Index of the element we want to access143* \return *(std::next(data, index))144*/145constexpr reference operator[](const size_type index) noexcept146{147assert(length > index);148return *(std::next(begin(), index));149}150151/*! \brief Unchecked const access operator152* \param[in] index Index of the element we want to access153* \return *(std::next(data, index))154*/155constexpr const_reference operator[](const size_type index) const noexcept156{157assert(length > index);158return *(std::next(begin(), index));159}160161/*! \brief Returns a reference to the last element of the span162* \return *(std::next(data, length - 1))163*/164constexpr reference back() noexcept165{166assert(length > 0);167return *(std::next(begin(), length - 1));168}169170/*! \brief Returns a const_reference to the last element of the span171* \return *(std::next(data, length - 1))172*/173constexpr const_reference back() const noexcept174{175assert(length > 0);176return *(std::next(begin(), length - 1));177}178179/*! \brief Returns a reference to the first element of the span180* \return *begin()181*/182constexpr reference front() noexcept183{184assert(length > 0);185return *begin();186}187188/*! \brief Returns a const_reference to the first element of the span189* \return *cbegin()190*/191constexpr const_reference front() const noexcept192{193assert(length > 0);194return *cbegin();195}196197/*! \brief Returns true if the span is empty198* \return length == 0199*/200constexpr bool empty() const noexcept { return length == 0; }201202/*! \brief Returns the size of the span203* \return length == 0204*/205constexpr size_type size() const noexcept { return length; }206207/*! \brief Decreases the size of the span by 1208*/209constexpr void pop_back() noexcept210{211assert(length > 0);212--length;213}214215/*! \brief Adds an element to the end of the span216*/217constexpr void push_back(const_reference val) noexcept { *std::next(begin(), length++) = val; }218219/*! \brief Clears the span220*/221constexpr void clear() noexcept222{223offset = 0;224length = 0;225}226227private:228uint16_t offset{0}; //!> Byte offset from span to data229size_type length{0}; //!> Size of the span230};231232/*233* Cache-friendly set of 32-bit IDs with O(1) insert/erase/lookup and234* the ability to efficiently iterate over contained elements.235*236* Internally implemented as a bit vector: If the set contains an ID, the237* corresponding bit is set. It doesn't use std::vector<bool> since we then238* couldn't efficiently iterate over the elements.239*240* The interface resembles a subset of std::set/std::unordered_set.241*/242struct IDSet {243struct Iterator {244const IDSet* set;245union {246struct {247uint32_t bit : 6;248uint32_t word : 26;249};250uint32_t id;251};252253Iterator& operator++();254255bool operator!=(const Iterator& other) const;256257uint32_t operator*() const;258};259260size_t count(uint32_t id) const261{262if (id >= words.size() * 64)263return 0;264265return words[id / 64u] & (1ull << (id % 64u)) ? 1 : 0;266}267268Iterator find(uint32_t id) const269{270if (!count(id))271return end();272273Iterator it;274it.set = this;275it.bit = id % 64u;276it.word = id / 64u;277return it;278}279280std::pair<Iterator, bool> insert(uint32_t id)281{282if (words.size() * 64u <= id)283words.resize(id / 64u + 1);284285Iterator it;286it.set = this;287it.bit = id % 64u;288it.word = id / 64u;289290uint64_t mask = 1ull << it.bit;291if (words[it.word] & mask)292return std::make_pair(it, false);293294words[it.word] |= mask;295bits_set++;296return std::make_pair(it, true);297}298299size_t erase(uint32_t id)300{301if (!count(id))302return 0;303304words[id / 64u] ^= 1ull << (id % 64u);305bits_set--;306return 1;307}308309Iterator cbegin() const310{311Iterator it;312it.set = this;313for (size_t i = 0; i < words.size(); i++) {314if (words[i]) {315it.word = i;316it.bit = ffsll(words[i]) - 1;317return it;318}319}320return end();321}322323Iterator cend() const324{325Iterator it;326it.set = this;327it.word = words.size();328it.bit = 0;329return it;330}331332Iterator begin() const { return cbegin(); }333334Iterator end() const { return cend(); }335336bool empty() const { return bits_set == 0; }337338size_t size() const { return bits_set; }339340std::vector<uint64_t> words;341uint32_t bits_set = 0;342};343344inline IDSet::Iterator&345IDSet::Iterator::operator++()346{347uint64_t m = set->words[word];348m &= ~((2ull << bit) - 1ull);349if (!m) {350/* don't continue past the end */351if (word == set->words.size())352return *this;353354word++;355for (; word < set->words.size(); word++) {356if (set->words[word]) {357bit = ffsll(set->words[word]) - 1;358return *this;359}360}361bit = 0;362} else {363bit = ffsll(m) - 1;364}365return *this;366}367368inline bool369IDSet::Iterator::operator!=(const IDSet::Iterator& other) const370{371assert(set == other.set);372return id != other.id;373}374375inline uint32_t376IDSet::Iterator::operator*() const377{378return (word << 6) | bit;379}380381} // namespace aco382383#endif // ACO_UTIL_H384385386