1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright 2011 Christoph Bumiller 3bf215546Sopenharmony_ci * 4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation 7bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 9bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions: 10bf215546Sopenharmony_ci * 11bf215546Sopenharmony_ci * The above copyright notice and this permission notice shall be included in 12bf215546Sopenharmony_ci * all copies or substantial portions of the Software. 13bf215546Sopenharmony_ci * 14bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 18bf215546Sopenharmony_ci * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19bf215546Sopenharmony_ci * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20bf215546Sopenharmony_ci * OTHER DEALINGS IN THE SOFTWARE. 21bf215546Sopenharmony_ci */ 22bf215546Sopenharmony_ci 23bf215546Sopenharmony_ci#include "nv50_ir_util.h" 24bf215546Sopenharmony_ci 25bf215546Sopenharmony_cinamespace nv50_ir { 26bf215546Sopenharmony_ci 27bf215546Sopenharmony_civoid DLList::clear() 28bf215546Sopenharmony_ci{ 29bf215546Sopenharmony_ci for (Item *next, *item = head.next; item != &head; item = next) { 30bf215546Sopenharmony_ci next = item->next; 31bf215546Sopenharmony_ci delete item; 32bf215546Sopenharmony_ci } 33bf215546Sopenharmony_ci head.next = head.prev = &head; 34bf215546Sopenharmony_ci} 35bf215546Sopenharmony_ci 36bf215546Sopenharmony_civoid 37bf215546Sopenharmony_ciDLList::Iterator::erase() 38bf215546Sopenharmony_ci{ 39bf215546Sopenharmony_ci Item *rem = pos; 40bf215546Sopenharmony_ci 41bf215546Sopenharmony_ci if (rem == term) 42bf215546Sopenharmony_ci return; 43bf215546Sopenharmony_ci pos = pos->next; 44bf215546Sopenharmony_ci 45bf215546Sopenharmony_ci DLLIST_DEL(rem); 46bf215546Sopenharmony_ci delete rem; 47bf215546Sopenharmony_ci} 48bf215546Sopenharmony_ci 49bf215546Sopenharmony_civoid DLList::Iterator::moveToList(DLList& dest) 50bf215546Sopenharmony_ci{ 51bf215546Sopenharmony_ci Item *item = pos; 52bf215546Sopenharmony_ci 53bf215546Sopenharmony_ci assert(term != &dest.head); 54bf215546Sopenharmony_ci assert(pos != term); 55bf215546Sopenharmony_ci 56bf215546Sopenharmony_ci pos = pos->next; 57bf215546Sopenharmony_ci 58bf215546Sopenharmony_ci DLLIST_DEL(item); 59bf215546Sopenharmony_ci DLLIST_ADDHEAD(&dest.head, item); 60bf215546Sopenharmony_ci} 61bf215546Sopenharmony_ci 62bf215546Sopenharmony_cibool 63bf215546Sopenharmony_ciDLList::Iterator::insert(void *data) 64bf215546Sopenharmony_ci{ 65bf215546Sopenharmony_ci Item *ins = new Item(data); 66bf215546Sopenharmony_ci 67bf215546Sopenharmony_ci ins->next = pos->next; 68bf215546Sopenharmony_ci ins->prev = pos; 69bf215546Sopenharmony_ci pos->next->prev = ins; 70bf215546Sopenharmony_ci pos->next = ins; 71bf215546Sopenharmony_ci 72bf215546Sopenharmony_ci if (pos == term) 73bf215546Sopenharmony_ci term = ins; 74bf215546Sopenharmony_ci 75bf215546Sopenharmony_ci return true; 76bf215546Sopenharmony_ci} 77bf215546Sopenharmony_ci 78bf215546Sopenharmony_civoid 79bf215546Sopenharmony_ciStack::moveTo(Stack& that) 80bf215546Sopenharmony_ci{ 81bf215546Sopenharmony_ci unsigned int newSize = this->size + that.size; 82bf215546Sopenharmony_ci 83bf215546Sopenharmony_ci while (newSize > that.limit) 84bf215546Sopenharmony_ci that.resize(); 85bf215546Sopenharmony_ci memcpy(&that.array[that.size], &array[0], this->size * sizeof(Item)); 86bf215546Sopenharmony_ci 87bf215546Sopenharmony_ci that.size = newSize; 88bf215546Sopenharmony_ci this->size = 0; 89bf215546Sopenharmony_ci} 90bf215546Sopenharmony_ci 91bf215546Sopenharmony_ciInterval::Interval(const Interval& that) : head(NULL), tail(NULL) 92bf215546Sopenharmony_ci{ 93bf215546Sopenharmony_ci this->insert(that); 94bf215546Sopenharmony_ci} 95bf215546Sopenharmony_ci 96bf215546Sopenharmony_ciInterval::~Interval() 97bf215546Sopenharmony_ci{ 98bf215546Sopenharmony_ci clear(); 99bf215546Sopenharmony_ci} 100bf215546Sopenharmony_ci 101bf215546Sopenharmony_civoid 102bf215546Sopenharmony_ciInterval::clear() 103bf215546Sopenharmony_ci{ 104bf215546Sopenharmony_ci for (Range *next, *r = head; r; r = next) { 105bf215546Sopenharmony_ci next = r->next; 106bf215546Sopenharmony_ci delete r; 107bf215546Sopenharmony_ci } 108bf215546Sopenharmony_ci head = tail = NULL; 109bf215546Sopenharmony_ci} 110bf215546Sopenharmony_ci 111bf215546Sopenharmony_cibool 112bf215546Sopenharmony_ciInterval::extend(int a, int b) 113bf215546Sopenharmony_ci{ 114bf215546Sopenharmony_ci Range *r, **nextp = &head; 115bf215546Sopenharmony_ci 116bf215546Sopenharmony_ci // NOTE: we need empty intervals for fixed registers 117bf215546Sopenharmony_ci // if (a == b) 118bf215546Sopenharmony_ci // return false; 119bf215546Sopenharmony_ci assert(a <= b); 120bf215546Sopenharmony_ci 121bf215546Sopenharmony_ci for (r = head; r; r = r->next) { 122bf215546Sopenharmony_ci if (b < r->bgn) 123bf215546Sopenharmony_ci break; // insert before 124bf215546Sopenharmony_ci if (a > r->end) { 125bf215546Sopenharmony_ci // insert after 126bf215546Sopenharmony_ci nextp = &r->next; 127bf215546Sopenharmony_ci continue; 128bf215546Sopenharmony_ci } 129bf215546Sopenharmony_ci 130bf215546Sopenharmony_ci // overlap 131bf215546Sopenharmony_ci if (a < r->bgn) { 132bf215546Sopenharmony_ci r->bgn = a; 133bf215546Sopenharmony_ci if (b > r->end) 134bf215546Sopenharmony_ci r->end = b; 135bf215546Sopenharmony_ci r->coalesce(&tail); 136bf215546Sopenharmony_ci return true; 137bf215546Sopenharmony_ci } 138bf215546Sopenharmony_ci if (b > r->end) { 139bf215546Sopenharmony_ci r->end = b; 140bf215546Sopenharmony_ci r->coalesce(&tail); 141bf215546Sopenharmony_ci return true; 142bf215546Sopenharmony_ci } 143bf215546Sopenharmony_ci assert(a >= r->bgn); 144bf215546Sopenharmony_ci assert(b <= r->end); 145bf215546Sopenharmony_ci return true; 146bf215546Sopenharmony_ci } 147bf215546Sopenharmony_ci 148bf215546Sopenharmony_ci (*nextp) = new Range(a, b); 149bf215546Sopenharmony_ci (*nextp)->next = r; 150bf215546Sopenharmony_ci 151bf215546Sopenharmony_ci for (r = (*nextp); r->next; r = r->next); 152bf215546Sopenharmony_ci tail = r; 153bf215546Sopenharmony_ci return true; 154bf215546Sopenharmony_ci} 155bf215546Sopenharmony_ci 156bf215546Sopenharmony_cibool Interval::contains(int pos) const 157bf215546Sopenharmony_ci{ 158bf215546Sopenharmony_ci for (Range *r = head; r && r->bgn <= pos; r = r->next) 159bf215546Sopenharmony_ci if (r->end > pos) 160bf215546Sopenharmony_ci return true; 161bf215546Sopenharmony_ci return false; 162bf215546Sopenharmony_ci} 163bf215546Sopenharmony_ci 164bf215546Sopenharmony_cibool Interval::overlaps(const Interval &that) const 165bf215546Sopenharmony_ci{ 166bf215546Sopenharmony_ci#if 1 167bf215546Sopenharmony_ci Range *a = this->head; 168bf215546Sopenharmony_ci Range *b = that.head; 169bf215546Sopenharmony_ci 170bf215546Sopenharmony_ci while (a && b) { 171bf215546Sopenharmony_ci if (b->bgn < a->end && 172bf215546Sopenharmony_ci b->end > a->bgn) 173bf215546Sopenharmony_ci return true; 174bf215546Sopenharmony_ci if (a->end <= b->bgn) 175bf215546Sopenharmony_ci a = a->next; 176bf215546Sopenharmony_ci else 177bf215546Sopenharmony_ci b = b->next; 178bf215546Sopenharmony_ci } 179bf215546Sopenharmony_ci#else 180bf215546Sopenharmony_ci for (Range *rA = this->head; rA; rA = rA->next) 181bf215546Sopenharmony_ci for (Range *rB = iv.head; rB; rB = rB->next) 182bf215546Sopenharmony_ci if (rB->bgn < rA->end && 183bf215546Sopenharmony_ci rB->end > rA->bgn) 184bf215546Sopenharmony_ci return true; 185bf215546Sopenharmony_ci#endif 186bf215546Sopenharmony_ci return false; 187bf215546Sopenharmony_ci} 188bf215546Sopenharmony_ci 189bf215546Sopenharmony_civoid Interval::insert(const Interval &that) 190bf215546Sopenharmony_ci{ 191bf215546Sopenharmony_ci for (Range *r = that.head; r; r = r->next) 192bf215546Sopenharmony_ci this->extend(r->bgn, r->end); 193bf215546Sopenharmony_ci} 194bf215546Sopenharmony_ci 195bf215546Sopenharmony_civoid Interval::unify(Interval &that) 196bf215546Sopenharmony_ci{ 197bf215546Sopenharmony_ci assert(this != &that); 198bf215546Sopenharmony_ci for (Range *next, *r = that.head; r; r = next) { 199bf215546Sopenharmony_ci next = r->next; 200bf215546Sopenharmony_ci this->extend(r->bgn, r->end); 201bf215546Sopenharmony_ci delete r; 202bf215546Sopenharmony_ci } 203bf215546Sopenharmony_ci that.head = NULL; 204bf215546Sopenharmony_ci} 205bf215546Sopenharmony_ci 206bf215546Sopenharmony_ciint Interval::length() const 207bf215546Sopenharmony_ci{ 208bf215546Sopenharmony_ci int len = 0; 209bf215546Sopenharmony_ci for (Range *r = head; r; r = r->next) 210bf215546Sopenharmony_ci len += r->bgn - r->end; 211bf215546Sopenharmony_ci return len; 212bf215546Sopenharmony_ci} 213bf215546Sopenharmony_ci 214bf215546Sopenharmony_civoid Interval::print() const 215bf215546Sopenharmony_ci{ 216bf215546Sopenharmony_ci if (!head) 217bf215546Sopenharmony_ci return; 218bf215546Sopenharmony_ci INFO("[%i %i)", head->bgn, head->end); 219bf215546Sopenharmony_ci for (const Range *r = head->next; r; r = r->next) 220bf215546Sopenharmony_ci INFO(" [%i %i)", r->bgn, r->end); 221bf215546Sopenharmony_ci INFO("\n"); 222bf215546Sopenharmony_ci} 223bf215546Sopenharmony_ci 224bf215546Sopenharmony_civoid 225bf215546Sopenharmony_ciBitSet::andNot(const BitSet &set) 226bf215546Sopenharmony_ci{ 227bf215546Sopenharmony_ci assert(data && set.data); 228bf215546Sopenharmony_ci assert(size >= set.size); 229bf215546Sopenharmony_ci for (unsigned int i = 0; i < (set.size + 31) / 32; ++i) 230bf215546Sopenharmony_ci data[i] &= ~set.data[i]; 231bf215546Sopenharmony_ci} 232bf215546Sopenharmony_ci 233bf215546Sopenharmony_ciBitSet& BitSet::operator|=(const BitSet &set) 234bf215546Sopenharmony_ci{ 235bf215546Sopenharmony_ci assert(data && set.data); 236bf215546Sopenharmony_ci assert(size >= set.size); 237bf215546Sopenharmony_ci for (unsigned int i = 0; i < (set.size + 31) / 32; ++i) 238bf215546Sopenharmony_ci data[i] |= set.data[i]; 239bf215546Sopenharmony_ci return *this; 240bf215546Sopenharmony_ci} 241bf215546Sopenharmony_ci 242bf215546Sopenharmony_cibool BitSet::resize(unsigned int nBits) 243bf215546Sopenharmony_ci{ 244bf215546Sopenharmony_ci if (!data || !nBits) 245bf215546Sopenharmony_ci return allocate(nBits, true); 246bf215546Sopenharmony_ci const unsigned int p = (size + 31) / 32; 247bf215546Sopenharmony_ci const unsigned int n = (nBits + 31) / 32; 248bf215546Sopenharmony_ci if (n == p) 249bf215546Sopenharmony_ci return true; 250bf215546Sopenharmony_ci 251bf215546Sopenharmony_ci data = (uint32_t *)REALLOC(data, 4 * p, 4 * n); 252bf215546Sopenharmony_ci if (!data) { 253bf215546Sopenharmony_ci size = 0; 254bf215546Sopenharmony_ci return false; 255bf215546Sopenharmony_ci } 256bf215546Sopenharmony_ci if (n > p) 257bf215546Sopenharmony_ci memset(&data[p], 0, (n - p) * 4); 258bf215546Sopenharmony_ci if (nBits < size && (nBits % 32)) 259bf215546Sopenharmony_ci data[(nBits + 31) / 32 - 1] &= (1 << (nBits % 32)) - 1; 260bf215546Sopenharmony_ci 261bf215546Sopenharmony_ci size = nBits; 262bf215546Sopenharmony_ci return true; 263bf215546Sopenharmony_ci} 264bf215546Sopenharmony_ci 265bf215546Sopenharmony_cibool BitSet::allocate(unsigned int nBits, bool zero) 266bf215546Sopenharmony_ci{ 267bf215546Sopenharmony_ci if (data && size < nBits) { 268bf215546Sopenharmony_ci FREE(data); 269bf215546Sopenharmony_ci data = NULL; 270bf215546Sopenharmony_ci } 271bf215546Sopenharmony_ci size = nBits; 272bf215546Sopenharmony_ci 273bf215546Sopenharmony_ci if (!data) 274bf215546Sopenharmony_ci data = reinterpret_cast<uint32_t *>(CALLOC((size + 31) / 32, 4)); 275bf215546Sopenharmony_ci 276bf215546Sopenharmony_ci if (zero) 277bf215546Sopenharmony_ci memset(data, 0, (size + 7) / 8); 278bf215546Sopenharmony_ci else 279bf215546Sopenharmony_ci if (size % 32) // clear unused bits (e.g. for popCount) 280bf215546Sopenharmony_ci data[(size + 31) / 32 - 1] &= (1 << (size % 32)) - 1; 281bf215546Sopenharmony_ci 282bf215546Sopenharmony_ci return data; 283bf215546Sopenharmony_ci} 284bf215546Sopenharmony_ci 285bf215546Sopenharmony_ciunsigned int BitSet::popCount() const 286bf215546Sopenharmony_ci{ 287bf215546Sopenharmony_ci unsigned int count = 0; 288bf215546Sopenharmony_ci 289bf215546Sopenharmony_ci for (unsigned int i = 0; i < (size + 31) / 32; ++i) 290bf215546Sopenharmony_ci if (data[i]) 291bf215546Sopenharmony_ci count += util_bitcount(data[i]); 292bf215546Sopenharmony_ci return count; 293bf215546Sopenharmony_ci} 294bf215546Sopenharmony_ci 295bf215546Sopenharmony_civoid BitSet::fill(uint32_t val) 296bf215546Sopenharmony_ci{ 297bf215546Sopenharmony_ci unsigned int i; 298bf215546Sopenharmony_ci for (i = 0; i < (size + 31) / 32; ++i) 299bf215546Sopenharmony_ci data[i] = val; 300bf215546Sopenharmony_ci if (val && i) 301bf215546Sopenharmony_ci data[i - 1] &= (1 << (size % 32)) - 1; 302bf215546Sopenharmony_ci} 303bf215546Sopenharmony_ci 304bf215546Sopenharmony_civoid BitSet::setOr(BitSet *pA, BitSet *pB) 305bf215546Sopenharmony_ci{ 306bf215546Sopenharmony_ci if (!pB) { 307bf215546Sopenharmony_ci *this = *pA; 308bf215546Sopenharmony_ci } else { 309bf215546Sopenharmony_ci for (unsigned int i = 0; i < (size + 31) / 32; ++i) 310bf215546Sopenharmony_ci data[i] = pA->data[i] | pB->data[i]; 311bf215546Sopenharmony_ci } 312bf215546Sopenharmony_ci} 313bf215546Sopenharmony_ci 314bf215546Sopenharmony_ciint BitSet::findFreeRange(unsigned int count, unsigned int max) const 315bf215546Sopenharmony_ci{ 316bf215546Sopenharmony_ci const uint32_t m = (1 << count) - 1; 317bf215546Sopenharmony_ci int pos = max; 318bf215546Sopenharmony_ci unsigned int i; 319bf215546Sopenharmony_ci const unsigned int end = (max + 31) / 32; 320bf215546Sopenharmony_ci 321bf215546Sopenharmony_ci if (count == 1) { 322bf215546Sopenharmony_ci for (i = 0; i < end; ++i) { 323bf215546Sopenharmony_ci pos = ffs(~data[i]) - 1; 324bf215546Sopenharmony_ci if (pos >= 0) 325bf215546Sopenharmony_ci break; 326bf215546Sopenharmony_ci } 327bf215546Sopenharmony_ci } else 328bf215546Sopenharmony_ci if (count == 2) { 329bf215546Sopenharmony_ci for (i = 0; i < end; ++i) { 330bf215546Sopenharmony_ci if (data[i] != 0xffffffff) { 331bf215546Sopenharmony_ci uint32_t b = data[i] | (data[i] >> 1) | 0xaaaaaaaa; 332bf215546Sopenharmony_ci pos = ffs(~b) - 1; 333bf215546Sopenharmony_ci if (pos >= 0) 334bf215546Sopenharmony_ci break; 335bf215546Sopenharmony_ci } 336bf215546Sopenharmony_ci } 337bf215546Sopenharmony_ci } else 338bf215546Sopenharmony_ci if (count == 4 || count == 3) { 339bf215546Sopenharmony_ci for (i = 0; i < end; ++i) { 340bf215546Sopenharmony_ci if (data[i] != 0xffffffff) { 341bf215546Sopenharmony_ci uint32_t b = 342bf215546Sopenharmony_ci (data[i] >> 0) | (data[i] >> 1) | 343bf215546Sopenharmony_ci (data[i] >> 2) | (data[i] >> 3) | 0xeeeeeeee; 344bf215546Sopenharmony_ci pos = ffs(~b) - 1; 345bf215546Sopenharmony_ci if (pos >= 0) 346bf215546Sopenharmony_ci break; 347bf215546Sopenharmony_ci } 348bf215546Sopenharmony_ci } 349bf215546Sopenharmony_ci } else { 350bf215546Sopenharmony_ci if (count <= 8) 351bf215546Sopenharmony_ci count = 8; 352bf215546Sopenharmony_ci else 353bf215546Sopenharmony_ci if (count <= 16) 354bf215546Sopenharmony_ci count = 16; 355bf215546Sopenharmony_ci else 356bf215546Sopenharmony_ci count = 32; 357bf215546Sopenharmony_ci 358bf215546Sopenharmony_ci for (i = 0; i < end; ++i) { 359bf215546Sopenharmony_ci if (data[i] != 0xffffffff) { 360bf215546Sopenharmony_ci for (pos = 0; pos < 32; pos += count) 361bf215546Sopenharmony_ci if (!(data[i] & (m << pos))) 362bf215546Sopenharmony_ci break; 363bf215546Sopenharmony_ci if (pos < 32) 364bf215546Sopenharmony_ci break; 365bf215546Sopenharmony_ci } 366bf215546Sopenharmony_ci } 367bf215546Sopenharmony_ci } 368bf215546Sopenharmony_ci 369bf215546Sopenharmony_ci // If we couldn't find a position, we can have a left-over -1 in pos. Make 370bf215546Sopenharmony_ci // sure to abort in such a case. 371bf215546Sopenharmony_ci if (pos < 0) 372bf215546Sopenharmony_ci return -1; 373bf215546Sopenharmony_ci 374bf215546Sopenharmony_ci pos += i * 32; 375bf215546Sopenharmony_ci 376bf215546Sopenharmony_ci return ((pos + count) <= max) ? pos : -1; 377bf215546Sopenharmony_ci} 378bf215546Sopenharmony_ci 379bf215546Sopenharmony_civoid BitSet::print() const 380bf215546Sopenharmony_ci{ 381bf215546Sopenharmony_ci unsigned int n = 0; 382bf215546Sopenharmony_ci INFO("BitSet of size %u:\n", size); 383bf215546Sopenharmony_ci for (unsigned int i = 0; i < (size + 31) / 32; ++i) { 384bf215546Sopenharmony_ci uint32_t bits = data[i]; 385bf215546Sopenharmony_ci while (bits) { 386bf215546Sopenharmony_ci int pos = ffs(bits) - 1; 387bf215546Sopenharmony_ci bits &= ~(1 << pos); 388bf215546Sopenharmony_ci INFO(" %i", i * 32 + pos); 389bf215546Sopenharmony_ci ++n; 390bf215546Sopenharmony_ci if ((n % 16) == 0) 391bf215546Sopenharmony_ci INFO("\n"); 392bf215546Sopenharmony_ci } 393bf215546Sopenharmony_ci } 394bf215546Sopenharmony_ci if (n % 16) 395bf215546Sopenharmony_ci INFO("\n"); 396bf215546Sopenharmony_ci} 397bf215546Sopenharmony_ci 398bf215546Sopenharmony_ci} // namespace nv50_ir 399