r600/sb: fix typo in field definitions
[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 case SV_GEOMETRY_EMIT: o << "GEOMETRY_EMIT"; break;
59 default: o << "???specialreg"; break;
60 }
61 break;
62 }
63
64 case VLK_REG:
65 o << "R" << v.select.sel() << "."
66 << chans[v.select.chan()];
67
68 break;
69 case VLK_KCACHE: {
70 o << "C" << v.select.sel() << "." << chans[v.select.chan()];
71 }
72 break;
73 case VLK_CONST:
74 o << v.literal_value.f << "|";
75 o.print_zw_hex(v.literal_value.u, 8);
76 break;
77 case VLK_PARAM:
78 o << "Param" << (v.select.sel() - ALU_SRC_PARAM_OFFSET)
79 << chans[v.select.chan()];
80 break;
81 case VLK_TEMP:
82 o << "t" << v.select.sel() - shader::temp_regid_offset;
83 break;
84 case VLK_REL_REG:
85
86 o << "A" << v.select;
87 o << "[";
88 o << *v.rel;
89 o << "]";
90
91 o << "_" << v.uid;
92
93 break;
94 case VLK_UNDEF:
95 o << "undef";
96 break;
97 default:
98 o << v.kind << "?????";
99 break;
100 }
101
102 if (v.version)
103 o << "." << v.version;
104
105 if (dead)
106 o << "}";
107
108 if (v.is_global())
109 o << "||";
110 if (v.is_fixed())
111 o << "F";
112 if (v.is_prealloc())
113 o << "P";
114
115 sel_chan g;
116
117 if (v.is_rel()) {
118 g = v.array->gpr;
119 } else {
120 g = v.gpr;
121 }
122
123 if (g) {
124 o << "@R" << g.sel() << "." << chans[g.chan()];
125 }
126
127 return o;
128 }
129
130 void value_table::add_value(value* v) {
131
132 if (v->gvn_source) {
133 return;
134 }
135
136 VT_DUMP(
137 sblog << "gvn add_value ";
138 dump::dump_val(v);
139 );
140
141 value_hash hash = v->hash();
142 vt_item & vti = hashtable[hash & size_mask];
143 vti.push_back(v);
144 ++cnt;
145
146 if (v->def && ex.try_fold(v)) {
147 VT_DUMP(
148 sblog << " folded: ";
149 dump::dump_val(v->gvn_source);
150 sblog << "\n";
151 );
152 return;
153 }
154
155 int n = 0;
156 for (vt_item::iterator I = vti.begin(), E = vti.end(); I != E; ++I, ++n) {
157 value *c = *I;
158
159 if (c == v)
160 break;
161
162 if (expr_equal(c, v)) {
163 v->gvn_source = c->gvn_source;
164
165 VT_DUMP(
166 sblog << " found : equal to ";
167 dump::dump_val(v->gvn_source);
168 sblog << "\n";
169 );
170 return;
171 }
172 }
173
174 v->gvn_source = v;
175 VT_DUMP(
176 sblog << " added new\n";
177 );
178 }
179
180 value_hash value::hash() {
181 if (ghash)
182 return ghash;
183 if (is_rel())
184 ghash = rel_hash();
185 else if (def)
186 ghash = def->hash();
187 else
188 ghash = ((uintptr_t)this) | 1;
189
190 return ghash;
191 }
192
193 value_hash value::rel_hash() {
194 value_hash h = rel ? rel->hash() : 0;
195 h |= select << 10;
196 h |= array->hash();
197 return h;
198 }
199
200 bool value_table::expr_equal(value* l, value* r) {
201 return ex.equal(l, r);
202 }
203
204 void value_table::get_values(vvec& v) {
205 v.resize(cnt);
206
207 vvec::iterator T = v.begin();
208
209 for(vt_table::iterator I = hashtable.begin(), E = hashtable.end();
210 I != E; ++I) {
211 T = std::copy(I->begin(), I->end(), T);
212 }
213 }
214
215 void value::add_use(node* n) {
216 if (0) {
217 sblog << "add_use ";
218 dump::dump_val(this);
219 sblog << " => ";
220 dump::dump_op(n);
221 }
222 uses.push_back(n);
223 }
224
225 struct use_node_comp {
226 explicit use_node_comp(const node *n) : n(n) {}
227 bool operator() (const node *o) {
228 return o->hash() == n->hash();
229 }
230
231 private:
232 const node *n;
233 };
234
235 void value::remove_use(const node *n) {
236 uselist::iterator it =
237 std::find_if(uses.begin(), uses.end(), use_node_comp(n));
238
239 if (it != uses.end())
240 {
241 // We only ever had a pointer, so don't delete it here
242 uses.erase(it);
243 }
244 }
245
246 unsigned value::use_count() {
247 return uses.size();
248 }
249
250 bool value::is_global() {
251 if (chunk)
252 return chunk->is_global();
253 return flags & VLF_GLOBAL;
254 }
255
256 void value::set_global() {
257 assert(is_sgpr());
258 flags |= VLF_GLOBAL;
259 if (chunk)
260 chunk->set_global();
261 }
262
263 void value::set_prealloc() {
264 assert(is_sgpr());
265 flags |= VLF_PREALLOC;
266 if (chunk)
267 chunk->set_prealloc();
268 }
269
270 bool value::is_fixed() {
271 if (array && array->gpr)
272 return true;
273 if (chunk && chunk->is_fixed())
274 return true;
275 return flags & VLF_FIXED;
276 }
277
278 void value::fix() {
279 if (chunk)
280 chunk->fix();
281 flags |= VLF_FIXED;
282 }
283
284 bool value::is_prealloc() {
285 if (chunk)
286 return chunk->is_prealloc();
287 return flags & VLF_PREALLOC;
288 }
289
290 void value::delete_uses() {
291 // We only ever had pointers, so don't delete them here
292 uses.erase(uses.begin(), uses.end());
293 }
294
295 void ra_constraint::update_values() {
296 for (vvec::iterator I = values.begin(), E = values.end(); I != E; ++I) {
297 assert(!(*I)->constraint);
298 (*I)->constraint = this;
299 }
300 }
301
302 void* sb_pool::allocate(unsigned sz) {
303 sz = (sz + SB_POOL_ALIGN - 1) & ~(SB_POOL_ALIGN - 1);
304 assert (sz < (block_size >> 6) && "too big allocation size for sb_pool");
305
306 unsigned offset = total_size % block_size;
307 unsigned capacity = block_size * blocks.size();
308
309 if (total_size + sz > capacity) {
310 total_size = capacity;
311 void * nb = malloc(block_size);
312 blocks.push_back(nb);
313 offset = 0;
314 }
315
316 total_size += sz;
317 return ((char*)blocks.back() + offset);
318 }
319
320 void sb_pool::free_all() {
321 for (block_vector::iterator I = blocks.begin(), E = blocks.end(); I != E;
322 ++I) {
323 free(*I);
324 }
325 }
326
327 value* sb_value_pool::create(value_kind k, sel_chan regid,
328 unsigned ver) {
329 void* np = allocate(aligned_elt_size);
330 value *v = new (np) value(size(), k, regid, ver);
331 return v;
332 }
333
334 void sb_value_pool::delete_all() {
335 unsigned bcnt = blocks.size();
336 unsigned toffset = 0;
337 for (unsigned b = 0; b < bcnt; ++b) {
338 char *bstart = (char*)blocks[b];
339 for (unsigned offset = 0; offset < block_size;
340 offset += aligned_elt_size) {
341 ((value*)(bstart + offset))->~value();
342 toffset += aligned_elt_size;
343 if (toffset >= total_size)
344 return;
345 }
346 }
347 }
348
349 bool sb_bitset::get(unsigned id) {
350 assert(id < bit_size);
351 unsigned w = id / bt_bits;
352 unsigned b = id % bt_bits;
353 return (data[w] >> b) & 1;
354 }
355
356 void sb_bitset::set(unsigned id, bool bit) {
357 assert(id < bit_size);
358 unsigned w = id / bt_bits;
359 unsigned b = id % bt_bits;
360 if (w >= data.size())
361 data.resize(w + 1);
362
363 if (bit)
364 data[w] |= (1 << b);
365 else
366 data[w] &= ~(1 << b);
367 }
368
369 inline bool sb_bitset::set_chk(unsigned id, bool bit) {
370 assert(id < bit_size);
371 unsigned w = id / bt_bits;
372 unsigned b = id % bt_bits;
373 basetype d = data[w];
374 basetype dn = (d & ~(1 << b)) | (bit << b);
375 bool r = (d != dn);
376 data[w] = r ? dn : data[w];
377 return r;
378 }
379
380 void sb_bitset::clear() {
381 std::fill(data.begin(), data.end(), 0);
382 }
383
384 void sb_bitset::resize(unsigned size) {
385 unsigned cur_data_size = data.size();
386 unsigned new_data_size = (size + bt_bits - 1) / bt_bits;
387
388
389 if (new_data_size != cur_data_size)
390 data.resize(new_data_size);
391
392 // make sure that new bits in the existing word are cleared
393 if (cur_data_size && size > bit_size && bit_size % bt_bits) {
394 basetype clear_mask = (~(basetype)0u) << (bit_size % bt_bits);
395 data[cur_data_size - 1] &= ~clear_mask;
396 }
397
398 bit_size = size;
399 }
400
401 unsigned sb_bitset::find_bit(unsigned start) {
402 assert(start < bit_size);
403 unsigned w = start / bt_bits;
404 unsigned b = start % bt_bits;
405 unsigned sz = data.size();
406
407 while (w < sz) {
408 basetype d = data[w] >> b;
409 if (d != 0) {
410 unsigned pos = __builtin_ctz(d) + b + w * bt_bits;
411 return pos;
412 }
413
414 b = 0;
415 ++w;
416 }
417
418 return bit_size;
419 }
420
421 sb_value_set::iterator::iterator(shader& sh, sb_value_set* s, unsigned nb)
422 : vp(sh.get_value_pool()), s(s), nb(nb) {}
423
424 bool sb_value_set::add_set_checked(sb_value_set& s2) {
425 if (bs.size() < s2.bs.size())
426 bs.resize(s2.bs.size());
427 sb_bitset nbs = bs | s2.bs;
428 if (bs != nbs) {
429 bs.swap(nbs);
430 return true;
431 }
432 return false;
433 }
434
435 void r600_sb::sb_value_set::remove_set(sb_value_set& s2) {
436 bs.mask(s2.bs);
437 }
438
439 bool sb_value_set::add_val(value* v) {
440 assert(v);
441 if (bs.size() < v->uid)
442 bs.resize(v->uid + 32);
443
444 return bs.set_chk(v->uid - 1, 1);
445 }
446
447 bool sb_value_set::remove_vec(vvec& vv) {
448 bool modified = false;
449 for (vvec::iterator I = vv.begin(), E = vv.end(); I != E; ++I) {
450 if (*I)
451 modified |= remove_val(*I);
452 }
453 return modified;
454 }
455
456 void sb_value_set::clear() {
457 bs.clear();
458 }
459
460 bool sb_value_set::remove_val(value* v) {
461 assert(v);
462 if (bs.size() < v->uid)
463 return false;
464 return bs.set_chk(v->uid - 1, 0);
465 }
466
467 bool r600_sb::sb_value_set::add_vec(vvec& vv) {
468 bool modified = false;
469 for (vvec::iterator I = vv.begin(), E = vv.end(); I != E; ++I) {
470 value *v = *I;
471 if (v)
472 modified |= add_val(v);
473 }
474 return modified;
475 }
476
477 bool r600_sb::sb_value_set::contains(value* v) {
478 unsigned b = v->uid - 1;
479 if (b < bs.size())
480 return bs.get(b);
481 else
482 return false;
483 }
484
485 bool sb_value_set::empty() {
486 return bs.size() == 0 || bs.find_bit(0) == bs.size();
487 }
488
489 void sb_bitset::swap(sb_bitset& bs2) {
490 std::swap(data, bs2.data);
491 std::swap(bit_size, bs2.bit_size);
492 }
493
494 bool sb_bitset::operator ==(const sb_bitset& bs2) {
495 if (bit_size != bs2.bit_size)
496 return false;
497
498 for (unsigned i = 0, c = data.size(); i < c; ++i) {
499 if (data[i] != bs2.data[i])
500 return false;
501 }
502 return true;
503 }
504
505 sb_bitset& sb_bitset::operator &=(const sb_bitset& bs2) {
506 if (bit_size > bs2.bit_size) {
507 resize(bs2.bit_size);
508 }
509
510 for (unsigned i = 0, c = std::min(data.size(), bs2.data.size()); i < c;
511 ++i) {
512 data[i] &= bs2.data[i];
513 }
514 return *this;
515 }
516
517 sb_bitset& sb_bitset::mask(const sb_bitset& bs2) {
518 if (bit_size < bs2.bit_size) {
519 resize(bs2.bit_size);
520 }
521
522 for (unsigned i = 0, c = data.size(); i < c;
523 ++i) {
524 data[i] &= ~bs2.data[i];
525 }
526 return *this;
527 }
528
529 bool ra_constraint::check() {
530 assert(kind == CK_SAME_REG);
531
532 unsigned reg = 0;
533
534 for (vvec::iterator I = values.begin(), E = values.end(); I != E; ++I) {
535 value *v = *I;
536 if (!v)
537 continue;
538
539 if (!v->gpr)
540 return false;
541
542 if (reg == 0)
543 reg = v->gpr.sel() + 1;
544 else if (reg != v->gpr.sel() + 1)
545 return false;
546
547 if (v->is_chan_pinned()) {
548 if (v->pin_gpr.chan() != v->gpr.chan())
549 return false;
550 }
551 }
552 return true;
553 }
554
555 bool gpr_array::is_dead() {
556 return false;
557 }
558
559 } // namespace r600_sb