00aee66f25b82288e8991899864812b632eca6d9
[mesa.git] / src / gallium / drivers / r600 / sb / sb_valtable.cpp
1 /*
2 * Copyright 2013 Vadim Girlin <vadimgirlin@gmail.com>
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 * on the rights to use, copy, modify, merge, publish, distribute, sub
8 * license, and/or sell copies of the Software, and to permit persons to whom
9 * the Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
19 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
20 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
21 * USE OR OTHER DEALINGS IN THE SOFTWARE.
22 *
23 * Authors:
24 * Vadim Girlin
25 */
26
27 #define VT_DEBUG 0
28
29 #if VT_DEBUG
30 #define VT_DUMP(q) do { q } while (0)
31 #else
32 #define VT_DUMP(q)
33 #endif
34
35 #include <cstring>
36
37 #include "sb_shader.h"
38 #include "sb_pass.h"
39
40 namespace r600_sb {
41
42 static const char * chans = "xyzw01?_";
43
44 sb_ostream& operator << (sb_ostream &o, value &v) {
45
46 bool dead = v.flags & VLF_DEAD;
47
48 if (dead)
49 o << "{";
50
51 switch (v.kind) {
52 case VLK_SPECIAL_REG: {
53 switch (v.select.sel()) {
54 case SV_AR_INDEX: o << "AR"; break;
55 case SV_ALU_PRED: o << "PR"; break;
56 case SV_EXEC_MASK: o << "EM"; break;
57 case SV_VALID_MASK: o << "VM"; break;
58 default: o << "???specialreg"; break;
59 }
60 break;
61 }
62
63 case VLK_REG:
64 o << "R" << v.select.sel() << "."
65 << chans[v.select.chan()];
66
67 break;
68 case VLK_KCACHE: {
69 o << "C" << v.select.sel() << "." << chans[v.select.chan()];
70 }
71 break;
72 case VLK_CONST:
73 o << v.literal_value.f << "|";
74 o.print_zw_hex(v.literal_value.u, 8);
75 break;
76 case VLK_PARAM:
77 o << "Param" << (v.select.sel() - ALU_SRC_PARAM_OFFSET)
78 << chans[v.select.chan()];
79 break;
80 case VLK_TEMP:
81 o << "t" << v.select.sel() - shader::temp_regid_offset;
82 break;
83 case VLK_REL_REG:
84
85 o << "A" << v.select;
86 o << "[";
87 o << *v.rel;
88 o << "]";
89
90 o << "_" << v.uid;
91
92 break;
93 case VLK_UNDEF:
94 o << "undef";
95 break;
96 default:
97 o << v.kind << "?????";
98 break;
99 }
100
101 if (v.version)
102 o << "." << v.version;
103
104 if (dead)
105 o << "}";
106
107 if (v.is_global())
108 o << "||";
109 if (v.is_fixed())
110 o << "F";
111 if (v.is_prealloc())
112 o << "P";
113
114 sel_chan g;
115
116 if (v.is_rel()) {
117 g = v.array->gpr;
118 } else {
119 g = v.gpr;
120 }
121
122 if (g) {
123 o << "@R" << g.sel() << "." << chans[g.chan()];
124 }
125
126 return o;
127 }
128
129 void value_table::add_value(value* v) {
130
131 if (v->gvn_source) {
132 return;
133 }
134
135 VT_DUMP(
136 sblog << "gvn add_value ";
137 dump::dump_val(v);
138 );
139
140 value_hash hash = v->hash();
141 vt_item & vti = hashtable[hash & size_mask];
142 vti.push_back(v);
143 ++cnt;
144
145 if (v->def && ex.try_fold(v)) {
146 VT_DUMP(
147 sblog << " folded: ";
148 dump::dump_val(v->gvn_source);
149 sblog << "\n";
150 );
151 return;
152 }
153
154 int n = 0;
155 for (vt_item::iterator I = vti.begin(), E = vti.end(); I != E; ++I, ++n) {
156 value *c = *I;
157
158 if (c == v)
159 break;
160
161 if (expr_equal(c, v)) {
162 v->gvn_source = c->gvn_source;
163
164 VT_DUMP(
165 sblog << " found : equal to ";
166 dump::dump_val(v->gvn_source);
167 sblog << "\n";
168 );
169 return;
170 }
171 }
172
173 v->gvn_source = v;
174 VT_DUMP(
175 sblog << " added new\n";
176 );
177 }
178
179 value_hash value::hash() {
180 if (ghash)
181 return ghash;
182 if (is_rel())
183 ghash = rel_hash();
184 else if (def)
185 ghash = def->hash();
186 else
187 ghash = ((uintptr_t)this) | 1;
188
189 return ghash;
190 }
191
192 value_hash value::rel_hash() {
193 value_hash h = rel ? rel->hash() : 0;
194 h |= select << 10;
195 h |= array->hash();
196 return h;
197 }
198
199 bool value_table::expr_equal(value* l, value* r) {
200 return ex.equal(l, r);
201 }
202
203 void value_table::get_values(vvec& v) {
204 v.resize(cnt);
205
206 vvec::iterator T = v.begin();
207
208 for(vt_table::iterator I = hashtable.begin(), E = hashtable.end();
209 I != E; ++I) {
210 T = std::copy(I->begin(), I->end(), T);
211 }
212 }
213
214 void value::add_use(node* n, use_kind kind, int arg) {
215 if (0) {
216 sblog << "add_use ";
217 dump::dump_val(this);
218 sblog << " => ";
219 dump::dump_op(n);
220 sblog << " kind " << kind << " arg " << arg << "\n";
221 }
222 uses = new use_info(n, kind, arg, uses);
223 }
224
225 unsigned value::use_count() {
226 use_info *u = uses;
227 unsigned c = 0;
228 while (u) {
229 ++c;
230 u = u->next;
231 }
232 return c;
233 }
234
235 bool value::is_global() {
236 if (chunk)
237 return chunk->is_global();
238 return flags & VLF_GLOBAL;
239 }
240
241 void value::set_global() {
242 assert(is_sgpr());
243 flags |= VLF_GLOBAL;
244 if (chunk)
245 chunk->set_global();
246 }
247
248 void value::set_prealloc() {
249 assert(is_sgpr());
250 flags |= VLF_PREALLOC;
251 if (chunk)
252 chunk->set_prealloc();
253 }
254
255 bool value::is_fixed() {
256 if (array && array->gpr)
257 return true;
258 if (chunk)
259 return chunk->is_fixed();
260 return flags & VLF_FIXED;
261 }
262
263 void value::fix() {
264 if (chunk)
265 chunk->fix();
266 flags |= VLF_FIXED;
267 }
268
269 bool value::is_prealloc() {
270 if (chunk)
271 return chunk->is_prealloc();
272 return flags & VLF_PREALLOC;
273 }
274
275 void value::delete_uses() {
276 use_info *u, *c = uses;
277 while (c) {
278 u = c->next;
279 delete c;
280 c = u;
281 }
282 uses = NULL;
283 }
284
285 void ra_constraint::update_values() {
286 for (vvec::iterator I = values.begin(), E = values.end(); I != E; ++I) {
287 assert(!(*I)->constraint);
288 (*I)->constraint = this;
289 }
290 }
291
292 void* sb_pool::allocate(unsigned sz) {
293 sz = (sz + SB_POOL_ALIGN - 1) & ~(SB_POOL_ALIGN - 1);
294 assert (sz < (block_size >> 6) && "too big allocation size for sb_pool");
295
296 unsigned offset = total_size % block_size;
297 unsigned capacity = block_size * blocks.size();
298
299 if (total_size + sz > capacity) {
300 total_size = capacity;
301 void * nb = malloc(block_size);
302 blocks.push_back(nb);
303 offset = 0;
304 }
305
306 total_size += sz;
307 return ((char*)blocks.back() + offset);
308 }
309
310 void sb_pool::free_all() {
311 for (block_vector::iterator I = blocks.begin(), E = blocks.end(); I != E;
312 ++I) {
313 free(*I);
314 }
315 }
316
317 value* sb_value_pool::create(value_kind k, sel_chan regid,
318 unsigned ver) {
319 void* np = allocate(aligned_elt_size);
320 value *v = new (np) value(size(), k, regid, ver);
321 return v;
322 }
323
324 void sb_value_pool::delete_all() {
325 unsigned bcnt = blocks.size();
326 unsigned toffset = 0;
327 for (unsigned b = 0; b < bcnt; ++b) {
328 char *bstart = (char*)blocks[b];
329 for (unsigned offset = 0; offset < block_size;
330 offset += aligned_elt_size) {
331 ((value*)(bstart + offset))->~value();
332 toffset += aligned_elt_size;
333 if (toffset >= total_size)
334 return;
335 }
336 }
337 }
338
339 bool sb_bitset::get(unsigned id) {
340 assert(id < bit_size);
341 unsigned w = id / bt_bits;
342 unsigned b = id % bt_bits;
343 return (data[w] >> b) & 1;
344 }
345
346 void sb_bitset::set(unsigned id, bool bit) {
347 assert(id < bit_size);
348 unsigned w = id / bt_bits;
349 unsigned b = id % bt_bits;
350 if (w >= data.size())
351 data.resize(w + 1);
352
353 if (bit)
354 data[w] |= (1 << b);
355 else
356 data[w] &= ~(1 << b);
357 }
358
359 inline bool sb_bitset::set_chk(unsigned id, bool bit) {
360 assert(id < bit_size);
361 unsigned w = id / bt_bits;
362 unsigned b = id % bt_bits;
363 basetype d = data[w];
364 basetype dn = (d & ~(1 << b)) | (bit << b);
365 bool r = (d != dn);
366 data[w] = r ? dn : data[w];
367 return r;
368 }
369
370 void sb_bitset::clear() {
371 std::fill(data.begin(), data.end(), 0);
372 }
373
374 void sb_bitset::resize(unsigned size) {
375 unsigned cur_data_size = data.size();
376 unsigned new_data_size = (size + bt_bits - 1) / bt_bits;
377
378
379 if (new_data_size != cur_data_size)
380 data.resize(new_data_size);
381
382 // make sure that new bits in the existing word are cleared
383 if (cur_data_size && size > bit_size && bit_size % bt_bits) {
384 basetype clear_mask = (~(basetype)0u) << (bit_size % bt_bits);
385 data[cur_data_size - 1] &= ~clear_mask;
386 }
387
388 bit_size = size;
389 }
390
391 unsigned sb_bitset::find_bit(unsigned start) {
392 assert(start < bit_size);
393 unsigned w = start / bt_bits;
394 unsigned b = start % bt_bits;
395 unsigned sz = data.size();
396
397 while (w < sz) {
398 basetype d = data[w] >> b;
399 if (d != 0) {
400 unsigned pos = __builtin_ctz(d) + b + w * bt_bits;
401 return pos;
402 }
403
404 b = 0;
405 ++w;
406 }
407
408 return bit_size;
409 }
410
411 sb_value_set::iterator::iterator(shader& sh, sb_value_set* s, unsigned nb)
412 : vp(sh.get_value_pool()), s(s), nb(nb) {}
413
414 bool sb_value_set::add_set_checked(sb_value_set& s2) {
415 if (bs.size() < s2.bs.size())
416 bs.resize(s2.bs.size());
417 sb_bitset nbs = bs | s2.bs;
418 if (bs != nbs) {
419 bs.swap(nbs);
420 return true;
421 }
422 return false;
423 }
424
425 void r600_sb::sb_value_set::remove_set(sb_value_set& s2) {
426 bs.mask(s2.bs);
427 }
428
429 bool sb_value_set::add_val(value* v) {
430 assert(v);
431 if (bs.size() < v->uid)
432 bs.resize(v->uid + 32);
433
434 return bs.set_chk(v->uid - 1, 1);
435 }
436
437 bool sb_value_set::remove_vec(vvec& vv) {
438 bool modified = false;
439 for (vvec::iterator I = vv.begin(), E = vv.end(); I != E; ++I) {
440 if (*I)
441 modified |= remove_val(*I);
442 }
443 return modified;
444 }
445
446 void sb_value_set::clear() {
447 bs.clear();
448 }
449
450 bool sb_value_set::remove_val(value* v) {
451 assert(v);
452 if (bs.size() < v->uid)
453 return false;
454 return bs.set_chk(v->uid - 1, 0);
455 }
456
457 bool r600_sb::sb_value_set::add_vec(vvec& vv) {
458 bool modified = false;
459 for (vvec::iterator I = vv.begin(), E = vv.end(); I != E; ++I) {
460 value *v = *I;
461 if (v)
462 modified |= add_val(v);
463 }
464 return modified;
465 }
466
467 bool r600_sb::sb_value_set::contains(value* v) {
468 unsigned b = v->uid - 1;
469 if (b < bs.size())
470 return bs.get(v->uid - 1);
471 else
472 return false;
473 }
474
475 bool sb_value_set::empty() {
476 return bs.size() == 0 || bs.find_bit(0) == bs.size();
477 }
478
479 void sb_bitset::swap(sb_bitset& bs2) {
480 std::swap(data, bs2.data);
481 std::swap(bit_size, bs2.bit_size);
482 }
483
484 bool sb_bitset::operator ==(const sb_bitset& bs2) {
485 if (bit_size != bs2.bit_size)
486 return false;
487
488 for (unsigned i = 0, c = data.size(); i < c; ++i) {
489 if (data[i] != bs2.data[i])
490 return false;
491 }
492 return true;
493 }
494
495 sb_bitset& sb_bitset::operator &=(const sb_bitset& bs2) {
496 if (bit_size > bs2.bit_size) {
497 resize(bs2.bit_size);
498 }
499
500 for (unsigned i = 0, c = std::min(data.size(), bs2.data.size()); i < c;
501 ++i) {
502 data[i] &= bs2.data[i];
503 }
504 return *this;
505 }
506
507 sb_bitset& sb_bitset::mask(const sb_bitset& bs2) {
508 if (bit_size < bs2.bit_size) {
509 resize(bs2.bit_size);
510 }
511
512 for (unsigned i = 0, c = data.size(); i < c;
513 ++i) {
514 data[i] &= ~bs2.data[i];
515 }
516 return *this;
517 }
518
519 bool ra_constraint::check() {
520 assert(kind == CK_SAME_REG);
521
522 unsigned reg = 0;
523
524 for (vvec::iterator I = values.begin(), E = values.end(); I != E; ++I) {
525 value *v = *I;
526 if (!v)
527 continue;
528
529 if (!v->gpr)
530 return false;
531
532 if (reg == 0)
533 reg = v->gpr.sel() + 1;
534 else if (reg != v->gpr.sel() + 1)
535 return false;
536
537 if (v->is_chan_pinned()) {
538 if (v->pin_gpr.chan() != v->gpr.chan())
539 return false;
540 }
541 }
542 return true;
543 }
544
545 bool gpr_array::is_dead() {
546 return false;
547 }
548
549 } // namespace r600_sb