Path: blob/21.2-virgl/src/gallium/drivers/nouveau/codegen/nv50_ir_util.cpp
4574 views
/*1* Copyright 2011 Christoph Bumiller2*3* Permission is hereby granted, free of charge, to any person obtaining a4* copy of this software and associated documentation files (the "Software"),5* to deal in the Software without restriction, including without limitation6* the rights to use, copy, modify, merge, publish, distribute, sublicense,7* and/or sell copies of the Software, and to permit persons to whom the8* Software is furnished to do so, subject to the following conditions:9*10* The above copyright notice and this permission notice shall be included in11* all copies or substantial portions of the Software.12*13* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR14* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,15* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL16* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR17* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,18* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR19* OTHER DEALINGS IN THE SOFTWARE.20*/2122#include "codegen/nv50_ir_util.h"2324namespace nv50_ir {2526void DLList::clear()27{28for (Item *next, *item = head.next; item != &head; item = next) {29next = item->next;30delete item;31}32head.next = head.prev = &head;33}3435void36DLList::Iterator::erase()37{38Item *rem = pos;3940if (rem == term)41return;42pos = pos->next;4344DLLIST_DEL(rem);45delete rem;46}4748void DLList::Iterator::moveToList(DLList& dest)49{50Item *item = pos;5152assert(term != &dest.head);53assert(pos != term);5455pos = pos->next;5657DLLIST_DEL(item);58DLLIST_ADDHEAD(&dest.head, item);59}6061bool62DLList::Iterator::insert(void *data)63{64Item *ins = new Item(data);6566ins->next = pos->next;67ins->prev = pos;68pos->next->prev = ins;69pos->next = ins;7071if (pos == term)72term = ins;7374return true;75}7677void78Stack::moveTo(Stack& that)79{80unsigned int newSize = this->size + that.size;8182while (newSize > that.limit)83that.resize();84memcpy(&that.array[that.size], &array[0], this->size * sizeof(Item));8586that.size = newSize;87this->size = 0;88}8990Interval::Interval(const Interval& that) : head(NULL), tail(NULL)91{92this->insert(that);93}9495Interval::~Interval()96{97clear();98}99100void101Interval::clear()102{103for (Range *next, *r = head; r; r = next) {104next = r->next;105delete r;106}107head = tail = NULL;108}109110bool111Interval::extend(int a, int b)112{113Range *r, **nextp = &head;114115// NOTE: we need empty intervals for fixed registers116// if (a == b)117// return false;118assert(a <= b);119120for (r = head; r; r = r->next) {121if (b < r->bgn)122break; // insert before123if (a > r->end) {124// insert after125nextp = &r->next;126continue;127}128129// overlap130if (a < r->bgn) {131r->bgn = a;132if (b > r->end)133r->end = b;134r->coalesce(&tail);135return true;136}137if (b > r->end) {138r->end = b;139r->coalesce(&tail);140return true;141}142assert(a >= r->bgn);143assert(b <= r->end);144return true;145}146147(*nextp) = new Range(a, b);148(*nextp)->next = r;149150for (r = (*nextp); r->next; r = r->next);151tail = r;152return true;153}154155bool Interval::contains(int pos) const156{157for (Range *r = head; r && r->bgn <= pos; r = r->next)158if (r->end > pos)159return true;160return false;161}162163bool Interval::overlaps(const Interval &that) const164{165#if 1166Range *a = this->head;167Range *b = that.head;168169while (a && b) {170if (b->bgn < a->end &&171b->end > a->bgn)172return true;173if (a->end <= b->bgn)174a = a->next;175else176b = b->next;177}178#else179for (Range *rA = this->head; rA; rA = rA->next)180for (Range *rB = iv.head; rB; rB = rB->next)181if (rB->bgn < rA->end &&182rB->end > rA->bgn)183return true;184#endif185return false;186}187188void Interval::insert(const Interval &that)189{190for (Range *r = that.head; r; r = r->next)191this->extend(r->bgn, r->end);192}193194void Interval::unify(Interval &that)195{196assert(this != &that);197for (Range *next, *r = that.head; r; r = next) {198next = r->next;199this->extend(r->bgn, r->end);200delete r;201}202that.head = NULL;203}204205int Interval::length() const206{207int len = 0;208for (Range *r = head; r; r = r->next)209len += r->bgn - r->end;210return len;211}212213void Interval::print() const214{215if (!head)216return;217INFO("[%i %i)", head->bgn, head->end);218for (const Range *r = head->next; r; r = r->next)219INFO(" [%i %i)", r->bgn, r->end);220INFO("\n");221}222223void224BitSet::andNot(const BitSet &set)225{226assert(data && set.data);227assert(size >= set.size);228for (unsigned int i = 0; i < (set.size + 31) / 32; ++i)229data[i] &= ~set.data[i];230}231232BitSet& BitSet::operator|=(const BitSet &set)233{234assert(data && set.data);235assert(size >= set.size);236for (unsigned int i = 0; i < (set.size + 31) / 32; ++i)237data[i] |= set.data[i];238return *this;239}240241bool BitSet::resize(unsigned int nBits)242{243if (!data || !nBits)244return allocate(nBits, true);245const unsigned int p = (size + 31) / 32;246const unsigned int n = (nBits + 31) / 32;247if (n == p)248return true;249250data = (uint32_t *)REALLOC(data, 4 * p, 4 * n);251if (!data) {252size = 0;253return false;254}255if (n > p)256memset(&data[p], 0, (n - p) * 4);257if (nBits < size && (nBits % 32))258data[(nBits + 31) / 32 - 1] &= (1 << (nBits % 32)) - 1;259260size = nBits;261return true;262}263264bool BitSet::allocate(unsigned int nBits, bool zero)265{266if (data && size < nBits) {267FREE(data);268data = NULL;269}270size = nBits;271272if (!data)273data = reinterpret_cast<uint32_t *>(CALLOC((size + 31) / 32, 4));274275if (zero)276memset(data, 0, (size + 7) / 8);277else278if (size % 32) // clear unused bits (e.g. for popCount)279data[(size + 31) / 32 - 1] &= (1 << (size % 32)) - 1;280281return data;282}283284unsigned int BitSet::popCount() const285{286unsigned int count = 0;287288for (unsigned int i = 0; i < (size + 31) / 32; ++i)289if (data[i])290count += util_bitcount(data[i]);291return count;292}293294void BitSet::fill(uint32_t val)295{296unsigned int i;297for (i = 0; i < (size + 31) / 32; ++i)298data[i] = val;299if (val && i)300data[i - 1] &= (1 << (size % 32)) - 1;301}302303void BitSet::setOr(BitSet *pA, BitSet *pB)304{305if (!pB) {306*this = *pA;307} else {308for (unsigned int i = 0; i < (size + 31) / 32; ++i)309data[i] = pA->data[i] | pB->data[i];310}311}312313int BitSet::findFreeRange(unsigned int count, unsigned int max) const314{315const uint32_t m = (1 << count) - 1;316int pos = max;317unsigned int i;318const unsigned int end = (max + 31) / 32;319320if (count == 1) {321for (i = 0; i < end; ++i) {322pos = ffs(~data[i]) - 1;323if (pos >= 0)324break;325}326} else327if (count == 2) {328for (i = 0; i < end; ++i) {329if (data[i] != 0xffffffff) {330uint32_t b = data[i] | (data[i] >> 1) | 0xaaaaaaaa;331pos = ffs(~b) - 1;332if (pos >= 0)333break;334}335}336} else337if (count == 4 || count == 3) {338for (i = 0; i < end; ++i) {339if (data[i] != 0xffffffff) {340uint32_t b =341(data[i] >> 0) | (data[i] >> 1) |342(data[i] >> 2) | (data[i] >> 3) | 0xeeeeeeee;343pos = ffs(~b) - 1;344if (pos >= 0)345break;346}347}348} else {349if (count <= 8)350count = 8;351else352if (count <= 16)353count = 16;354else355count = 32;356357for (i = 0; i < end; ++i) {358if (data[i] != 0xffffffff) {359for (pos = 0; pos < 32; pos += count)360if (!(data[i] & (m << pos)))361break;362if (pos < 32)363break;364}365}366}367368// If we couldn't find a position, we can have a left-over -1 in pos. Make369// sure to abort in such a case.370if (pos < 0)371return -1;372373pos += i * 32;374375return ((pos + count) <= max) ? pos : -1;376}377378void BitSet::print() const379{380unsigned int n = 0;381INFO("BitSet of size %u:\n", size);382for (unsigned int i = 0; i < (size + 31) / 32; ++i) {383uint32_t bits = data[i];384while (bits) {385int pos = ffs(bits) - 1;386bits &= ~(1 << pos);387INFO(" %i", i * 32 + pos);388++n;389if ((n % 16) == 0)390INFO("\n");391}392}393if (n % 16)394INFO("\n");395}396397} // namespace nv50_ir398399400