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